Android APK 反编译与重打包:从 APK 到可调试应用的完整实战
``
面向:移动安全研究者、逆向工程师、想深入理解 App 实现原理的开发者 声明:本文所有操作仅限自有应用或已获授权的目标,请勿用于非法用途。
一、为什么需要反编译与重打包
在日常工作中,我们经常会遇到这样的场景:
- 拿到一个 APK,想分析它的接口、加密逻辑或核心算法;
- 需要给应用加日志、去广告、修改行为做调试验证;
- 做合规测试时,需要绕过完整性校验定位问题点;
- 学习优秀的开源/闭源实现,理解别人怎么设计。
无论哪种场景,核心链路都是一样的:解包 -> 反编译 -> 分析/修改 -> 重打包 -> 签名 -> 安装。本文把这套链路完整串一遍,并给出常见坑的规避方案。
二、环境准备
| 工具 | 用途 | 获取方式 |
|---|---|---|
| apktool | 解包/重打包资源与 smali | brew install apktool 或官网 |
| jadx | Java 层反编译为可读代码 | GitHub releases |
| jadx-gui | 可视化分析 | 同上 |
| keytool / apksigner | 签名 | Android SDK build-tools 自带 |
| Frida | 动态 hook(进阶) | pip install frida-tools |
建议使用 Android SDK 自带的 build-tools(内含 apksigner、zipalign),版本选择 30+ 以保证对新版 targetSdk 的兼容。
三、解包与反编译
# 用 apktool 解包(会产出 smali 目录、AndroidManifest.xml、res 资源)
apktool d target.apk -o out_dir
# 用 jadx 反编译出 Java 可读代码
jadx -d java_out target.apk
3.1 两个工具的分工
- apktool 侧重回编译:修改 smali 后能重新打包成 APK,适合"改完还要装回去"的场景;
- jadx 侧重阅读:把 dex 转成接近源码的 Java,适合静态分析找逻辑。
实战中通常配合使用:先用 jadx 看逻辑定位修改点,再用 apktool 改 smali 重打包。
3.2 快速定位关键代码
# 在 jadx 输出中全局搜索敏感关键字
grep -rn "sign\|encrypt\|AES\|DES\|secret\|token" java_out/ --include="*.java" | head -50
# 查看 AndroidManifest 中的组件与权限
cat out_dir/AndroidManifest.xml | grep -E "uses-permission|application|activity"
常用搜索词:Base64、getBytes、Cipher、HttpURLConnection、okhttp3、onClick、isVip、checkSign。
四、修改与重打包实战
4.1 场景:修改 smali 实现逻辑变更
假设我们要让某个判断恒为真。jadx 中看到:
if (a.b(context).c()) {
// 进入付费逻辑
}
对应 smali 类似:
invoke-virtual {p0}, Lcom/example/App;->isVip()Z
move-result v0
if-eqz v0, :cond_skip
把 if-eqz(等于 0 跳转)改成 if-nez(不等于 0 跳转),或直接把 move-result v0 后面跟 const/4 v0, 0x1,即可改变分支走向。
提示:smali 修改后建议用
apktool b回编译验证语法,报错行号通常能直接定位问题。
4.2 场景:给应用注入日志
在目标方法入口插入:
const-string v0, "DEBUG_TAG"
const-string v1, "enter method xxx, args="
invoke-static {v0, v1}, Landroid/util/Log;->d(Ljava/lang/String;Ljava/lang/String;)I
如果方法里已有寄存器使用,注意寄存器分配,必要时 add-int/lit8 扩展寄存器数量。
4.3 重打包
apktool b out_dir -o repacked.apk
五、签名与安装
重打包后的 APK 签名丢失,必须重新签名才能安装。
# 1. 生成签名密钥(已有可跳过)
keytool -genkey -v -keystore my.keystore -alias mykey -keyalg RSA -keysize 2048 -validity 10000
# 2. 签名
apksigner sign --ks my.keystore --ks-key-alias mykey --out signed.apk repacked.apk
# 3. 可选:zipalign 对齐(Google Play 要求,自用可不做)
zipalign -f 4 signed.apk aligned.apk
# 4. 安装
adb install -r aligned.apk
六、常见坑与规避
6.1 签名不一致导致覆盖安装失败
原应用签名与重打包签名不同,adb install -r 会报 INSTALL_FAILED_UPDATE_INCOMPATIBLE。解决:
- 先卸载原应用(会丢数据);
- 或保留原签名(从原 APK 提取签名信息,用相同 keystore 重签,一般做不到,除非原作者泄露)。
6.2 targetSdk 30+ 签名方案问题
高版本 targetSdk 默认要求 v2 签名,apksigner 会自动选择 v1+v2,一般无碍;若遇到 INSTALL_PARSE_FAILED_NO_CERTIFICATES,检查是否用了过旧的 jarsigner——统一用 apksigner。
6.3 资源混淆与加固
- 加固应用(腾讯乐固/360/梆梆等):apktool 解包后看不到真实 dex,需要先脱壳(Frida 内存 dump 或脱壳机),脱壳后再走本文流程;
- 资源混淆:apktool 解包资源路径被混淆(res/xxx),用 jadx 的"反混淆"功能可缓解;
- 完整性校验:应用会在启动时比对签名/文件哈希,重打包后闪退。定位校验点后 patch smali 绕过,这是另一篇的范畴。
6.4 多 DEX 处理
apktool 自动处理多 dex;手动改 smali 时注意 classes.dex / classes2.dex 的归属,不要跨 dex 引用未声明的类(可用 --use-aapt2 重新分配)。
七、总结
完整链路回顾:
apktool d -> 解包
jadx -> 静态分析定位
smali 修改 -> 逻辑变更 / 注入日志
apktool b -> 回编译
apksigner -> 重签名
adb install -> 安装调试
这套流程是移动安全研究的基本功,也是理解 Android 应用实现最快的路径。掌握了它,无论是分析、调试、还是合规测试,你都能从容应对。
下一篇预告:《Frida 实战:脱壳、Hook 与动态调试》,感兴趣可以关注。
本文为技术研究用途,请务必在合法授权范围内使用相关技术。