[{"data":1,"prerenderedAt":656},["ShallowReactive",2],{"navigation_docs":3,"-android-hidden-hardening":173,"-android-hidden-hardening-surround":651},[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":56,"body":175,"description":633,"extension":634,"links":635,"meta":639,"navigation":646,"path":52,"seo":647,"stem":53,"__hash__":650},"docs\u002F3.android\u002F02.hidden-hardening\u002Findex.md",{"type":176,"value":177,"toc":620},"minimark",[178,203,211,215,218,221,224,227,237,240,346,355,416,419,510,513,579,587,590,616],[179,180,181,185,186,190,191,194,195,198,199,202],"p",{},[182,183,184],"code",{},"hidden-dex-minidemo"," 隐藏的是 ",[187,188,189],"strong",{},"自管理来电实现","，不是整个 App。宿主只依赖公开 SDK。真正的 ",[182,192,193],{},"HiddenLandingPage"," 在构建期打成加密 DEX，放入 AAR 的 ",[182,196,197],{},"assets\u002F","。进程启动后，由 ",[182,200,201],{},"libhiddendecrypt.so"," 解密，并在内存里加载。",[204,205,206,207,210],"warning",{},"这只能提高静态分析成本，并不能彻底防止反编译。so 仍可被 hook，密钥仍须由接入方保管。用 JADX 打开主 DEX，只能看到 ",[182,208,209],{},"HiddenSdk.invoke(Int, Any?, Any?)","。",[212,213,214],"h2",{"id":214},"下载示例",[179,216,217],{},"可运行工程与本文档对应，归在 Android 分类。解压后用 Android Studio 打开。",[219,220],"demo-download",{"demo":184},[212,222,223],{"id":223},"产物如何拆分",[179,225,226],{},"接入方拿到的 AAR：",[228,229,235],"pre",{"className":230,"code":232,"language":233,"meta":234},[231],"language-text","hidden-sdk-1.0.0.aar\n├── classes.jar\n│   ├── HiddenSdk\n│   └── HiddenInitResult\n├── jni\u002F*\u002Flibhiddendecrypt.so\n├── assets\u002Fpayload\u002Fhidden.dex.enc\n└── proguard.txt\n","text","",[182,236,232],{"__ignoreMap":234},[179,238,239],{},"公开接口只剩：",[228,241,245],{"className":242,"code":243,"language":244,"meta":234,"style":234},"language-kotlin shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","object HiddenSdk {\n    fun init(context: Context, payloadKey: String?): HiddenInitResult\n    fun invoke(op: Int, a: Any? = null, b: Any? = null): Any?\n}\n","kotlin",[182,246,247,264,292,340],{"__ignoreMap":234},[248,249,252,256,260],"span",{"class":250,"line":251},"line",1,[248,253,255],{"class":254},"sMK4o","object",[248,257,259],{"class":258},"sBMFI"," HiddenSdk",[248,261,263],{"class":262},"sTEyZ"," {\n",[248,265,267,270,274,277,280,283,286,289],{"class":250,"line":266},2,[248,268,269],{"class":254},"    fun",[248,271,273],{"class":272},"s2Zo4"," init",[248,275,276],{"class":262},"(context: ",[248,278,279],{"class":258},"Context",[248,281,282],{"class":262},", payloadKey: ",[248,284,285],{"class":258},"String",[248,287,288],{"class":262},"?): ",[248,290,291],{"class":258},"HiddenInitResult\n",[248,293,295,297,300,303,306,309,312,315,318,321,324,326,328,330,332,335,337],{"class":250,"line":294},3,[248,296,269],{"class":254},[248,298,299],{"class":272}," invoke",[248,301,302],{"class":262},"(op: ",[248,304,305],{"class":258},"Int",[248,307,308],{"class":262},", a: ",[248,310,311],{"class":258},"Any",[248,313,314],{"class":262},"? ",[248,316,317],{"class":254},"=",[248,319,320],{"class":254}," null",[248,322,323],{"class":262},", b: ",[248,325,311],{"class":258},[248,327,314],{"class":262},[248,329,317],{"class":254},[248,331,320],{"class":254},[248,333,334],{"class":262},"): ",[248,336,311],{"class":258},[248,338,339],{"class":262},"?\n",[248,341,343],{"class":250,"line":342},4,[248,344,345],{"class":262},"}\n",[179,347,348,351,352,210],{},[182,349,350],{},":hidden-landing-page"," 只在 SDK 仓库里编 jar → d8 → AES-256-GCM，不要给宿主 ",[182,353,354],{},"implementation",[356,357,358,374],"table",{},[359,360,361],"thead",{},[362,363,364,368,371],"tr",{},[365,366,367],"th",{},"模块",[365,369,370],{},"给接入方吗",[365,372,373],{},"进主 DEX？",[375,376,377,391,403],"tbody",{},[362,378,379,385,388],{},[380,381,382],"td",{},[182,383,384],{},":hidden-sdk",[380,386,387],{},"只交付这个 AAR",[380,389,390],{},"接口、JNI、KeepAlive 占位类",[362,392,393,397,400],{},[380,394,395],{},[182,396,350],{},[380,398,399],{},"不交付",[380,401,402],{},"否，只进加密 payload",[362,404,405,410,413],{},[380,406,407],{},[182,408,409],{},":app",[380,411,412],{},"不发布",[380,414,415],{},"权限、清单占位、Compose 页",[212,417,418],{"id":418},"十种加固方式",[420,421,422],"u-page-section",{},[423,424,425,438,446,454,462,470,478,486,494,502],"u-page-grid",{},[426,427,432,435],"u-page-card",{":spotlight":428,"className":429,"icon":21,"to":60},"true",[430,431],"col-span-2","lg:col-span-1",[433,434,59],"template",{"v-slot:title":234},[433,436,437],{"v-slot:description":234},"构建期把 landing-page 打成 AES-256-GCM 密文，文件头为 HDX1。",[426,439,441,443],{":spotlight":428,"className":440,"icon":66,"to":64},[430,431],[433,442,63],{"v-slot:title":234},[433,444,445],{"v-slot:description":234},"自实现 AES-GCM 在 so 里运行，Java 不接触明文 DEX。",[426,447,449,451],{":spotlight":428,"className":448,"icon":71,"to":69},[430,431],[433,450,68],{"v-slot:title":234},[433,452,453],{"v-slot:description":234},"InMemoryDexClassLoader 接收 ByteBuffer，不落明文文件。",[426,455,457,459],{":spotlight":428,"className":456,"icon":76,"to":74},[430,431],[433,458,73],{"v-slot:title":234},[433,460,461],{"v-slot:description":234},"公开入口只有 invoke(op)，对照表不进入 AAR。",[426,463,465,467],{":spotlight":428,"className":464,"icon":81,"to":79},[430,431],[433,466,78],{"v-slot:title":234},[433,468,469],{"v-slot:description":234},"资源路径、类名、方法名在 so 里按 0x5A 异或。",[426,471,473,475],{":spotlight":428,"className":472,"icon":86,"to":84},[430,431],[433,474,83],{"v-slot:title":234},[433,476,477],{"v-slot:description":234},"AAR 不带密钥。CI 用环境变量，本地用 gitignore 文件。",[426,479,481,483],{":spotlight":428,"className":480,"icon":91,"to":89},[430,431],[433,482,88],{"v-slot:title":234},[433,484,485],{"v-slot:description":234},"compileOnly 加解析期检查，禁止明文 class 进入 APK。",[426,487,489,491],{":spotlight":428,"className":488,"icon":96,"to":94},[430,431],[433,490,93],{"v-slot:title":234},[433,492,493],{"v-slot:description":234},"AAR、APK、源码三道检查，漏依赖则无法通过编译。",[426,495,497,499],{":spotlight":428,"className":496,"icon":101,"to":99},[430,431],[433,498,98],{"v-slot:title":234},[433,500,501],{"v-slot:description":234},"FLAG_SECURE。未 init 也会给当前页加上该标志。",[426,503,505,507],{":spotlight":428,"className":504,"icon":106,"to":104},[430,431],[433,506,103],{"v-slot:title":234},[433,508,509],{"v-slot:description":234},"so 与加密实现约定版本 12，对不上就拒绝加载。",[212,511,512],{"id":512},"运行时序",[514,515,516,521,527,531,540,544,555,559,568,572],"steps",{},[517,518,520],"h3",{"id":519},"宿主先-init","宿主先 init",[179,522,523,526],{},[182,524,525],{},"Application.onCreate"," 传入 64 个 hex 字符。密钥为空则直接失败，不读取 assets。",[517,528,530],{"id":529},"so-读密文","so 读密文",[179,532,533,536,537,210],{},[182,534,535],{},"AAssetManager"," 打开 XOR 后的路径 ",[182,538,539],{},"payload\u002Fhidden.dex.enc",[517,541,543],{"id":542},"aes-gcm-解密","AES-GCM 解密",[179,545,546,547,550,551,554],{},"校验 ",[182,548,549],{},"HDX1"," 头和 GCM tag。明文必须以 ",[182,552,553],{},"dex"," 开头。",[517,556,558],{"id":557},"内存里-loadclass","内存里 loadClass",[179,560,561,564,565,567],{},[182,562,563],{},"InMemoryDexClassLoader"," 加载 XOR 后的 ",[182,566,193],{},"，并核对 ABI。",[517,569,571],{"id":570},"invoke-分发","invoke 分发",[179,573,574,575,578],{},"Java 只传整数指令，native 再通过 ",[182,576,577],{},"GetMethodID"," 调用实现。",[580,581,582,583,586],"tip",{},"可读的方法名应放在宿主自己的包装里，例如 Demo 的 ",[182,584,585],{},"HostBridge","。不要把对照表写进 SDK 源码。",[212,588,589],{"id":589},"下一步",[591,592,593,601,608],"ul",{},[594,595,596,597,600],"li",{},"从 ",[598,599,59],"a",{"href":60}," 了解密文如何生成",[594,602,603,604,607],{},"对照仓库 ",[182,605,606],{},"接入与使用.md"," 查看接入约定",[594,609,610,611,615],{},"到 ",[598,612,614],{"href":613},"\u002Fdemos","示例项目"," 按分类浏览全部可下载工程",[617,618,619],"style",{},"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 .s2Zo4, html code.shiki .s2Zo4{--shiki-light:#6182B8;--shiki-default:#82AAFF;--shiki-dark:#82AAFF}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);}",{"title":234,"searchDepth":266,"depth":266,"links":621},[622,623,624,625,632],{"id":214,"depth":266,"text":214},{"id":223,"depth":266,"text":223},{"id":418,"depth":266,"text":418},{"id":512,"depth":266,"text":512,"children":626},[627,628,629,630,631],{"id":519,"depth":294,"text":520},{"id":529,"depth":294,"text":530},{"id":542,"depth":294,"text":543},{"id":557,"depth":294,"text":558},{"id":570,"depth":294,"text":571},{"id":589,"depth":266,"text":589},"hidden-dex-minidemo 把业务实现编成加密 DEX。运行时由 so 解密后在内存里加载。主 DEX 只保留公开接口。","md",[636,637,638],{"label":59,"icon":21,"to":60},{"label":63,"icon":66,"to":64},{"label":73,"icon":76,"to":74},{"date":640,"categories":641,"tags":643},"2026-09-21",[642],"android",[37,644,645],"HiddenDEX","加固",{"icon":57},{"title":648,"description":649},"安卓代码加固：Hidden DEX 总览","梳理 hidden-dex-minidemo 当前使用的加固方式：加密 DEX、Native 解密、内存加载、指令分发、XOR 混淆、密钥外置、依赖隔离、构建校验、防录屏与 ABI 门禁。","rvwRi-QBJOnXWx6gkfYt-xgItFiCXBIqQTWDbjEfQSA",[652,654],{"title":45,"path":46,"stem":47,"description":653,"icon":48,"children":-1},"从依赖、类型安全路由到 NavHost、跳转、读参、返回栈与深层链接，按任务顺序在 Jetpack Compose 中接入 Navigation。",{"title":59,"path":60,"stem":61,"description":655,"icon":21,"children":-1},"构建期把 :hidden-landing-page 打成 AES-256-GCM 密文，以 HDX1 头写入 AAR assets。",1790767042878]