# App Package Forensics Workflow

本目录能力用于从 APK/XAPK/APKS 的静态证据快速判断 App 的实现方式、包结构、SDK、权限、接口线索和版本变化。它服务于机会深挖，不替代广告、评论、商店、真机 paywall 和动态抓包证据。

## 目标

- 静态 intake：记录包名、版本、hash、大小、inner APK 数。
- 实现线索：识别 Unity / Cocos / Flutter / Unreal / native 等框架信号。
- 业务线索：提取权限、组件、deeplink、SDK markers、endpoint candidates、interesting files。
- 版本 diff：比较 earliest / latest / 指定版本的权限、SDK、endpoint、native libs 和资源路径变化。
- 深挖联动：把输出放到 `research/app-package-forensics/<target>/<version>/`，并通过 `config/package_forensics.json` 关联机会深挖目录。

## 边界

- 不提交 APK/XAPK/APKS/IPA、解包产物、原始 HAR、截图、token、cookie、设备 ID 或付费 vendor export。
- 不默认运行 App、不安装到设备、不启动 Frida、不开 MITM。
- 静态 endpoint candidates 只是字符串证据；必须用动态抓包或 replay 验证后才能写成接口结论。
- iOS 先只保留 `platforms=["ios"]` 和目录契约；IPA/Mach-O/Swift/ObjC 分析后续单独实现。

## 目录

| Path | Rule |
|---|---|
| `config/package_forensics.json` | 目标 backlog、owner、focus、deep-dive 关联和清理规则 |
| `scripts/package_forensics/` | 薄 CLI 入口 |
| `src/app_factory/package_forensics/` | 长期模块：模型、Android 静态分析、报告、diff、配置 |
| `research/app-package-forensics/` | 可提交的分析报告、evidence、version diff |
| `data/raw/app_packages/` | 本地原始包，ignored |
| `data/extracted/app_packages/` | 本地解包、jadx、apktool、AssetRipper、Ghidra 输出，ignored |
| `tools/vendor/` | 本地可重建工具链，ignored |

## Static MVP

单包 dry-run：

```bash
PYTHONPATH=src python3 scripts/package_forensics/analyze_package.py \
  data/raw/app_packages/cleaner-guru/latest.apk \
  --app-id cleaner-guru-cleaning-app \
  --opportunity-id 2026-06-09-cleaner-guru-cleaning-app \
  --dry-run
```

写报告：

```bash
PYTHONPATH=src python3 scripts/package_forensics/analyze_package.py \
  data/raw/app_packages/cleaner-guru/latest.apk \
  --app-id cleaner-guru-cleaning-app \
  --opportunity-id 2026-06-09-cleaner-guru-cleaning-app
```

默认输出：

```text
research/app-package-forensics/<app-id>/<version>/analysis.json
research/app-package-forensics/<app-id>/<version>/brief.md
research/app-package-forensics/<app-id>/<version>/evidence.csv
research/app-package-forensics/<app-id>/<version>/report.html
```

单包或批量报告生成后，刷新统一阅读入口：

```bash
.venv/bin/python scripts/radar/build_report_portal.py
```

入口会把单包输出归到 `APK 静态分析 / 先看实现线索和静态边界`，把 `research/app-package-forensics/runs/<run-id>/` 下的批量输出归到 `APK 批量 intake / 先看覆盖和优先级`。公开视频目录默认只复制 HTML、Markdown、CSV 和图片；`analysis.json` 会保留在结构化 manifest 里，但不作为默认公开视频复制资产。

## Optional Deep Tool Lane

这条 lane 用于在已经解包后的目录上运行更重的逆向工具。原始输出可能很大，也可能包含完整业务 bundle / Dart object dump，因此默认写入 ignored 的 `data/extracted/package_forensics/...`，报告侧只沉淀摘要和人工结论。

### Activity Triage

Activity 深挖好做，但它解决的是“模块边界和入口图谱”，不是完整代码还原。对 Activity-heavy 的 Java/Kotlin 应用，Manifest Activity 命名通常能快速分出：

- first-party 业务页面：home、template、camera、crop、generate、result、settings、privacy、paywall。
- SDK 页面：广告、支付、Facebook/Google 登录、WebView、permission proxy。
- 学习优先级：先追 first-party 的 launch/home/onboarding/paywall/media/result，再把广告/支付 SDK 当作外部模块。

运行 Activity triage：

```bash
PYTHONPATH=src python3 scripts/package_forensics/triage_activities.py \
  --analysis-json research/app-package-forensics/refoto-ai-photo-studio/apk-pure-latest/analysis.json \
  --out-dir research/app-package-forensics/refoto-ai-photo-studio/apk-pure-latest
```

输出：

```text
activity-triage.json
activity-triage.html
```

判断规则：

- Activity-heavy native 包：优先 jadx / apktool / smali 追 Activity `onCreate`、Intent extra、layout/resource id、跳转调用、billing/ad 调用点。
- React Native / Hermes 包：Activity 多数只是 `ReactActivity` 容器，核心逻辑优先看 Hermes bundle。
- Flutter 包：Activity 多数只是 Flutter shell / plugin bridge，核心逻辑优先看 `flutter_assets`、`libapp.so`、blutter 输出和动态证据。
- Ghidra 不适合作 Activity 主路径；Ghidra 用于 native `.so`、JNI、Flutter AOT、Unity IL2CPP 等 compiled code。

### React Native / Hermes

Hermes 是 React Native 常用的 JavaScript 引擎。启用 Hermes 后，Android 包里的 `assets/index.android.bundle` 不再是明文 JS，而是 Hermes bytecode。它比 Flutter AOT 更容易做产品级还原：字符串表、模块边界、路由、接口、埋点和部分控制流通常能被反汇编/反编译工具恢复；但变量名、原始 TypeScript 文件结构、完整业务语义仍可能丢失或混淆。

推荐工具：

- `hermes-decomp`：Rust decompiler，面向 HBC v40-v99，优先用于 Hermes v96 这类新包。
- `hermes-dec`：提供 `hbc-file-parser`、`hbc-disassembler`、`hbc-decompiler`，适合作 parser/disasm/pseudo-code 兜底。
- `hbctool`：适合老版本 HBC；新版 Hermes 兼容性有限，只作为 fallback。

本地安装建议：

```bash
# Python 兜底工具
uv tool install hermes-dec
# 或：
pipx install hermes-dec

# Rust decompiler，建议放 tools/vendor 但不提交源码/构建产物
mkdir -p tools/vendor/hermes
git clone https://github.com/SymbioticSec/hermes-decomp tools/vendor/hermes/hermes-decomp
(cd tools/vendor/hermes/hermes-decomp && cargo build --release)
```

运行 Hermes lane：

```bash
PYTHONPATH=src python3 scripts/package_forensics/run_deep_tools.py \
  --input-root data/extracted/package_forensics/runs/20260610-002429/cleaner-guru-cleaning-app/manifest-only \
  --out-dir data/extracted/package_forensics/runs/20260610-002429/cleaner-guru-cleaning-app/deep-tools \
  --tool hermes
```

不确定工具是否可用时先 dry-run：

```bash
PYTHONPATH=src python3 scripts/package_forensics/run_deep_tools.py \
  --input-root data/extracted/package_forensics/runs/20260610-002429/cleaner-guru-cleaning-app/manifest-only \
  --out-dir data/extracted/package_forensics/runs/20260610-002429/cleaner-guru-cleaning-app/deep-tools \
  --tool hermes \
  --dry-run
```

### Flutter AOT

Flutter release 包的核心 Dart 逻辑通常在 `lib/<abi>/libapp.so` 中，以 Dart AOT snapshot 形式存在。它不是 Java/Kotlin/Dart 源码，普通 JADX 只能看到 Android 壳和插件桥。静态逆向优先尝试 `blutter`：

- 输入：解包后的 `lib/arm64-v8a` 目录，要求同时有 `libapp.so` 和 `libflutter.so`。
- 输出：Dart object pool、assembly with symbols、Frida 模板等。
- 限制：主要支持 Android arm64；依赖 Dart/Flutter 版本；首次运行可能拉 Dart runtime 并编译，耗时较长。runner 会列出所有 Flutter AOT ABI，但只把 `arm64-v8a` 自动送入 blutter；`armeabi-v7a` 会明确标记为 skipped，并提示重新采集 arm64 split。
- `unflutter` 可作为第二静态工具试点，适合输出 functions/classes/call edges 等结构化索引；接入时仍写 ignored 输出目录。
- `reFlutter` 是动态/重打包/代理抓包 lane，不默认接入静态 runner；需要改包、签名、安装设备，必须单独确认。

本地安装状态 / 建议：

```bash
# 当前本机已安装到 ignored vendor：
# tools/vendor/blutter

# 重新安装示例
mkdir -p tools/vendor
git clone https://github.com/worawit/blutter tools/vendor/blutter
# macOS 依赖示例：brew install cmake ninja pkg-config icu4c capstone
# Python 依赖示例：.venv/bin/python -m pip install pyelftools requests
```

运行 Flutter AOT lane：

```bash
PYTHONPATH=src python3 scripts/package_forensics/run_deep_tools.py \
  --input-root data/extracted/package_forensics/runs/20260610-002429/ai-photo-lab-generate-and-edit/apk_contents \
  --out-dir data/extracted/package_forensics/runs/20260610-002429/ai-photo-lab-generate-and-edit/deep-tools \
  --tool flutter-aot
```

如果 `blutter.py` 不在默认位置，可显式指定：

```bash
PACKAGE_FORENSICS_BLUTTER_PY=/abs/path/blutter.py \
PYTHONPATH=src python3 scripts/package_forensics/run_deep_tools.py \
  --input-root <extracted-root> \
  --out-dir <ignored-output-dir> \
  --tool flutter-aot
```

### Native / Ghidra

Ghidra 是 native compiled code 的重型补证工具，适合：

- Flutter AOT 的 `libapp.so`：在 blutter 输出之外补函数、字符串、交叉引用和伪 C。
- Unity IL2CPP 的 `libil2cpp.so`：配合 metadata 和 IL2CPP 专用工具看 native call edge。
- 原生 JNI/图像处理/压缩/加密/模型推理 `.so`：学习核心算法或本地处理链。

不适合：

- 直接还原 Java/Kotlin Activity 页面逻辑；这类优先 jadx/smali。
- 完整恢复 Flutter widget tree 或 Dart 源码；这类优先 blutter + runtime hook。
- 大批量无筛选跑所有 SDK `.so`；会慢且噪声大。

本地安装状态 / 建议：

```bash
# 当前本机已安装：
# tools/vendor/ghidra -> tools/vendor/ghidra_12.1.2_PUBLIC
# tools/vendor/ghidra_12.1.2_PUBLIC_20260605.zip
# JDK 21: /opt/homebrew/opt/openjdk@21/libexec/openjdk.jdk/Contents/Home
#
# runner 会自动发现 tools/vendor/ghidra/support/analyzeHeadless，
# 并在未设置 JAVA_HOME 时自动注入 Homebrew JDK 21。

# 重新安装示例
mkdir -p tools/vendor
# 设置 headless 路径，避免提交工具本体
export PACKAGE_FORENSICS_GHIDRA_HEADLESS=/abs/path/ghidra/support/analyzeHeadless
```

运行 Ghidra native lane：

```bash
PYTHONPATH=src python3 scripts/package_forensics/run_deep_tools.py \
  --input-root data/extracted/package_forensics/runs/20260610-002429/ai-photo-lab-generate-and-edit/apk_contents \
  --out-dir data/extracted/package_forensics/runs/20260610-002429/ai-photo-lab-generate-and-edit/deep-tools \
  --tool native-ghidra \
  --max-native-libs 2 \
  --timeout-seconds 900
```

输出在 ignored `native-ghidra/<lib>/` 下：

```text
ghidra-native-summary.json
analyzeHeadless.log
script.log
ghidra-project/
```

`ghidra-native-summary.json` 由 `scripts/package_forensics/ghidra/PackageNativeSummary.java` 导出，包含函数名、入口地址、签名和有限伪代码 preview。大项目初次分析会慢；建议先 `--dry-run`，再只跑 `libapp.so`、`libil2cpp.so` 或明显 first-party/native media 库。

两个版本对比：

```bash
PYTHONPATH=src python3 scripts/package_forensics/diff_versions.py \
  --old research/app-package-forensics/cleaner-guru-cleaning-app/1.0.0/analysis.json \
  --new research/app-package-forensics/cleaner-guru-cleaning-app/1.1.0/analysis.json \
  --out-dir research/app-package-forensics/cleaner-guru-cleaning-app/diffs/1.0.0-to-1.1.0
```

## Target Backlog

首版目标来自 `research/opportunity-deep-dives/`：

| Target | 当前用途 | Static focus |
|---|---|---|
| Cleaner Guru: Cleaning App | Promote with guardrails | onboarding、paywall、subscription SDK、photo/contact permissions、delete safety |
| PDF Reader - PDF Viewer | Watch | file permissions、ad SDK、IAP、default reader intents |
| Opera: AI browser with VPN | Learning only | trust messaging、VPN/browser modules、AI packaging |
| NordVPN | Learning only | trust/pricing reference、VPN native stack |
| AI Art Magic - Photo Generator | Hooks only | photo permissions、template packaging、ad/IAP、face AI risk |
| AI Photo Lab: Generate & Edit | Watch | model feature packaging、ad/IAP、privacy claims |
| Sherlock: AI Face Search | Kill core / safe wedge only | face-data permissions、network endpoints、trust disclosure |
| Refoto : AI Photo Studio | Promote with guardrails | avatar/photo packaging、subscription SDK、template catalog |

## Evidence Rules

- `direct`：来自 Manifest、ZIP inventory、文件名、静态字符串的事实。
- `inference`：由 SDK marker、engine marker、endpoint candidate 推断的实现方向。
- `verified`：静态证据已在包内出现。
- `inferred`：需要动态或人工验证。
- 报告必须保留 warnings，尤其是 binary Manifest 未解码、split 不完整、inner APK 缺失。

## Dynamic Later Lane

动态分析进入下一阶段前先做计划和 dry-run：

- 环境检查：ADB device、root、Appium/Waydroid/模拟器、Frida server、mitmproxy、代理恢复。
- Start/stop 脚本必须成对：设置代理、iptables、Frida 后必须能恢复。
- 原始 HAR/flows/logcat/screenshots 放 `data/raw/app_packages/<target>/dynamic_runs/`。
- 提交面只保留 endpoint map、redacted evidence、run manifest 和结论。

## Verification

```bash
PYTHONPATH=src pytest tests/package_forensics -q
python3 -m py_compile src/app_factory/package_forensics/*.py scripts/package_forensics/*.py
```
