Skip to main content
Glama
README.md
# gdb-mcp

MCP 服务器,让大模型(Claude Code 等)驱动 Linux 下的 **gdb 进程本身**(可带 pwndbg 插件),用于用户态二进制漏洞挖掘与 exploit 开发中的动态调试与崩溃快速定位。

- 目标是 **gdb 前端**,不是 gdbserver——即使 pwntools 的 `gdb.debug()` 内部用 gdbserver + `target remote`,MCP 统一通过 gdb 控制一切。
- **原生支持 pwntools 拉起的 gdb**(`gdb.debug()` / `gdb.attach()`),无需改造 pwntools 代码。
- 服务器跑在 **Windows**(Claude Code),gdb 跑在 **WSL2 / Linux**:gdb 内插件通过 TCP 回连服务器,多会话注册表自动管理。
- 结构化工具(内存/寄存器/回溯/断点/线程/反汇编)+ **pwndbg 命令透传**(`vmmap`/`heap`/`got`/`checksec`/`ropgadget`…)+ 一键崩溃定位(`crash_report`)。

## 架构

```
Claude Code (Windows) ──stdio/MCP──► gdb-mcp server (FastMCP, Windows)
                                          │ TCP listener 127.0.0.1:3939(会话注册表)
                                          ▼ 插件从 WSL2 回连(JSON-lines 协议 v1)
                    WSL2: gdb (+pwndbg) ── gdb_mcp_plugin.py(stdlib-only 单文件)
                          ▲
                          └── pwntools 经 gdb_args=['-x', plugin] 注入;或 MCP 经 wsl.exe 自启动
```

- 插件是 TCP **客户端**:谁先启动都无所谓,断线自动退避重连。
- gdb 非线程安全:插件内所有 `gdb.*` 调用经 `gdb.post_event` 派发到 gdb 主线程;`stop`/`running`/`exited`/`prompt` 等异步通知经 `gdb.events` 推送。
- 打断运行中的 inferior:`post_event(execute("interrupt"))`(gdb 17.2 实测唯一可靠机制;`gdb.interrupt()` 与进程 SIGINT 均不可靠)。

## 安装

**Windows 侧(MCP 服务器)**(在仓库根目录执行)

```powershell
pip install -e .
```

**WSL2 侧(kali-linux)**

```bash
sudo apt install gdb python3 python3-pip gcc   # pwndbg 可选
```

无需在 WSL 内安装任何 gdb-mcp 组件——插件文件直接经 `/mnt/c/...` 由 gdb 的 `-x` 加载。若 `/mnt/c` 不可用,把 `src/gdb_mcp/plugin/gdb_mcp_plugin.py` 复制进 WSL 并设置 `GDB_MCP_PLUGIN` 指向它。

## WSL2 网络(重要)

插件从 WSL2 **回连** Windows 侧服务器,依次尝试:`GDB_MCP_HOST` → `127.0.0.1` → WSL 默认网关 → `/etc/resolv.conf` 的 nameserver IP。

| 模式 | 配置(`%USERPROFILE%\.wslconfig`) | 插件应连 |
|---|---|---|
| **Mirrored**(推荐) | `[wsl2] networkingMode=Mirrored` | `127.0.0.1`(共享 localhost) |
| NAT(默认) | 无配置 | 默认网关(自动发现);服务端需非 loopback 监听并配置 token |

排查:`wsl.exe -l -q` 报 `0x8007054f` / VM 内 `ip route` 为空 → mirrored 网络未生效,`wsl --shutdown` 重启或改回 NAT。NAT 下若自动发现失败,显式设置:

```bash
export GDB_MCP_HOST=$(ip route show default | awk '{print $3}')
```

服务器默认只绑定 `127.0.0.1:3939`。NAT 模式需要设置
`GDB_MCP_HOST_BIND=0.0.0.0`,此时服务端会强制要求同时设置
`GDB_MCP_TOKEN`;gdb 进程侧必须使用相同 token。非 loopback 监听可能触发
Windows 防火墙授权。

## Claude Code 配置

项目根目录 `.mcp.json`(或 Claude Code 的 MCP 设置):

```json
{
  "mcpServers": {
    "gdb-mcp": {
      "command": "gdb-mcp",
      "env": { "GDB_MCP_PORT": "3939" }
    }
  }
}
```

## 用法

### 方式 1:pwntools 脚本拉起 gdb(核心场景)

```python
from pwn import *

# 插件路径:examples 脚本会自动定位仓库内的插件文件(也可用 GDB_MCP_PLUGIN 覆盖)
import os
PLUGIN = os.environ.get("GDB_MCP_PLUGIN") or "<repo>/src/gdb_mcp/plugin/gdb_mcp_plugin.py"

io = gdb.debug("./vuln", gdb_args=["-x", PLUGIN])     # 或 gdb.attach(io, gdb_args=["-x", PLUGIN])
io.interactive()
```

gdb 在新终端(tmux 窗格)中打开、pwndbg 照常加载、插件自动回连 → MCP 里 `list_sessions` 即可看到会话。完整示例见 `examples/pwntools_debug.py`、`examples/pwntools_attach.py`。

### 方式 2:MCP 自启动(headless)

- `launch_gdb(program="/mnt/c/.../vuln", run=True)` —— wsl.exe 后台拉起 gdb + 插件
- `launch_script(script="C:\\...\\exploit.py")` —— 后台跑脚本,等待其 gdb 注册;纯脚本退出时立即返回状态、退出码与日志尾
- `kill_session(force=False)` 仅断开插件、保留 gdb;`force=True` 终止 gdb
- `quit_gdb(kill_gdb=False)` —— 断开外部启动的 gdb

### 方式 3:手动 gdb

```bash
bash examples/bare_gdb.sh ./vuln        # 等价于 gdb -q -x plugin.py --args ./vuln
```

gdb 内还有 `mcp status|reconnect|detach` 命令。

## 崩溃定位流程(LLM 视角)

```
continue_execution → wait_for_stop → crash_report(一次调用返回:
  signal / fault_addr / pc / thread / registers / backtrace /
  disasm(PC±) / memory@PC / memory@SP / memory@fault / 内存映射头部)
→ evaluate / read_memory / write_memory 验证利用思路
→ execute_command("vmmap") 拿 libc/PIE 基址
→ set_reg / write_memory 现场修补
→ continue_execution 复跑
```

## 工具一览(27 个)

| 类别 | 工具 |
|---|---|
| 会话/启动 | `list_sessions` `session_status` `launch_gdb` `launch_script` `get_process_output` `kill_session` `quit_gdb` |
| 执行控制 | `execute_command`(raw 透传,pwndbg 全兼容)`continue_execution` `interrupt` `wait_for_stop` `get_stop_reason` |
| 崩溃定位 | `crash_report` |
| 状态检查 | `read_memory` `write_memory` `read_registers` `write_register` `get_backtrace` `disassemble` `evaluate` `list_threads` `select_frame` `get_memory_map` `load_target` |
| 断点 | `set_breakpoint`(软件/硬件/watch/条件/临时/线程)`list_breakpoints` `manage_breakpoint` |

所有工具带可选 `session_id`(唯一会话自动选中;多会话时报错并列出)。地址参数均支持 gdb 表达式(`main+0x20`、`&puts@got`,PIE 按实时基址解析)。

## 环境变量

| 变量 | 位置 | 说明 |
|---|---|---|
| `GDB_MCP_PORT` | 两侧 | 端口(默认 3939) |
| `GDB_MCP_HOST_BIND` | 服务器 | 监听地址(默认 127.0.0.1) |
| `GDB_MCP_TOKEN` | 两侧 | 共享 token;非 loopback 监听时必需 |
| `GDB_MCP_HOST` | gdb 进程 | 强制指定服务器地址 |
| `GDB_MCP_SESSION_ID` | gdb 进程 | launch_gdb 内部使用 |
| `GDB_MCP_AUTOSTART` | gdb 进程 | `0` = 仅加载不连接 |
| `GDB_MCP_DEBUG` | gdb 进程 | `1` = 插件调试输出(stderr) |
| `GDB_MCP_WSL_DISTRO` / `GDB_MCP_LOG_DIR` | 服务器 | launch 工具配置 |
| `GDB_MCP_REQUEST_TIMEOUT` / `GDB_MCP_HEARTBEAT_SEC` | 服务器 | 请求与心跳超时 |
| `GDB_MCP_MAX_MEM_READ` / `GDB_MCP_MAX_ASYNC_LINE` | 两侧 | 内存读取与协议帧上限 |

部分内存读取返回 `segments`(每段都含实际 `addr`、`length`、`hex` 和
`ascii`)以及 `unreadable` 范围;存在缺口时顶层 `hex` / `ascii` 为 `null`,
避免把不连续数据误当成连续内存。

## 与 pwndbg / pwntools 共存

- 插件只 `connect` 自己的 `gdb.events` 处理器,绝不接管 `gdb.prompt_hook`、不抓 prompt;在 pwndbg 前后加载均可。
- 对 pwntools 的 gdbscript(含 `target remote`)完全惰性,inferior 如何被接管与插件无关。
- 已知事实(gdb 17.2 实测):`gdb.execute("continue")` 从 post_event 回调中执行时**异步返回**;`gdb.events.stop` 在 execute 返回之后触发;`StopEvent.details` 不含 fault addr(插件用 `$_siginfo._sifields._sigfault.si_addr` 兜底);`gdb.interrupt()` 无法中断异步运行的 inferior(插件用 `post_event(execute("interrupt"))`)。

## 测试

```bash
python -m pytest tests/                 # 单元测试(Windows 直接跑,无需 gdb)
bash tests/integration/run_wsl_integration.sh   # WSL2 内真实 gdb 端到端
```

集成测试覆盖:握手 → 断点 → SIGSEGV 崩溃定位 → 寄存器/回溯/反汇编/内存读写 → 表达式求值 → interrupt 中断死循环 → 优雅退出。

## 安全说明

该 TCP 通道具备执行任意 gdb 命令的能力。默认仅监听 loopback;任何非
loopback 监听都必须配置共享 token,并仍建议用防火墙限制 3939 端口来源。
协议拒绝版本不匹配和结构不合法的消息。

TDQS

B3.4/5.0

Scored across 27 tools

Disambiguation4/5

Most tools target distinct gdb actions such as memory, registers, breakpoints, and execution control. The main ambiguity is between quit_gdb and kill_session, which overlap in detaching/terminating sessions, but descriptions are detailed enough to guide selection in most cases.

Naming Consistency4/5

The set mostly follows verb_noun conventions: list_*, get_*, read_*, write_*, set_breakpoint, launch_*. Minor inconsistencies exist, such as session_status and crash_report using noun phrases instead of get_* and interrupt/continue_execution/wait_for_stop using different patterns, but the overall style remains readable and predictable.

Tool Count3/5

At 27 tools, the set is above the typical well-scoped range and feels heavy, though gdb is a broad debugging domain and most tools cover a concrete operation. The count could be reduced by merging quit_gdb into kill_session and avoiding the catch-all nature of execute_command.

Completeness4/5

The core debugging lifecycle is well covered: launching/loading targets, breakpoints, execution control, memory and register inspection, threads/frames, and crash triage. Minor gaps such as setting breakpoint conditions or modifying variables directly can be worked around using execute_command or evaluate.

Maintenance

ActivityMaintained
ResponsivenessNo issues