[{"data":1,"prerenderedAt":1470},["ShallowReactive",2],{"navigation_docs":3,"-android-hidden-hardening-opcode-dispatch":173,"-android-hidden-hardening-opcode-dispatch-surround":1465},[4,22,29,36,107,138,145,161],{"title":5,"icon":6,"path":7,"stem":8,"children":9},"博客","i-lucide-pen-line","\u002Fblog","0.blog",[10,12,17],{"title":5,"path":7,"stem":11,"icon":6},"0.blog\u002Findex",{"title":13,"path":14,"stem":15,"icon":16},"创建基于 UIKit 的原生 iOS 项目","\u002Fblog\u002Fcreate-uikit-ios-project","0.blog\u002F01.create-uikit-ios-project","i-lucide-app-window",{"title":18,"path":19,"stem":20,"icon":21},"Lockify：把账号和密码留在自己的手机里","\u002Fblog\u002Flockify","0.blog\u002F02.lockify","i-lucide-lock",{"title":23,"path":24,"stem":25,"children":26,"icon":28},"年度总结","\u002Fannual-review","1.annual-review\u002Findex",[27],{"title":23,"path":24,"stem":25,"icon":28},"i-lucide-git-commit",{"title":30,"path":31,"stem":32,"children":33,"icon":35},"故事","\u002Fstories","2.stories\u002Findex",[34],{"title":30,"path":31,"stem":32,"icon":35},"i-lucide-feather",{"title":37,"icon":38,"path":39,"stem":40,"children":41},"Android","i-simple-icons-android","\u002Fandroid","3.android",[42,44,49],{"title":37,"path":39,"stem":43,"icon":38},"3.android\u002Findex",{"title":45,"path":46,"stem":47,"icon":48},"初探Navigation","\u002Fandroid\u002Fcompose-navigation","3.android\u002F01.compose-navigation","i-lucide-route",{"title":50,"icon":51,"path":52,"stem":53,"children":54},"安卓代码加固","i-lucide-shield","\u002Fandroid\u002Fhidden-hardening","3.android\u002F02.hidden-hardening\u002Findex",[55,58,62,67,72,77,82,87,92,97,102],{"title":56,"path":52,"stem":53,"icon":57},"安卓代码加固：总览","i-lucide-map",{"title":59,"path":60,"stem":61,"icon":21},"安卓代码加固（1）：加密DEX","\u002Fandroid\u002Fhidden-hardening\u002Fencrypt-dex","3.android\u002F02.hidden-hardening\u002F01.encrypt-dex",{"title":63,"path":64,"stem":65,"icon":66},"安卓代码加固（2）：Native解密","\u002Fandroid\u002Fhidden-hardening\u002Fnative-decrypt","3.android\u002F02.hidden-hardening\u002F02.native-decrypt","i-lucide-cpu",{"title":68,"path":69,"stem":70,"icon":71},"安卓代码加固（3）：内存加载","\u002Fandroid\u002Fhidden-hardening\u002Fmemory-load","3.android\u002F02.hidden-hardening\u002F03.memory-load","i-lucide-memory-stick",{"title":73,"path":74,"stem":75,"icon":76},"安卓代码加固（4）：指令分发","\u002Fandroid\u002Fhidden-hardening\u002Fopcode-dispatch","3.android\u002F02.hidden-hardening\u002F04.opcode-dispatch","i-lucide-hash",{"title":78,"path":79,"stem":80,"icon":81},"安卓代码加固（5）：XOR混淆","\u002Fandroid\u002Fhidden-hardening\u002Fxor-obfuscate","3.android\u002F02.hidden-hardening\u002F05.xor-obfuscate","i-lucide-shuffle",{"title":83,"path":84,"stem":85,"icon":86},"安卓代码加固（6）：密钥外置","\u002Fandroid\u002Fhidden-hardening\u002Fkey-external","3.android\u002F02.hidden-hardening\u002F06.key-external","i-lucide-key",{"title":88,"path":89,"stem":90,"icon":91},"安卓代码加固（7）：依赖隔离","\u002Fandroid\u002Fhidden-hardening\u002Fdep-isolate","3.android\u002F02.hidden-hardening\u002F07.dep-isolate","i-lucide-layers",{"title":93,"path":94,"stem":95,"icon":96},"安卓代码加固（8）：构建校验","\u002Fandroid\u002Fhidden-hardening\u002Fbuild-verify","3.android\u002F02.hidden-hardening\u002F08.build-verify","i-lucide-shield-check",{"title":98,"path":99,"stem":100,"icon":101},"安卓代码加固（9）：防录屏","\u002Fandroid\u002Fhidden-hardening\u002Fflag-secure","3.android\u002F02.hidden-hardening\u002F09.flag-secure","i-lucide-eye-off",{"title":103,"path":104,"stem":105,"icon":106},"安卓代码加固（10）：ABI门禁","\u002Fandroid\u002Fhidden-hardening\u002Fabi-gate","3.android\u002F02.hidden-hardening\u002F10.abi-gate","i-lucide-git-compare",{"title":108,"icon":109,"path":110,"stem":111,"children":112},"iOS","i-simple-icons-apple","\u002Fios","4.ios",[113,115,120,125,129,133],{"title":108,"path":110,"stem":114,"icon":109},"4.ios\u002Findex",{"title":116,"path":117,"stem":118,"icon":119},"iOS面试题1","\u002Fios\u002Fios-interview1","4.ios\u002F01.ios-interview1","i-lucide-sparkles",{"title":121,"path":122,"stem":123,"icon":124},"设置启动图","\u002Fios\u002Fset-launch-screen","4.ios\u002F02.set-launch-screen","i-lucide-image",{"title":126,"path":127,"stem":128,"icon":48},"路由管理","\u002Fios\u002Frouting","4.ios\u002F03.routing",{"title":130,"path":131,"stem":132,"icon":91},"状态管理","\u002Fios\u002Fstate-management","4.ios\u002F04.state-management",{"title":134,"path":135,"stem":136,"icon":137},"事件传递","\u002Fios\u002Fevent-delivery","4.ios\u002F05.event-delivery","i-lucide-pointer",{"title":139,"path":140,"stem":141,"children":142,"icon":144},"Flutter","\u002Fflutter","5.flutter\u002Findex",[143],{"title":139,"path":140,"stem":141,"icon":144},"i-simple-icons-flutter",{"title":146,"icon":147,"path":148,"stem":149,"children":150,"page":160},"面试","i-lucide-graduation-cap","\u002Finterview","6.interview",[151,156],{"title":152,"path":153,"stem":154,"icon":155},"Flutter面试题1","\u002Finterview\u002Fflutter-interview1","6.interview\u002F01.flutter-interview1","i-lucide-boxes",{"title":157,"path":158,"stem":159,"icon":66},"Flutter面试题2","\u002Finterview\u002Fflutter-interview2","6.interview\u002F02.flutter-interview2",false,{"title":162,"icon":163,"path":164,"stem":165,"children":166},"算法学习","i-lucide-binary","\u002Falgorithm","7.algorithm",[167,169],{"title":162,"path":164,"stem":168,"icon":163},"7.algorithm\u002Findex",{"title":170,"path":171,"stem":172},"算法基础1：复杂度分析","\u002Falgorithm\u002Ftime-space-complexity","7.algorithm\u002F01.time-space-complexity",{"id":174,"title":73,"body":175,"description":1448,"extension":1449,"links":1450,"meta":1453,"navigation":1460,"path":74,"seo":1461,"stem":75,"__hash__":1464},"docs\u002F3.android\u002F02.hidden-hardening\u002F04.opcode-dispatch.md",{"type":176,"value":177,"toc":1441},"minimark",[178,203,359,372,377,391,659,670,681,772,775,778,1055,1068,1097,1100,1115,1261,1270,1273,1286,1411,1417,1420,1437],[179,180,181,182,186,187,190,191,194,195,198,199,202],"p",{},"如果主 DEX 出现 ",[183,184,185],"code",{},"startIncomingCall","、",[183,188,189],{},"performAnswer"," 这类名字，静态分析就能还原调用图。当前公开类型只有 ",[183,192,193],{},"HiddenSdk"," 和 ",[183,196,197],{},"HiddenInitResult","。业务全部通过 ",[183,200,201],{},"invoke"," 调用。",[204,205,211],"pre",{"className":206,"code":207,"filename":208,"language":209,"meta":210,"style":210},"language-kotlin shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","\u002F**\n * 唯一公开入口：校验密钥、加载 payload、按整数指令分发。\n * 主 DEX 不暴露业务方法名。指令含义见仓库 `接入与使用.md`。\n *\u002F\n@JvmStatic\n@JvmOverloads\nfun invoke(op: Int, a: Any? = null, b: Any? = null): Any? {\n    if (!nativeReady()) {\n        return fallback(op, a, b)\n    }\n    return nativeDispatch(op, a, b)\n}\n","hidden-sdk\u002Fsrc\u002Fmain\u002Fjava\u002Fcom\u002Fexample\u002Fminidex\u002Fsdk\u002FHiddenSdk.kt","kotlin","",[183,212,213,222,228,234,240,247,253,305,324,336,342,353],{"__ignoreMap":210},[214,215,218],"span",{"class":216,"line":217},"line",1,[214,219,221],{"class":220},"sHwdD","\u002F**\n",[214,223,225],{"class":216,"line":224},2,[214,226,227],{"class":220}," * 唯一公开入口：校验密钥、加载 payload、按整数指令分发。\n",[214,229,231],{"class":216,"line":230},3,[214,232,233],{"class":220}," * 主 DEX 不暴露业务方法名。指令含义见仓库 `接入与使用.md`。\n",[214,235,237],{"class":216,"line":236},4,[214,238,239],{"class":220}," *\u002F\n",[214,241,243],{"class":216,"line":242},5,[214,244,246],{"class":245},"sBMFI","@JvmStatic\n",[214,248,250],{"class":216,"line":249},6,[214,251,252],{"class":245},"@JvmOverloads\n",[214,254,256,260,264,268,271,274,277,280,283,286,289,291,293,295,297,300,302],{"class":216,"line":255},7,[214,257,259],{"class":258},"sMK4o","fun",[214,261,263],{"class":262},"s2Zo4"," invoke",[214,265,267],{"class":266},"sTEyZ","(op: ",[214,269,270],{"class":245},"Int",[214,272,273],{"class":266},", a: ",[214,275,276],{"class":245},"Any",[214,278,279],{"class":266},"? ",[214,281,282],{"class":258},"=",[214,284,285],{"class":258}," null",[214,287,288],{"class":266},", b: ",[214,290,276],{"class":245},[214,292,279],{"class":266},[214,294,282],{"class":258},[214,296,285],{"class":258},[214,298,299],{"class":266},"): ",[214,301,276],{"class":245},[214,303,304],{"class":266},"? {\n",[214,306,308,312,315,318,321],{"class":216,"line":307},8,[214,309,311],{"class":310},"s7zQu","    if",[214,313,314],{"class":266}," (",[214,316,317],{"class":258},"!",[214,319,320],{"class":262},"nativeReady",[214,322,323],{"class":266},"()) {\n",[214,325,327,330,333],{"class":216,"line":326},9,[214,328,329],{"class":310},"        return",[214,331,332],{"class":262}," fallback",[214,334,335],{"class":266},"(op, a, b)\n",[214,337,339],{"class":216,"line":338},10,[214,340,341],{"class":266},"    }\n",[214,343,345,348,351],{"class":216,"line":344},11,[214,346,347],{"class":310},"    return",[214,349,350],{"class":262}," nativeDispatch",[214,352,335],{"class":266},[214,354,356],{"class":216,"line":355},12,[214,357,358],{"class":266},"}\n",[360,361,362,363,367,368,371],"caution",{},"对照表只写在仓库文档和宿主本地包装里，",[364,365,366],"strong",{},"不要","写进 SDK 源码或 AAR。JADX 只能看到 ",[183,369,370],{},"invoke(Int, Any?, Any?)","。",[373,374,376],"h2",{"id":375},"native-如何分发","native 如何分发",[179,378,379,382,383,386,387,390],{},[183,380,381],{},"nativeDispatch"," 是一个 ",[183,384,385],{},"switch (cmd)","。每个 case 用 XOR 过的方法名做 ",[183,388,389],{},"GetMethodID","，再按签名拆箱参数。",[204,392,397],{"className":393,"code":394,"filename":395,"language":396,"meta":210,"style":210},"language-cpp shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","case 3: {\n    static const uint8_t n[] = {\n            0x29, 0x2e, 0x3b, 0x28, 0x2e, 0x13, 0x34, 0x39, 0x35, 0x37,\n            0x33, 0x34, 0x3d, 0x19, 0x3b, 0x36, 0x36\n    };\n    jmethodID mid = mid_by_xor(\n            env, impl, n, sizeof(n),\n            \"(Landroid\u002Fcontent\u002FContext;)Z\");\n    if (mid != nullptr) {\n        result = box_bool(env, env->CallBooleanMethod(instance, mid, arg1));\n    }\n    break;\n}\n","hidden-sdk\u002Fsrc\u002Fmain\u002Fcpp\u002Fhidden_bridge.cpp","cpp",[183,398,399,414,435,488,521,526,539,565,580,597,642,646,654],{"__ignoreMap":210},[214,400,401,404,408,411],{"class":216,"line":217},[214,402,403],{"class":310},"case",[214,405,407],{"class":406},"sbssI"," 3",[214,409,410],{"class":266},": ",[214,412,413],{"class":258},"{\n",[214,415,416,420,423,426,430,432],{"class":216,"line":224},[214,417,419],{"class":418},"spNyl","    static",[214,421,422],{"class":418}," const",[214,424,425],{"class":418}," uint8_t",[214,427,429],{"class":428},"swJcz"," n[] ",[214,431,282],{"class":258},[214,433,434],{"class":258}," {\n",[214,436,437,440,443,446,448,451,453,456,458,460,462,465,467,470,472,475,477,480,482,485],{"class":216,"line":230},[214,438,439],{"class":406},"            0x29",[214,441,442],{"class":258},",",[214,444,445],{"class":406}," 0x2e",[214,447,442],{"class":258},[214,449,450],{"class":406}," 0x3b",[214,452,442],{"class":258},[214,454,455],{"class":406}," 0x28",[214,457,442],{"class":258},[214,459,445],{"class":406},[214,461,442],{"class":258},[214,463,464],{"class":406}," 0x13",[214,466,442],{"class":258},[214,468,469],{"class":406}," 0x34",[214,471,442],{"class":258},[214,473,474],{"class":406}," 0x39",[214,476,442],{"class":258},[214,478,479],{"class":406}," 0x35",[214,481,442],{"class":258},[214,483,484],{"class":406}," 0x37",[214,486,487],{"class":258},",\n",[214,489,490,493,495,497,499,502,504,507,509,511,513,516,518],{"class":216,"line":236},[214,491,492],{"class":406},"            0x33",[214,494,442],{"class":258},[214,496,469],{"class":406},[214,498,442],{"class":258},[214,500,501],{"class":406}," 0x3d",[214,503,442],{"class":258},[214,505,506],{"class":406}," 0x19",[214,508,442],{"class":258},[214,510,450],{"class":406},[214,512,442],{"class":258},[214,514,515],{"class":406}," 0x36",[214,517,442],{"class":258},[214,519,520],{"class":406}," 0x36\n",[214,522,523],{"class":216,"line":242},[214,524,525],{"class":258},"    };\n",[214,527,528,531,533,536],{"class":216,"line":249},[214,529,530],{"class":428},"    jmethodID mid ",[214,532,282],{"class":258},[214,534,535],{"class":262}," mid_by_xor",[214,537,538],{"class":258},"(\n",[214,540,541,544,546,549,551,554,556,559,562],{"class":216,"line":255},[214,542,543],{"class":428},"            env",[214,545,442],{"class":258},[214,547,548],{"class":428}," impl",[214,550,442],{"class":258},[214,552,553],{"class":428}," n",[214,555,442],{"class":258},[214,557,558],{"class":258}," sizeof(",[214,560,561],{"class":428},"n",[214,563,564],{"class":258},"),\n",[214,566,567,570,574,577],{"class":216,"line":307},[214,568,569],{"class":258},"            \"",[214,571,573],{"class":572},"sfazB","(Landroid\u002Fcontent\u002FContext;)Z",[214,575,576],{"class":258},"\"",[214,578,579],{"class":258},");\n",[214,581,582,584,586,589,592,595],{"class":216,"line":326},[214,583,311],{"class":310},[214,585,314],{"class":258},[214,587,588],{"class":428},"mid ",[214,590,591],{"class":258},"!=",[214,593,594],{"class":258}," nullptr)",[214,596,434],{"class":258},[214,598,599,602,604,607,610,613,615,618,621,624,626,629,631,634,636,639],{"class":216,"line":338},[214,600,601],{"class":428},"        result ",[214,603,282],{"class":258},[214,605,606],{"class":262}," box_bool",[214,608,609],{"class":258},"(",[214,611,612],{"class":428},"env",[214,614,442],{"class":258},[214,616,617],{"class":266}," env",[214,619,620],{"class":258},"->",[214,622,623],{"class":262},"CallBooleanMethod",[214,625,609],{"class":258},[214,627,628],{"class":428},"instance",[214,630,442],{"class":258},[214,632,633],{"class":428}," mid",[214,635,442],{"class":258},[214,637,638],{"class":428}," arg1",[214,640,641],{"class":258},"));\n",[214,643,644],{"class":216,"line":344},[214,645,341],{"class":258},[214,647,648,651],{"class":216,"line":355},[214,649,650],{"class":310},"    break",[214,652,653],{"class":258},";\n",[214,655,657],{"class":216,"line":656},13,[214,658,358],{"class":258},[179,660,661,662,665,666,669],{},"用 ",[183,663,664],{},"0x5A"," 解开后，上面这段是 ",[183,667,668],{},"startIncomingCall(Context): Boolean","。Java 侧看不到这个名字。",[179,671,672,673,676,677,680],{},"未初始化时 ",[364,674,675],{},"不会"," 进入 native。",[183,678,679],{},"fallback"," 按指令返回空结果，不抛异常：",[682,683,684,697],"table",{},[685,686,687],"thead",{},[688,689,690,694],"tr",{},[691,692,693],"th",{},"op",[691,695,696],{},"未初始化",[698,699,700,711,719,730,740,751,762],"tbody",{},[688,701,702,706],{},[703,704,705],"td",{},"2 \u002F 3 \u002F 11",[703,707,708],{},[183,709,710],{},"false",[688,712,713,716],{},[703,714,715],{},"4",[703,717,718],{},"不排队",[688,720,721,724],{},[703,722,723],{},"5",[703,725,726,727],{},"立刻断开的空 ",[183,728,729],{},"Connection",[688,731,732,735],{},[703,733,734],{},"12 \u002F 15",[703,736,737],{},[183,738,739],{},"\"SDK 未初始化\"",[688,741,742,745],{},[703,743,744],{},"13",[703,746,747,748],{},"仍给当前 Activity 加 ",[183,749,750],{},"FLAG_SECURE",[688,752,753,756],{},[703,754,755],{},"16",[703,757,758,759],{},"常量 ",[183,760,761],{},"12",[688,763,764,767],{},[703,765,766],{},"其余",[703,768,769],{},[183,770,771],{},"null",[373,773,774],{"id":774},"对照指令表",[179,776,777],{},"实现类方法名（XOR 解开后）和 op 的对应关系：",[682,779,780,795],{},[685,781,782],{},[688,783,784,786,789,792],{},[691,785,693],{},[691,787,788],{},"实现方法",[691,790,791],{},"参数",[691,793,794],{},"作用",[698,796,797,815,833,849,869,885,901,915,930,945,960,975,991,1011,1026,1041],{},[688,798,799,802,807,812],{},[703,800,801],{},"1",[703,803,804],{},[183,805,806],{},"configure",[703,808,809],{},[183,810,811],{},"String?",[703,813,814],{},"指定接听后落地页",[688,816,817,820,825,830],{},[703,818,819],{},"2",[703,821,822],{},[183,823,824],{},"registerPhoneAccount",[703,826,827],{},[183,828,829],{},"Context",[703,831,832],{},"登记自管理账号",[688,834,835,838,842,846],{},[703,836,837],{},"3",[703,839,840],{},[183,841,185],{},[703,843,844],{},[183,845,829],{},[703,847,848],{},"立刻发起",[688,850,851,853,858,866],{},[703,852,715],{},[703,854,855],{},[183,856,857],{},"startIncomingCallLater",[703,859,860,862,863],{},[183,861,829],{},", ",[183,864,865],{},"Long",[703,867,868],{},"延迟发起",[688,870,871,873,878,882],{},[703,872,723],{},[703,874,875],{},[183,876,877],{},"createIncomingConnection",[703,879,880],{},[183,881,829],{},[703,883,884],{},"ConnectionService 占位",[688,886,887,890,895,898],{},[703,888,889],{},"6",[703,891,892],{},[183,893,894],{},"hangUp",[703,896,897],{},"—",[703,899,900],{},"结束会话",[688,902,903,906,910,912],{},[703,904,905],{},"7",[703,907,908],{},[183,909,189],{},[703,911,897],{},[703,913,914],{},"接听",[688,916,917,920,925,927],{},[703,918,919],{},"8",[703,921,922],{},[183,923,924],{},"performReject",[703,926,897],{},[703,928,929],{},"拒绝",[688,931,932,935,940,942],{},[703,933,934],{},"9",[703,936,937],{},[183,938,939],{},"onLandingOpened",[703,941,897],{},[703,943,944],{},"落地页已打开",[688,946,947,950,955,957],{},[703,948,949],{},"10",[703,951,952],{},[183,953,954],{},"onIncomingUiShown",[703,956,897],{},[703,958,959],{},"全屏路由页已展示",[688,961,962,965,970,972],{},[703,963,964],{},"11",[703,966,967],{},[183,968,969],{},"isIncomingRinging",[703,971,897],{},[703,973,974],{},"是否仍在振铃",[688,976,977,979,984,988],{},[703,978,761],{},[703,980,981],{},[183,982,983],{},"statusText",[703,985,986],{},[183,987,829],{},[703,989,990],{},"调试状态",[688,992,993,995,1000,1008],{},[703,994,744],{},[703,996,997],{},[183,998,999],{},"applyScreenProtection",[703,1001,1002,862,1005],{},[183,1003,1004],{},"Activity",[183,1006,1007],{},"Boolean",[703,1009,1010],{},"防录屏",[688,1012,1013,1016,1021,1023],{},[703,1014,1015],{},"14",[703,1017,1018],{},[183,1019,1020],{},"getLastError",[703,1022,897],{},[703,1024,1025],{},"最近错误",[688,1027,1028,1031,1036,1038],{},[703,1029,1030],{},"15",[703,1032,1033],{},[183,1034,1035],{},"getLastStatus",[703,1037,897],{},[703,1039,1040],{},"最近状态",[688,1042,1043,1045,1050,1052],{},[703,1044,755],{},[703,1046,1047],{},[183,1048,1049],{},"getAbiVersion",[703,1051,897],{},[703,1053,1054],{},"ABI",[179,1056,1057,1058,186,1061,186,1064,1067],{},"Kotlin 属性 ",[183,1059,1060],{},"abiVersion",[183,1062,1063],{},"lastError",[183,1065,1066],{},"lastStatus"," 在 JNI 里对应 getter。改属性名等于改 so 里的 XOR 字节。",[1069,1070,1071],"accordion",{},[1072,1073,1076,1077,1080,1081,1084,1085,1088,1089,1092,1093,1096],"accordion-item",{"icon":1074,"label":1075},"i-lucide-file-x","为什么删掉 HiddenApi？","旧方案先在 Java 里 ",[183,1078,1079],{},"loadClass","，再 ",[183,1082,1083],{},"as HiddenApi","。接口方法名会出现在主 DEX。现在由 so 直接构造 ",[183,1086,1087],{},"HiddenLandingPage","，主 DEX 不再包含 ",[183,1090,1091],{},"HiddenApi","。APK 自检还会确认 ",[183,1094,1095],{},"Lcom\u002Fexample\u002Fminidex\u002Fsdk\u002FHiddenApi;"," 不存在。",[373,1098,1099],{"id":1099},"把可读名留在宿主",[179,1101,1102,1103,1106,1107,1110,1111,1114],{},"Demo 用 ",[183,1104,1105],{},"HostBridge"," 把整数封装成方法。这个对象是 ",[364,1108,1109],{},"internal","，只存在于 ",[183,1112,1113],{},":app","，不进入 SDK AAR。",[204,1116,1119],{"className":206,"code":1117,"filename":1118,"language":209,"meta":210,"style":210},"internal object HostBridge {\n    fun start(context: Context): Boolean =\n        HiddenSdk.invoke(3, context) as? Boolean ?: false\n\n    fun answer() {\n        HiddenSdk.invoke(7)\n    }\n\n    fun protect(activity: Activity, enable: Boolean = true) {\n        HiddenSdk.invoke(13, activity, enable)\n    }\n}\n","app\u002Fsrc\u002Fmain\u002Fjava\u002Fcom\u002Fexample\u002Fminidex\u002FHostBridge.kt",[183,1120,1121,1133,1153,1177,1183,1193,1206,1210,1214,1240,1253,1257],{"__ignoreMap":210},[214,1122,1123,1125,1128,1131],{"class":216,"line":217},[214,1124,1109],{"class":418},[214,1126,1127],{"class":258}," object",[214,1129,1130],{"class":245}," HostBridge",[214,1132,434],{"class":266},[214,1134,1135,1138,1141,1144,1146,1148,1150],{"class":216,"line":224},[214,1136,1137],{"class":258},"    fun",[214,1139,1140],{"class":262}," start",[214,1142,1143],{"class":266},"(context: ",[214,1145,829],{"class":245},[214,1147,299],{"class":266},[214,1149,1007],{"class":245},[214,1151,1152],{"class":258}," =\n",[214,1154,1155,1158,1160,1162,1164,1167,1170,1173],{"class":216,"line":230},[214,1156,1157],{"class":266},"        HiddenSdk.",[214,1159,201],{"class":262},[214,1161,609],{"class":266},[214,1163,837],{"class":406},[214,1165,1166],{"class":266},", context) ",[214,1168,1169],{"class":258},"as",[214,1171,1172],{"class":266},"? Boolean ?: ",[214,1174,1176],{"class":1175},"sfNiH","false\n",[214,1178,1179],{"class":216,"line":236},[214,1180,1182],{"emptyLinePlaceholder":1181},true,"\n",[214,1184,1185,1187,1190],{"class":216,"line":242},[214,1186,1137],{"class":258},[214,1188,1189],{"class":262}," answer",[214,1191,1192],{"class":266},"() {\n",[214,1194,1195,1197,1199,1201,1203],{"class":216,"line":249},[214,1196,1157],{"class":266},[214,1198,201],{"class":262},[214,1200,609],{"class":266},[214,1202,905],{"class":406},[214,1204,1205],{"class":266},")\n",[214,1207,1208],{"class":216,"line":255},[214,1209,341],{"class":266},[214,1211,1212],{"class":216,"line":307},[214,1213,1182],{"emptyLinePlaceholder":1181},[214,1215,1216,1218,1221,1224,1226,1229,1231,1234,1237],{"class":216,"line":326},[214,1217,1137],{"class":258},[214,1219,1220],{"class":262}," protect",[214,1222,1223],{"class":266},"(activity: ",[214,1225,1004],{"class":245},[214,1227,1228],{"class":266},", enable: ",[214,1230,1007],{"class":245},[214,1232,1233],{"class":258}," =",[214,1235,1236],{"class":1175}," true",[214,1238,1239],{"class":266},") {\n",[214,1241,1242,1244,1246,1248,1250],{"class":216,"line":338},[214,1243,1157],{"class":266},[214,1245,201],{"class":262},[214,1247,609],{"class":266},[214,1249,744],{"class":406},[214,1251,1252],{"class":266},", activity, enable)\n",[214,1254,1255],{"class":216,"line":344},[214,1256,341],{"class":266},[214,1258,1259],{"class":216,"line":355},[214,1260,358],{"class":266},[179,1262,1263,1264,1267,1268,371],{},"工具包对外再包一层 ",[183,1265,1266],{},"YourLandingPageKit","，也是同一做法：最终 App 调用接入方自己的方法名。分析 SDK AAR 时，仍然只能看到 ",[183,1269,201],{},[373,1271,1272],{"id":1272},"处理占位组件",[179,1274,1275,1278,1279,1281,1282,1285],{},[183,1276,1277],{},"ConnectionService"," 必须留在主 DEX，系统按清单类名绑定。Demo 占位组件走本地 ",[183,1280,1105],{},"，内部仍是 ",[183,1283,1284],{},"invoke(5)","：",[204,1287,1290],{"className":206,"code":1288,"filename":1289,"language":209,"meta":210,"style":210},"override fun onCreateIncomingConnection(...): Connection {\n    return runCatching {\n        HostBridge.createConnection(this)\n    }.getOrElse { error ->\n        object : Connection() {\n            init {\n                setDisconnected(DisconnectCause(DisconnectCause.ERROR, error.message))\n                destroy()\n            }\n        }\n    }\n}\n","app\u002Fsrc\u002Fmain\u002Fjava\u002Fcom\u002Fexample\u002Fminidex\u002FDemoConnectionService.kt",[183,1291,1292,1315,1324,1339,1353,1365,1372,1385,1393,1398,1403,1407],{"__ignoreMap":210},[214,1293,1294,1297,1300,1303,1305,1308,1311,1313],{"class":216,"line":217},[214,1295,1296],{"class":418},"override",[214,1298,1299],{"class":258}," fun",[214,1301,1302],{"class":262}," onCreateIncomingConnection",[214,1304,609],{"class":266},[214,1306,1307],{"class":258},"..",[214,1309,1310],{"class":266},".): ",[214,1312,729],{"class":245},[214,1314,434],{"class":266},[214,1316,1317,1319,1322],{"class":216,"line":224},[214,1318,347],{"class":310},[214,1320,1321],{"class":262}," runCatching",[214,1323,434],{"class":266},[214,1325,1326,1329,1332,1334,1337],{"class":216,"line":230},[214,1327,1328],{"class":266},"        HostBridge.",[214,1330,1331],{"class":262},"createConnection",[214,1333,609],{"class":266},[214,1335,1336],{"class":258},"this",[214,1338,1205],{"class":266},[214,1340,1341,1344,1347,1350],{"class":216,"line":236},[214,1342,1343],{"class":266},"    }.",[214,1345,1346],{"class":262},"getOrElse",[214,1348,1349],{"class":266}," { error ",[214,1351,1352],{"class":418},"->\n",[214,1354,1355,1358,1361,1363],{"class":216,"line":242},[214,1356,1357],{"class":258},"        object",[214,1359,1360],{"class":266}," : ",[214,1362,729],{"class":245},[214,1364,1192],{"class":266},[214,1366,1367,1370],{"class":216,"line":249},[214,1368,1369],{"class":258},"            init",[214,1371,434],{"class":266},[214,1373,1374,1377,1379,1382],{"class":216,"line":255},[214,1375,1376],{"class":262},"                setDisconnected",[214,1378,609],{"class":266},[214,1380,1381],{"class":262},"DisconnectCause",[214,1383,1384],{"class":266},"(DisconnectCause.ERROR, error.message))\n",[214,1386,1387,1390],{"class":216,"line":307},[214,1388,1389],{"class":262},"                destroy",[214,1391,1392],{"class":266},"()\n",[214,1394,1395],{"class":216,"line":326},[214,1396,1397],{"class":266},"            }\n",[214,1399,1400],{"class":216,"line":338},[214,1401,1402],{"class":266},"        }\n",[214,1404,1405],{"class":216,"line":344},[214,1406,341],{"class":266},[214,1408,1409],{"class":216,"line":355},[214,1410,358],{"class":266},[179,1412,1413,1414,1416],{},"未初始化时，",[183,1415,679],{}," 返回已断开的空 Connection，reason 为「SDK 未初始化」。Telecom 不会一直挂起一通无效来电。",[373,1418,1419],{"id":1419},"下一步",[1421,1422,1423,1431],"ul",{},[1424,1425,1426,1430],"li",{},[1427,1428,1429],"a",{"href":79},"XOR混淆","：方法名字节怎么来",[1424,1432,1433,1436],{},[1427,1434,1435],{"href":89},"依赖隔离","：宿主为什么不能 import 实现类",[1438,1439,1440],"style",{},"html pre.shiki code .sHwdD, html code.shiki .sHwdD{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#546E7A;--shiki-default-font-style:italic;--shiki-dark:#676E95;--shiki-dark-font-style:italic}html pre.shiki code .sBMFI, html code.shiki .sBMFI{--shiki-light:#E2931D;--shiki-default:#FFCB6B;--shiki-dark:#FFCB6B}html pre.shiki code .sMK4o, html code.shiki .sMK4o{--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF}html pre.shiki code .s2Zo4, html code.shiki .s2Zo4{--shiki-light:#6182B8;--shiki-default:#82AAFF;--shiki-dark:#82AAFF}html pre.shiki code .sTEyZ, html code.shiki .sTEyZ{--shiki-light:#90A4AE;--shiki-default:#EEFFFF;--shiki-dark:#BABED8}html pre.shiki code .s7zQu, html code.shiki .s7zQu{--shiki-light:#39ADB5;--shiki-light-font-style:italic;--shiki-default:#89DDFF;--shiki-default-font-style:italic;--shiki-dark:#89DDFF;--shiki-dark-font-style:italic}html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sbssI, html code.shiki .sbssI{--shiki-light:#F76D47;--shiki-default:#F78C6C;--shiki-dark:#F78C6C}html pre.shiki code .spNyl, html code.shiki .spNyl{--shiki-light:#9C3EDA;--shiki-default:#C792EA;--shiki-dark:#C792EA}html pre.shiki code .swJcz, html code.shiki .swJcz{--shiki-light:#E53935;--shiki-default:#F07178;--shiki-dark:#F07178}html pre.shiki code .sfazB, html code.shiki .sfazB{--shiki-light:#91B859;--shiki-default:#C3E88D;--shiki-dark:#C3E88D}html pre.shiki code .sfNiH, html code.shiki .sfNiH{--shiki-light:#FF5370;--shiki-default:#FF9CAC;--shiki-dark:#FF9CAC}",{"title":210,"searchDepth":224,"depth":224,"links":1442},[1443,1444,1445,1446,1447],{"id":375,"depth":224,"text":376},{"id":774,"depth":224,"text":774},{"id":1099,"depth":224,"text":1099},{"id":1272,"depth":224,"text":1272},{"id":1419,"depth":224,"text":1419},"公开入口只有 invoke(Int, Any?, Any?)。指令含义不进入 AAR，native 按整数查找方法。","md",[1451,1452],{"label":78,"icon":81,"to":79},{"label":68,"icon":71,"to":69},{"date":1454,"categories":1455,"tags":1457},"2026-09-21",[1456],"android",[37,1458,1459],"JNI","API",{"icon":76},{"title":1462,"description":1463},"安卓代码加固（4）：用整数指令分发 Hidden SDK","hidden-dex-minidemo 的 HiddenSdk 不暴露业务方法名。宿主只调用 invoke(op)。对照表写在接入文档和 Demo HostBridge 里。","gE88skB1GbGKMFm_XL3zGIrl4zen2DcjeVKpDKoJu_E",[1466,1468],{"title":68,"path":69,"stem":70,"description":1467,"icon":71},"解密后的 dex 只存在于 ByteBuffer 中，用 InMemoryDexClassLoader 加载，不写入 filesDir。",{"title":78,"path":79,"stem":80,"description":1469,"icon":81},"so 里的资源路径、实现类名、方法名按 0x5A 异或存放，用完立即清零。",1790767046078]