Skip to main content

app-reverse

移动端(Android/iOS)加密参数逆向 — 当 Web 抓包发现某 sign/token/加密参数其实由配套 App 生成、JS 端根本找不到时,下沉到 App 层定位加密函数。覆盖 jadx/apktool 反编译、smali 阅读、Frida hook 关键加密函数(Cipher/Mac/MessageDigest/自定义 native)提取密钥与输入输出样本、SSL Pinning 绕过、native .so 用 IDA/Ghidra 分析、JNI 桥追踪;iOS 砸壳/class-dump/objection 思路。目标=拿到「函数位置 + 一组输入→输出样本 + 密钥来源」,再转交 param-encryptor 纯算复现、reverse-parity-gate 对齐。触发词:「App 生成的签名」「抓包参数 JS 里找不到」「下沉到 App 层」「jadx」「frida」「smali」「so 逆向」「移动端加密」「SSL Pinning」「砸壳」。边界:只负责「从 App 定位到加密函数 + 拿样本」,算法复现转交 param-encryptor,交付前对齐转交 reverse-parity-gate。

Source facts

Repository
woxiangyangzhimao/skills
Last source activity
July 2, 2026 at 04:14
Detected SKILL.md language
Chinese
Stars
14
Forks
8

Install options

The review-first prompt is selected by default. You can switch to a direct command or download a local copy.

Review the source files

Read SKILL.md and any companion files shown by SkillsMP before deciding whether to install.

Showing SKILL.md

SKILL.md
Source instructions · Read-only preview
name
app-reverse
description_zh
移动端逆向(Android/iOS)— 抓包参数 JS 里找不到、其实由 App 生成时,jadx/Frida hook 提密钥+样本,转 param-encryptor
description
移动端(Android/iOS)加密参数逆向 — 当 Web 抓包发现某 sign/token/加密参数其实由配套 App 生成、JS 端根本找不到时,下沉到 App 层定位加密函数。覆盖 jadx/apktool 反编译、smali 阅读、Frida hook 关键加密函数(Cipher/Mac/MessageDigest/自定义 native)提取密钥与输入输出样本、SSL Pinning 绕过、native .so 用 IDA/Ghidra 分析、JNI 桥追踪;iOS 砸壳/class-dump/objection 思路。目标=拿到「函数位置 + 一组输入→输出样本 + 密钥来源」,再转交 param-encryptor 纯算复现、reverse-parity-gate 对齐。触发词:「App 生成的签名」「抓包参数 JS 里找不到」「下沉到 App 层」「jadx」「frida」「smali」「so 逆向」「移动端加密」「SSL Pinning」「砸壳」。边界:只负责「从 App 定位到加密函数 + 拿样本」,算法复现转交 param-encryptor,交付前对齐转交 reverse-parity-gate。
# App Reverse · 移动端加密参数逆向 > 核心场景:Web 抓包定位到某个 `sign`/`token`/`X-Sign` 加密参数,但翻遍 JS 都找不到生成位置——因为它其实是配套 **App**(Android/iOS)算出来后塞进请求的。此时 Web 链路走不通,必须下沉到 App 层。 > 核心理念:**定位加密函数(位置) → Hook 拿一组输入→输出样本 → 摸清密钥来源 → 转交 param-encryptor 纯算复现 → reverse-parity-gate 逐字节对齐**。 > 不在 App 里硬扣算法、不重打包跑业务、不绕风控——只把「黑盒加密」变成「已知输入输出 + 已知密钥」的纯算问题。 --- ## 一、Scope 与授权(与 web-reverse-master 同口径) - 只对**你被授权测试的系统、你自有的应用、公开学习目标、或防御/调试研究**作业。 - 不协助:账号滥用、绕过访问控制、凭据窃取、大规模抓取、对第三方服务的隐蔽规避、击穿生产反滥用系统。遇到这类请求,改写为防御性分析、插桩、限速设计或合规调试。 - 每一个算法结论在拿到**源码位置 / Hook 输出 / 真实样本 / 可复现本地测试**之前,一律视为「待验证」。 - 目标是第三方真实 App 时:完成定位与取样后先给 Plan,征得用户确认再写 Phase 4 生产代码。 - 本技能聚焦**读与观测**:反编译阅读、动态 Hook 观测、密钥取样。重打包/patch smali/绕 root 等**修改设备或应用**的动作,仅在用户明确要求且授权范围内进行,且默认不触碰。 --- ## 二、角色规则 **此 Skill 激活后,以移动端逆向工程师身份工作。** - 加密方式、密钥、IV 必须通过**动态 Hook 实证确认**,禁止从函数名猜测。 - 优先静态读懂逻辑(jadx/smali),读不动再上动态 Hook;能 Java 层 Hook 就不碰 native。 - 核心逻辑沉到 `.so`/native 时,明确切到 IDA/Ghidra,不在 Java 层死磕。 - 不做自动安装、不联网 bootstrap、不依赖任何 MCP server;所有工具均为**本机命令行**直连(adb/frida/jadx/apktool/objection)。工具缺失时给手动安装指引,由用户自行安装。 - **本技能不负责算法复现**。定位到加密函数并拿到样本后,产出交接物转交 `param-encryptor`;交付前用 `reverse-parity-gate` 对齐。 --- ## 三、环境与工具(均需手动安装,不自动装) > Windows + PowerShell。Python 一律用 `python3.11`(本机 `python`/`python3`/`py` 是坏的 Store stub)。 > 默认 **No-MCP 路由**:不依赖 `ida-pro-mcp` / `frida-mcp` 等;全部用命令行直连。若当前会话恰好暴露了对应 MCP 工具,可作为可选加速,但主路径始终是命令行。 | 工具 | 用途 | 手动安装 | 验证 | |------|------|---------|------| | `adb` | 设备连接 / 进程 / 日志 / 拉文件 | winget `Google.PlatformTools` 或官网 Android Platform-Tools 解压 | `adb devices` | | `jadx` | APK → Java 反编译阅读 | 官网 github.com/skylot/jadx Release 解压 | `jadx --version` | | `apktool` | APK 解包/看 smali/看 Manifest | github.com/iBotPeaches/Apktool 下 jar + bat | `apktool --version` | | `frida` / `frida-ps` | 动态 Hook(Java/native) | `python3.11 -m pip install frida-tools` | `frida-ps -U` | | `objection` | Frida 增强 REPL(免写脚本绕 pinning) | `python3.11 -m pip install objection` | `objection version` | | `ghidra` | `.so`/Mach-O 反编译(免费) | github.com/NationalSecurityAgency/ghidra Release | GUI 启动 | | IDA | `.so`/Mach-O 深度分析(商业) | hex-rays.com 官网 | GUI 启动 | | `unidbg` | 把 Android native `.so` 拉进 JVM **模拟执行**算 sign(无需真机) | github.com/zhkl0228/unidbg 源码 + `gradle build`(JDK 8+) | 跑通自带示例 | > 设备端还需 `frida-server`(与本机 frida 版本一致的对应架构二进制,从 frida GitHub Release 取)推到设备 `/data/local/tmp/` 并以 root 运行。这一步需要用户自备 root 设备/模拟器,本技能不代为安装。 **PowerShell 常用命令:** ```powershell # 设备 / 进程 adb devices frida-ps -U # 列出 USB 设备上的进程 frida-ps -Uai # 仅列已安装应用 # 反编译阅读 jadx -d .\jadx_out app.apk # Java 反编译落盘 jadx --deobf -d .\jadx_out app.apk # 混淆名时加去混淆 apktool d app.apk -o .\apktool_out # 解包看 smali + Manifest # 动态 Hook frida -U -f com.example.app -l hook.js --no-pause # spawn 注入 frida -U -n com.example.app -l hook.js # attach 到已运行进程 frida-trace -U -n com.example.app -j "javax.crypto.Cipher!*" # 快速追 Cipher # 拉 native 库出来分析 adb shell pm path com.example.app # 找 base.apk 路径 adb pull /data/app/.../base.apk . # 拉下来后解包取 lib/arm64-v8a/*.so ``` --- ## 四、纪律化流程(从 Web 下沉到 App,六步) > 每步带 CHECKPOINT 的必须达成后才能进入下一步。禁止跳步直接扣算法。 ### Step 0 — 确认「确实在 App 层」(下沉判据) 由 Web 抓包侧(`reverse-traffic-triage` / `web-reverse-master`)转入。进入本技能前先确认: - 目标参数在 **App 发出的请求**里出现,但同站 H5/Web 的 JS 调用栈里**写不出该参数**(initiator 追不到、断点打不上)。 - 或该参数只在 App 原生请求里有,H5 请求里压根没有。 🔴 **CHECKPOINT**:能说清「这个 `sign` 在 Web JS 里找不到、确属 App 生成」才下沉;否则退回 `reverse-traffic-triage` 继续在 Web 侧定位,别白拆 App。 ### Step 1 — Triage:摸清 App 构成 不急着 Hook。先建立地图。 ```powershell jadx -d .\jadx_out app.apk apktool d app.apk -o .\apktool_out ``` 看四样: - `AndroidManifest.xml`:主 `package`、`application` 类、入口 `activity`、网络相关 service。 - 主包结构:业务包名、第三方 SDK(okhttp/retrofit/网络库)。 - `lib/` 下是否有 `.so`(`arm64-v8a`/`armeabi-v7a`)——决定后面要不要切 native。 - 是否**加壳**(360/腾讯乐固/梆梆/爱加密):jadx 打开几乎全是空壳类 / `attachBaseContext` 里解密 dex → 已加固。加固需先脱壳(用户授权范围内),本技能不展开脱壳工具链,仅标注「需脱壳」。 🔴 **CHECKPOINT**:记录 `包名 + 入口类 + 有无 .so + 是否加固`。加固未脱壳 → 静态读不动,直接走 Step 3 动态 Hook。 ### Step 2 — 静态定位候选加密函数 在 `jadx_out` 里搜目标参数名 + 加密关键词,缩小到几个候选函数。 常见关键词:`sign` `token` `encrypt` `cipher` `getInstance` `doFinal` `Mac` `digest` `MessageDigest` `secretKey` `IvParameterSpec` `base64` + 你的**参数名本身**(如 `X-Sign`、`mtgsig`)。 读到这些就是命中: - `javax.crypto.Cipher.getInstance("AES/CBC/PKCS5Padding")` → 对称加密。 - `javax.crypto.Mac.getInstance("HmacSHA256")` → HMAC 签名。 - `java.security.MessageDigest.getInstance("MD5"/"SHA-256")` → 哈希。 - `System.loadLibrary("xxx")` + `native` 方法 → 核心在 `.so`,Java 只是 JNI 壳。 🔴 **CHECKPOINT**:列出 ≥1 个候选函数(类名+方法名+文件)。混淆严重读不出 → 不硬读,转 Step 3 用 Hook 反向定位。 ### Step 3 — 动态 Hook 拿密钥 + 输入输出样本(本技能核心产出) 无论静态是否读懂,都用 Frida hook **标准加密 API**,直接截获算法、密钥、明文、密文。这是把黑盒变白盒的关键一步。 把下面脚本存为 `hook_crypto.js`,`frida -U -f <包名> -l hook_crypto.js --no-pause` 注入,然后在 App 里触发那个请求: ```javascript // hook_crypto.js — 截获 Java 层标准加密 API 的算法/密钥/输入/输出 function hex(bytes) { if (bytes === null) return "null"; return Java.array('byte', bytes).map(b => ('0' + (b & 0xff).toString(16)).slice(-2)).join(''); } function utf8(bytes) { try { return Java.use('java.lang.String').$new(bytes); } catch (e) { return '<bin>'; } } Java.perform(function () { // ── 对称加密 Cipher:拿算法 + 密钥 + IV ── var Cipher = Java.use('javax.crypto.Cipher'); Cipher.getInstance.overload('java.lang.String').implementation = function (algo) { console.log('[Cipher.getInstance] ' + algo); return this.getInstance(algo); }; var SecretKeySpec = Java.use('javax.crypto.spec.SecretKeySpec'); SecretKeySpec.$init.overload('[B', 'java.lang.String').implementation = function (k, a) { console.log('[Key] algo=' + a + ' key(hex)=' + hex(k) + ' key(utf8)=' + utf8(k)); return this.$init(k, a); }; var IvSpec = Java.use('javax.crypto.spec.IvParameterSpec'); IvSpec.$init.overload('[B').implementation = function (iv) { console.log('[IV] ' + hex(iv)); return this.$init(iv); }; Cipher.doFinal.overload('[B').implementation = function (input) { var out = this.doFinal(input); console.log('[Cipher.doFinal] in(hex)=' + hex(input) + '\n in(utf8)=' + utf8(input) + '\n out(hex)=' + hex(out)); return out; }; // ── HMAC / Mac:拿密钥 + 输入 + 输出 ── var Mac = Java.use('javax.crypto.Mac'); Mac.getInstance.overload('java.lang.String').implementation = function (a) { console.log('[Mac.getInstance] ' + a); return this.getInstance(a); }; Mac.doFinal.overload('[B').implementation = function (input) { var out = this.doFinal(input); console.log('[Mac.doFinal] in=' + utf8(input) + '\n out(hex)=' + hex(out)); return out; }; // ── MessageDigest:哈希签名常见 ── var MD = Java.use('java.security.MessageDigest'); MD.digest.overload('[B').implementation = function (input) { var out = this.digest(input); console.log('[MD.digest] algo=' + this.getAlgorithm() + '\n in=' + utf8(input) + '\n out(hex)=' + hex(out)); return out; }; }); ``` 如果 Step 2 发现核心是**自定义 native 方法**(Java 只是 `native` 声明),改 hook 它的 JNI 导出: ```javascript // hook 自定义 native 函数(先用 frida-trace 或读 .so 导出表确定名字/模块) Interceptor.attach(Module.findExportByName('libsign.so', 'Java_com_example_Sign_sign'), { onEnter: function (args) { // args[0]=JNIEnv, args[1]=jclass/this;后续是入参,需按签名读 this.start = Date.now(); console.log('[native sign] called'); }, onLeave: function (retval) { console.log('[native sign] returned in ' + (Date.now() - this.start) + 'ms'); } }); ``` > 取样要求(交给 param-encryptor 前必须够用): > - **≥3 组** 输入→输出样本,覆盖典型输入、空输入、边界输入。 > - 明确记录:算法字符串(如 `AES/CBC/PKCS5Padding`)、key(hex+utf8)、IV、输入编码、输出格式(hex/base64)。 > - **密钥来源**:是硬编码常量、接口下发、还是设备指纹派生?这决定能否纯算复现。 🔴 **CHECKPOINT · 关键门控**:拿到 `算法 + 密钥 + 密钥来源 + ≥3 组 输入→输出样本` → 进入交接。任一缺失 → 不要宣称定位完成,继续 Hook 或回 Step 2/4。 ### Step 4 — 排障:Hook 不到时 请求带加密参数发出了,但上面脚本没打印 → 多半是**没走标准 JCE API**,或被 SSL Pinning / root 检测挡在前面。对照「失败模式表」处理。常用绕过(仅授权范围内): ```powershell # objection 一键绕 SSL Pinning + root 检测,便于先抓到明文请求确认参数确实在这个流程里生成 objection -g com.example.app explore # 进入 REPL 后: # android sslpinning disable # android root disable # 或 Frida 通用 pinning bypass 脚本 frida -U -f com.example.app -l ssl_pinning_bypass.js --no-pause ``` 绕过 pinning 的目的只有一个:**让你能用代理(Burp/mitmproxy)看清楚 App 到底发了什么、加密参数长什么样**,从而回到 Step 2/3 精确定位。不是为了篡改业务。 ### Step 5 — native 分流(核心在 `.so` 时) Java 层只是 JNI 包装、`System.loadLibrary` 后逻辑消失、签名在 `.so` 里 → 切静态反汇编: ```powershell # 从设备/APK 取出目标 .so adb pull /data/app/.../lib/arm64-v8a/libsign.so . ``` - 用 **Ghidra**(免费)或 **IDA** 打开 `.so`,看导出表(`Java_*` JNI 函数)、字符串(密钥常量、算法名常常以明文字符串躺在 `.rodata`)。 - 目标不是读懂整个 `.so`,而是:**确认算法 + 找出密钥/盐/常量**,再回 Step 3 用 Frida hook 该 native 函数拿 运行时输入输出样本对账。 - 静态(看常量)+ 动态(Hook 取样)**双向印证**,比纯静态啃汇编快得多。 - **第三条路 — 模拟执行**:不想上真机 Hook、或想要可移植纯算时,用 **unidbg**(`zhkl0228/unidbg`,见上方工具表)把 `.so` 拉进 JVM 模拟跑,喂输入拿输出、按报错补齐缺失的 JNI/syscall,即可脱离设备复现 sign。适合"算法在 native、又要纯算落地"的场景。 🔴 **CHECKPOINT**:`.so` 里能定位到算法 + 关键常量,且 Frida 能 hook 到该函数拿样本 → 回 Step 3 的取样标准收口。 ### Step 6 — iOS(简述思路,同样产出「函数位置 + 样本 + 密钥」) iOS 流程与 Android 对称,工具不同: - **砸壳**:App Store 下载的二进制是加密的,先解密。Hook/分析前必须砸壳。常用 `frida-ios-dump`(需越狱设备或可注入环境)拿到解密 IPA。 - **class-dump**:对解密后的二进制 `class-dump` 导出 ObjC 头文件,定位疑似签名/加密类与方法名(`-sign`、`-encrypt`、`-hmac`)。 - **Frida hook**:hook `CommonCrypto` 的 `CCCrypt`(对称加密)、`CCHmac`(HMAC),onEnter 时 `hexdump` 读 key/iv/明文,拿算法 + 密钥 + 输入输出。 - **objection**:`objection -g <bundleid> explore` → `ios sslpinning disable` / `ios jailbreak disable`,同样为了先抓到明文请求确认参数来源。 - Swift 符号用 `swift-demangle` 还原;`.dylib`/Mach-O 深度分析用 Ghidra/IDA/Hopper。 🔴 **CHECKPOINT**:iOS 侧同样要收口到 `算法 + 密钥 + 密钥来源 + ≥3 组样本`,标准与 Android 一致。 --- ## 五、失败模式表 | 症状 | 原因 | 一线修复 | 仍失败兜底 | |------|------|---------|----------| | 触发请求了,Cipher/Mac/MD hook 全无打印 | 没走标准 JCE,用了自研/native 加密 | 读 Step 2 候选找 `native` 方法 / `.so` | Step 5 反汇编 `.so` + hook JNI 导出 | | frida 注入即闪退 / 进程消失 | App 有 frida-server / root 检测 | objection `android root disable`;改 attach 而非 spawn | 自定义 anti-frida bypass 脚本(端口/字符串检测) | | `frida-ps -U` 列不出进程 | frida-server 没起/版本不符/无 root | 推对应架构 frida-server 到 `/data/local/tmp` 并 root 运行,版本对齐本机 frida | 换 root 模拟器 / frida-gadget 注入(需重签) | | 抓不到明文请求,全是 TLS 密文 | SSL Pinning | objection `android sslpinning disable` | Frida 通用 pinning bypass / 系统证书 | | jadx 打开几乎全是空类 | App 加固(壳) | 标注「需脱壳」,直接走动态 Hook | 用户授权下脱壳(本技能不含脱壳链) |
View on GitHub
This SKILL.md is very large, so SkillsMP previews the first section here. View on GitHub