Bundle
frida-dsh-plugin
Frida device instrumentation tools for DeepSeek Harness
- Source
- mang0cola
- stars
- 1 stars
- License
- MIT
- Updated
- Updated 5 days ago
Readme
# frida-dsh-plugin
将 [Frida](https://frida.re/) 作为一组受策略约束的工具接入 [DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness)。安装后,大模型可以发现已配置设备、枚举进程或应用、附加或拉起目标、加载 Frida Agent、调用 RPC、读取异步消息,并在会话结束时自动释放资源。
本插件只应用于你拥有或已明确获准测试的设备和程序。
## 设计概览
```mermaid
flowchart LR
M["DeepSeek Harness Agent"] --> T["9 个 Frida tools"]
T --> P["能力档位与审批策略"]
P --> R["FridaRuntime"]
R --> O["Agent 资源归属与限额"]
R --> E["有界事件缓冲"]
R --> N["官方 frida-node"]
N --> D["local / USB / remote device"]
```
关键约束:
- 模型只看到部署方配置的设备别名,不能自行提交远程地址或认证信息。
- Session 和 Script 使用不透明句柄,并绑定到创建它们的 Agent;其他 Agent 无法复用。
- 默认 `discovery` 档只允许发现设备、进程和应用,不允许注入。
- 注入操作默认进入 Harness 审批链;无审批服务时,`ask` 会失败关闭。
- 脚本消息使用游标式环形缓冲;二进制、事件 JSON 和 RPC JSON 均有字节上限。
- Agent 销毁、插件热替换或 Harness 退出时会清理 Script、Session 和未恢复的暂停进程。
## 环境要求
- Node.js 20 或更高版本。
- DeepSeek Harness `0.1.0-rc.6` 兼容版本。
- 与目标端兼容的 Frida 环境。Android USB 场景通常需要目标设备上运行版本匹配的 `frida-server`;其他部署也可以使用 Frida Gadget 或远程 Frida 服务。
默认后端是当前 Node 进程中的 `frida-node`。如果设备端必须保留旧版 Frida,而旧版 `frida-node` 不支持宿主 Node 版本,可以选择 `backend: python`,让插件通过一个持久、可取消的 JSON-lines worker 复用版本匹配的 Python 虚拟环境;模型工具和安全策略保持不变。
先确认宿主机能够正常使用 Frida 连接目标设备,再让 Harness 接管调用。插件不会替你绕过设备授权、代码签名、越狱、root 或系统调试限制。
## 构建与安装
在本仓库中执行:
```sh
npm install
npm run build
npm test
dsh plugin --profile demo add .
dsh --profile demo --dump-config
dsh --profile demo
```
组合包安装后会插入三行:`frida-runtime`、`frida-tools` 和 `frida-policy`。默认配置是只读的 `discovery` 档。
Harness 的后置 patch 会按 `id` 覆盖前面的行,并整体替换该行的 `config`。要开启注入能力,请把下列某个示例加入目标 profile 的 `cordis.patch.yml`;仓库中的 [`examples`](./examples) 目录也提供了可复制版本。
## 能力档位
| 档位 | 发现设备/目标 | Attach | 内置模板 | 原始 JS | Spawn/Resume/Kill |
| --- | --- | --- | --- | --- | --- |
| `discovery` | 是 | 否 | 否 | 否 | 否 |
| `templates` | 是 | 是 | 是 | 否 | 否 |
| `full` | 是 | 是 | 是 | 是 | 是;Kill 还需 `allowKill: true` |
### 仅发现设备与目标(默认)
```yaml
- id: frida-runtime
config:
backend: node
pythonExecutable: python3
capabilityProfile: discovery
approvalMode: ask
devices:
- alias: local
kind: local
- alias: usb
kind: usb
timeoutMs: 5000
defaultDevice: usb
targetAllowlist: []
allowKill: false
operationTimeoutMs: 30000
maxSessions: 8
maxScriptsPerSession: 8
maxScriptBytes: 262144
eventBufferSize: 1000
maxEventDataBytes: 65536
```
### 只允许审计过的模板
```yaml
- id: frida-runtime
config:
backend: node
pythonExecutable: python3
capabilityProfile: templates
approvalMode: ask
devices:
- alias: usb
kind: usb
timeoutMs: 10000
defaultDevice: usb
targetAllowlist:
- 'com.example.*'
- 'Example App'
allowKill: false
operationTimeoutMs: 30000
maxSessions: 4
maxScriptsPerSession: 4
maxScriptBytes: 262144
eventBufferSize: 1000
maxEventDataBytes: 65536
```
### 完整能力与远程设备
认证令牌只从宿主进程环境变量读取,不写入 Harness 配置或模型上下文:
```yaml
- id: frida-runtime
config:
backend: node
pythonExecutable: python3
capabilityProfile: full
approvalMode: ask
devices:
- alias: lab-android
kind: remote
address: '10.20.0.15:27042'
tokenEnv: FRIDA_LAB_TOKEN
keepaliveInterval: 30
defaultDevice: lab-android
targetAllowlist:
- 'com.example.app'
allowKill: false
operationTimeoutMs: 30000
maxSessions: 4
maxScriptsPerSession: 4
maxScriptBytes: 262144
eventBufferSize: 1000
maxEventDataBytes: 65536
```
设备项支持:
| 字段 | 含义 |
| --- | --- |
| `alias` | 暴露给模型的稳定名称,必须唯一 |
| `kind` | `local`、`usb`、`remote` 或 `id` |
| `id` | `id` 设备必填;USB 多设备时也可指定 |
| `address` | `remote` 设备必填,由部署方固定 |
| `tokenEnv` | 包含远程认证令牌的环境变量名 |
| `certificate` / `origin` | Frida 远程连接参数 |
| `keepaliveInterval` | 远程连接保活间隔 |
| `timeoutMs` | 发现该设备时的等待上限 |
`targetAllowlist` 使用区分大小写的 `*` 通配符,匹配运行进程名或 Spawn 的程序/应用标识。空数组表示不额外限制目标;生产环境开启 `templates` 或 `full` 时建议显式列出目标。
`approvalMode` 的含义:
- `ask`:Attach、加载脚本、RPC、Spawn 和进程控制进入 Harness 审批流程。
- `allow`:策略层直接放行档位内的操作,适合隔离且已有外部授权控制的自动化环境。
- `deny`:保留发现工具,但拒绝所有注入和控制操作。
### 使用已有 Frida Python 虚拟环境
下面的配置适用于设备端 Frida 16.0.2、宿主 Node 版本无法加载同版本 `frida-node` 的场景:
```yaml
- id: frida-runtime
config:
backend: python
pythonExecutable: '/absolute/path/to/frida-16/bin/python'
capabilityProfile: templates
approvalMode: ask
devices:
- alias: usb16
kind: usb
timeoutMs: 30000
defaultDevice: usb16
targetAllowlist:
- 'com.example.*'
allowKill: false
operationTimeoutMs: 30000
maxSessions: 4
maxScriptsPerSession: 4
maxScriptBytes: 262144
eventBufferSize: 1000
maxEventDataBytes: 65536
```
`pythonExecutable` 是部署方信任边界内的本机可执行文件路径,不会暴露为模型参数。该 Python 环境必须已经安装与设备端兼容的 `frida` 包。
## 模型工具
| 工具 | 用途 |
| --- | --- |
| `frida_list_devices` | 返回配置过的设备别名及可用状态 |
| `frida_enumerate` | 分页枚举进程或应用 |
| `frida_attach` | 按 PID 或精确进程名附加,返回 `sessionId` |
| `frida_spawn` | 暂停启动并立即附加,返回 `sessionId` |
| `frida_load_script` | 加载内置模板或原始 JavaScript,返回 `scriptId` |
| `frida_call_rpc` | 调用脚本的 `rpc.exports` 方法 |
| `frida_read_events` | 用游标读取 `send()`、错误和 console 日志 |
| `frida_process_control` | 恢复插件 Spawn 的暂停进程,或在允许时终止它 |
| `frida_close` | 卸载 Script 或关闭 Session |
典型 Attach 流程:
1. `frida_list_devices`
2. `frida_enumerate`
3. `frida_attach`
4. `frida_load_script`
5. `frida_call_rpc` 和/或 `frida_read_events`
6. `frida_close`
典型 Spawn 流程是 `frida_spawn` → `frida_load_script` → `frida_process_control(action: resume)`。如果在 Resume 前关闭 Session 或 Agent 被销毁,插件会尽力终止它创建的暂停进程,避免设备上遗留挂起目标。
## 内置模板
| 模板 | `templateArgs` | RPC |
| --- | --- | --- |
| `enumerate-modules` | 无 | `run(offset?, limit?)` |
| `enumerate-exports` | `{ "moduleName": "..." }` | `run(offset?, limit?)` |
| `java-classes` | 无 | `run(offset?, limit?)` |
| `objc-classes` | 无 | `run(offset?, limit?)` |
| `hook-native-export` | `{ "moduleName": "...", "exportName": "..." }` | 通过事件返回 enter/leave |
例如,枚举目标模块时依次调用:
```json
{"sessionId":"frida-session-1","template":"enumerate-modules"}
```
然后:
```json
{"scriptId":"frida-script-1","exportName":"run","args":[0,3]}
```
上述四个枚举模板返回 `{ items, total, offset, limit, truncated }`;`limit` 默认为 100,最大为 500。模型可以直接读取总数并按游标分页,不需要借助 Shell 处理大型 RPC 结果。
`frida_load_script` 返回的 `nextCursor` 是模板加载完成后的游标。读取后续 hook 消息时把它传给 `frida_read_events`,并在下一次读取时继续使用新返回的 `nextCursor`。若缓冲区发生覆盖,`droppedCount` 会明确报告丢失数量。
## 开发命令
```sh
npm run typecheck
npm test
npm run build
npm pack --dry-run
```
对已经运行的授权测试目标执行 Python 后端端到端冒烟测试:
```sh
FRIDA_PYTHON=/absolute/path/to/frida-16/bin/python \
FRIDA_TARGET=com.example.app \
npm run test:device
```
该命令只 Attach 已运行目标,不负责启动或终止应用;它会完成设备/应用/进程枚举、原始脚本 RPC、事件回读、内置模块模板分页和 Session 清理。
测试中的 Runtime 使用 provider-neutral 假设备,因此不要求连接真实手机。真实部署仍应在授权测试设备上完成一次端到端验证,包括 Frida 主机端/目标端版本、Attach 权限、目标名称 allowlist 和 Harness 审批交互。
## 当前边界
- 原始 Agent 只接受 JavaScript;插件暂不负责 TypeScript 编译或 Frida Compiler 工程构建。
- 句柄和事件缓冲只存在于当前 Harness 进程,不跨重启恢复。
- 插件提供结构化工具,不模拟交互式 `frida` REPL。
- 高风险能力没有内置 Stalker、内存任意读写等模板;在 `full` 档中可通过经过审批的原始脚本显式实现。
## License
[MIT](./LICENSE)
Install
dsh plugin --profile web add github:mang0cola/frida_dsh_plugin
Profile: web
With the hub plugin installed, ask your agent to install it by name — it resolves the same plan shown here.
dsh plugin --profile web add github:stvlynn/dsh.fish#path:packages/dsh-plugin-hub
install frida-dsh-plugin from the hub
- This package builds from source on install. pnpm will ask you to allow its build script — that is permission to run the package’s code on your machine, outside the agent sandbox. Only allow sources you trust.
- This source has no pinned commit, so a later push upstream changes what installs. Prefer pinning a commit.