[{"data":1,"prerenderedAt":930},["ShallowReactive",2],{"navigation_docs":3,"-android-hidden-hardening-build-verify":173,"-android-hidden-hardening-build-verify-surround":925},[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":93,"body":175,"description":908,"extension":909,"links":910,"meta":913,"navigation":920,"path":94,"seo":921,"stem":95,"__hash__":924},"docs\u002F3.android\u002F02.hidden-hardening\u002F08.build-verify.md",{"type":176,"value":177,"toc":901},"minimark",[178,192,208,213,223,430,436,468,486,490,501,736,739,777,781,784,800,803,811,814,827,870,878,881,897],[179,180,181,182,186,187,191],"p",{},"即便依赖写对了，Manifest Merger 或某次误改仍可能把明文打进去。工程用 ",[183,184,185],"strong",{},"打包后扫描 zip"," 再检查一遍。",[188,189,190],"code",{},"assemble"," 成功不等于加固成功，还要经过 verify 任务。",[193,194,195,196,199,200,203,204,207],"tip",{},"这些任务挂在 ",[188,197,198],{},"assemble*"," 的 ",[188,201,202],{},"finalizedBy"," 上。本地编译 debug 就能看到 ",[188,205,206],{},"[hidden-dex] … 通过","。",[209,210,212],"h2",{"id":211},"校验-sdk-aar","校验 SDK AAR",[179,214,215,218,219,222],{},[188,216,217],{},"verifyHiddenSdkAarDebug"," \u002F ",[188,220,221],{},"Release"," 打开刚打好的 AAR：",[224,225,231],"pre",{"className":226,"code":227,"filename":228,"language":229,"meta":230,"style":230},"language-kotlin shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","val payload = zip.getEntry(\"assets\u002Fpayload\u002Fhidden.dex.enc\")\n    ?: error(\"$aar 缺少 assets\u002Fpayload\u002Fhidden.dex.enc\")\nval head = zip.getInputStream(payload).use { it.readNBytes(4) }\ncheck(head.contentEquals(\"HDX1\".toByteArray())) {\n    \"$aar 里的 payload 不是 AES-GCM（缺少 HDX1 头）\"\n}\nval nativeLib = zip.getEntry(\"jni\u002Farm64-v8a\u002Flibhiddendecrypt.so\")\n    ?: zip.getEntry(\"jni\u002Farmeabi-v7a\u002Flibhiddendecrypt.so\")\ncheck(nativeLib != null) { \"$aar 缺少 libhiddendecrypt.so\" }\n","hidden-sdk\u002Fbuild.gradle.kts","kotlin","",[188,232,233,266,288,324,350,361,367,388,403],{"__ignoreMap":230},[234,235,238,242,246,249,252,256,259,263],"span",{"class":236,"line":237},"line",1,[234,239,241],{"class":240},"sMK4o","val",[234,243,245],{"class":244},"sTEyZ"," payload ",[234,247,248],{"class":240},"=",[234,250,251],{"class":244}," zip.",[234,253,255],{"class":254},"s2Zo4","getEntry",[234,257,258],{"class":244},"(",[234,260,262],{"class":261},"sfazB","\"assets\u002Fpayload\u002Fhidden.dex.enc\"",[234,264,265],{"class":244},")\n",[234,267,269,272,275,277,280,283,286],{"class":236,"line":268},2,[234,270,271],{"class":244},"    ?: ",[234,273,274],{"class":254},"error",[234,276,258],{"class":244},[234,278,279],{"class":261},"\"",[234,281,282],{"class":244},"$aar",[234,284,285],{"class":261}," 缺少 assets\u002Fpayload\u002Fhidden.dex.enc\"",[234,287,265],{"class":244},[234,289,291,293,296,298,300,303,306,309,312,315,317,321],{"class":236,"line":290},3,[234,292,241],{"class":240},[234,294,295],{"class":244}," head ",[234,297,248],{"class":240},[234,299,251],{"class":244},[234,301,302],{"class":254},"getInputStream",[234,304,305],{"class":244},"(payload).",[234,307,308],{"class":254},"use",[234,310,311],{"class":244}," { it.",[234,313,314],{"class":254},"readNBytes",[234,316,258],{"class":244},[234,318,320],{"class":319},"sbssI","4",[234,322,323],{"class":244},") }\n",[234,325,327,330,333,336,338,341,344,347],{"class":236,"line":326},4,[234,328,329],{"class":254},"check",[234,331,332],{"class":244},"(head.",[234,334,335],{"class":254},"contentEquals",[234,337,258],{"class":244},[234,339,340],{"class":261},"\"HDX1\"",[234,342,343],{"class":244},".",[234,345,346],{"class":254},"toByteArray",[234,348,349],{"class":244},"())) {\n",[234,351,353,356,358],{"class":236,"line":352},5,[234,354,355],{"class":261},"    \"",[234,357,282],{"class":244},[234,359,360],{"class":261}," 里的 payload 不是 AES-GCM（缺少 HDX1 头）\"\n",[234,362,364],{"class":236,"line":363},6,[234,365,366],{"class":244},"}\n",[234,368,370,372,375,377,379,381,383,386],{"class":236,"line":369},7,[234,371,241],{"class":240},[234,373,374],{"class":244}," nativeLib ",[234,376,248],{"class":240},[234,378,251],{"class":244},[234,380,255],{"class":254},[234,382,258],{"class":244},[234,384,385],{"class":261},"\"jni\u002Farm64-v8a\u002Flibhiddendecrypt.so\"",[234,387,265],{"class":244},[234,389,391,394,396,398,401],{"class":236,"line":390},8,[234,392,393],{"class":244},"    ?: zip.",[234,395,255],{"class":254},[234,397,258],{"class":244},[234,399,400],{"class":261},"\"jni\u002Farmeabi-v7a\u002Flibhiddendecrypt.so\"",[234,402,265],{"class":244},[234,404,406,408,411,414,417,420,422,424,427],{"class":236,"line":405},9,[234,407,329],{"class":254},[234,409,410],{"class":244},"(nativeLib ",[234,412,413],{"class":240},"!=",[234,415,416],{"class":240}," null",[234,418,419],{"class":244},") { ",[234,421,279],{"class":261},[234,423,282],{"class":244},[234,425,426],{"class":261}," 缺少 libhiddendecrypt.so\"",[234,428,429],{"class":244}," }\n",[179,431,432,435],{},[188,433,434],{},"classes.jar"," 再拆一次：",[437,438,439,452],"table",{},[440,441,442],"thead",{},[443,444,445,449],"tr",{},[446,447,448],"th",{},"必须有",[446,450,451],{},"必须没有",[453,454,455],"tbody",{},[443,456,457,463],{},[458,459,460],"td",{},[188,461,462],{},"com\u002Fexample\u002Fminidex\u002Fsdk\u002FHiddenSdk",[458,464,465],{},[188,466,467],{},"com\u002Fexample\u002Fminidex\u002Fhidden\u002FHiddenLandingPage",[179,469,470,471,474,475,478,479,482,483,207],{},"加密任务里还有前置检查：landing-page 的 jar ",[183,472,473],{},"不能"," 带上 ",[188,476,477],{},"HiddenSdk","。出现这种情况，说明有人把 ",[188,480,481],{},"compileOnly"," 改成了 ",[188,484,485],{},"implementation",[209,487,489],{"id":488},"校验最终-apk","校验最终 APK",[179,491,492,493,496,497,500],{},"宿主任务 ",[188,494,495],{},"verifyHiddenLandingPageNotInApk*"," 扫描 ",[188,498,499],{},"classes*.dex"," 的原始字节，查找 UTF-8 类描述符：",[224,502,505],{"className":226,"code":503,"filename":504,"language":229,"meta":230,"style":230},"fun File.containsClassDescriptor(descriptor: String): Boolean {\n    val marker = descriptor.toByteArray(Charsets.UTF_8)\n    ZipFile(this).use { zip ->\n        val dexEntries = zip.entries().asSequence()\n            .filter { it.name.matches(Regex(\"\"\"classes\\d*\\.dex\"\"\")) }\n        for (entry in dexEntries) {\n            val bytes = zip.getInputStream(entry).use { it.readBytes() }\n            if (bytes.indexOfSlice(marker) >= 0) return true\n        }\n    }\n    return false\n}\n","app\u002Fbuild.gradle.kts",[188,506,507,536,554,576,600,639,654,681,711,716,722,731],{"__ignoreMap":230},[234,508,509,512,516,518,521,524,527,530,533],{"class":236,"line":237},[234,510,511],{"class":240},"fun",[234,513,515],{"class":514},"sBMFI"," File",[234,517,343],{"class":244},[234,519,520],{"class":254},"containsClassDescriptor",[234,522,523],{"class":244},"(descriptor: ",[234,525,526],{"class":514},"String",[234,528,529],{"class":244},"): ",[234,531,532],{"class":514},"Boolean",[234,534,535],{"class":244}," {\n",[234,537,538,541,544,546,549,551],{"class":236,"line":268},[234,539,540],{"class":240},"    val",[234,542,543],{"class":244}," marker ",[234,545,248],{"class":240},[234,547,548],{"class":244}," descriptor.",[234,550,346],{"class":254},[234,552,553],{"class":244},"(Charsets.UTF_8)\n",[234,555,556,559,561,564,567,569,572],{"class":236,"line":290},[234,557,558],{"class":254},"    ZipFile",[234,560,258],{"class":244},[234,562,563],{"class":240},"this",[234,565,566],{"class":244},").",[234,568,308],{"class":254},[234,570,571],{"class":244}," { zip ",[234,573,575],{"class":574},"spNyl","->\n",[234,577,578,581,584,586,588,591,594,597],{"class":236,"line":326},[234,579,580],{"class":240},"        val",[234,582,583],{"class":244}," dexEntries ",[234,585,248],{"class":240},[234,587,251],{"class":244},[234,589,590],{"class":254},"entries",[234,592,593],{"class":244},"().",[234,595,596],{"class":254},"asSequence",[234,598,599],{"class":244},"()\n",[234,601,602,605,608,611,614,616,619,621,624,627,630,633,636],{"class":236,"line":352},[234,603,604],{"class":244},"            .",[234,606,607],{"class":254},"filter",[234,609,610],{"class":244}," { it.name.",[234,612,613],{"class":254},"matches",[234,615,258],{"class":244},[234,617,618],{"class":254},"Regex",[234,620,258],{"class":244},[234,622,623],{"class":261},"\"\"\"classes",[234,625,626],{"class":244},"\\d",[234,628,629],{"class":261},"*",[234,631,632],{"class":244},"\\.",[234,634,635],{"class":261},"dex\"\"\"",[234,637,638],{"class":244},")) }\n",[234,640,641,645,648,651],{"class":236,"line":363},[234,642,644],{"class":643},"s7zQu","        for",[234,646,647],{"class":244}," (entry ",[234,649,650],{"class":240},"in",[234,652,653],{"class":244}," dexEntries) {\n",[234,655,656,659,662,664,666,668,671,673,675,678],{"class":236,"line":369},[234,657,658],{"class":240},"            val",[234,660,661],{"class":244}," bytes ",[234,663,248],{"class":240},[234,665,251],{"class":244},[234,667,302],{"class":254},[234,669,670],{"class":244},"(entry).",[234,672,308],{"class":254},[234,674,311],{"class":244},[234,676,677],{"class":254},"readBytes",[234,679,680],{"class":244},"() }\n",[234,682,683,686,689,692,695,698,701,704,707],{"class":236,"line":390},[234,684,685],{"class":643},"            if",[234,687,688],{"class":244}," (bytes.",[234,690,691],{"class":254},"indexOfSlice",[234,693,694],{"class":244},"(marker) ",[234,696,697],{"class":240},">=",[234,699,700],{"class":319}," 0",[234,702,703],{"class":244},") ",[234,705,706],{"class":643},"return",[234,708,710],{"class":709},"sfNiH"," true\n",[234,712,713],{"class":236,"line":405},[234,714,715],{"class":244},"        }\n",[234,717,719],{"class":236,"line":718},10,[234,720,721],{"class":244},"    }\n",[234,723,725,728],{"class":236,"line":724},11,[234,726,727],{"class":643},"    return",[234,729,730],{"class":709}," false\n",[234,732,734],{"class":236,"line":733},12,[234,735,366],{"class":244},[179,737,738],{},"通过条件：",[740,741,742,752,760,768],"ol",{},[743,744,745,748,749],"li",{},[183,746,747],{},"没有"," ",[188,750,751],{},"Lcom\u002Fexample\u002Fminidex\u002Fhidden\u002FHiddenLandingPage;",[743,753,754,748,757],{},[183,755,756],{},"有",[188,758,759],{},"Lcom\u002Fexample\u002Fminidex\u002Fsdk\u002FHiddenSdk;",[743,761,762,748,764,767],{},[183,763,747],{},[188,765,766],{},"Lcom\u002Fexample\u002Fminidex\u002Fsdk\u002FHiddenApi;","（旧接口不得残留）",[743,769,770,773,774],{},[188,771,772],{},"assets\u002Fpayload\u002Fhidden.dex.enc"," 头是 ",[188,775,776],{},"HDX1",[778,779,780],"warning",{},"这是字节搜索，不是完整 dex 解析。类名被 R8 改掉后描述符会变，所以公开入口必须 keep。实现类根本不该出现在主 dex，无论是否 keep，都不应搜到。",[209,782,783],{"id":783},"校验源码与解析图",[179,785,786,789,790,207,793,796,797,207],{},[188,787,788],{},"preBuild"," 禁止 ",[188,791,792],{},"import com.example.minidex.hidden",[188,794,795],{},"configurations.afterResolve"," 禁止 runtime 图里出现 ",[188,798,799],{},":hidden-landing-page",[179,801,802],{},"三道检查分别拦住这些情况：",[224,804,809],{"className":805,"code":807,"language":808,"meta":230},[806],"language-text","手写 import     → 源码扫描\nGradle 依赖写反 → 解析期 check\n漏掉的明文 class  → APK \u002F AAR zip 扫描\n","text",[188,810,807],{"__ignoreMap":230},[209,812,813],{"id":813},"发布前再打包",[179,815,816,819,820,823,824,207],{},[188,817,818],{},"packageDistAar"," 依赖 ",[188,821,822],{},"assembleRelease","，因此会先跑 release 加密（必须有环境变量）和 AAR 校验，再把 AAR 拷到仓库根目录 ",[188,825,826],{},"dist\u002F",[224,828,830],{"className":226,"code":829,"filename":228,"language":229,"meta":230,"style":230},"tasks.register(\"packageDistAar\") {\n    dependsOn(\"assembleRelease\")\n    \u002F\u002F dist\u002Fhidden-sdk-\u003Cversion>.aar\n}\n",[188,831,832,848,860,866],{"__ignoreMap":230},[234,833,834,837,840,842,845],{"class":236,"line":237},[234,835,836],{"class":244},"tasks.",[234,838,839],{"class":254},"register",[234,841,258],{"class":244},[234,843,844],{"class":261},"\"packageDistAar\"",[234,846,847],{"class":244},") {\n",[234,849,850,853,855,858],{"class":236,"line":268},[234,851,852],{"class":254},"    dependsOn",[234,854,258],{"class":244},[234,856,857],{"class":261},"\"assembleRelease\"",[234,859,265],{"class":244},[234,861,862],{"class":236,"line":290},[234,863,865],{"class":864},"sHwdD","    \u002F\u002F dist\u002Fhidden-sdk-\u003Cversion>.aar\n",[234,867,868],{"class":236,"line":326},[234,869,366],{"class":244},[871,872,873,874,877],"note",{},"AAR 自检确认「有加密 payload」，但 ",[183,875,876],{},"不会、也不该"," 在构建机用密钥解开它。密钥属于运行时接入方。",[209,879,880],{"id":880},"下一步",[882,883,884,891],"ul",{},[743,885,886,890],{},[887,888,889],"a",{"href":89},"依赖隔离","：从源头避免明文进包",[743,892,893,896],{},[887,894,895],{"href":84},"密钥外置","：release 没有环境变量会在加密阶段就失败",[898,899,900],"style",{},"html pre.shiki code .sMK4o, html code.shiki .sMK4o{--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF}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 pre.shiki code .sfazB, html code.shiki .sfazB{--shiki-light:#91B859;--shiki-default:#C3E88D;--shiki-dark:#C3E88D}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 .sBMFI, html code.shiki .sBMFI{--shiki-light:#E2931D;--shiki-default:#FFCB6B;--shiki-dark:#FFCB6B}html pre.shiki code .spNyl, html code.shiki .spNyl{--shiki-light:#9C3EDA;--shiki-default:#C792EA;--shiki-dark:#C792EA}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 .sfNiH, html code.shiki .sfNiH{--shiki-light:#FF5370;--shiki-default:#FF9CAC;--shiki-dark:#FF9CAC}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}",{"title":230,"searchDepth":268,"depth":268,"links":902},[903,904,905,906,907],{"id":211,"depth":268,"text":212},{"id":488,"depth":268,"text":489},{"id":783,"depth":268,"text":783},{"id":813,"depth":268,"text":813},{"id":880,"depth":268,"text":880},"assemble 之后检查 AAR \u002F APK：无明文 HiddenLandingPage，有 HDX1 payload 和 so。","md",[911,912],{"label":88,"icon":91,"to":89},{"label":59,"icon":21,"to":60},{"date":914,"categories":915,"tags":917},"2026-09-21",[916],"android",[37,918,919],"Gradle","校验",{"icon":96},{"title":922,"description":923},"安卓代码加固（8）：Hidden DEX 构建期校验","hidden-dex-minidemo 在打包 AAR 和 APK 后扫描 zip：禁止明文实现类，必须带 HDX1 加密 payload 与 libhiddendecrypt.so。","DXILnc6kp6lPNye_9nYwHIG6BuAgTzGhziZhz0H8I9M",[926,928],{"title":88,"path":89,"stem":90,"description":927,"icon":91,"children":-1},"宿主只 implementation hidden-sdk。landing-page 对 SDK 必须 compileOnly，明文 class 不准进入 APK。",{"title":98,"path":99,"stem":100,"description":929,"icon":101,"children":-1},"来电页、落地页、全屏广告使用 FLAG_SECURE。截屏与录屏得到黑屏，无需额外权限。",1790767046769]