Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 7 additions & 4 deletions boards/android/AI-USAGE.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,18 @@
- jadx: `tools/android/jadx/`
- uber-apk-signer: `tools/android/uber-apk-signer/uber-apk-signer.jar`
- frida-server: 通过 MCP `android_frida_ensure_server` 部署
- frida-tools: 桌面端通过 `pip install frida-tools` 安装
- frida-tools: 桌面端通过 `pip install frida-tools` 安装,版本须与目标端 frida-server 兼容
- Ghidra + 兼容 Java: Native SO 静态分析首选,需可运行 `analyzeHeadless`
- IDA Pro / Hex-Rays: 可选的人工复核工具;不属于本项目 MCP 或 CI 依赖

## 分析流程

1. 先用 apktool 解包 APK
2. 用 jadx 打开 DEX 反编译
3. 关注 AndroidManifest.xml、入口 Activity、native 库
4. Frida 动态 hook 时脚本保存到 `scripts/android/`
5. 重打包产物放入 `patches/android/apk-builds/`
4. Native SO 优先用 Ghidra headless 分析,再用 Frida 运行时证据验证;IDA Pro 仅作为可选人工复核
5. Frida 动态 hook 时脚本保存到 `scripts/android/`
6. 重打包产物放入 `patches/android/apk-builds/`

## MCP 工具链(AI 可自动调用)

Expand Down Expand Up @@ -100,4 +103,4 @@

### 知识库

APK 逆向知识库位于 `kb/apk-reverse/`,8 个分类 17 篇技术文件(每篇含可运行 Frida 代码)。详见 `kb/apk-reverse/README.md`。
APK 逆向知识库位于 `kb/apk-reverse/`,8 个分类 20 篇技术文件。先调用 `kb_router(board="apk-reverse")` 按信号定位文章,再使用对应 MCP 工具,并将运行时证据保存到 `exports/android/`、分析笔记保存到 `notes/android/`。详见 `kb/apk-reverse/README.md`。
2 changes: 1 addition & 1 deletion boards/android/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ Android APK 分析有一整套 MCP 自动化工具链,涵盖 ADB 连接、包

## 知识库

APK 逆向知识库 `kb/apk-reverse/`:17 篇 Frida 可运行技术文件,8 个分类覆盖 DEX/Java、Native、Manifest、Crypto、Network、Dynamic、Packer、Patch/Repack。
APK 逆向知识库 `kb/apk-reverse/`:20 篇可运行技术文件,8 个分类覆盖 DEX/Java、Native、Manifest、Crypto、Network、Dynamic、Packer、Patch/Repack。

## 分析流程

Expand Down
136 changes: 91 additions & 45 deletions docs/llms-full.txt
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# ReverseLab — Full Knowledge Base Dump for LLM Ingestion

Total articles: 178
Generated: 2026-07-04
Generated: 2026-07-31

---
## [ctf-website] 24h Loop Orchestration
Expand Down Expand Up @@ -34989,66 +34989,82 @@ strings exports/android/app-apktool/lib/arm64-v8a/*.so | rg -i "RegisterNatives|

如果导出表只有 `JNI_OnLoad`,说明很可能使用动态注册;下一步 hook `RegisterNatives`。

## 3. RegisterNatives Frida 打点
## 3. MCP 模板:加载器与 RegisterNatives 证据

```javascript
function readJniString(ptrValue) {
return ptrValue.isNull() ? "" : ptrValue.readCString();
}
优先使用 MCP 模板,而不是复制临时脚本。先检查可用模板:

const reg = Module.findExportByName("libart.so", "_ZN3art3JNI15RegisterNativesEP7_JNIEnvP7_jclassPK15JNINativeMethodi")
|| Module.findExportByName("libart.so", "RegisterNatives");
```text
android_frida_template_library
android_frida_render_template(template_id="native_module_load_hook", substitutions_json='{"library_name":"libguard.so"}')
android_frida_render_template(template_id="native_register_natives")
```

Interceptor.attach(reg, {
onEnter(args) {
const env = args[0];
const clazz = args[1];
const methods = args[2];
const count = args[3].toInt32();
console.log("[jni] RegisterNatives count=" + count + " methods=" + methods);
for (let i = 0; i < count; i++) {
const item = methods.add(i * Process.pointerSize * 3);
const name = readJniString(item.readPointer());
const sig = readJniString(item.add(Process.pointerSize).readPointer());
const fn = item.add(Process.pointerSize * 2).readPointer();
const mod = Process.findModuleByAddress(fn);
console.log("[jni] " + name + sig + " -> " + fn + " " + (mod ? mod.name : "unknown"));
}
}
});
`native_module_load_hook` 先检查目标 SO 是否已加载;未加载时仅观察 `android_dlopen_ext` / `dlopen`,在加载返回后记录路径、模块基址和大小。它不会 hook `.init_array`、构造函数或修改目标行为。

`native_register_natives` 对每次注册最多解析 64 项,输出 declaring Java class、方法名、JNI 签名、native 运行时地址、模块路径、模块基址、架构和 RVA;每一项的字符串/指针读取失败会单独标为 unresolved,字符串读取上限为 256 bytes,不会中止整次观察。

```text
# 对已运行的受控 app:将两个已渲染模板合并后交给 android_frida_run_script,
# 但 attach 只能观察 attach 之后的新注册。
# 要捕获 JNI_OnLoad 的启动期注册:先 android_force_stop,再使用
# android_frida_run_script(target=<package>, mode="spawn");该模式会先加载脚本、
# 再 resume 进程。仅在受控环境显式选择 spawn,避免静默改变 app 生命周期。
# crypto/unpack 场景:android_crypto_unpack_recipe 已包含 native_dlopen、
# native_memory_map 与 native_register_natives,适合先取得基础证据。
```

成功标志:输出 `nativeName(signature) -> address module`,地址可直接丢给 Ghidra/x64dbg 风格的函数定位。
成功标志不是单一 `dlopen` 句柄,而是可审计的映射(Java class 必须包含在身份中,避免不同 class 的同名方法混淆):

Comment thread
coderabbitai[bot] marked this conversation as resolved.
## 4. JNI_OnLoad 调用链
```text
Java class + method name + JNI signature
-> module path + runtime base
-> native runtime VA + derived RVA
```

```powershell
# Ghidra headless 后搜索 JNI_OnLoad、RegisterNatives xref
python scripts/misc/ai_tool.py run ghidra_headless_analyze -- samples/app.apk --out exports/android/ghidra
## 4. Ghidra 静态关联与 ASLR/PIE 归一化

对动态观察到的实际 `.so` 做 Ghidra 分析,而不是只分析 APK 容器:

```text
1. ghidra_headless_analyze:导入观察到的 SO,生成 summary。
2. ghidra_summary_functions:查 JNI_OnLoad、RegisterNatives、Java_ 或观察到的方法名。
3. ghidra_summary_strings:查 JNI 签名、方法名、库标识。
4. ghidra_summary_function_detail:读取候选函数的 signature、callers/callees、imports、strings、decompile。
5. ghidra_summary_call_focus:以 JNI/native/crypto 等关键词排序后续函数。
```

Ghidra 中按这个顺序命名:
运行时地址受 PIE/ASLR 影响,不能直接当作 Ghidra 静态地址。关联前先确认 runtime VA 位于记录模块的映射范围:

```text
module base <= runtime native VA < module base + module size
RVA = runtime native VA - runtime module base
Ghidra candidate = Ghidra image base + RVA
```

RVA 只可用于同一二进制:记录并核对 SO 的完整路径、架构、SHA256 或 build ID,再把该文件导入 Ghidra。模块路径相同不代表内容相同;hash/build ID、架构或地址范围不一致时,保留 unresolved,不要进行地址关联。

Ghidra 中按这个顺序建立候选命名:

```text
JNI_OnLoad
-> register_native_methods
-> native_sign
-> native_encrypt_packet
-> native_check_license
-> candidate_register_native_methods
-> candidate_native_sign
-> candidate_native_encrypt_packet
```

对每个 native 函数记录:

```text
Java method:
JNI signature:
SO:
VA/RVA:
Inputs from Java:
Return to Java:
Next hop:
Java class / method name / JNI signature:
SO path / SHA256 or build ID / architecture:
Runtime module base / module size / runtime VA / derived RVA:
Ghidra function entry / current name / signature:
Callers, callees, imports, strings, decompile evidence:
Confidence / unresolved assumptions:
```

地址、模块或函数不能匹配时保留 unresolved 状态;不要把运行时 VA 与静态 Ghidra 地址直接等同,也不要把候选名称写成已确认符号。

## 5. 参数/返回值打点

```javascript
Expand Down Expand Up @@ -35078,7 +35094,7 @@ Java.perform(function () {
});
```

## 6. 路径分叉
## 6. 分析流程与路径分叉

| 发现 | 下一跳 |
|---|---|
Expand All @@ -35093,7 +35109,7 @@ Java.perform(function () {
| 项 | 记录内容 |
|---|---|
| Java 入口 | 类名、方法名、JNI 签名 |
| Native 映射 | SO、VA/RVA、RegisterNatives 输出 |
| Native 映射 | Java class、方法名、JNI 签名、SO path、架构、SHA256/build ID、module base/size、VA/RVA、RegisterNatives 输出 |
| 参数 | Java 入参长度、hex 摘要、返回值类型 |
| Ghidra | 函数名、调用者、被调用者、关键字符串 |
| 下一跳 | crypto、network、license、patch 或 packer |
Expand All @@ -35104,7 +35120,7 @@ Java.perform(function () {
|---|---|---|
| JNI/crypto 模板 | `android_crypto_unpack_recipe` | 生成 RegisterNatives 和 crypto hook |
| SO 静态分析 | `ghidra_headless_analyze` | 函数边界、xref、伪代码 |
| 动态执行 | `android_frida_run_script` | spawn 早期捕获注册表 |
| 动态执行 | `android_frida_run_script` | attach 观察后续注册;受控环境显式 `spawn` 捕获启动期注册 |
| 知识路由 | `kb_router` | 按 JNI/native/crypto 信号查文档 |


Expand Down Expand Up @@ -37752,6 +37768,24 @@ while (item) {
}
```

## 证据账本与置信度

在写出 `struct` 前,为每个字段维护一条证据账本。Ghidra 的反编译与 xref 是静态证据;受控运行时的 Frida/x64dbg/ReClass 观察才是动态佐证。不要因单次内存快照就把语义命名为 confirmed。

| Offset | Width / Read-Write | Candidate type / meaning | Function / Address | Static evidence | Dynamic evidence | Confidence |
|---:|---|---|---|---|---|---|
| `+0x190` | `8 / read` | `USceneComponent* RootComponent` | `FUN_... @ RVA ...` | `mov rax, [rcx+190h]`; 后续解引用 | 指针落在已知 heap object | Inferred |
| `+0x268` | `4 / write` | `int health` | `FUN_... @ RVA ...` | `mov [rcx+268h], eax`; 调用点与伤害流程相连 | 受控测试时值递减 | Confirmed |
Comment thread
coderabbitai[bot] marked this conversation as resolved.
| `+0x378` | `4 / read` | `float moveSpeed` | `FUN_... @ RVA ...` | `movss`; 与移动分支关联 | 尚未观察 | Inferred |

证据级别:

- **Observed**:原始反汇编、Ghidra 伪代码、xref 或运行时日志直接显示的事实。
- **Inferred**:由偏移、访问宽度、调用上下文或值域推导出的类型/语义;必须保留推导依据。
- **Confirmed**:至少有相互独立的静态证据,并在安全、授权的测试中获得动态一致性验证。

记录时始终同时保留样本 SHA256、模块 image base、RVA/VA/文件偏移换算、函数地址和工具版本,避免把 ASLR 下的运行时地址误写成静态偏移。

## Frida 辅助验证

```javascript
Expand Down Expand Up @@ -38338,6 +38372,18 @@ ReClass hex dump:
→ 类型: float[16]
```

## 运行时验证前的证据账本

在 ReClass 中创建字段前,先使用[内存结构体逆向重建](01-struct-reconstruction.md)的字段证据账本。每条候选字段至少保留:偏移、宽度、读/写方向、候选类型/语义、Ghidra 函数/RVA、静态证据、动态观察和置信度。

```text
Observed — Ghidra/xref/断点/内存快照直接显示的事实
Inferred — 由访问模式或值域推导的字段含义
Confirmed — 独立静态证据与受控运行时变化一致
```

ReClass 负责可视化和动态佐证,不会自动证明字段语义。把单次值匹配保留为 Inferred;只有在可重复的状态变化、访问代码和对象边界共同吻合时才升为 Confirmed。

## 导出为 C++

```cpp
Expand Down
2 changes: 1 addition & 1 deletion docs/llms.txt
Original file line number Diff line number Diff line change
Expand Up @@ -383,5 +383,5 @@
>

---
Generated: 2026-07-04
Generated: 2026-07-31
Total articles: 178
36 changes: 36 additions & 0 deletions docs/upstreams/reverse-skills.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# P4nda0s/reverse-skills provenance and local mapping

## Review record

- Upstream: <https://github.com/P4nda0s/reverse-skills>
- Reviewed revision: `a2baa31c58a3567977188414da68c8c842057152`
- Review date: 2026-07-31
- Relevant upstream paths reviewed:
- `skills/rev-frida/SKILL.md`
- `skills/rev-symbol/SKILL.md`
- `skills/rev-struct/SKILL.md`

The upstream README states MIT, but the reviewed repository tree does not contain a committed `LICENSE` file. Under this repository's public migration boundary (`PUBLICATION.md`), the upstream is therefore treated as **reference-only**. This project does not vendor its prompt text, source snippets, templates, binaries, submodules, or package dependencies. The implementation below is independently written and uses existing ReverseLab interfaces.

## Capability mapping

| Upstream workflow idea | Open-ReverseLab implementation | Primary execution/evidence surface |
|---|---|---|
| `rev-frida` loader-aware instrumentation | Android native Frida templates and JNI tracing guidance | `android_frida_template_library`, `android_frida_render_template`, `android_frida_run_script`, `android_crypto_unpack_recipe` |
| `rev-symbol` function-name inference | Ghidra summary evidence plus conservative Function Map suggestions | `ghidra_headless_analyze`, `ghidra_summary_functions`, `ghidra_summary_function_detail`, `ghidra_summary_call_focus`, generated analysis notes |
| `rev-struct` layout inference | Existing PE struct/ReClass techniques plus a symbol/field evidence ledger | `kb/pe-reverse/techniques/03-static-analysis/01-struct-reconstruction.md`, `04-reclass-reconstruction.md` |

## Tool baseline

For the supported Ghidra-first workflow, install or provide:

- Ghidra and the compatible Java runtime; `analyzeHeadless` is the primary automated path.
- Android SDK platform-tools (`adb`) for Android work.
- Host Frida tooling plus an Android `frida-server` version compatible with the host client.
- JADX and Apktool for Android static preparation.

IDA Pro/Hex-Rays may be used as an analyst-provided optional second opinion. It is not required by this integration, is not added to `.mcp.json`, and is not a CI dependency. Ghidra summary evidence remains the portable project contract.

## Update policy

Before using a newer upstream revision as inspiration, review its tree and license metadata again, update the pinned revision and date in this file, and check that no unconfirmed third-party source or binary crosses the public migration boundary.
Loading