第二十节 Android 加固原理
(第2章 安卓逆向基础)
学习目标
学完本节,希望你能够:
- 说出 Android 加固 在干啥:对 DEX 或 so 做加密/隐藏 ,运行时由壳 解密并加载,防止静态直接反编译;和混淆(只改名字)不同。
- 知道常见加固方式:DEX 加密 、壳 Application 、动态加载 DexClassLoader 、反调试/反 Hook 、so 保护等;常见加固产品有 360、腾讯乐固、爱加密等。
- 能判断 APK 是否加固:看 classes.dex 是否异常小或缺失、看 lib 里是否有 libjiagu.so 、libturing.so 等壳 so;或用 APKiD 等工具检测。
- 了解脱壳 在干啥:在运行时拿到解密后的 DEX(Dump 内存或 Hook DexClassLoader 等),再反编译分析;仅限授权环境。
阅读提示 :脱壳、绕过加固仅限授权环境、学习与安全研究;不得对他人应用做未授权脱壳或传播脱壳包。
常见疑问:加固和混淆有啥区别?混淆只改类名/方法名,不加密;加固会把 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;需先反反调试再脱壳。
bash
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 被加密/隐藏,运行时由壳解密加载;和混淆不同,静态看不到真实代码。
- 检测加固 :看 classes.dex 、lib/*.so (libjiagu、libturing 等)、用 APKiD。
- 脱壳 = 运行时拿到解密后的 DEX(Frida Dump、GDB dump memory、Xposed Hook 等),再 jadx 反编译;需先反反调试时先绕过。
- 仅限授权、合规环境下分析与脱壳;不得传播他人应用的脱壳包。
本节术语速查
| 术语 | 一句话解释 |
|---|---|
| 加固 | 对 DEX/so 加密或隐藏,运行时解密加载,防静态分析。 |
| 壳 | 负责解密和加载真实 DEX 的代码(常在各 so 里)。 |
| 脱壳 | 在运行时从内存中取出已解密的 DEX 并保存。 |
| APKiD | 检测 APK 加固、混淆、编译器等特征的工具。 |
本节思考与练习
- 概念:加固和混淆对「直接反编译 APK」各有什么影响?为啥脱壳能拿到真实代码?
- 应用:若 apkid 报「360 加固」或「Tencent Legu」,你会优先做哪一步(反反调试还是直接 Dump)?为什么?
- 动手 :在授权环境下,对一个已知加固的练习 APK 用 APKiD 检测,用 unzip/ls 看 lib 下是否有壳 so,并尝试用 Frida 附加(若崩溃则先加反反调试脚本)。
- 动手:在授权环境下,使用 FRIDA-DEXDump 或类似脚本尝试 Dump 出 DEX,用 jadx 打开 Dump 出的文件,看是否能看到业务代码(仅限授权环境)。
下一节预告 :下一节是解密加固 APK(初级),会结合具体步骤:检测是否加密、用 Frida 监听 DEX 加载、用 DumpDex 或 gdb 提取 DEX、以及绕过 Anti-Dump 的入门做法(仅限授权环境)。