# Android App Reverse

> Android App 逆向分析全流程（环境准备→流量捕获→动态Hook→算法还原）。整合 frida-mcp、adb-mcp、android_proxy_mcp 三个 MCP 工具。 TRIGGER when: 用户提到 Android 逆向、App 抓包、Frida hook、So层分析、APK 分析、App 签名逆向、App 加密参数、Java 层 hook、Native hook、SSL Pinning 绕过、Android 协议分析。包括但不限于"分析这个App"、"抓包看看"、"hook 这个函数"、"App的签名怎么算的"、"绕过证书校验"、"Frida脚本"。 DO NOT TRIGGER when: 只是 Web 端 JS 逆向（用 find-crypto-entry）、纯 PC 软件逆向、iOS 专项分析。

- Skill: `zxzvsdcj/android-app-reverse` (Agent Skill, multi-file: 4 files)
- Install (CLI): `npx skillmds@latest add zxzvsdcj/android-app-reverse`
- Raw SKILL.md: https://api.skillmd.com/api/skills/zxzvsdcj/android-app-reverse/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: AI & ML
- Author: zxzvsdcj (https://skillmd.com/u/zxzvsdcj)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/zxzvsdcj/android-app-reverse

---


# android-app-reverse

对 **$ARGUMENTS** 执行 Android App 逆向分析。

**MCP 依赖**:
- `frida-mcp` — Frida 动态 Hook（spawn/attach/注入脚本/消息读取）
- `adb-mcp` — ADB 设备管理（安装/文件传输/截屏/日志/输入模拟）
- `android_proxy_mcp` — 流量捕获（HTTP/HTTPS 抓包/API 分析）

---

## 前置检查

开始分析前确认环境：

```
1. list_devices → 检查 ADB 是否连接到设备
2. get_device_info → 确认设备信息（型号、Android 版本、root 状态）
3. check_frida_status → 检查 frida-server 是否运行
   └── 未运行 → start_frida_server
4. proxy_status → 检查代理服务是否运行（如需抓包）
```

---

## 分析流程

根据目标灵活选择阶段，不必全部执行：

### Stage 1: 目标识别与信息收集

```
1. list_packages → 查找目标 App 包名
   └── 未安装 → install_app(apk_path) 安装 APK
2. get_frontmost_application → 确认目标 App 在前台
3. pull_file → 提取 APK:
   - /data/app/<package>/base.apk → 本地分析
4. 静态分析（本地执行，非 MCP）:
   - jadx / apktool 反编译
   - 查看 AndroidManifest.xml（权限、组件、入口）
   - 识别加固壳（360、腾讯、梆梆等）
   - 定位网络请求相关类
```

### Stage 2: 流量捕获与 API 发现

**目标**: 找到目标 API 请求、识别加密参数

```
1. 配置代理:
   - 手机 WiFi 设置代理 → 指向 android_proxy_mcp 的 IP:8288
   - 需要 HTTPS → get_cert_info 获取 CA 证书安装指引

2. 驱动 App 操作:
   - send_tap(x, y) / send_swipe(...) → 模拟用户操作触发请求
   - send_text("搜索关键词") → 输入文本
   - take_screenshot → 截屏确认当前界面

3. 分析流量:
   - traffic_list → 列出捕获的请求（按域名/状态码筛选）
   - traffic_search("sign") → 搜索包含加密参数的请求
   - traffic_get_detail(reqid) → 查看请求头、响应头
   - traffic_read_body(reqid) → 读取请求/响应体
   
4. 识别加密参数:
   - 记录加密字段名、位置（header/body/query）
   - 记录字段值的特征（长度、编码格式、是否时间相关）
   - 对比多次相同请求，观察哪些字段变化
```

### Stage 3: SSL Pinning 绕过

如果 HTTPS 抓包失败（证书错误），需要绕过 SSL Pinning：

```
方案 A: Frida 脚本 Hook（推荐）
  spawn(package_name, script_file_path="ssl_bypass.js")
  
  通用 SSL Pinning 绕过脚本思路:
    - Hook TrustManager.checkServerTrusted → 置空
    - Hook OkHttp CertificatePinner.check → 绕过
    - Hook SSLContext.init → 替换为信任所有证书
    - Hook WebViewClient.onReceivedSslError → proceed
  
方案 B: LSPosed + TrustMeAlready 模块（免 Frida）
  参考 references/ssl-pinning-bypass.md

方案 C: 修改 APK（network-security-config）
  解包 → 修改 res/xml/network_security_config.xml → 重打包签名
```

### Stage 4: 动态 Hook

**目标**: 拦截加密函数的输入输出，理解加密逻辑

#### 4.1 Java 层 Hook

```javascript
// spawn 或 attach 后注入 Frida 脚本

// Hook 加密方法，打印输入输出
Java.perform(function() {
    var EncryptUtil = Java.use("com.target.utils.EncryptUtil");
    
    EncryptUtil.encrypt.overload("java.lang.String").implementation = function(input) {
        console.log("[encrypt] input: " + input);
        var result = this.encrypt(input);
        console.log("[encrypt] output: " + result);
        return result;
    };
});
```

**操作流程**:
```
1. spawn(package_name, initial_script=上述脚本)
   或 attach(package_name, initial_script=上述脚本)
2. 操作 App 触发加密
3. get_messages(max_messages=200) → 读取 hook 输出
4. 分析输入输出关系
```

#### 4.2 Native 层 Hook（.so 文件）

```javascript
// Hook native 函数
Interceptor.attach(Module.findExportByName("libnative.so", "Java_com_target_NativeLib_sign"), {
    onEnter: function(args) {
        console.log("[native sign] arg0: " + args[0]);
        console.log("[native sign] arg1: " + Memory.readUtf8String(args[1]));
    },
    onLeave: function(retval) {
        console.log("[native sign] return: " + Memory.readUtf8String(retval));
    }
});
```

#### 4.3 常用 Hook 目标

| 目标 | Hook 位置 | 用途 |
|------|----------|------|
| MD5/SHA | `java.security.MessageDigest.digest` | 拦截标准 Hash |
| HMAC | `javax.crypto.Mac.doFinal` | 拦截 HMAC 签名 |
| AES/DES | `javax.crypto.Cipher.doFinal` | 拦截对称加密 |
| RSA | `java.security.Signature.sign` | 拦截非对称签名 |
| Base64 | `android.util.Base64.encodeToString` | 拦截编码 |
| SharedPrefs | `SharedPreferences.getString` | 读取本地配置 |
| OkHttp | `okhttp3.OkHttpClient.newCall` | 拦截 HTTP 请求构造 |

### Stage 5: 算法还原

根据 Stage 4 的 Hook 结果，还原加密算法：

```
情况 A: 标准加密算法（MD5/SHA/AES/RSA/HMAC）
  → Hook 拿到 key/iv/salt 等参数
  → 直接用 Python 标准库实现
  → 验证：相同输入 → 相同输出

情况 B: 自定义算法（Java 层）
  → 反编译代码 + Hook 中间值
  → 逐步还原逻辑到 Python
  → 多组数据验证

情况 C: Native 层算法（.so 文件）
  → IDA/Ghidra 反编译 .so
  → Frida hook native 函数拿中间值
  → 还原到 Python 或直接调用 .so（ctypes/cffi）

情况 D: 第三方加固/保护
  → 先脱壳（Frida dump dex）
  → 再按 A/B/C 处理
```

---

## 反模式

- **不要在未 root 设备上尝试 Frida** — 非 root 需要重打包 APK 注入 frida-gadget，流程完全不同。
- **不要忽略 ProGuard 混淆** — 大部分 App 的类名/方法名被混淆，需要在反编译代码中搜索特征字符串（如 "sign"、"encrypt"、"MD5"）定位目标类。
- **不要只 hook 一层** — 很多 App 的签名是多步组合（先 MD5 再 HMAC 再 Base64），需要 hook 整个调用链。
- **不要忘记时间戳** — 大部分签名包含时间因子，重放时需要更新时间戳。
- **spawn vs attach** — 需要在 App 启动前 hook（如 onCreate 中的初始化逻辑）用 `spawn`；hook 已运行 App 的实时行为用 `attach`。

---

## 完成标准

```
分析结果：
- App：$ARGUMENTS
- 目标 API：https://api.example.com/v1/feed
- 加密参数：X-Sign（位于请求头）
- 算法类型：HMAC-SHA256
- 密钥来源：固定密钥，硬编码在 so 层
- Python 实现：output/sign.py（已验证）
- 验证结果：相同输入产生相同签名，HTTP 200 + 业务数据返回
```

## References

遇到具体场景时按需读取：

| 文件 | 何时读取 |
|------|---------|
| `references/frida-hooks.md` | 需要 Frida hook 模板（Java 层/Native 层/常见框架） |
| `references/ssl-pinning-bypass.md` | HTTPS 抓包失败，需要绕过 SSL Pinning |
| `references/common-android-crypto.md` | 识别 Android App 中常见的加密实现模式 |

