reverse-skills-max: initial public release (restored, redacted, hardened)
This commit is contained in:
134
vendor-new/rev-skills/.claude/skills/re-apk/SKILL.md
Normal file
134
vendor-new/rev-skills/.claude/skills/re-apk/SKILL.md
Normal file
@@ -0,0 +1,134 @@
|
||||
---
|
||||
name: re-apk
|
||||
description: >
|
||||
APK 静态分析:jadx/apktool、manifest、smali、加固识别。
|
||||
触发词:apk、android逆向、jadx、smali、dex
|
||||
capabilities: [dex-parser]
|
||||
---
|
||||
|
||||
# APK 静态分析
|
||||
|
||||
## 何时使用 / 何时不用
|
||||
|
||||
- 用:拿到 APK / 安卓应用包,需要看清单、Java 代码、资源、权限、组件结构
|
||||
- 用:需要识别加固 / 混淆(壳、资源混淆),为脱壳或补丁做准备
|
||||
- 不用:需要运行时 hook / 解密 / 绕过(走 [[re-frida]])
|
||||
- 不用:目标是原生库 .so 的逻辑(走 [[re-binary-core]] 的 [[re-format-elf]])
|
||||
- 不用:需要从运行时内存提取 DEX(走 [[re-memdump]])
|
||||
|
||||
## 工具准备
|
||||
|
||||
纯静态分析(解包 / 反编译)可免沙箱([[re-analyze/platform-tips]] 最高原则);涉及动态 / 脱壳转 [[re-frida]] / 脱壳域。所有工具先验证再使用。
|
||||
|
||||
### jadx —— Java 反编译主力(含 JADX GUI)
|
||||
|
||||
- 官方/GitHub release:`https://github.com/skylot/jadx/releases` 下载 `jadx-<版本>.zip`,解压后运行 `bin/jadx`(Linux/macOS)或 `bin\jadx.bat`(Windows);GUI 是 `bin/jadx-gui`
|
||||
- macOS: `brew install jadx`;Arch: `pacman -S jadx`
|
||||
- 依赖 Java 11+(官方要求 11+ 且 64 位):Linux `apt install openjdk-17-jre` / `dnf install java-17-openjdk` / `pacman -S jre17-openjdk`;macOS `brew install openjdk`
|
||||
- Windows/WSL: WSL 内用 Linux 版 zip
|
||||
- 验证: `jadx --version`;版本注——release zip 与 brew/pacman 包同步更新,以实测版本为准
|
||||
|
||||
### apktool —— 解包 / 回编译(官方/GitHub release)
|
||||
|
||||
- 依赖 Java 8+(官方安装页的最低要求,jar 以 Java 8 为目标编译)。官方 wrapper:从 `https://github.com/iBotPeaches/Apktool/releases` 下载 `apktool_<版本>.jar` 与 wrapper 脚本(Linux/macOS `apktool`、Windows `apktool.bat`),脚本与 jar 放同目录
|
||||
- **版本模型:3.x 为当前主线,2.x 为维护线**——两线命令不完全兼容,官方文档也按 3.x / 2.x 分轨。下载后先 `apktool --version` 确认 major version;2.x 时代的命令与教程直接拿到 3.x 上会报 `Unrecognized option`(变化清单见 [[gotchas]] 版本差异)
|
||||
- Debian/Ubuntu: `apt install apktool`(仓库版较旧,命令行为兼容即可)
|
||||
- macOS: `brew install apktool`
|
||||
- Windows/WSL: WSL 内 Linux 版
|
||||
- 验证: `apktool --version`
|
||||
|
||||
### aapt2 —— 资源转储 / 还原混淆资源
|
||||
|
||||
- Android SDK build-tools 自带。安装 cmdline-tools 后:`sdkmanager "build-tools;34.0.0"`,路径 `$ANDROID_HOME/build-tools/34.0.0/aapt2`
|
||||
- macOS: `brew install --cask android-commandlinetools` 后 `sdkmanager "build-tools;34.0.0"`
|
||||
- Windows: Android Studio → SDK Manager 勾选 build-tools
|
||||
- 验证: `aapt2 version`;版本注——build-tools 版本随 SDK 更新(示例 34.0.0,新版 SDK 自带更高版本),命令接口稳定,按已装版本使用即可
|
||||
|
||||
### dex2jar(可选)—— dex → jar
|
||||
|
||||
- GitHub release:`https://github.com/pxb1988/dex2jar/releases` 下载 zip,解压后 `d2j-dex2jar.sh classes.dex` 得 jar,再用 jd-gui 浏览
|
||||
- 需要 Java
|
||||
- 验证: `d2j-dex2jar.sh --version`
|
||||
|
||||
### apksigner / keytool —— 重打包签名(smali 补丁配套)
|
||||
|
||||
- apksigner 在 Android SDK build-tools(同 aapt2 路径);keytool 随 Java 自带
|
||||
- 验证: `apksigner --version`;`keytool -help`
|
||||
|
||||
### adb —— 设备安装 / 重打包闭环验证
|
||||
|
||||
- Android SDK platform-tools 自带(`sdkmanager "platform-tools"`)
|
||||
- Linux: `apt install adb`(Debian/Ubuntu);macOS: `brew install --cask android-platform-tools`;Arch: `pacman -S android-tools`
|
||||
- Windows: platform-tools zip 官方下载
|
||||
- 验证: `adb version`
|
||||
|
||||
## 操作步骤
|
||||
|
||||
按顺序执行,每步记下结果(证据路径 + sha256,见 [[re-triage]])。
|
||||
|
||||
1. **解包(apktool d)**:
|
||||
```sh
|
||||
apktool d app.apk -o out/
|
||||
```
|
||||
解出 `AndroidManifest.xml`、`smali/`(可回编译的字节码)、`res/`、`assets/`、`lib/`。`-s`(`--no-src`)不解码源码(只出资源)、`-r`(`--no-res`)不解码资源(只出 smali),补丁时按需组合。产物比 jadx 更适合改后回编译。
|
||||
|
||||
2. **AndroidManifest 入口/权限/组件**:
|
||||
```sh
|
||||
grep -E 'application|activity|service|receiver|provider' out/AndroidManifest.xml | head -40
|
||||
```
|
||||
记录:主入口(`application` / 首个 `activity` 的 `android:name`)、`uses-permission`(短信 / 通话记录 / 设备管理权限是恶意或敏感信号)、exported 组件、`android:debuggable="true"`(可调试应用可直接 [[re-frida]] attach)。加固后入口常被替换成壳类(见坑 1)。
|
||||
|
||||
3. **jadx 反编译 Java**:
|
||||
```sh
|
||||
jadx -d java-out app.apk # 批量反编译全部 dex 类
|
||||
jadx app.apk # 或 GUI 模式逐类浏览
|
||||
```
|
||||
先看入口类(Application / MainActivity)与算法 / 校验类;敏感串(密钥、URL、校验逻辑)按 `grep -rE 'key|secret|sign|license' java-out/` 定位。dex2jar 等价替代:`d2j-dex2jar.sh app.apk` 得 jar 后用 jd-gui,jar 也可转 [[re-java]] 流程(CFR/JD-GUI 浏览、Java 加固识别)。反编译不出业务代码 → 加固识别(步骤 5)。
|
||||
|
||||
4. **smali 补丁思路**:
|
||||
```sh
|
||||
# 改 smali 后回编译、对齐、签名、安装(用 apksigner 时 zipalign 必须在签名之前,签名后不得再改包)
|
||||
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
|
||||
apksigner sign --ks ks.jks --out signed.apk aligned.apk
|
||||
adb install signed.apk
|
||||
```
|
||||
常用改法:条件跳转取反(`if-eqz` ↔ `if-nez`)、把 `const/4 v0, 0x0` 改成返回常量、把校验方法直接 `return-void`。先 `jadx` 定位逻辑再在对应 smali 里改。目标含签名自校验时补丁可能被拦(见坑 2)。
|
||||
|
||||
5. **加固/混淆识别**:
|
||||
- 壳特征:jadx 只见壳类(`com.stub.StubApp`=爱加密、`com.secneo.apkwrapper` / `com.bangcle.*`=梆梆,乐固等);`lib/` 多一个壳 so(`libjiagu.so`=360 加固、`libDexHelper.so`=爱加密…);`classes.dex` 体积异常小(真 dex 运行时解密)
|
||||
- 资源混淆特征:`res/` 资源路径被随机改名、`resources.arsc` 结构异常
|
||||
- 识别为加固 → 转脱壳域([[re-anti-analysis]] / [[re-mobile-pack]])或动态取内存 DEX([[re-frida]] / [[re-memdump]]);壳名/节区/熵的细粒度指纹对照走 [[re-packer-id]];资源混淆用 aapt2 还原:
|
||||
```sh
|
||||
aapt2 dump badging app.apk # 包名 / 入口 / 权限速览
|
||||
aapt2 dump resources app.apk # 混淆后的资源映射
|
||||
```
|
||||
|
||||
6. **AAB 与 split APK(分发形态边界)**:
|
||||
- `.aab`(Android App Bundle):本质是 zip,内含 dex 与资源——jadx 可直接打开读代码;真机安装需经 bundletool 生成 APKS,拿到 .aab 按步骤 1-3 走即可
|
||||
- split APK(`base.apk` + `config.*.apk`):主 dex 与代码在 base,语言/密度等配置在 split——静态分析以 base 为主,资源差异在 split 中比对;apktool 对 base 与 split 分别解包
|
||||
|
||||
## 跨域联合
|
||||
|
||||
- [[re-mobile]]:工作流第 2 步(APK 静态分支)固定调用本技能
|
||||
- 需要运行时(解密 / hook / 绕过)→ [[re-frida]];运行时内存取 DEX → [[re-memdump]]
|
||||
- 加固 / 带壳 → [[re-anti-analysis]](脱壳域)与 [[re-mobile-pack]](加固脱壳专项);原生 .so → [[re-binary-core]]([[re-format-elf]] / [[re-ghidra]])
|
||||
- dex→jar 后的 Java 层深挖(混淆 / Java 加固)→ [[re-java]]
|
||||
- 本技能被 [[re-analyze]] 的 triage「移动 App 分析」路径调用(re-mobile → re-apk)
|
||||
|
||||
## 常见坑与陷阱
|
||||
|
||||
- **加固样本 jadx 只看到壳壳**:现象——反编译出来只有 StubApp 之类壳类,业务代码全无;原因——真 dex 加密存放在 assets/ 或运行时才解密;对策——按步骤 5 识别壳,转 [[re-anti-analysis]] 脱壳,或 [[re-frida]] / [[re-memdump]] 运行时取内存 DEX
|
||||
- **签名校验拦补丁**:现象——重打包安装后闪退或报"签名不一致 / 未签名";原因——应用内自校验签名(对比 PackageManager 的签名信息);对策——定位校验点打补丁绕过(smali 改返回值 / 跳转),或 [[re-frida]] hook `PackageManager.getPackageInfo` 调用链
|
||||
- **资源混淆后无法直接看资源**:现象——`res/` 路径与资源 ID 对不上、strings 定位不到目标资源;原因——资源被混淆随机改名;对策——aapt2 dump 还原映射(步骤 5),必要时结合动态分析对照
|
||||
- **原生 .so 被当 Java 分析**:现象——Java 层找不到核心逻辑(算法 / 反调试);原因——敏感逻辑写在 JNI 的 .so 里;对策——`lib/` 下 so 转 [[re-format-elf]] + [[re-ghidra]]([[re-binary-core]]),用导出表 / `Java_<包名>_<类名>_<方法名>` 风格符号对 JNI 函数
|
||||
- **apktool 回编译失败**:现象——`apktool b` 报资源编译错误;原因——解包时资源被解码、部分资源格式不兼容回编译;对策——`apktool d -r` 保留原资源不解码,只改 smali 后回编译
|
||||
- **split APK 只分析 base 会缺资源**:现象——目标字符串/资源在 base 里找不到;原因——语言/密度配置拆在 `config.*.apk` split 里;对策——apktool 对 base 与各 split 分别解包,资源差异按 split 比对(步骤 6)
|
||||
|
||||
- **自写 dex 解析四细节**:opcode 是 **u16 低字节**(高字节是寄存器位,读完整 u16 当 opcode 全错位);`fill-array-data` 是 **0x26**(31t)、goto 是 **0x28**(0x24 是 filled-new-array,凭记忆必错);string_data_item 有 **uleb128 长度前缀**(不跳过会把长度当字符);code_item 的 `insns_size` 在 **+12**(+4 是 outs_size)——手写解析器前先对照 dex 规范核对布局
|
||||
- **jadx 目录只剩启动脚本**:现象——`jadx` 报 ClassNotFound;原因——安装不完整(jar 缺失/被清理);对策——从 GitHub release 重下完整 zip(codeload.github.com 比 github.com 稳),或直接用 baksmali 等单一工具
|
||||
- **容器/双开(VirtualApp 类)样本分析**:现象——样本跑在双开容器里行为异常、hook 不到目标进程,或要分析容器本身;原因——VA/Blackbox 容器通过"代理桩 + 动态注册"模拟系统:启动 Activity 走容器内假 AMS(Binder 动态代理拦截,把 VAPP 请求参数还原后再转发真实系统);IO 重定向把写死的绝对路径转向容器内安装路径;ContentProvider 的 `onCreate` 作为容器初始化入口(`handleBindApplication` 主动调用);原理同老版 Android(VA 只支持老版本,Blackbox 为现代参考实现);对策——分析容器内应用时注意进程真实归属(容器进程 vs 宿主进程)、hook 点选在容器框架层(假 AMS/IO 重定向函数)而非应用层;识别双开环境(双开检测)看 `/proc/self/maps` 容器 so、假包名路径特征;这类原理对免安装运行/插件化分析也通用
|
||||
|
||||
- **重打包后 `install -r` 不生效(重打包陷阱)**:现象——重打包签名安装后行为毫无变化,误判「patch 无效」;原因——同包名同签名时 `-r` 会替换既有应用并保留数据,versionCode 未递增不阻止内容更新(它主要影响降级安装规则),「patch 未生效」应排查:签名校验链(见下条)、split APK 不一致、多用户/profile 的安装目标、构建产物缓存(apktool 回编译 build 缓存未清理)、目标进程未重启;对策——装机后做闭环验证:`adb shell pm path <包名>` 取回已装 APK,对 patch 地址做字节级比对,字节确认在位后再排查逻辑层(消费点错误等)(来源:reverse-skills(inliver233),MIT)
|
||||
- **签名校验跨层链与系统版本漂移**:现象——重打包后仍弹「签名不一致」类提示,或复用旧式签名适配 hook 后在新系统上反而误报篡改;原因——签名校验常是跨层链(Java 层取签名信息 → 摘要计算 → 原生层与硬编码基线比对,任一层不匹配即判失败),只中和单点不够;应用自带 PackageManager 签名适配 hook 可复用(拦截 getPackageInfo 系列、同时替换 signatures 与 signingInfo、只作用于自身包),但其反射构造的内部签名对象(如 SigningDetails)构造器签名随系统版本变化,抛异常返回 null 后触发误判;对策——优先复用应用自带的签名适配 hook,版本漂移时用 Frida 探测活构造器、改走公开构造器重建;带壳目标优先免重打包(运行时签名适配),无壳再考虑重打包;静态侧找原生比对函数中和失败分支(来源:reverse-skills(inliver233),MIT)
|
||||
@@ -0,0 +1,107 @@
|
||||
# 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]] 运行时取值,静态侧不硬猜
|
||||
|
||||
## 使用注意
|
||||
|
||||
- 纯静态可免沙箱([[re-analyze/platform-tips]] 最高原则);涉及运行样本(重打包安装、脱壳验证)按 [[re-analyze/platform-tips]] 沙箱分支执行
|
||||
- 每步产物(解包目录 hash、补丁 APK sha256、签名证书)对照 [[re-triage]] 入档;结论写 [[re-analyze/analysis-contract]]
|
||||
- 重打包目标含签名自校验时先评估校验链(见 [[gotchas]] 签名坑组),带壳目标优先免重打包方案
|
||||
@@ -0,0 +1,42 @@
|
||||
# APK 静态分析工具特有坑与边界
|
||||
|
||||
## jadx 坑组
|
||||
|
||||
- **反编译不出业务代码 ≠ 工具坏了**:加固样本 jadx 只输出壳类(StubApp/壳 Application),业务 dex 运行时才解密——先按 SKILL.md 步骤 5 识别加固,再走 [[re-anti-analysis]] / [[re-mobile-pack]] 或 [[re-frida]]/[[re-memdump]] 取内存 DEX,别在 jadx 层面反复折腾
|
||||
- **大样本 OOM / 卡死**:dex 巨大或异常样本(畸形 resources.arsc)会拖垮默认堆——用 `jadx-gui` 单类浏览替代全量反编译,或给 jadx 进程加大堆(JAVA_OPTS 类环境变量按发行版脚本而定);先用 `unzip -l` 看 dex 数量评估规模
|
||||
- **反编译质量随 dex 畸形程度下降**:混淆/畸形 code_item 会产生坏代码——`--show-bad-code` 容错输出可读性差但保底;优先交叉 smali 侧(apktool 产物)核对逻辑
|
||||
- **Java 版本不匹配直接起不来**:jadx 要求 Java 11+(64 位)——ClassNotFound / 启动即退先 `java -version` 确认;多 JDK 环境把 `JAVA_HOME` 指到 11+ 再跑
|
||||
|
||||
## apktool 坑组
|
||||
|
||||
- **回编译失败先换 `-r` 解包**:完整解包(资源被解码)后 `apktool b` 常报资源编译错误——smali 补丁一律 `apktool d -r`,资源原样保留;必须改资源时再完整解包后回编译(3.x 只有 aapt2 这一条编译路径,没有换编译器的开关)
|
||||
- **回编译产物与原始包签名必然不一致**:任何重打包都改变包内容——目标含签名自校验(对比 PackageManager 签名信息)时补丁会被拦,先评估校验链(SKILL.md 坑 2);带壳目标优先免重打包(运行时 hook 签名适配)
|
||||
- **`apktool d` 覆盖输出目录**:默认 `--force` 直接覆盖旧目录——多次解包时旧产物被静默替换,补丁对比拿错版本;敏感操作前先 `cp` 存档或换 `-o` 目录
|
||||
- **仓库版 apktool 较旧**:apt/dnf 包落后官方 release(wrapper jar 机制)——回编译行为差异(aapt 版本、资源处理)以官方 release 为准,异常时先升官方版再排查
|
||||
|
||||
## 签名与重打包坑组
|
||||
|
||||
- **zipalign 与签名方案是正交要求,且顺序不能颠倒**:用 `apksigner` 时必须**先 `zipalign` 再签名**(官方 zipalign 文档:If you sign your APK using apksigner and make further changes to the APK, its signature is invalidated)。v2/v3 把 ZIP 元数据纳入签名保护,签名后再对齐会直接破坏签名——实测 `apksigner sign` 后再 `zipalign -f 4` 会 `DOES NOT VERIFY` 并报 `APK is signed using APK Signature Scheme v2 but no such signature was found. Signature stripped?`,v3 同。jarsigner(v1 JAR 签名)顺序相反(先签名后对齐),但 v1 已不推荐。实际启用哪些 scheme 由 `apksigner` 依 `--min-sdk-version`/`--max-sdk-version` 决定,不是固定 v1+v2(对 minSdk 24 的目标签名会得到 v1=false / v2=true / v3=true)
|
||||
- **`install -r` 不生效 ≠ patch 无效**:同包名同签名覆盖安装保留数据,行为无变化时先做字节级闭环验证(`pm path` + `adb pull` 比对 patch 地址,见 [[commands]] 序列 2),再排查消费点/构建缓存
|
||||
- **签名校验是跨层链,单点中和不够**:Java 层取签名 → 摘要 → 原生层与硬编码基线比对,任一层不匹配判失败——优先复用应用自带的签名适配 hook,静态侧找原生比对函数中和失败分支(SKILL.md 坑 2 细节)
|
||||
- **debuggable 目标可直接 attach**:`android:debuggable="true"` 或可调试构建的 APK 无需重打包,直接 [[re-frida]] attach 绕过校验——重打包前先确认有没有这条捷径
|
||||
|
||||
## 加固识别坑组
|
||||
|
||||
- **单个特征别下结论**:libjiagu.so 之外还有自研壳/混淆 dex(无壳 so 但 dex 变形)——壳 so + 壳类 + dex 体积三特征交叉,仍不确定走 [[re-packer-id]] 指纹
|
||||
- **资源混淆 ≠ 加固**:只混淆资源不改代码的样本,jadx 输出正常但资源名随机——用 `aapt2 dump resources` 还原映射([[commands]] 序列 3),别误送脱壳流程
|
||||
- **多 dex 拆包误判**:`classes2.dex`/`classes3.dex` 是正常多 dex(方法数超 64K),不是加固——按 dex 总量与入口 Application 类判断,单看文件名会误判
|
||||
|
||||
## 版本差异
|
||||
|
||||
- **jadx**:1.4.x 起要求 Java 11;1.5.x 主线(本地实测 1.5.6 可用 `--version`)——release zip 与 brew/pacman 包同步,功能差异小;反编译器本身迭代快,老版本对 Kotlin/新 dex 特征支持弱,异常时先升版本
|
||||
- **apktool**:**3.x 为当前主线、2.x 为维护线**,两线命令不完全兼容;apt/dnf 仓库版明显落后官方 release。拿到旧教程/脚本先确认目标 major version
|
||||
- **apktool 3.x 的 CLI breaking changes**(照 2.x 写法会直接报错):① **aapt1 移除**——3.x 只随包发布 aapt2(2.x 的无后缀二进制是 32 位、`_64` 后缀才是 64 位;3.x 只剩单个 64 位),2.x 的 `--use-aapt2` 开关随之消失,换 aapt2 二进制改用 `--aapt <file>`,传入 aapt1 会被直接拒绝;② **不再提供 32 位构建**——32 位系统上无可用产物;③ **`--api-level` 移除**;④ **`--only-main-classes` 由 `-a`/`--all-src` 取代**,语义相反:前者只解主 dex,后者把未知 dex 也一并解出(加固/畸形样本的 dex 常被改名,需要 `-a` 才解得到);⑤ **高级选项只认长参数**——3.x 的短参数仅 `-a -f -j -l -o -p -q -r -s -t -v`,`-m`/`-k` 一类旧短参报 `Unrecognized option`,须写 `--match-original`/`--keep-broken-res`/`--res-resolve-mode`
|
||||
- **aapt2 / build-tools**:34.0.0 示例、新版 SDK 自带更高版本;`aapt2 dump xmltree --file` 等接口稳定;老环境用 `aapt`(34 前默认)
|
||||
- **apksigner**:build-tools 内置版本随 SDK;`--min-sdk-version`/`--max-sdk-version` 决定实际启用 v1/v2/v3 中的哪些(默认按目标 SDK 范围取舍),`apksigner verify --verbose` 会逐 scheme 打印 true/false;`--version` 输出以实际版本为准
|
||||
|
||||
## 使用注意
|
||||
|
||||
- 纯静态可免沙箱([[re-analyze/platform-tips]] 最高原则);重打包/安装/运行验证样本按沙箱分支执行
|
||||
- 补丁产物与原始样本 sha256 对照存证([[re-triage]]);分析结论写 [[re-analyze/analysis-contract]]
|
||||
- 版本相关行为(apktool 回编译细节、jadx 反编译质量)以目标版本实际表现为准
|
||||
Reference in New Issue
Block a user