一、apktool 深度解析
apktool(https://github.com/iBotPeaches/Apktool)是 Android 逆向的基石工具,主要功能是对 APK 进行解码(decode)和重构建(rebuild)。
内部工作原理
当执行 apktool d target.apk 时,apktool 执行以下步骤:
- 解析 AndroidManifest.xml:将二进制的 AXML 格式还原为可读的 XML
- 解析 resources.arsc:将二进制的资源表还原为
res/values/*.xml - 反汇编 DEX:使用 smali/baksmali 库将 DEX 字节码转为 smali 汇编代码
- 提取资源文件:保留
res/下原始资源的目录结构
# 基础用法 |
smali/baksmali 引擎
apktool 的 DEX 处理能力来自 smali(https://github.com/JesusFreke/smali)。baksmali 负责 DEX → smali,smali 负责 smali → DEX。
# 直接使用 baksmali 将 DEX 反汇编为 smali |
二、JADX 深度解析
JADX(https://github.com/skylot/jadx)的作用是将 DEX 字节码反编译为 Java 源代码,质量在所有开源工具中名列前茅。
反编译流水线
DEX 文件 → baksmali 反汇编 → JADX 中间表示 (IR) → 控制流分析 → 变量恢复 → 类型推断 → Java 源码输出。
核心特性
搜索能力:
Ctrl+Shift+F → 全文搜索(字符串、方法名、类名) |
反混淆能力:
Tools → Deobfuscation → 重命名混淆的类/方法名 |
代码导航:
右键 → Find Usage → 查找所有调用点 |
JADX vs GDA vs BytecodeViewer
| 特性 | JADX | GDA | BytecodeViewer |
|---|---|---|---|
| 反编译质量 | ★★★★★ | ★★★★☆ | ★★★★☆ |
| 搜索能力 | ★★★★★ | ★★★★☆ | ★★★☆☆ |
| GUI 体验 | ★★★★☆ | ★★★☆☆ | ★★★☆☆ |
| 反混淆 | ★★★★☆ | ★★★★★ | ★★★☆☆ |
| Smali 对比 | ★★☆☆☆ | ★★★★★ | ★★★★★ |
| 开源 | ✓ | ✗ | ✓ |
| 仓库 | github.com/skylot/jadx | - | github.com/Konloch/bytecode-viewer |
三、实战工作流
推荐的逆向工作流:
# Step 1: apktool 解包(获得 smali 和资源) |
配合使用技巧: 当 JADX 反编译某个方法出错时,右键 → Show Bytecode 查看 smali;想修改代码逻辑时,在 apktool 输出的 smali 目录中操作,因为 JADX 只是查看工具。
面试常考问题
Q1:apktool 反编译后修改了资源,重打包失败的原因有哪些?
A:常见原因:(1)资源 ID 冲突或引用错误;(2)apktool 版本与 APK 的 aapt 版本不匹配;(3)使用了 -r/--no-res 跳过了资源解码但后续又引用了未解码的资源;(4)AndroidManifest.xml 中的 namespace 引用版本不兼容。解决方案:升级 apktool 到最新版,使用 -f 强制覆盖。
Q2:JADX 遇到反编译死循环或 OOM 怎么办?
A:在 JADX 偏好设置中调低反编译强度(关闭某些高级优化),或在命令行使用 --deobf 限制反混淆深度。针对特定类,在 GUI 中右键 → Exclude from decompilation 跳过,看 smali 替代。也可以分配更大堆内存:jadx-gui -Xmx4g target.apk。
Q3:如何利用 apktool + JADX 配合实现代码注入?
A:(1)apktool d 获取 smali 代码;(2)编写注入代码并编译为 smali:javac Inject.java → dx --dex --output=inject.dex Inject.class → baksmali d inject.dex;(3)将生成的 smali 文件复制到 apktool 输出的 smali 目录中;(4)在目标方法的 smali 中添加 invoke-static 调用注入的方法;(5)apktool b 重打包签名。若目标 APK 使用 ProGuard 混淆,需注意注入类的包名不要与目标冲突。



