第二十节 Android 加固原理
(第2章 安卓逆向基础)
学习目标
学完本节,希望你能够:
阅读提示:脱壳、绕过加固仅限授权环境、学习与安全研究;不得对他人应用做未授权脱壳或传播脱壳包。
常见疑问:加固和混淆有啥区别?混淆只改类名/方法名,不加密;加固会把 DEX 加密或藏起来,直接反编译看不到真实代码,要脱壳才能拿到。
一、Android 加固是啥?
加固(Application Hardening)说白了就是:把应用的 DEX(或 so)加密或隐藏,安装包里的 classes.dex 可能是壳或无效;运行时由壳代码(如 libjiagu.so)解密并动态加载 DEX,这样静态反编译 APK 看不到真实业务逻辑。
加固和混淆一句话区别
| 混淆 | 改类名/方法名/删未用代码 | 名字难读,逻辑仍在 |
| 加固 | 加密/隐藏 DEX,运行时解密加载 | 静态看不到真实 DEX,需脱壳 |
记一句:混淆 = 名字难读;加固 = 代码被藏/加密,要运行时脱壳。
二、加固常见在干啥?
- DEX 加密:真实 classes.dex 被 AES 等加密放在 assets 或别处,壳在运行时解密。
- 壳 Application:AndroidManifest 里 Application 指向壳的类,壳先执行,再加载真实 DEX 和真实 Application。
- DexClassLoader 动态加载:壳用 DexClassLoader 加载解密后的 DEX,再通过反射调真实入口。
- 反调试 / 反 Hook:壳里带 ptrace、isDebuggerConnected、Frida 检测等,增加脱壳难度。
- so 保护:关键逻辑放 so,so 自身也可能加壳或混淆。
三、怎么判断 APK 是否加固?
在干啥:看结构、看 so、用工具
- 解压 APK:看 classes.dex 是否特别小或没有;看 lib 里是否有 libjiagu.so、libturing.so、libshell.so 等常见壳 so。
- APKiD:pip install apkid 后 apkid app.apk,可识别部分加固方案。
- 运行时:用 Frida 附加,若应用一附就崩溃,可能有反调试/反 Frida;需先反反调试再脱壳。
unzip -l app.apk
ls output/lib/arm64-v8a/
apkid app.apk
四、脱壳(Dump DEX)在干啥?一般怎么干?(仅限授权环境)
在干啥:在运行时拿到已解密的 DEX,保存成文件再反编译
思路:等壳把 DEX 加载进内存后,从内存里把 DEX 抠出来(Dump)。常见做法:
- Frida 脚本:Hook DexClassLoader、ClassLoader.loadClass 或 dalvik 内部接口,在 DEX 被加载后遍历内存中的 DexFile,按 DEX 格式 Dump 到文件;或使用现成脚本如 FRIDA-DEXDump(以实际仓库为准)。
- GDB:附加进程,info proc mappings 找 DEX 所在内存区间(通常有 dex 字样或可执行段),dump memory 导出。
- Xposed:Hook DexClassLoader 等,在 afterHookedMethod 里拿到 DexFile 或 byte[],写文件。
注意:仅限授权环境;不得对他人应用未授权脱壳或传播脱壳包。
五、绕过反调试 / 反 Frida 再脱壳(简要)
在干啥:壳常带反调试,需先绕过才能稳定附加和 Dump
先用反反调试脚本 Hook ptrace、isDebuggerConnected、Frida 检测等(见第十九节),再在同一个 Frida 会话里跑脱壳脚本(或先反反调试,再另起一次 Frida 跑 Dump)。仅限授权环境。
本节小结
你只要记住这几条就行:
本节术语速查
| 加固 | 对 DEX/so 加密或隐藏,运行时解密加载,防静态分析。 |
| 壳 | 负责解密和加载真实 DEX 的代码(常在各 so 里)。 |
| 脱壳 | 在运行时从内存中取出已解密的 DEX 并保存。 |
| APKiD | 检测 APK 加固、混淆、编译器等特征的工具。 |
本节思考与练习
下一节预告:下一节是解密加固 APK(初级),会结合具体步骤:检测是否加密、用 Frida 监听 DEX 加载、用 DumpDex 或 gdb 提取 DEX、以及绕过 Anti-Dump 的入门做法(仅限授权环境)。