QM4RS/FridaBox
GitHub: QM4RS/FridaBox
FridaBox 是一个无需 root 和 APK 重打包的 Android 动态插桩研究工作空间,通过虚拟进程在应用启动早期加载 Frida Gadget 实现动态分析。
Stars: 7 | Forks: 2
# FridaBox
### 设备端 Android 插桩,运行于私有虚拟工作空间内
[](docs/TEST_RESULTS.md)
[](docs/BUILDING.md)
[](THIRD_PARTY_NOTICES.md)
[](CHANGELOG.md)
[](LICENSE)
[](docs/device-validation.log)
[](https://github.com/QM4RS/FridaBox/actions/workflows/android.yml)
**导入原始 APK。选择 per-app 模式。直接在手机上运行受信任的 Frida JavaScript,从电脑连接,或者纯净启动。**
[功能](#what-fridabox-does) · [工作原理](#how-it-works) ·
[快速开始](#quick-start) · [研究](#engineering-and-research) ·
[限制](#scope-and-limitations) · [致谢](#acknowledgements)
FridaBox 是一个为授权的动态分析构建的 Android 移动安全研究工作空间。它在应用私有的虚拟进程中运行原始的、未修改的 APK,并且可以在 guest `Application` 创建之前加载 Frida Gadget。
它**不需要** root、Magisk、Zygisk、frida-server、修改过的系统镜像、真实的 PackageManager 安装、APK 修补、重新打包或重新签名。宿主应用程序 ID 和 Android namespace 均为
`com.qm4rs.fridabox`。
## 为什么开发 FridaBox
传统的 Gadget 工作流会修补目标 APK,添加一个 native 库,重新构建它,并对修改后的包进行签名。这会改变测试中的工件,并可能使签名、完整性假设、更新路径和实验结果失效。frida-server 工作流避免了重新打包,但通常需要 root 过的或特殊准备的设备。
FridaBox 探索了一个不同的边界:
- 逐字节保留导入的 APK;
- 仅将其安装到私有的虚拟包管理器中;
- 创建 guest 的真实 Android `LoadedApk` 和 `ClassLoader`;
- 在分配的虚拟进程内加载固定的 Gadget;
- 当请求交互式附加时,在 guest `Application.onCreate()` 之前暂停;
- 将插桩策略保持为每个 guest 独立,而不是全局生效。
结果是一个用于早期 Java/native hook 的可重复的实验室,同时原始软件包仍然不存在于 Android 真实的 PackageManager 中。
## FridaBox 的功能
| 功能 | 提供的内容 |
| --- | --- |
| 原始 APK 导入 | 基于 SAF 导入到私有存储,并在虚拟安装前后进行 SHA-256 验证。 |
| 三种启动模式 | **On-device**、**Computer** 和 **Clean**,每个 guest 独立记忆。 |
| 尽可能早的 Gadget 加载 | Gadget 在 guest runtime/IO 设置之后,但在 `makeApplication()` 和 guest `Application.onCreate()` 之前加载。 |
| 无需电脑的插桩 | 可以选择一次受信任的 JavaScript agent,并在每次 On-device 启动时自动加载。 |
| 熟悉的桌面工作流 | Computer 模式支持正常的 `frida -U gadget -l agent.js` 流程,并在附加之前暂停启动。 |
| 确定性的纯净启动 | 虚拟进程在不使用 Gadget 启动之前被回收,防止先前进程的模式泄漏。 |
| 正确的 Java 上下文 | 在用户 hook 执行之前,控制器会选择 guest `PathClassLoader`,而不是宿主 loader。 |
| Runtime 可观测性 | 公开 package、process、虚拟用户、进程槽位、源 APK、ClassLoader、模式、状态和最新错误。 |
| Endpoint 发现 | 控制器探测有限的转发范围,并为 guest 识别正确的 Gadget endpoint。 |
| Native 可见性 | 可以在安装用户 agent 之前枚举已加载的 native 模块。 |
| ARM64 验证 | 在导入之前检查 native guest;明确拒绝不兼容的 native APK 和 split 容器。 |
| 面向产品级的宿主 | 独立的 FridaBox 身份、响应式 Material UI、R8/资源收缩以及明确的发布签名。 |
## 启动模式
### On-device
通过 Android 的文档选择器选择一个受信任的 `.js` 文件。FridaBox 会存储一个私有的逐字节副本,记录其哈希值,创建 per-guest 的 Script 交互配置,并在以后的启动中加载它——无需 ADB、USB 数据线、端口转发或电脑端的 Frida 客户端。
### 计算机
```
frida -U gadget -l path/to/agent.js
```
为了实现确定性的多 guest 发现和自动的 ClassLoader 选择:
```
python tools/attach_guest.py --list
python tools/attach_guest.py --package com.example.app --script scripts/example.js
```
### 清理
FridaBox 会停止现有的虚拟进程,为下一个进程禁用插桩,并正常启动 guest。已保存的 on-device agent 仍可供以后使用。
## 工作原理
```
Original APK selected with SAF
│
▼
Private copy + SHA-256 + ABI inspection
│
▼
Virtual package installation (not Android PackageManager)
│
▼
Virtual process allocation and guest runtime setup
│
├── Clean ───────────────► guest makeApplication()
│
├── On-device ───────────► Gadget + private agent.js
│ │
│ ▼
│ guest makeApplication()
│
└── Computer ────────────► Gadget listens + startup waits
│
controller attaches
│
▼
guest makeApplication()
```
插桩 hook 位于 `BActivityThread.handleBindApplication()` 中。
此时,虚拟身份、文件系统重定向、guest 上下文和 guest ClassLoader 已经存在,但 guest `Application` 尚未创建。
此顺序由构建验证任务强制执行。
有关组件边界,请参阅 [ARCHITECTURE.md](ARCHITECTURE.md),有关塑造了该实现的失败、约束和修复,请参阅 [docs/ENGINEERING_JOURNEY.md](docs/ENGINEERING_JOURNEY.md)。
## 演示结果
该仓库包含一个生成的示例 guest 和一个小 hook:
```
Java.perform(function () {
const Target = Java.use('com.qm4rs.fridabox.sample.Target');
Target.add.implementation = function (a, b) {
return 1337;
};
});
```
完整的 Android 16 设备验证证明:
- 示例 package 不存在于真实的 Android PackageManager 中;
- 启动在 `SampleApplication.onCreate()` 之前暂停;
- 发现了正确的 Gadget endpoint 和 guest ClassLoader;
- native 模块枚举返回了数百个模块;
- `Target.add(2, 3)` 的结果从 `5` 变为了 `1337`;
- 回收进入 Clean 模式移除了监听器并将结果恢复为 `5`。
商业工作空间流程也在真实的 ARM64 Unity guest 上通过 On-device、Computer 和 Clean 模式进行了验证。证据和确切命令位于
[docs/TEST_RESULTS.md](docs/TEST_RESULTS.md) 和
[docs/device-validation.log](docs/device-validation.log)。
## 快速开始
### 要求
- ARM64 Android 12–16 设备;
- JDK 21;
- Android SDK 35 和 NDK 29.0.14206865;
- Python 3.10+;
- Node.js 20+ 和 npm(在重新构建内置的 Frida 17 agent 时)。
### 构建
```
python tools/fetch_frida_gadget.py
npm ci
python tools/build_frida_agents.py
./gradlew :app:assembleDebug :Bcore:testDebugUnitTest :app:testDebugUnitTest :app:check
```
包含空格的 Windows 路径需要 [docs/BUILDING.md](docs/BUILDING.md) 中记录的 scoped native-build 变通方法。输出写入在
`app/build/outputs/apk/debug/` 下。
### 使用
1. 安装并打开 FridaBox。
2. 点击 **Import APK** 并选择一个 ARM64 基础 APK。
3. 在该 guest 的卡片上选择 **On-device**、**Computer** 或 **Clean**。
4. 为 On-device 模式选择一个 agent,或者在 Computer 模式下正常附加。
5. 在 **Runtime** 标签页中检查实时状态。
完整的工作流请参阅 [docs/USAGE.md](docs/USAGE.md) 和
[docs/FRIDA_CONNECTION.md](docs/FRIDA_CONNECTION.md)。
## 工程与研究
FridaBox 是 runtime 调查的结果,而不是对单个 `System.loadLibrary()` 调用的简单封装。该项目必须解决:
- 在 guest `Application` 创建之前对 Gadget 进行排序,而无需在宿主进程中加载它;
- 为 Java hook 保留 guest 真正的 `LoadedApk` ClassLoader;
- 在发生冲突的虚拟进程中发现正确的 loopback Gadget;
- 为 Frida 17 agent 显式捆绑 `frida-java-bridge`;
- 使自主的 Script 交互能够处理私有、只读的工件;
- 在 Android 上维护可靠的跨进程 runtime 状态;
- 回收虚拟进程,以确保插桩模式永远不会泄漏;
- 满足 Android 16 的可执行文件限制;
- 保持导入的 APK 逐字节完全一致,且位于真实的 PackageManager 之外;
- 在 Windows 路径和 NDK 约束下产生可重现的 debug/release 构建;
- 将继承的应用程序外壳替换为独立的 FridaBox 产品,同时保留成熟的 runtime 引擎边界。
每个问题、失败的假设、狭隘的修复和验证方法都记录在[工程旅程](docs/ENGINEERING_JOURNEY.md)中。
## 仓库结构图
```
app/ FridaBox Android product, UI, import and per-app policy
Bcore/ Virtual Android runtime and instrumentation integration
black-reflection/ Hidden-framework reflection layer used by the runtime
compiler/ Compile-time reflection helpers
sample-guest/ Deterministic hook demonstration target
scripts/ Frida probe, bootstrap, sample and native agents
tools/ Gadget fetch, agent build, forwarding and attach tools
docs/ Build, usage, limitations and device evidence
```
## 范围与限制
FridaBox 目前针对单文件 ARM64 APK。Split APK 集合、特权或系统应用程序、完整的 Google Play Services、Play Integrity、硬件支持的认证以及完美的抗插桩阻力不在当前范围内。供应商行为和隐藏的 Android API 仍然可能影响兼容性。
FridaBox 刻意不声称具有隐蔽性。Frida 的 mappings、socket 和 thread;虚拟存根进程;共享的宿主 UID;Binder 合成;以及 ClassLoader 拓扑可能都是可观察的。请阅读
[docs/LIMITATIONS.md](docs/LIMITATIONS.md) 和
[docs/DETECTION_SURFACES.md](docs/DETECTION_SURFACES.md)。
## 研究路线图
下一阶段的研究重点将是使虚拟环境在内部更加一致,并减少可避免的插桩指纹:
- 减少不必要的 Frida 可见工件和默认标识符;
- 研究对 `/proc` 的安全中介,包括进程 mappings 的连贯视图;
- 改进文件系统、package、process、Binder、身份、ClassLoader 和服务行为,以便 guest 观察到更忠实的 sandbox;
- 用人工主导的产品设计过程、原创的 FridaBox 图标系统和更强大的视觉识别来取代可行的 Codex 辅助 UI 基准;
- 扩展 Android/供应商测试矩阵,并为解决的每个检测表面添加回归探针。
这项工作在 [ROADMAP.md](ROADMAP.md) 中进行跟踪。FridaBox 将继续记录仍然可观察到的内容,并且不会将尽力而为的强化描述为不可检测性。
### 贡献一周的工程,而不是金钱
使用您自己的帐户并自己审查每个生成的更改。切勿共享帐户、API key、session token、私有 APK 或专有 agent。一个经过良好测试且带有可重现设备证据的小型 PR,比一大堆未经审查的代码转储更有价值。
## 项目状态
FridaBox 4.0.0 是一个经过设备验证的研究版本。完整的示例 hook 和三模式 guest 流程已在运行 ARM64 Android 16/API 36 的三星 SM-S928B 上通过。欢迎对其他设备和 ROM 的兼容性报告,前提是它们包含可重现的日志和授权的测试目标。
## 联系方式
- LinkedIn:[Mahdi Karzari](https://www.linkedin.com/in/mahdikarzari)
- Telegram:[@QM4RS](https://t.me/QM4RS)
对于安全敏感的报告,请在可用时从 GitHub 的私有漏洞报告开始。如果该渠道不可用,请使用上述联系方式之一,并避免在第一条消息中发送机密或敏感的证据。
## 致谢
FridaBox 建立在 Android 插桩和虚拟化社区多年工作的基础之上。
- **[Frida](https://github.com/frida/frida)** 提供了动态插桩引擎、Frida Gadget、GumJS、Java bridge 以及使这项研究成为可能的工具模型。FridaBox 固定并验证了 Gadget 17.16.0,并使用了官方的 Frida 17 Java-agent 工具链。
- **[NewBlackbox](https://github.com/ALEX5402/NewBlackbox)** 和更广泛的 **BlackBox** 项目谱系提供了虚拟 package/process/Binder/IO runtime 基础。FridaBox 从 NewBlackbox 的提交 `89b59836c66f173756a4ae258cf379a957649820` 开始,然后添加了其插桩生命周期、控制器协议、per-app 模式、完整性 pipeline、研究工具、验证套件和独立的产品表面。
- Android 开源项目及其贡献者提供了本项目研究的平台接口和 runtime 行为。
感谢每一位上游维护者和研究员,是他们发布了使 FridaBox 成为可能的工作。所有权和许可细节保留在
[THIRD_PARTY_NOTICES.md](THIRD_PARTY_NOTICES.md) 中。
## 许可证
FridaBox 根据 [Apache License 2.0](LICENSE) 分发。捆绑的 Frida 组件保留其各自的许可条款;请参阅
[THIRD_PARTY_NOTICES.md](THIRD_PARTY_NOTICES.md)。标签:JS文件枚举, MITM代理, 后台面板检测, 域名枚举, 逆向工具