muhammadrizwan87/frida-bridge
GitHub: muhammadrizwan87/frida-bridge
一个无需 root 和 APK 重打包即可在 Android 容器/虚拟空间中加载 Frida Gadget 的原生 JNI 桥接库。
Stars: 14 | Forks: 7
# Frida Bridge
## 📖 概述
frida-bridge 是一个原生的 JNI 库,只需最少的配置即可将 Frida Gadget 加载到宿主 Android 进程中。它会自动解析磁盘上的真实路径——包括在重新映射文件系统的容器中——等待 Android Runtime 可用,并将 gadget 的配置和脚本文件准确放置在 Frida 预期的位置。
无需 root,无需重打包目标 APK。
只需两步,您就可以让任何容器/虚拟空间支持 Frida 模式。
## 📋 目录
1. [特殊优势](#-1-special-advantages)
2. [Gadget 文件与目录布局](#-2-gadget-files--directory-layout)
3. [延迟配置](#%EF%B8%8F-3-delay-configuration)
4. [使用指南](#-4-usage-guide)
5. [安全视角](#%EF%B8%8F-5-security-perspective)
6. [故障排除](#-6-troubleshooting)
## 🚀 1. 特殊优势
## 📁 2. Gadget 文件与目录布局
所有文件均位于 `/frida/` 下:
| 文件 | 用途 |
|---|---|
| `libfrida-gadget.so` | Frida Gadget 共享库(由您提供) |
| `libfrida-gadget.config.so` | Gadget 配置 JSON —— 由 bridge 自动管理 |
| `libfrida-gadget.script.so` | 编译后的 JS agent(由您提供,用于脚本模式) |
| `frida-bridge.cfg` | Bridge 配置 —— 目前支持 `delay=` |
**自动路径解析**
无论您在配置的 `"path"` 字段中填入什么内容(绝对、相对、真实或逻辑路径),bridge 都会在运行时对其进行修复。它会将脚本文件复制到真实的 gadget 目录中,并将 `"path"` 重写为单纯的文件名 `libfrida-gadget.script.so`。这保证了 gadget 始终能找到脚本,即使文件系统被容器重新映射也是如此。
## ⏱️ 3. 延迟配置
在相同的 `frida/` 目录中创建 `frida-bridge.cfg`:
```
delay=3
```
| 值 | 行为 |
|---|---|
| 缺省 / `0`(默认) | 无额外延迟。一旦 `Application` 准备就绪,Gadget 就会加载。 |
| `1`–`60` | 在 `Application` 准备就绪后,Bridge 会休眠相应的秒数,然后再加载 gadget。 |
当您的脚本需要宿主应用先完成其自身的初始化(例如特定的 `Activity` 或 `Service`),然后再激活 hook 时,此功能非常有用。
## 💡 4. 使用指南
### 📝 前置条件
- Android NDK(用于原生编译)
- Termux app(用于在设备上构建),或桌面工具链
### 🛠️ 构建说明
```
# Clone the repository
git clone https://github.com/muhammadrizwan87/frida-bridge.git
cd frida-bridge
# 设置 NDK path
export NDK_HOME=/path/to/your/ndk
# export NDK_HOME=/data/data/com.termux/files/home/android-sdk/ndk/24.0.8215888
# Build for all architectures
$NDK_HOME/ndk-build NDK_PROJECT_PATH=. NDK_APPLICATION_MK=./jni/Application.mk
# Output will be in libs/
ls libs/
# armeabi-v7a/ arm64-v8a/ x86/ x86_64/
```
### 🚩 构建标志
| 标志 | 效果 |
|---|---|
| (无,默认) | Release 构建 —— 仅输出 `LOGI`/`LOGW`/`LOGE` |
| `-DFRIDA_BRIDGE_DEBUG` | 详细的 `LOGD` 输出:maps 转储、真实目录列表、JNI 等待进度 |
通过在 `jni/Android.mk` 中取消注释相应行来启用。
### 🔀 实施说明
**📌 重要提示:** 本节是对独立的容器 APK 进行补丁操作,而不是针对目标 app。目标 app 的完整性和代码保持 100% 不变。如果您是直接将其集成到自己的容器源代码中,请跳至选项 B。
#### 选项 A:补丁现有的容器 APK (Smali)
确保在容器自定义 Application 子类的类初始化器中加载原生库
```
.method static constructor ()V
.registers 1
const-string v0, "frida-bridge"
invoke-static {v0}, Ljava/lang/System;->loadLibrary(Ljava/lang/String;)V
return-void
.end method
```
为每种架构添加 `lib//libfrida-bridge.so`,并按照第 2 节的说明将 gadget 文件放在 `files/frida/` 下。
#### 选项 B:集成到您自己的容器项目中
```
public class MyApp extends Application {
static {
System.loadLibrary("frida-bridge");
}
}
```
```
android {
sourceSets {
main {
jniLibs.srcDirs = ['libs']
}
}
}
```
## 🛡️ 5. 安全视角
### 🔑 本库可以访问的内容
该库**完全在宿主进程现有的安全边界内**运作。它:
- ✅ 读取 `/proc/self/maps` 和 `/proc/self/cmdline` —— 系统设计上允许每个进程访问
- ✅ 在 app 自己的文件目录内进行读写 —— 这是进程已经拥有的存储空间
- ✅ 使用 app 自己的 `JavaVM` 进行 JNI 调用 —— 标准的 Android API
- ✅ 对由集成者提供的、已存在于磁盘上的库文件调用 `dlopen()`
**不会发起任何 app 自身无法发起的系统调用。**
### ❎ 本库不会执行的操作
- ❌ 不提升权限
- ❌ 不自行通过网络进行通信
- ❌ 不访问其他 app 的数据
- ❌ 不下载或获取 gadget 二进制文件 —— 必须在本地提供
- ❌ 不请求额外的 Android 权限
### 🏛️ 策略合规
该库作为宿主 app 自身进程的一部分加载,运行于 app 的 UID 下,并完全在 Android 标准的应用沙箱内运作。
## 🔧 6. 故障排除
### 🪵 首先查看日志
大多数问题都可以通过 `logcat` 进行诊断。过滤标签 `FridaBridge`。
一次正常的运行会显示以下序列:
```
I/FridaBridge: Bridge started
I/FridaBridge: Files dir: /data/…
I/FridaBridge: ART detected via maps: …
I/FridaBridge: Gadget loaded
I/FridaBridge: Bridge done
```
如果您看到 `Gadget loaded` 和 `Bridge done`,**说明 bridge 本身正在工作** —— 问题出在 gadget 配置、脚本或环境上。
### ❗ 脚本未生效?
- **脚本质量**:导致静默失败的最常见原因是脚本本身的错误——调用了缺失的方法、使用了已被移除的 API,或者是在应用 hook 之前就导致 agent 崩溃的逻辑错误。请在非容器环境(真机/模拟器)中测试脚本,以确认其可以独立运行。
- **脚本编译**:如果您的脚本需要编译,请使用 `frida-compile` 并确保输出的文件名为 `libfrida-gadget.script.so`。
- **配置模式**:bridge 会重写 `"path"` 字段;请验证配置的其余部分(尤其是 `"interaction"` 块)是否正确。
- **二次启动行为**:在首次启动(或清除 app 数据后),bridge 会在 gadget 初始化*之后*将配置和脚本复制到真实路径。gadget 仅在**下一次**启动时才会读取它们。请运行 app 两次 —— 第二次运行应该就能生效了。
- **时序/ hook 缺失**:如果某些 hook 未触发,请增加 `frida-bridge.cfg` 中的 `delay` 值。这为 app 提供了更多时间,以便在脚本运行之前到达目标代码。
### 🧪 提交 Issue 前的检查事项
- 提供从 `Bridge started` 到 `Bridge done` 的完整 `logcat`(或者至少是相关的 `FridaBridge` 行)。
- 注明 Frida Gadget 版本、Android 版本,以及您是否处于容器/VM 环境中。
- 尝试在非容器环境中进行相同的设置,以排查问题原因。
标签:Android, Docker支持, DSL, Frida, UML, 云资产清单, 客户端加密, 目录枚举, 移动安全, 逆向工程