memoryforensics1/windbg-mcp
GitHub: memoryforensics1/windbg-mcp
一个C#实现的MCP服务器,为AI代理提供Windows内核和用户态调试的自动化控制,通过直接集成DbgEng和VMware提升稳定性。
Stars: 15 | Forks: 1
# WinDbg MCP 服务器
一个[模型上下文协议](https://modelcontextprotocol.io/) (MCP) 服务器,为 AI 代理提供对 Windows 虚拟机的完全控制权,用于内核调试、逆向工程、恶意软件分析和漏洞研究。
使用 C# (.NET 8) 构建,它将 Windows 调试引擎(DbgEng COM)、VMware Workstation、Frida 和 dbgsrv 封装成 **29 个 MCP 工具**,任何兼容 MCP 的 LLM 客户端均可调用。




## 为什么有这个项目?
其他 WinDbg MCP 服务器已经存在——大多数是启动 `cdb.exe` 或 `windbg.exe` 作为子进程并通过 stdin/stdout 驱动的 Python 封装。这很容易原型化,但在实践中很脆弱:子调试器会崩溃、在模态对话框上挂起、使自身管道死锁,或在会话中途死亡并带走代理的上下文。
本项目采用了不同的方法:
- **直接使用 DbgEng COM** —— 通过其 COM 接口原生调用 Windows 调试引擎。无需管理子进程,无需解析 stdout,没有挂起的管道。命令在服务器进程中执行,位于一个带有事件泵的专用 MTA COM 线程上——因此调试器无法拖垮整个 MCP 服务器。
- **内核调试是主要用例,而非事后补充** —— 完整的 KDNET 集成:附加到运行中的内核、设置断点、单步执行、在目标挂起时运行任何 WinDbg 命令、等待带硬超时的事件、检测蓝屏,并通过传递首次机会异常使 Windows 继续正常运行。执行控制命令(`g`/`t`/`p`)在 `kd_execute` 中被阻止,因此 LLM 无法意外地从断点处继续运行——它必须使用显式的 `kd_continue`/`kd_step` 工具,这些工具总会返回。
- **用户模式也被覆盖** —— Frida(带有永恒钩子,用于跨会话的持久化插桩)、用于非侵入性进程检查的 dbgsrv(可访问完整的 WinDbg 命令)以及 TTD(时间旅行调试)——都位于同一服务器之后。
- **虚拟机生命周期与调试会话集成** —— 快照恢复会先干净地拆卸 KD/Frida/dbgsrv,然后再还原虚拟机;客户机命令、文件传输和进程控制都基于虚拟机电源状态进行门控,这样代理永远不会遇到“状态错误”的提示。`vm_set_target` 允许运行中的服务器在运行时切换到不同的虚拟机。
- **专为 LLM 代理设计** —— 每个工具都有硬超时(没有无限阻塞),每条错误消息都明确告知 LLM 下一步该做什么,并且 `get_system_state` 按需为模型提供单个“我在哪里?”的快照。`StateCoordinator` 在每次调用前验证前置条件,因此代理获得的是有用的反馈,而不是静默失败。
## 它能做什么?
连接到此服务器的 LLM 可以自主地:
- **控制虚拟机** —— 启动、停止、暂停、恢复、快照、恢复、截图
- **内核调试** —— 通过 KDNET 连接、设置断点、单步执行、执行任何 WinDbg 命令、等待事件
- **在客户机中运行命令** —— 执行程序、传输文件、列出/终止进程
- **用户模式调试** —— 附加 Frida 以钩子函数、通过 dbgsrv 检查进程、记录 TTD 跟踪
整个过程 LLM 无需直接访问 WinDbg、终端或虚拟机本身。
## 快速开始
### 前置条件
| 要求 | 用途 |
|---|---|
| [.NET 8 SDK](https://dotnet.microsoft.com/download/dotnet/8.0) | 构建并运行服务器 |
| [VMware Workstation Pro](https://www.vmware.com/products/workstation-pro.html) | 虚拟机管理 (vmrun) |
| Windows 客户机虚拟机 | 调试目标 |
| 客户机中启用 KDNET | 内核调试(参见[设置](#vm-setup)) |
| [frida-tools](https://frida.re/) *(可选)* | 用户模式插桩 |
| [WinDbg Preview](https://aka.ms/windbg) *(可选)* | 提供用于远程用户模式调试的 dbgsrv.exe |
### 1. 克隆并构建
```
git clone https://github.com/memoryforensics1/windbg-mcp.git
cd windbg-mcp
dotnet build src/WinDbgMCP.Server/WinDbgMCP.Server.csproj
```
### 2. 配置 *(可选)*
将 `src/WinDbgMCP.Server/appsettings.example.json` 复制到 `appsettings.json` 并编辑:
```
{
"Vm": {
"VmxPath": "C:\\path\\to\\your\\vm.vmx",
"VmrunPath": "C:\\Program Files (x86)\\VMware\\VMware Workstation\\vmrun.exe",
"VmPassword": "",
"GuestUsername": "YourUser",
"GuestPassword": "YourPass"
},
"KernelDebug": {
"Transport": "kdnet",
"Kdnet": {
"Port": 50000,
"Key": "your.kdnet.key.here"
},
"SymbolPath": "srv*C:\\Symbols*https://msdl.microsoft.com/download/symbols"
},
"Guest": {
"FridaPort": 27042,
"DbgsrvPort": 5064
}
}
```
### 3. 添加到您的 MCP 客户端
**Claude Code**(项目根目录下的 `.mcp.json`):
```
{
"mcpServers": {
"windbg-mcp": {
"command": "dotnet",
"args": ["run", "--project", "C:\\path\\to\\windbg-mcp\\src\\WinDbgMCP.Server\\WinDbgMCP.Server.csproj"]
}
}
}
```
**Claude Desktop**(`claude_desktop_config.json`):
```
{
"mcpServers": {
"windbg-mcp": {
"command": "C:\\Program Files\\dotnet\\dotnet.exe",
"args": ["run", "--project", "C:\\path\\to\\windbg-mcp\\src\\WinDbgMCP.Server\\WinDbgMCP.Server.csproj"]
}
}
}
```
### 4. 运行
当您的 MCP 客户端连接时,服务器会自动启动。它通过 stdio 进行通信。
```
# 或独立运行以进行测试
dotnet run --project src/WinDbgMCP.Server/WinDbgMCP.Server.csproj
```
## 工具目录 (29 个工具)
### 元数据
| 工具 | 描述 |
|---|---|
| `get_system_state` | 完整状态概览——虚拟机电源、KD、客户机操作、UMD。始终允许。 |
### 虚拟机工具 (8 个)
| 工具 | 描述 |
|---|---|
| `vm_start` | 启动虚拟机电源 |
| `vm_stop` | 关机(优雅或强制) |
| `vm_pause` | 冻结整个虚拟机 |
| `vm_resume` | 恢复已暂停的虚拟机 |
| `vm_snapshot_restore` | 恢复命名快照(调试会话会被干净拆卸,之后可以重新连接) |
| `vm_snapshot_list` | 列出可用快照 |
| `vm_screenshot` | 将虚拟机显示捕获为 PNG |
| `vm_set_target` | 在运行时切换活动的虚拟机目标(VMX 路径 + 凭据) |
### 内核调试工具 (7 个)
| 工具 | 描述 |
|---|---|
| `kd_connect` | 通过 KDNET 附加到内核。连接时目标会中断。 |
| `kd_disconnect` | 从内核分离。恢复目标运行,使虚拟机继续运行。 |
| `kd_break` | 挂起运行中的目标 (Ctrl+Break) |
| `kd_continue` | 恢复目标执行 |
| `kd_step` | 单步执行一条指令(进入或越过) |
| `kd_execute` | 运行任何 WinDbg 命令(`k`, `r`, `lm`, `!process 0 0`, `!analyze -v` 等) |
| `kd_wait_for_event` | 带超时等待断点/异常。总会返回。 |
### 客户机工具 (5 个)
| 工具 | 描述 |
|---|---|
| `guest_run_command` | 在客户机操作系统中执行命令,捕获 stdout/stderr |
| `guest_transfer_to_vm` | 将文件从主机复制到客户机 |
| `guest_transfer_from_vm` | 将文件从客户机复制到主机 |
| `guest_list_processes` | 列出正在运行的进程及其 PID |
| `guest_kill_process` | 通过 PID 终止进程 |
### 用户模式调试工具 (8 个)
| 工具 | 描述 |
|---|---|
| `umd_frida_attach` | 将 Frida 附加到客户机进程 |
| `umd_frida` | 注入 JS,求值表达式,列出进程,分离 |
| `umd_frida_skill` | 适用于 LLM 的 Frida 最佳实践和 API 参考 |
| `umd_dbgsrv_connect` | 连接到客户机中的远程 dbgsrv |
| `umd_dbgsrv_execute` | 附加到 PID,运行 WinDbg 命令,分离 |
| `umd_dbgsrv_skill` | 适用于 LLM 的 dbgsrv 最佳实践和 WinDbg 命令参考 |
| `umd_ttd` | 时间旅行调试——录制、停止、检索、列出跟踪 |
| `umd_ttd_query` | 查询 TTD 跟踪 *(尚未实现)* |
## 示例工作流
### 检查运行中的内核
```
get_system_state
kd_connect
kd_execute("lm") # list loaded modules
kd_execute("!process 0 0") # list all processes
kd_execute("vertarget") # target version info
kd_disconnect
```
### 设置断点并捕获
```
kd_connect
kd_execute("bp nt!NtCreateFile") # set breakpoint
kd_continue # let target run
kd_wait_for_event(30) # wait up to 30s for hit
kd_execute("k") # show call stack
kd_execute("r") # show registers
kd_disconnect
```
### 部署并调试驱动程序
```
guest_transfer_to_vm("MyDriver.sys", "C:\\Windows\\System32\\drivers\\MyDriver.sys")
guest_run_command("sc create MyDrv type= kernel binPath= C:\\Windows\\System32\\drivers\\MyDriver.sys")
guest_run_command("sc start MyDrv")
kd_connect
kd_execute("lm m MyDrv") # verify driver loaded
kd_execute("bp MyDrv!DriverEntry")
kd_disconnect
```
### 使用 Frida 钩子函数
```
umd_frida_skill # read best practices first
umd_frida_attach(processName="target.exe")
umd_frida(action="eval", code="Process.enumerateModules().map(m=>m.name)")
umd_frida(action="inject", code="""
Interceptor.attach(Module.getExportByName('kernel32.dll','CreateFileW'), {
onEnter(args) { console.log('CreateFileW: ' + args[0].readUtf16String()); }
});
console.log('Hook installed');
""", timeoutSeconds=10)
umd_frida(action="detach")
```
### 使用 dbgsrv 检查进程
```
umd_dbgsrv_skill # read best practices first
guest_run_command("start /b C:\\Tools\\DbgSrv\\dbgsrv.exe -t tcp:port=5064")
umd_dbgsrv_connect(vmIpAddress="192.168.x.x")
umd_dbgsrv_execute(action="attach", argument="")
umd_dbgsrv_execute(action="command", argument="lm")
umd_dbgsrv_execute(action="command", argument="!peb")
umd_dbgsrv_execute(action="command", argument="~*k")
umd_dbgsrv_execute(action="detach")
umd_dbgsrv_execute(action="disconnect")
```
### 崩溃分析
```
kd_connect # connect after BSOD
kd_execute("!analyze -v") # automated crash analysis
kd_execute("k") # faulting stack
kd_execute("r") # registers at crash
kd_execute(".trap") # switch to trap frame
kd_disconnect
```
## 架构
```
┌─────────────────────────────────────────────────────────────┐
│ MCP Client (LLM) │
│ Claude Code / Claude Desktop │
└──────────────────────────┬──────────────────────────────────┘
│ stdio (JSON-RPC)
┌──────────────────────────▼──────────────────────────────────┐
│ WinDbgMCP.Server │
│ │
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────────┐ │
│ │ VM Tools │ │ KD Tools │ │ Guest Tools │ │
│ │ (vmrun) │ │ (DbgEng) │ │ (vmrun guest) │ │
│ └──────┬───────┘ └──────┬───────┘ └──────┬───────────┘ │
│ │ │ │ │
│ ┌──────▼───────┐ ┌──────▼───────┐ ┌──────▼───────────┐ │
│ │ VmwareManager│ │ DbgEngManager│ │ GuestExecManager │ │
│ └──────────────┘ └──────┬───────┘ └──────────────────┘ │
│ │ │
│ ┌────────────────────────▼─────────────────────────────┐ │
│ │ StateCoordinator │ │
│ │ (precondition gate — validates every tool call) │ │
│ └───────────────────────────────────────────────────────┘ │
│ │
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────────┐ │
│ │ UMD: Frida │ │ UMD: dbgsrv │ │ UMD: TTD │ │
│ │ (frida CLI) │ │ (DbgEng COM) │ │ (TTD.exe) │ │
│ └──────────────┘ └──────────────┘ └──────────────────┘ │
└──────────────────────────────────────────────────────────────┘
│ │ │
▼ ▼ ▼
┌─────────────────────────────────────────────────────────────┐
│ Windows Guest VM │
│ (VMware Workstation Pro) │
│ │
│ KDNET (:50000) │ frida-server (:27042) │ dbgsrv (:5064)│
└─────────────────────────────────────────────────────────────┘
```
### 关键设计原则
1. **每个工具都验证前置条件** —— `StateCoordinator` 在任何操作执行前检查虚拟机电源、KD 状态、客户机操作可用性
2. **每个操作都有超时** —— 永无阻塞调用。LLM 永远不会挂起。
3. **错误消息即提示** —— 每个错误都明确告知 LLM 下一步该做什么
4. **执行控制命令被阻止** —— `g`, `t`, `p` 在 `kd_execute` 中被阻止;请使用 `kd_continue`/`kd_step` 代替
5. **DbgEng COM 线程亲和性** —— 所有 COM 调用都编组到带有事件泵的专用 MTA 线程
6. **蓝屏检测** —— 错误检查被检测并以不同于普通断点的方式处理
7. **快照恢复重置一切** —— KD、Frida、dbgsrv 会话都会被清理
## 虚拟机设置
### 启用 KDNET(内核调试)
在客户机虚拟机中(以管理员身份运行 cmd):
```
bcdedit /debug on
bcdedit /dbgsettings net hostip: port:50000 key:
shutdown /r /t 0
```
使用 Windows SDK 中的 `kdnet.exe` 生成密钥,或使用任何点分四格式的密钥。
### 安装 Frida 服务器(可选)
在**主机**上:
```
pip install frida-tools
```
从 [Frida 发布版](https://github.com/frida/frida/releases) 下载 `frida-server--windows-x86_64.exe`,部署到客户机作为 `C:\Tools\frida-server.exe`,然后运行:
```
frida-server.exe -l 0.0.0.0:27042
```
### 安装 dbgsrv(可选)
将 `dbgsrv.exe`、`dbgeng.dll` 和 `dbghelp.dll` 从 WinDbg Preview(或 Windows SDK)复制到客户机,然后运行:
```
dbgsrv.exe -t tcp:port=5064
```
### 防火墙
主机防火墙必须允许:
- UDP 端口 50000 入站 (KDNET)
- TCP 端口 27042 出站 (Frida)
- TCP 端口 5064 出站 (dbgsrv)
## 项目结构
```
src/WinDbgMCP.Server/
├── Program.cs # Entry point, MCP server setup, DI
├── appsettings.json # Configuration (VM creds, KDNET, timeouts)
├── Configuration/
│ └── ServerConfig.cs # Typed configuration model
├── State/
│ ├── SystemState.cs # State model + enums
│ ├── StateCoordinator.cs # Precondition gate (heart of system)
│ ├── ErrorMessages.cs # LLM-friendly error catalog
│ └── ToolResult.cs # Result type
├── Vmware/
│ └── VmwareManager.cs # vmrun wrapper
├── KernelDebug/
│ ├── DbgEngThread.cs # Dedicated MTA thread for COM
│ ├── DbgEngManager.cs # Kernel debug session manager
│ ├── DebugEventCallbacks.cs # Breakpoint/exception/module events
│ ├── OutputCapture.cs # Command output capture
│ └── Interop/ # P/Invoke, constants
├── Guest/
│ └── GuestExecManager.cs # Guest command execution + file transfer
├── UserModeDebug/
│ ├── FridaManager.cs # Frida CLI wrapper
│ ├── DbgsrvManager.cs # Remote user-mode debugging via dbgsrv
│ └── TtdManager.cs # Time Travel Debugging
└── Tools/
├── VmTools.cs # vm_* tools
├── KernelDebugTools.cs # kd_* tools
├── GuestTools.cs # guest_* tools
├── UserModeDebugTools.cs # umd_* tools
└── MetaTools.cs # get_system_state
src/WinDbgMCP.Tests/ # Unit tests (126 tests)
```
## 运行测试
```
dotnet test src/WinDbgMCP.Tests/WinDbgMCP.Tests.csproj
```
## 技术栈
| 组件 | 技术 |
|---|---|
| 运行时 | .NET 8 (C#) |
| MCP SDK | [ModelContextProtocol](https://github.com/modelcontextprotocol/csharp-sdk) 0.1.0-preview.12 |
| DbgEng | 原生 COM 互操作 (`dbgeng.dll`) |
| 虚拟机控制 | VMware vmrun CLI |
| 用户模式钩子 | Frida (frida-tools Python CLI) |
| 远程调试 | dbgsrv.exe (WinDbg 组件) |
| TTD | TTD.exe (时间旅行调试) |
## 许可证
MIT
appsettings.json 中的所有内容都只是默认值——LLM 可以在运行时通过 vm_set_target 更改虚拟机目标、凭据、KDNET 密钥等。仅当您想设置初始配置时才展开。
将 `src/WinDbgMCP.Server/appsettings.example.json` 复制到 `appsettings.json` 并编辑:
```
{
"Vm": {
"VmxPath": "C:\\path\\to\\your\\vm.vmx",
"VmrunPath": "C:\\Program Files (x86)\\VMware\\VMware Workstation\\vmrun.exe",
"VmPassword": "",
"GuestUsername": "YourUser",
"GuestPassword": "YourPass"
},
"KernelDebug": {
"Transport": "kdnet",
"Kdnet": {
"Port": 50000,
"Key": "your.kdnet.key.here"
},
"SymbolPath": "srv*C:\\Symbols*https://msdl.microsoft.com/download/symbols"
},
"Guest": {
"FridaPort": 27042,
"DbgsrvPort": 5064
}
}
```
标签:AI代理调试, BSOD检测, C#编程, DAST, DbgEng接口, dbgsrv调试服务, Frida动态插桩, KDNET网络调试, LLM工具集成, MCP协议, .NET框架, TLS抓取, TTD时间旅行调试, VMware虚拟化, Windows系统, 云资产清单, 内核调试, 分布式计算, 威胁情报, 开发者工具, 异常处理, 性能分析, 恶意软件分析, 情报收集, 执行控制, 断点管理, 漏洞研究, 用户模式调试, 网络安全, 虚拟机控制, 调试, 调试命令, 软件安全, 逆向工程, 隐私保护