FuzzySecurity/kahlo-mcp
GitHub: FuzzySecurity/kahlo-mcp
一个基于 MCP 协议的 Frida 服务端,将 Android 动态插桩能力开放给 AI 智能体实现自主化移动安全分析。
Stars: 33 | Forks: 1
# (Frida) Kahlo MCP
Kahlo is a Frida MCP server that exposes Android dynamic instrumentation capabilities to AI agents. It wraps Frida's runtime manipulation APIs into a structured tool interface, enabling AI systems to attach to processes, inject instrumentation code, capture telemetry, and iterate on analysis workflows without manual intervention.
The server manages the full lifecycle of instrumentation sessions: device discovery, process attachment or spawning, job execution with per-script isolation, event streaming with cursor-based pagination, and binary artifact storage. Jobs run in isolated Frida scripts with automatic cleanup on cancellation. A built-in stdlib provides many standard code primitives for Java object inspection, stack traces, Intent parsing, and method hooking.
欲了解更多详情,请阅读随附的博客文章:
[https://knifecoat.com/Posts/Scalable+research+tooling+for+agent+systems](https://knifecoat.com/Posts/Scalable+research+tooling+for+agent+systems)
## 设置与安装
编辑此仓库中现有的 [`kahlo-mcp/config.json`](kahlo-mcp/config.json),并将 `adbPath` 设置为您想使用的 ADB 二进制文件的 **完整路径**。这在 Windows 和 UNIX 系统上都能正常工作。
```
{
"transport": "stdio",
"logLevel": "info",
"dataDir": "./data",
"adbPath": "/path/to/adb"
}
```
安装依赖并构建:
```
cd kahlo-mcp
npm install
npm run build
```
| 字段 | 必需 | 描述 |
|-------|----------|-------------|
| `transport` | 是 | 目前仅支持 `"stdio"`(SSE 即将推出) |
| `logLevel` | 是 | 目前请使用 `"info"`(更多控制选项即将推出) |
| `dataDir` | 是 | 用于运行、模块、草稿、 artifacts 的目录。默认为 `kahlo-mcp/data` |
| `adbPath` | 是 | ADB 二进制文件的完整路径 |
上传一个与 [`kahlo-mcp/package.json`](kahlo-mcp/package.json) 中 `frida` 版本匹配的 `frida-server` 二进制文件到您的设备上,然后运行它(最好以 root 身份运行)。
## MCP 集成
### Claude Code
编辑您的 claude 用户 json 配置文件(`/mcp` 会显示其位置):
```
{
"mcpServers": {
"frida-kahlo": {
"type": "stdio",
"command": "node",
"args": [
"C:/Your/Full/Path/k4hlo/kahlo-mcp/dist/index.js"
],
"cwd": "C:/Your/Full/Path/k4hlo/kahlo-mcp"
}
}
}
```
### Cursor
添加到 Cursor MCP 设置中(Preferences > Cursor Settings > Tools & MCP):
```
{
"mcpServers": {
"frida-kahlo": {
"command": "node",
"args": ["/Your/Full/Path/k4hlo/kahlo-mcp/dist/index.js"],
"cwd": "/Your/Full/Path/k4hlo/kahlo-mcp"
}
}
}
```
### Codex CLI
您可以在 `.codex` 的用户配置文件夹下找到您的 `toml` 文件:
```
model = "gpt-5.3-codex"
model_reasoning_effort = "medium"
[mcp_servers.frida-kahlo]
command = "node"
args = ["/Your/Full/Path/k4hlo/kahlo-mcp/dist/index.js"]
cwd = "/Your/Full/Path/k4hlo/kahlo-mcp"
```
## MCP 工具参考
本节是工具层面的快速、实用映射。有关完整的操作契约(概念、工作流、故障模式和完整的 stdlib 参考),请让您的 AI 调用 `kahlo_mcp_about` 以了解更多!
### 自省
- `kahlo_mcp_about`:返回 kahlo 操作契约(工具清单、概念、工作流、故障模式、stdlib 参考)。
### 设备、进程和 ADB
- `kahlo_devices_list`:列出已连接且准备好进行检测的设备。
- `kahlo_devices_get` (`device_id`):详细的设备信息(型号/版本/传输)及就绪信号。
- `kahlo_devices_health` (`device_id`):ADB + frida-server 存在/运行状态的健康检查。
- `kahlo_processes_list` (`device_id`, `scope?`):列出正在运行的进程(pid + 名称)。在执行 `mode="attach"` 之前使用此命令可获取准确的进程名称。
- `kahlo_adb_command` (`command[]`, `device_id?`, `timeout_ms?`):使用配置的 ADB 二进制文件运行 ADB 命令。对于仅限 root 的路径,请使用 `su -c` 包装(例如 `['shell','su','-c','ls /data/data/
']`)。
### 目标(附加/启动 + 生命周期)
- `kahlo_targets_ensure`:
- **用途**:创建/确保一个目标(一个承载进程内编排器的被检测应用进程)。
- **参数**:`device_id`、`package`、`mode` (`attach|spawn`)、`gating?` (`none|spawn|child`)、`bootstrap?`、`bootstrap_params?`、`bootstrap_type?`,以及可选的 `child_*` 引导字段。
- **注意**:
- `mode="attach"`:`package` 是来自 `kahlo_processes_list` 的 *进程名称*(通常不是 Android 包 id)。
- `mode="spawn"`:`package` 是 Android 包 id(例如 `com.example.app`)。
- `gating="spawn"` 需要 `bootstrap`(在应用挂起时进行早期挂钩,随后自动恢复)。
- `gating="child"` 虽然存在,但 **在 Android 上不起作用**(zygote forks 子进程)。对于多进程应用,请发现 `com.example.app:process` 名称并单独附加。
- `kahlo_targets_status` (`target_id`):目标生命周期 + 编排器代理状态(用于诊断崩溃/重新注入)。
- `kahlo_targets_detach` (`target_id`):干净地分离;取消该目标的所有作业。
### 作业(运行检测代码)
- `kahlo_jobs_start`:
- **用途**:在目标内启动一个独立的作业(一个 Frida 脚本实例)。
- **参数**:`target_id`、`type?` (`oneshot|interactive|daemon`)、`ttl?`、`params?`,以及 `module`:
- `{ kind: 'module_ref', module_ref: 'name@version' }`
- `{ kind: 'draft_id', draft_id: '...' }`
- `{ kind: 'source', source: '...' }` (用于快速迭代的内联 JS)
- **注意**:daemon 作业应定期调用 `ctx.heartbeat()`;取消操作会卸载脚本,Frida 会清理挂钩/定时器/状态。
- `kahlo_jobs_status` (`job_id`):作业生命周期 + 心跳健康 + 指标 + 错误/结果。
- `kahlo_jobs_list` (`target_id`):列出某个目标的作业(活动 + 历史)。
- `kahlo_jobs_cancel` (`job_id`):取消作业;卸载其脚本(通过 Frida 尽力清理)。
### 遥测和快照
- `kahlo_events_fetch` (`target_id?` 或 `job_id?`, `cursor?`, `limit?`, `filters?`):基于游标分页轮询结构化事件。`filters` 支持 `kind` 和/或 `level`。
- `kahlo_snapshots_get` (`target_id`, `kind`, `options?`):时间点状态查询(请谨慎使用;可能开销较大)。
### Artifacts(大型输出)
- `kahlo_artifacts_list` (`target_id?` 或 `job_id?`):列出作业产生的 artifacts(文件/转储/跟踪等)。
- `kahlo_artifacts_get` (`artifact_id`):获取 artifact 元数据以及内联 payload(小文件)或存储引用(大文件)。
### 模块和草稿(可复用的作业代码)
- `kahlo_modules_list`:列出模块存储中的版本化模块。
- `kahlo_modules_get` (`module_ref` 如 `name@1.2.3`):获取模块源码 + 清单 + 来源。
- `kahlo_modules_createDraft` (`source`, `name?`, `manifest?`):创建一个可变的草稿用于迭代。
- `kahlo_modules_createDraftFromJob` (`job_id`, `name?`):将“我正在运行的作业”保存为草稿。
- `kahlo_modules_listDrafts`:列出草稿(仅元数据)。
- `kahlo_modules_getDraft` (`draft_id`):获取草稿元数据 + 完整源码。
- `kahlo_modules_updateDraft` (`draft_id`, `source`):替换草稿源码(快速迭代)。
- `kahlo_modules_promoteDraft` (`draft_id`, `name`, `version_strategy`, `notes?`):将草稿冻结为版本化模块(`patch|minor|major`)。
- `kahlo_modules_promoteFromJob` (`job_id`, `name`, `version_strategy`, `notes?`):将测试过的作业直接提升为版本化模块。
## 标准库 (`ctx.stdlib`)
每个作业脚本都会在 `ctx.stdlib` 下获得一个预加载的标准库。这是执行常见“检测杂务”(堆栈捕获、安全的 Java 调用、重载安全的挂钩、字节/字符串、Intent 解析等)的首选方式,无需重写样板代码。
真实来源:`kahlo-mcp/src/backend/jobs/jobScriptStdlib.js`。
### 顶级辅助工具
- `ctx.stdlib.isJavaAvailable()`:如果在此进程中可以使用 Java API,则返回 `true`。
- `ctx.stdlib.getJavaBridge()`:返回 Java 桥接句柄(或 `null`)。
- `ctx.stdlib.requireJava(operation?)`:返回 Java 桥接或抛出带有提示信息的错误。
### `stack` - Java 堆栈跟踪
- `capture({ skip?, limit? })`:将帧捕获为对象(`className`、`methodName`、`fileName`、`lineNumber`、`isNative`)。
- `toString({ skip?, limit?, separator? })`:格式化的堆栈跟踪字符串。
- `filter(frames, pattern)`:保留匹配前缀字符串或 RegExp 的帧。
- `findFirst(frames, pattern)`:第一个匹配的帧(或 `null`)。
- `getCaller()`:尽力而为的“调用者”帧(跳过内部/运行时帧)。
- `getException(throwable)`:将 Java `Throwable`(消息 + 堆栈 + 原因)格式化为字符串。
### `inspect` - Java 对象自省
- `className(obj)`, `simpleClassName(obj)`
- `fields(obj, { includeInherited?, includeStatic? }?)`:枚举字段(包括私有字段)。
- `methods(obj, { includeInherited?, includeStatic? }?)`:枚举方法。
- `getField(obj, fieldName)`:安全的字段读取(`{ ok, value, error? }`)。
- `toJson(obj, { maxDepth?, maxArrayLength?, maxStringLength? }?)`:将常见的 Java 对象转换为 JSON 安全的结构。
- `isInstance(obj, className)`
- `superclassChain(obj)`
- `interfaces(obj, includeInherited?)`
### `classes` - 发现与加载
- `find(pattern, { limit? }?)`:按前缀字符串或 RegExp 搜索已加载的类。
- `enumerate(callbackOrOptions?)`:列出已加载的类(根据用法返回数组或通过回调流式传输)。
- `load(className)`:安全的 `Java.use`(失败时返回 `null`)。
- `isLoaded(className)`:快速检查类是否已加载。
- `instances(className, { limit? }?)`:枚举活动堆实例(尽力而为,可能开销较大)。
- `getClassLoader(className)`:获取已加载类的 `ClassLoader`(或 `null`)。
### `bytes` - 二进制辅助工具
- `toHex(data, { uppercase?, separator? }?)`, `fromHex(hex)`
- `toBase64(data)`, `fromBase64(base64)`
- `fromJavaBytes(byteArray)`, `toJavaBytes(uint8Array)`
- `equals(a, b)`, `concat(...arrays)`, `slice(data, start, end?)`
### `strings` - 转换与编码
- `fromJava(javaStringLike)`, `toJava(jsString)`
- `truncate(str, maxLength, ellipsis?)`
- `fromUtf8(data)`, `toUtf8(str)`
- `matches(str, pattern)`
- `safeToString(obj, maxLength?)`
### `intent` - Intent 解析与构建
- `parse(intent)`:返回结构化摘要(action/data/type/categories/component/flags/extras)。
- `getExtras(intent)`:将 extras Bundle 提取到 JS 对象中(递归嵌套的 Bundles)。
- `getComponent(intent)`, `isExplicit(intent)`
- `create({ action?, data?, type?, flags?, packageName?, className?, extras? })`:构建一个新的 Intent(失败时返回 `null`)。
- `flagsToStrings(flags)`:将位掩码解码为标志名称。
### `hook` - 挂钩辅助工具(Java + native)
- `method(className, methodName, { onEnter?, onLeave? })`:挂钩一个方法(如果存在则包含所有重载)。
- `methodWithSignature(className, methodName, paramTypes[], { onEnter?, onLeave? })`:挂钩特定的重载。
- `allOverloads(className, methodName, handler)`:使用单个处理程序挂钩所有重载。
- `constructor(className, handler)`:挂钩所有 `$init` 重载。
- `onClassLoad(className, callback)`:一旦类可用,运行 `callback(Java.use(className))`。
- `native(addressOrSymbol, callbacks)`:用于 native 挂钩的 `Interceptor.attach` 包装器。
- `replace(classWrapper, methodName, replacement)`:替换实现并获取一个恢复函数。
### `safe` - 故障关闭包装器
- `java(fn)`:在 `Java.performNow` 中运行并返回 `{ ok, result?, error? }`。
- `call(fn)`:返回 `{ ok, result?, error? }` 的 try/catch 包装器。
- `timeout(fn, timeoutMs)`:返回 `{ ok, result?, error? }` 的 Promise 包装器(不会取消底层工作)。
- `tryUse(className)`:安全的 `Java.use`(返回 `null` 而不是抛出异常)。
- `invoke(obj, methodName, ...args)`:安全的方法调用(任何失败均返回 `null`)。
- `get(obj, keyPath, defaultValue?)`:安全的属性查找(支持点路径)。
### `time` - 时间戳与速率限制
- `now()`, `nowMs()`, `hrNow()`
- `format(ms)`, `stopwatch()`
- `sleep)`, `measure(fn)`
- `debounce(fn, delayMs)`, `throttle(fn, intervalMs)`标签:ADB, Android 安全, DNS 反向解析, Docker支持, Frida, GNU通用公共许可证, Hook 框架, Java 对象检测, MCP Server, MITM代理, Node.js, Runtime Manipulation, SSH蜜罐, 事件流, 二进制分析, 云安全运维, 协议上下文, 威胁狩猎, 安全测试, 攻击性安全, 数据可视化, 模型上下文协议, 漏洞分析, 目录枚举, 移动安全, 自动化攻击, 自动化攻击, 自动化逆向, 自动渗透测试, 路径探测, 进程注入