re-apk

Breaks down Android apps to see how they work and find security problems.

Installation
Run `npx skills add "https://github.com/dslsdzc/rev-skills" --skill "re-apk"` to install this skill, then follow its SKILL.md instructions for my next request.

Paste this into Claude Code, Cursor, or any agent that can run commands.

What this skill does
What it does: This skill takes apart Android phone applications to see their code and resources without running them. It reads the app manifest to find permissions and entry points, converts compiled code back to readable Java, and identifies if the app uses protection techniques like encryption or code obfuscation. What it does: This skill takes apart Android phone applications to see their code and resources without running them. It reads the app manifest to find permissions and entry points, converts compiled code back to readable Java, and identifies if the app uses protection techniques like encryption or code obfuscation. When to use it: Use this when you have an APK file and need to see what the app does before installing it. Use it to check if an app has suspicious permissions or hidden code. Use it to identify what protection method was used so you know what tools you need next.
SKILL.mdShow the author's original SKILL.md (not in English)
---
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]])

## 工具准备

纯静态分析(解包 / 反编译)可免沙箱([[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+。官方 wrapper:从 `https://github.com/iBotPeaches/Apktool/releases` 下载 `apktool_<版本>.jar` 与 wrapper 脚本(Linux/macOS `apktool`、Windows `apktool.bat`),脚本与 jar 放同目录
- 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 后回编译、签名、安装
   apktool b out/ -o patched.apk
   keytool -genkey -v -keystore ks.jks -alias r -keyalg RSA -validity 3650 -storepass 123456
   apksigner sign --ks ks.jks --out signed.apk patched.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)

Ships with 2 supporting files:

  • references/commands.md
  • references/gotchas.md

Mirrored from the author's public source. Install counts from the open skills registry.

The systems behind these skills get built for partners every week.

Partner with us