Files
reverse-skills-max/vendor-new/rev-skills/.claude/skills/re-apk/references/commands.md

6.5 KiB
Raw Blame History

APK 静态分析命令速查与操作序列

工具族分三层:jadx(反编译 Java)、apktool(解包/回编译 smali)、aapt2/apksigner/adb(资源转储/签名/安装闭环)。各工具命令与参数以官方文档为准(jadx: skylot/jadx;apktool: iBotPeaches/Apktool)。

命令族速查

jadx(反编译)

  • jadx -d java-out app.apk 批量反编译全部 dex 类到目录
  • jadx --show-bad-code app.apk 容错模式(部分反编译失败时仍输出)
  • jadx -j <n> app.apk 线程数;-r 不反编译资源;--no-imports 去掉 import 行(diff 友好)
  • jadx-gui 图形界面(单类浏览、跳转、搜索);jadx-gui app.apk 直接打开
  • jadx --version 验证;依赖 Java 11+(64 位)

apktool(解包/回编译)

  • apktool d app.apk -o out/ 解包(资源转成可读 XML + smali)
  • apktool d -r app.apk -o out/ 只出 smali 不解码资源(回编译成功率更高,smali 补丁常用形态)
  • apktool d -s app.apk -o out/ 只出资源不出 smali
  • apktool b out/ -o patched.apk 回编译(3.x 起回编译固定走 aapt2,无 aapt1 可选,--use-aapt2 这个选择项已随 aapt1 一并移除)
  • apktool d -a app.apk -o out/ 解全部源码,含未知 dex 文件(3.x 的 -a/--all-src,取代 2.x 的 --only-main-classes;语义相反——前者放开、后者收窄)
  • apktool b out/ --aapt <file> 指定 aapt2 二进制(3.x 的换 aapt2 入口,2.x 的 --use-aapt2 是开关、这里是路径;传入 aapt1 会被直接拒绝)
  • apktool --version 验证;apktool d 默认带 --force(覆盖旧输出)

aapt2 / aapt(资源与清单)

  • aapt2 dump badging app.apk 包名/版本/入口 activity/权限/目标 SDK 速览
  • aapt2 dump resources app.apk 资源 ID → 名称映射(资源混淆还原用)
  • aapt2 dump xmltree app.apk --file AndroidManifest.xml 二进制 XML 直接解码
  • aapt2 version 验证;build-tools 版本随 SDK 更新,命令接口稳定
  • 老 SDK 环境用 aapt dump badging app.apk(build-tools 34 前默认)

apksigner / keytool / zipalign(重打包签名)

  • keytool -genkey -v -keystore ks.jks -alias r -keyalg RSA -validity 3650 -storepass 123456 生成自签密钥库
  • zipalign -P 16 -f -v 4 patched.apk aligned.apk 先对齐(4 字节对齐;-P 16 使未压缩的 .so 按 16 KiB 页对齐,含 native 库时按官方要求加)
  • apksigner sign --ks ks.jks --out signed.apk aligned.apk 签名(实际启用的 scheme 由 --min-sdk-version/--max-sdk-version 决定,非固定 v1+v2)
  • apksigner verify --print-certs signed.apk 验证签名并打印证书(确认签名生效)
  • zipalign -c -P 16 -v 4 signed.apk 校验对齐(签名后不得再 zipalign,会破坏 v2/v3 签名)
  • apksigner --version 验证;用 apksigner 时对齐必须在签名之前完成

adb / 辅助(闭环验证)

  • adb version 验证;adb devices 列设备
  • adb install signed.apk 安装;adb install -r signed.apk 覆盖安装
  • adb shell pm path <包名> 取回已装 APK 路径,adb pull 拉回做字节级补丁验证
  • file app.apk 确认 zip 格式;unzip -l app.apk | head 看包内结构(dex 数量/so 列表)

常用操作序列(组合套路)

1. 完整静态分析流(入口 → 权限 → 代码 → 敏感点)

apktool d app.apk -o out/                         # 清单与 smali
grep -E 'application|activity|uses-permission' out/AndroidManifest.xml
jadx -d java-out app.apk                          # Java 层
grep -rE 'key|secret|sign|license|http' java-out/ # 敏感串定位
# 定位到的校验/算法类 → jadx-gui 单类深读 → 交叉引用上溯调用者

2. smali 补丁重打包闭环(改 → 回编译 → 签名 → 安装 → 字节验证)

apktool d -r app.apk -o out/          # 保留原资源,只改 smali
# 在对应 smali 里改:if-eqz ↔ if-nez、const/4 v0, 0x0、return-void
apktool b out/ -o patched.apk
keytool -genkey -v -keystore ks.jks -alias r -keyalg RSA -validity 3650 -storepass 123456
zipalign -P 16 -f -v 4 patched.apk aligned.apk    # 必须在签名之前对齐(含未压缩 .so 时 -P 16 做 16 KiB 页对齐)
apksigner sign --ks ks.jks --out signed.apk aligned.apk
apksigner verify --print-certs signed.apk        # 签名先自证
zipalign -c -P 16 -v 4 signed.apk                # 对齐校验(签名后不得再 zipalign,否则 v2/v3 签名失效)
adb install signed.apk
adb shell pm path <包名> && adb pull <路径>       # 取回已装 APK
# 对 patch 地址做字节级比对,确认修改在位后再排查逻辑层(见 SKILL.md 坑)

3. 资源混淆还原(aapt2 dump 对照)

aapt2 dump badging app.apk            # 包名/入口/权限基线
aapt2 dump resources app.apk > res-map.txt   # 混淆后资源 ID → 名称映射
# 动态侧([[re-frida]])取运行时资源 ID,回查 res-map.txt 还原真实资源名

4. 加固识别与分流

jadx -d java-out app.apk 且只见壳类(com.stub.StubApp 等) → 加固
ls out/lib/ 找壳 so(libjiagu.so / libDexHelper.so / libsecneo.so 等)
ls -la out/classes*.dex | 体积异常小 → 真 dex 运行时解密
# 判定加固后:转 [[re-anti-analysis]] 脱壳,或 [[re-frida]]/[[re-memdump]] 运行时取内存 DEX
# 壳名/节区/熵指纹对照 → [[re-packer-id]]

实现教训(内化)

  • jadx 反编译结果与 smali 严格对应:先 jadx 定位方法,再按类名/方法名在 apktool 产物里找对应 smali 改写,比直接读 smali 快一个量级
  • 补丁闭环验证分两层:先字节级(pull 已装 APK 比对 patch 地址),后逻辑级(行为变化)——字节在位说明签名/安装链路没破坏
  • apktool d -r 是 smali 补丁默认形态:资源原样保留,回编译失败面最小;只有需要改资源时才用完整解包
  • 加固判定优先看「jadx 输出 vs 包内 dex」两处交叉,单一特征(如只有一个壳 so)可能误判
  • 静态结论与动态证据对照:资源混淆目标用 aapt2 dump 映射 + re-frida 运行时取值,静态侧不硬猜

使用注意