[{"data":1,"prerenderedAt":706},["ShallowReactive",2],{"navigation_docs":3,"-android-hidden-hardening-abi-gate":173,"-android-hidden-hardening-abi-gate-surround":701},[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":103,"body":175,"description":684,"extension":685,"links":686,"meta":689,"navigation":696,"path":104,"seo":697,"stem":105,"__hash__":700},"docs\u002F3.android\u002F02.hidden-hardening\u002F10.abi-gate.md",{"type":176,"value":177,"toc":677},"minimark",[178,199,207,211,214,241,244,289,296,299,306,561,580,588,591,601,622,625,632,636,653,656,673],[179,180,181,185,186,189,190,193,194,198],"p",{},[182,183,184],"code",{},"libhiddendecrypt.so"," 按方法名和 JNI 签名调用加密 dex。如果改了 ",[182,187,188],{},"HiddenLandingPage"," 的方法表，却仍使用旧 so（或反过来），",[182,191,192],{},"GetMethodID"," 会静默失败，表现为 init 成功，但所有 invoke 都没有实际效果。因此，加载末尾加了一道 ",[195,196,197],"strong",{},"整数版本"," 检查。",[200,201,202,203,206],"note",{},"这里的 ABI 不是 CPU 的 armeabi \u002F arm64，而是 ",[195,204,205],{},"SDK 与 landing-page 的协议版本","。两边必须成对升级。",[208,209,210],"h2",{"id":210},"两边固定同一数字",[179,212,213],{},"so：",[215,216,222],"pre",{"className":217,"code":218,"filename":219,"language":220,"meta":221,"style":221},"language-cpp shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","#define ABI_VERSION 12\n","hidden-sdk\u002Fsrc\u002Fmain\u002Fcpp\u002Fhidden_bridge.cpp","cpp","",[182,223,224],{"__ignoreMap":221},[225,226,229,233,237],"span",{"class":227,"line":228},"line",1,[225,230,232],{"class":231},"s7zQu","#define",[225,234,236],{"class":235},"s2Zo4"," ABI_VERSION",[225,238,240],{"class":239},"sbssI"," 12\n",[179,242,243],{},"实现类：",[215,245,250],{"className":246,"code":247,"filename":248,"language":249,"meta":221,"style":221},"language-kotlin shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","class HiddenLandingPage {\n    val abiVersion: Int = 12\n}\n","hidden-landing-page\u002Fsrc\u002Fmain\u002Fjava\u002Fcom\u002Fexample\u002Fminidex\u002Fhidden\u002FHiddenLandingPage.kt","kotlin",[182,251,252,266,283],{"__ignoreMap":221},[225,253,254,258,262],{"class":227,"line":228},[225,255,257],{"class":256},"sMK4o","class",[225,259,261],{"class":260},"sBMFI"," HiddenLandingPage",[225,263,265],{"class":264},"sTEyZ"," {\n",[225,267,269,272,275,278,281],{"class":227,"line":268},2,[225,270,271],{"class":256},"    val",[225,273,274],{"class":264}," abiVersion: ",[225,276,277],{"class":260},"Int",[225,279,280],{"class":256}," =",[225,282,240],{"class":239},[225,284,286],{"class":227,"line":285},3,[225,287,288],{"class":264},"}\n",[179,290,291,292,295],{},"未初始化时，Java fallback 的 op 16 也返回 ",[182,293,294],{},"12","，避免调试接口在加载前报出一个还没核对过的版本。",[208,297,298],{"id":298},"加载后立刻核对",[179,300,301,302,305],{},"构造实例之后，用 XOR 方法名取 ",[182,303,304],{},"getAbiVersion","：",[215,307,309],{"className":217,"code":308,"filename":219,"language":220,"meta":221,"style":221},"static const uint8_t abi_enc[] = {\n        0x3d, 0x3f, 0x2e, 0x1b, 0x38, 0x33, 0x0c, 0x3f, 0x28, 0x29, 0x33, 0x35, 0x34\n};\njmethodID abi_mid = mid_by_xor(env, impl, abi_enc, sizeof(abi_enc), \"()I\");\nconst jint abi = env->CallIntMethod(instance, abi_mid);\nif (pending(env) || abi != ABI_VERSION) {\n    pthread_mutex_unlock(&g_lock);\n    return jerr(env, \"ABI 不匹配\");\n}\n",[182,310,311,331,395,400,451,483,517,532,556],{"__ignoreMap":221},[225,312,313,317,320,323,326,329],{"class":227,"line":228},[225,314,316],{"class":315},"spNyl","static",[225,318,319],{"class":315}," const",[225,321,322],{"class":315}," uint8_t",[225,324,325],{"class":264}," abi_enc[] ",[225,327,328],{"class":256},"=",[225,330,265],{"class":256},[225,332,333,336,339,342,344,347,349,352,354,357,359,362,364,367,369,371,373,376,378,381,383,385,387,390,392],{"class":227,"line":268},[225,334,335],{"class":239},"        0x3d",[225,337,338],{"class":256},",",[225,340,341],{"class":239}," 0x3f",[225,343,338],{"class":256},[225,345,346],{"class":239}," 0x2e",[225,348,338],{"class":256},[225,350,351],{"class":239}," 0x1b",[225,353,338],{"class":256},[225,355,356],{"class":239}," 0x38",[225,358,338],{"class":256},[225,360,361],{"class":239}," 0x33",[225,363,338],{"class":256},[225,365,366],{"class":239}," 0x0c",[225,368,338],{"class":256},[225,370,341],{"class":239},[225,372,338],{"class":256},[225,374,375],{"class":239}," 0x28",[225,377,338],{"class":256},[225,379,380],{"class":239}," 0x29",[225,382,338],{"class":256},[225,384,361],{"class":239},[225,386,338],{"class":256},[225,388,389],{"class":239}," 0x35",[225,391,338],{"class":256},[225,393,394],{"class":239}," 0x34\n",[225,396,397],{"class":227,"line":285},[225,398,399],{"class":256},"};\n",[225,401,403,406,408,411,414,417,419,422,424,427,429,432,435,438,441,445,448],{"class":227,"line":402},4,[225,404,405],{"class":264},"jmethodID abi_mid ",[225,407,328],{"class":256},[225,409,410],{"class":235}," mid_by_xor",[225,412,413],{"class":256},"(",[225,415,416],{"class":264},"env",[225,418,338],{"class":256},[225,420,421],{"class":264}," impl",[225,423,338],{"class":256},[225,425,426],{"class":264}," abi_enc",[225,428,338],{"class":256},[225,430,431],{"class":256}," sizeof(",[225,433,434],{"class":264},"abi_enc",[225,436,437],{"class":256},"),",[225,439,440],{"class":256}," \"",[225,442,444],{"class":443},"sfazB","()I",[225,446,447],{"class":256},"\"",[225,449,450],{"class":256},");\n",[225,452,454,457,460,462,465,468,471,473,476,478,481],{"class":227,"line":453},5,[225,455,456],{"class":315},"const",[225,458,459],{"class":264}," jint abi ",[225,461,328],{"class":256},[225,463,464],{"class":264}," env",[225,466,467],{"class":256},"->",[225,469,470],{"class":235},"CallIntMethod",[225,472,413],{"class":256},[225,474,475],{"class":264},"instance",[225,477,338],{"class":256},[225,479,480],{"class":264}," abi_mid",[225,482,450],{"class":256},[225,484,486,489,492,495,497,499,502,505,508,511,513,515],{"class":227,"line":485},6,[225,487,488],{"class":231},"if",[225,490,491],{"class":256}," (",[225,493,494],{"class":235},"pending",[225,496,413],{"class":256},[225,498,416],{"class":264},[225,500,501],{"class":256},")",[225,503,504],{"class":256}," ||",[225,506,507],{"class":264}," abi ",[225,509,510],{"class":256},"!=",[225,512,236],{"class":264},[225,514,501],{"class":256},[225,516,265],{"class":256},[225,518,520,523,526,530],{"class":227,"line":519},7,[225,521,522],{"class":235},"    pthread_mutex_unlock",[225,524,525],{"class":256},"(&",[225,527,529],{"class":528},"swJcz","g_lock",[225,531,450],{"class":256},[225,533,535,538,541,543,545,547,549,552,554],{"class":227,"line":534},8,[225,536,537],{"class":231},"    return",[225,539,540],{"class":235}," jerr",[225,542,413],{"class":256},[225,544,416],{"class":528},[225,546,338],{"class":256},[225,548,440],{"class":256},[225,550,551],{"class":443},"ABI 不匹配",[225,553,447],{"class":256},[225,555,450],{"class":256},[225,557,559],{"class":227,"line":558},9,[225,560,288],{"class":256},[179,562,563,564,567,568,571,572,575,576,579],{},"对不上时 ",[195,565,566],{},"不会"," 设置 ",[182,569,570],{},"g_instance","。Java 看到 ",[182,573,574],{},"LOAD_FAILED","，文案类似「SDK 未初始化：加载失败（ABI 不匹配）」。之后所有 ",[182,577,578],{},"invoke"," 走 fallback。",[581,582,583,584,587],"warning",{},"最常见的错位，是旧 AAR 里的 so 搭配从新仓库拷出的 enc（或反过来）。更换 AAR 后应先 Clean，不要解压后再自行放入一份过期的 ",[182,585,586],{},"hidden.dex.enc","。",[208,589,590],{"id":590},"什么时候加版本",[179,592,593,594,596,597,600],{},"改了以下内容就应将版本从 ",[182,595,294],{}," 调整为 ",[182,598,599],{},"13","，并同时修改 so 与 Kotlin：",[602,603,604,610,616,619],"ul",{},[605,606,607,609],"li",{},[182,608,188],{}," 方法增删、改名、改签名",[605,611,612,615],{},[182,613,614],{},"nativeDispatch"," 的 case 与 XOR 数组",[605,617,618],{},"密文布局（HDX1 头、nonce、算法）",[605,620,621],{},"ClassLoader 协议（例如不再无参构造）",[179,623,624],{},"只改来电 UI 文案、不改方法表，可以不动 ABI。",[179,626,627,628,631],{},"接入文档把当前版本写在显眼位置：",[182,629,630],{},"当前 ABI：12","。工具包升级时应成对更换，不要只换 so 或只换 enc。",[208,633,635],{"id":634},"和指令-16-的关系","和指令 16 的关系",[179,637,638,641,642,644,645,648,649,652],{},[182,639,640],{},"invoke(16)"," 在已加载时走 ",[182,643,304],{},"，未加载时返回常量 12。它用于调试当前协议号，不能代替 ",[182,646,647],{},"init"," 的失败码。真正拦截错位的，是 ",[182,650,651],{},"nativeInit"," 里的那一次比较。",[208,654,655],{"id":655},"下一步",[602,657,658,667],{},[605,659,660,305,664,666],{},[661,662,663],"a",{"href":79},"XOR混淆",[182,665,304],{}," 的字节从哪来",[605,668,669,672],{},[661,670,671],{"href":52},"总览","：十种方式如何串起来",[674,675,676],"style",{},"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 pre.shiki code .s2Zo4, html code.shiki .s2Zo4{--shiki-light:#6182B8;--shiki-default:#82AAFF;--shiki-dark:#82AAFF}html pre.shiki code .sbssI, html code.shiki .sbssI{--shiki-light:#F76D47;--shiki-default:#F78C6C;--shiki-dark:#F78C6C}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 .sMK4o, html code.shiki .sMK4o{--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF}html pre.shiki code .sBMFI, html code.shiki .sBMFI{--shiki-light:#E2931D;--shiki-default:#FFCB6B;--shiki-dark:#FFCB6B}html pre.shiki code .sTEyZ, html code.shiki .sTEyZ{--shiki-light:#90A4AE;--shiki-default:#EEFFFF;--shiki-dark:#BABED8}html pre.shiki code .spNyl, html code.shiki .spNyl{--shiki-light:#9C3EDA;--shiki-default:#C792EA;--shiki-dark:#C792EA}html pre.shiki code .sfazB, html code.shiki .sfazB{--shiki-light:#91B859;--shiki-default:#C3E88D;--shiki-dark:#C3E88D}html pre.shiki code .swJcz, html code.shiki .swJcz{--shiki-light:#E53935;--shiki-default:#F07178;--shiki-dark:#F07178}",{"title":221,"searchDepth":268,"depth":268,"links":678},[679,680,681,682,683],{"id":210,"depth":268,"text":210},{"id":298,"depth":268,"text":298},{"id":590,"depth":268,"text":590},{"id":634,"depth":268,"text":635},{"id":655,"depth":268,"text":655},"so 与加密实现约定整数版本 12。对不上就拒绝加载，避免新旧 AAR 错位。","md",[687,688],{"label":68,"icon":71,"to":69},{"label":78,"icon":81,"to":79},{"date":690,"categories":691,"tags":693},"2026-09-21",[692],"android",[37,694,695],"ABI","JNI",{"icon":106},{"title":698,"description":699},"安卓代码加固（10）：Hidden DEX 的 ABI 版本门禁","hidden-dex-minidemo 在 nativeInit 里调用 getAbiVersion，必须等于 ABI_VERSION 12，否则卸载 ClassLoader 并返回加载失败。","NGVEOtiel_MPAoHiK3d0TIrY_uelB-x_Szz_wi_6GDk",[702,704],{"title":98,"path":99,"stem":100,"description":703,"icon":101,"children":-1},"来电页、落地页、全屏广告使用 FLAG_SECURE。截屏与录屏得到黑屏，无需额外权限。",{"title":108,"path":110,"stem":114,"description":705,"icon":109,"children":-1},"iOS 开发实践与笔记。",1790767046921]