
خادم MCP (بروتوكول سياق النموذج) يحول جميع وظائف مصحح الأخطاء pybag Windows إلى أدوات MCP أصلية. يسمح للعملاء المتوافقين مع MCP (Claude Desktop, Claude Code, Cowork, OpenAI Codex CLI, Cursor، والعوامل المخصصة) بالتحكم في عمليات وضع المستخدم، وجلسات kernel، وتحليل تفريغ الأعطال من خلال استدعاءات JSON منظمة.
خادم MCP (بروتوكول السياق النموذجي) يعرض كل دالة من دوال مصحح أخطاء Windows في pybag كأداة MCP أصلية. يمنح أي عميل متوافق مع MCP (Claude Desktop، Claude Code، Cowork، OpenAI Codex CLI، Cursor، والعوامل المخصصة) تحكمًا كاملاً في عمليات وضع المستخدم، وجلسات النواة، وتحليل تفريغ الأعطال — كل ذلك من خلال استدعاءات أدوات مقولبة مع استجابات JSON منظمة.
git clone https://github.com/your-username/windbg-mcp.git cd windbg-mcp
### 2. تثبيت تبعيات بايثون```bat
pip install pybag mcp
قم بتنزيل Windows SDK واختر Debugging Tools for Windows أثناء الإعداد: https://developer.microsoft.com/en-us/windows/downloads/windows-sdk/
يعمل الخادم كعملية stdio محلية. جميع العملاء أدناه يطلقونه بنفس الطريقة — python <path-to>/windbg_mcp.py — لكن لكل منها تنسيق إعدادات خاص به.
قم بتعديل ملف إعدادات Claude Desktop وأضف الإدخال windbg-mcp:
موقع ملف الإعدادات:
%APPDATA%\Claude\claude_desktop_config.jsonأعد تشغيل Claude Desktop. ستظهر جميع أدوات التصحيح البالغ عددها 55 تلقائياً.
---
### Claude Code (CLI)
قم بتشغيل الأمر التالي مرة واحدة لتسجيل الخادم. يخزن Claude Code الإدخال
في إعدادات MCP config الخاصة به ويجعل الأدوات متاحة في كل جلسة لاحقة.```bash
claude mcp add windbg-mcp python C:\path\to\windbg-mcp\windbg_mcp.py
للتحقق من تسجيل الخادم:```bash claude mcp list
لإزالته لاحقًا:```bash
claude mcp remove windbg-mcp
هناك طريقتان لإضافة WinDbg MCP إلى Cowork: عبر إعدادات JSON (سريع) أو
عن طريق تثبيته كحزمة إضافة .mcpb (قابلة للنقل، قابلة للمشاركة).
3. احفظ وأعد تشغيل Cowork. ستكون الأدوات متاحة في جلستك التالية.
#### الخيار ب — التثبيت كحزمة إضافات `.mcpb`
ملف `.mcpb` هو أرشيف مضغوط لدليل الإضافات الذي يمكن لـ Cowork تثبيته مباشرة. هذا هو الأسلوب الموصى به عند مشاركة الخادم مع فريق أو عبر الأجهزة.
**الخطوة 1 — بناء ملف `.mcpb`**
من جذر المستودع المستنسخ، شغّل:```bat
powershell -Command "Compress-Archive -Path '.\*' -DestinationPath 'windbg-mcp.zip'; Rename-Item 'windbg-mcp.zip' 'windbg-mcp.mcpb'"
هذا يُنشئ windbg-mcp.mcpb في الدليل الحالي، ويضم windbg_mcp.py وmanifest.json وأي ملفات مشروع أخرى.
الخطوة 2 — التثبيت في Cowork
windbg-mcp.mcpb.manifest.json من الحزمة، ويسجِّل خادم MCP، ويجعل جميع الأدوات متاحة فورًا — دون الحاجة إلى تهيئة مسار يدوية.ملف manifest.json المضمَّن في هذا المستودع مُهيَّأ بالفعل بشكل صحيح:```json
{
"manifest_version": "0.2",
"name": "windbg-mcp",
"version": "1.0.0",
"description": "WinDbg MCP — full Windows debugger control via MCP tools",
"server": {
"type": "python",
"entry_point": "windbg_mcp.py",
"mcp_config": {
"command": "python",
"args": ["${__dirname}/windbg_mcp.py"]
}
}
}
`${__dirname}` يتم تحليلها وقت التثبيت إلى الدليل الذي فك فيه Cowork الحزمة، لذا لا تحتاج إلى ترميز أي مسارات بشكل ثابت.
---
### واجهة سطر الأوامر Codex CLI من OpenAI
أضف الخادم إلى ملف إعدادات Codex CLI الخاص بك. يوجد الملف عادةً في
`~/.codex/config.json` (لينكس/ماك) أو `%USERPROFILE%\.codex\config.json` (ويندوز).```json
{
"mcpServers": {
"windbg-mcp": {
"command": "python",
"args": ["C:\\path\\to\\windbg-mcp\\windbg_mcp.py"]
}
}
}
بمجرد الحفظ، ابدأ جلسة Codex جديدة. ستكون أدوات WinDbg متاحة للنموذج لاستدعائها.
4. حفظ. سيتصل Cursor بالخادم في جلسته التالية من Composer.
---
### Continue.dev
أضف ما يلي إلى ملف `~/.continue/config.json` الخاص بك (أو ملف `.continue/config.json` على مستوى مساحة العمل):```json
{
"experimental": {
"modelContextProtocolServers": [
{
"transport": {
"type": "stdio",
"command": "python",
"args": ["C:\\path\\to\\windbg-mcp\\windbg_mcp.py"]
}
}
]
}
}
أعد تحميل امتداد Continue. ستظهر أدوات التصحيح الـ55 في قائمة الأدوات.
إذا كنت تقوم ببناء وكيل خاص بك أو خط أنابيب أتمتة، فاتصل بـ WinDbg MCP عبر نقل stdio القياسي الخاص بـ MCP. يتحدث الخادم JSON-RPC 2.0 عبر stdin/stdout.
mcp SDK)```pythonimport asyncio from mcp import ClientSession, StdioServerParameters from mcp.client.stdio import stdio_client
server_params = StdioServerParameters( command="python", args=[r"C:\path\to\windbg-mcp\windbg_mcp.py"], )
async def main(): async with stdio_client(server_params) as (read, write): async with ClientSession(read, write) as session: await session.initialize()
# List all available tools
tools = await session.list_tools()
print([t.name for t in tools.tools])
# Load a crash dump
result = await session.call_tool(
"load_dump",
arguments={"path": r"C:\crashes\crash.dmp"},
)
print(result.content)
# Read 64 bytes at RSP
result = await session.call_tool(
"read_mem",
arguments={"addr": "0x00000000001FF000", "size": 64},
)
print(result.content)
asyncio.run(main())
#### TypeScript / Node.js (باستخدام حزمة `@modelcontextprotocol/sdk`)```typescript
import { Client } from "@modelcontextprotocol/sdk/client/index.js";
import { StdioClientTransport } from "@modelcontextprotocol/sdk/client/stdio.js";
const transport = new StdioClientTransport({
command: "python",
args: ["C:\\path\\to\\windbg-mcp\\windbg_mcp.py"],
});
const client = new Client({ name: "my-agent", version: "1.0.0" }, {});
await client.connect(transport);
// Call a tool
const result = await client.callTool({
name: "load_dump",
arguments: { path: "C:\\crashes\\crash.dmp" },
});
console.log(result.content);
await client.close();
from langchain_mcp_adapters.tools import load_mcp_tools from mcp import ClientSession, StdioServerParameters from mcp.client.stdio import stdio_client
server_params = StdioServerParameters( command="python", args=[r"C:\path\to\windbg-mcp\windbg_mcp.py"], )
async def get_tools(): async with stdio_client(server_params) as (read, write): async with ClientSession(read, write) as session: await session.initialize() return await load_mcp_tools(session)
#### JSON-RPC المباشر عبر stdio (مستقل عن اللغة)
يتواصل الخادم عبر رسائل JSON-RPC 2.0 المفصولة بأسطر جديدة. يمكنك تشغيله
من أي لغة عن طريق الكتابة إلى stdin الخاص بالعملية والقراءة من stdout:```
→ {"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2024-11-05","capabilities":{},"clientInfo":{"name":"my-client","version":"1.0"}}}
← {"jsonrpc":"2.0","id":1,"result":{"protocolVersion":"2024-11-05","capabilities":{...},"serverInfo":{"name":"WinDbg MCP","version":"1.0.0"}}}
→ {"jsonrpc":"2.0","id":2,"method":"tools/call","params":{"name":"load_dump","arguments":{"path":"C:\\crashes\\crash.dmp"}}}
← {"jsonrpc":"2.0","id":2,"result":{"content":[{"type":"text","text":"{\"status\": \"ok\", ...}"}]}}
create — يطلق عملية جديدة تحت المصحح. اضبط initial_break=True (الافتراضي) للتوقف عند نقطة دخول العملية.
attach — يلحق بعملية قيد التشغيل. قدم إما pid (عدد صحيح) أو name (اسم ملف العملية). لا تقدم كليهما.
kernel_attach — يتصل بمصحح نواة بعيد. يستخدم connect_string بناء جملة KD، مثل "net:port=55000,key=1.2.3.4".
load_dump — يفتح ملف .dmp لتحليل ما بعد الوفاة. يعيد عنوان التعطل وأقرب رمز فورًا.
connect — يتصل بخادم عمليات لتصحيح الأخطاء عن بُعد في وضع المستخدم. يستخدم options بناء جملة اتصال DbgEng، مثل "tcp:server=192.168.1.10,port=5555".
go — يستأنف التنفيذ ويُغلَق حتى الحدث التالي للمصحح (نقطة توقف، استثناء، أو مهلة زمنية). يعيد RIP الجديد وأي لقطات تم جمعها أثناء التشغيل.
step_into — يتقدم إلى التعليمية التالية، متبعًا الاستدعاءات داخل الوظائف المُستدعاة.
step_over — يتجاوز التعليمية التالية، معاملًا الاستدعاءات كخطوة واحدة.
step_out — يعمل حتى عودة الوظيفة الحالية.
goto — يعمل حتى الوصول إلى رمز محدد أو عنوان سداسي عشري، مثل "Kernel32!ExitProcess" أو "0x7fff12340000".
trace — يُجري N من التكرارات الفردية ويُسجل كل تعليمة تم زيارتها.
bp — يُعين نقطة توقف برمجية (كودية) عند رمز أو عنوان.
expr: رمز ("ntdll!NtCreateFile") أو عنوان سداسي عشري ("0x7ff800001234")capture: عندما يكون true (الافتراضي) يُحفظ تلقائيًا الحالة الكاملة — السجلات، المكدس، الذاكرة — إلى مخزن اللقطات في كل مرة تُطلق فيها نقطة التوقف هذهaction: "go" (الافتراضي) يواصل التنفيذ بعد اللقطة؛ "break" يتوقفoneshot: يزيل نقطة التوقف بعد إطلاقها مرة واحدةpasscount: تُطلق فقط بعد N مرور في الموقعhw_bp — يُعين نقطة توقف عتادية/بيانات (نقطة مراقبة).
addr: عنوان سداسي عشري للمراقبةsize: عرض المراقبة بالبايت — 1 أو 2 أو 4 أو 8 (الافتراضي 4)access: "e" تنفيذ، "w" كتابة (الافتراضي)، "r" قراءة/كتابةcapture، action، oneshot: نفس دلالات bplist_bps — يعيد جميع نقاط التوقف النشطة حاليًا مع معرفاتها وتعبيراتها وأنواعها وإعداداتها.
remove_bp / enable_bp / disable_bp — إدارة نقاط التوقف بواسطة id المُعاد من bp أو hw_bp.
نقاط التوقف مع capture: true (الافتراضي) تُحفظ تلقائيًا لقطة كاملة للمصحح في كل مرة تُطلق. تتضمن اللقطة جميع السجلات، وسلسلة الاستدعاءات، و64 بايت من ذاكرة المكدس عند RSP، و32 بايت من الكود عند RIP. تتراكم اللقطات في مخزن ويمكن استردادها في أي وقت باستخدام get_captures.
get_captures — يعيد جميع اللقطات التي تم جمعها منذ آخر clear_captures. تحتوي كل لقطة على:
registers — جميع قيم السجلات كسلاسل سداسية عشرية {name: "0x..."}rip — مؤشر التعليمات لحظة اللقطةsymbol_at_rip — أقرب رمز إلى RIPinstruction — تفكيك التعليمية عند RIPstack — أعلى 10 إطارات لسلسلة الاستدعاءات مع العناوين وعناوين العودةcontext_memory.stack_at_rsp — 64 بايت عند RSP كسداسي عشري ومنسق وASCIIcontext_memory.code_at_rip — 32 بايت عند RIP كسداسي عشري ومنسقclear_captures — يمسح مخزن اللقطات. مفيد قبل بدء تشغيل جديد.
capture_state — يأخذ لقطة فورية عند الطلب للحالة الحالية. استخدمه عندما تكون متوقفًا بالفعل، بدلاً من انتظار إطلاق نقطة توقف.
read_mem — يقرأ size بايت خام من addr. يعيد البيانات كـ hex (مضغوط)، وformatted (بايت مفصول بمسافات)، وascii (أحرف قابلة للطباعة، . لغير القابلة للطباعة).
write_mem — يكتب بايتات إلى الذاكرة. data هي سلسلة سداسية عشرية - تتم إزالة المسافات والبادئات \x تلقائيًا، مثل "90909090"، أو "\\x90\\x90\\x90\\x90"، أو "90 90 90 90".
read_ptr — يقرأ count من القيم المتتالية بحجم المؤشر (4 بايت على 32 بت، 8 بايت على 64 بت) بدءًا من addr.
poi — يفك إشارة مؤشر واحد عند addr (مؤشر الاهتمام).
read_str — يقرأ سلسلة منتهية بالصفر. اضبط wide=true لـ UTF-16LE (WCHAR في Windows).
dump_mem — تفريغ منسق للكلمات المزدوجة/المؤشرات، يعادل dd/dp في WinDbg.
mem_info — يعيد خصائص منطقة الذاكرة للصفحة التي تحتوي على addr: العنوان الأساسي، الحجم، النوع، الحالة، وأعلام الحماية.
mem_list — يسرد جميع مناطق الذاكرة الافتراضية في مساحة عنوان العملية المستهدفة.
get_regs — يعيد كل سجل متاح كـ {name: "0x..."}. تعتمد المجموعة الدقيقة على بنية الهدف (x86 مقابل x64).
get_reg — يعيد سجلًا واحدًا، مثل name="rax"، name="eflags".
set_reg — يكتب فوق سجل. يقبل value سلاسل سداسية عشرية ("0x1234") أو سلاسل أعداد صحيحة عشرية.
get_pc — يعيد مؤشر التعليمات مع تحليل الرمز ونص التعليمية المُفككة في ذلك العنوان.
get_sp — يعيد قيمة مؤشر المكدس الحالي.
resolve — يحل اسم رمز إلى عنوانه الافتراضي. استخدم تنسيق Module!Function، مثل "Kernel32!WriteFile"، "ntdll!NtCreateFile".
find_symbols — بحث رمز بحرف بدل، مثل "ntdll!*Alloc*"، "kernel32!*File*". يعيد جميع سلاسل الرموز المطابقة.
addr_to_symbol — يحل عكسيًا عنوانًا افتراضيًا إلى أقرب اسم رمز.
disasm — يفكك count تعليمة بدءًا من addr. الافتراضي هو RIP الحالي إذا لم يُعط عنوان.
whereami — يعيد وصفًا قابلًا للقراءة البشرية للوحدة والوظيفة والإزاحة في العنوان المحدد.
list_modules — يسرد جميع الوحدات المحملة في الهدف، مع عنوانها الأساسي وحجمها.
module_info — يعيد نقطة الدخول وقائمة الأقسام (الاسم، العنوان الافتراضي، الحجم) لوحدة معينة، مثل "kernel32.dll"، "ntdll.dll".
get_exports — يعيد جدول التصدير الكامل لوحدة كقائمة من السلاسل.
get_imports — يعيد جدول الاستيراد الكامل لوحدة كقائمة من السلاسل.
list_threads — يسرد جميع الخيوط في العملية المستهدفة.
get_thread — يعيد سياق الخيط النشط حاليًا.
set_thread — يبدّل سياق الخيط النشط بواسطة معرف الخيط (من list_threads).
get_stack — يعيد سلسلة الاستدعاءات كبيانات منظمة. يتضمن كل إطار عنوان التعليمية وعنوان العودة ومؤشر الإطار.
get_teb — يعيد عنوان كتلة بيئة الخيط للخيط الحالي.
get_peb — يعيد عنوان كتلة بيئة العملية.
get_handles — يسرد جميع المقابض المفتوحة في العملية المستهدفة.
get_bitness — يعيد 32 أو 64 اعتمادًا على بنية الهدف.
raw — ينفذ أي سلسلة أمر WinDbg ويعيد الناتج كنص. استخدم هذا كمنفذ طوارئ لأي شيء لا تغطيه الأدوات الأخرى:```
raw(cmd="!heap -stat")
raw(cmd="dt _PEB @$peb")
raw(cmd="!locks")
raw(cmd="lm")
raw(cmd="!address @rsp")
---
## سير العمل النموذجية
### التحقق من الاستغلال```
1. create(path="C:/target/vuln.exe", args="exploit_input.bin")
2. bp(expr="vuln!processInput+0x2A", action="break")
3. go(timeout=15000)
4. get_captures()
In get_captures, inspect captures[0].registers.rip:
"0x4141414141414141" — تتحكم في RIP باستخدام بايتات 'A'تحقق من captures[0].context_memory.stack_at_rsp.formatted لرؤية الحشو أو عناوين العودة أو بايتات الشيلكود على المكدس.
### التحقق من Heap spray```
1. attach(name="target.exe")
2. hw_bp(addr="0x1001F000", size=8, access="w", action="break")
3. go()
4. get_captures() → see what wrote to the spray address
5. read_mem(addr="0x1001EFC0", size=128) → surrounding memory context
### تصحيح النواة عن بُعد```
1. kernel_attach(connect_string="net:port=55000,key=1.2.3.4")
2. list_modules() → all loaded kernel modules
3. module_info(name="ntoskrnl.exe") → entry point and sections
4. raw(cmd="!process 0 0") → list all processes from kernel context
5. raw(cmd="!pcr") → processor control region
---
## نصائح
**مسار الرموز** — إذا لم يُرجع تحليل الرموز أي نتائج، قم بتكوين خادم رموز Microsoft:```
raw(cmd=".sympath srv*C:\\symbols*https://msdl.microsoft.com/download/symbols")
raw(cmd=".reload")
ضبط المهلة الزمنية — go() تبلغ القيمة الافتراضية 30 ثانية. بالنسبة للأهداف التي تعمل لفترة أطول قبل الوصول إلى نقطة توقف:```
go(timeout=120000) # 2 minutes
go(timeout=300000) # 5 minutes
**تنسيق العنوان** — جميع معاملات `addr` تقبل سلاسل سداسية عشرية (`"0x1234abcd"`, `"7fff12340000"`) أو أعدادًا صحيحة. البادئة `0x` اختيارية للقيم السداسية العشرية.
**التحقق من شيلكود** — بعد الالتقاط، استخدم `read_mem` و `disasm` على العنوان حيث يجب أن يهبط شيلكود الخاص بك. إذا أظهر `disasm` التعليمات المقصودة، فإن الحمولة قد وصلت سليمة.
**بعد `terminate` أو `detach`** — يتم مسح جميع الالتقاطات ونقاط التوقف تلقائيًا. اتصل بـ `create` أو `attach` لبدء جلسة جديدة.
**`capture_state` مقابل `get_captures`** — استخدم `capture_state` للحصول على لقطة عند الطلب عندما تكون متوقفًا بالفعل عند نقطة توقف. استخدم `get_captures` لاسترجاع الحالة التي تم حفظها تلقائيًا في كل مرة يتم فيها تشغيل نقطة توقف أثناء استدعاء `go`.
**أوامر `raw` للنواة** — امتدادات تصحيح أخطاء النواة الشائعة التي تعمل بشكل جيد من خلال `raw`:```
raw(cmd="!process 0 0") → list all processes
raw(cmd="!thread") → current thread details
raw(cmd="!irql") → current IRQL
raw(cmd="!pcr") → processor control region
raw(cmd="!pte <addr>") → page table entry for an address
raw(cmd="dt nt!_EPROCESS @$proc") → dump EPROCESS structure
MIT
| الأداة | المعاملات | النتائج |
|---|
status | — | {connected, type, pid, bitness} |
list_processes | — | [{pid, name, description}] |
create | path (مطلوب), args, initial_break | {status, pid, bitness} |
attach | pid أو name (وليس كلاهما), initial_break | {status, pid, bitness} |
kernel_attach | connect_string (مطلوب), initial_break | {status, type, connect_string} |
load_dump | path (مطلوب) | {status, bitness, rip, symbol_at_rip} |
connect | options (مطلوب) | {status, options} |
detach | — | {status} |
terminate | — | {status} |
| الأداة | المعاملات | النتائج |
|---|
go | timeout (مللي ثانية، الافتراضي 30000) | {status, rip, symbol, new_captures, captures} |
step_into | count (الافتراضي 1) | {rip, instruction, symbol} |
step_over | count (الافتراضي 1) | {rip, instruction, symbol} |
step_out | — | {rip, instruction, symbol} |
goto | expr (مطلوب) | {rip, symbol} |
trace | count (الافتراضي 10) | {instructions: [{rip, instruction, symbol}], count} |
| الأداة | المعاملات | النتائج |
|---|
bp | expr (مطلوب), capture, action, oneshot, passcount | {id, expr, addr, capture} |
hw_bp | addr (مطلوب), size, access, capture, action, oneshot | {id, addr, size, access} |
list_bps | — | [{id, expr, type, capture, action, ...}] |
remove_bp | id (مطلوب) | {status, id} |
enable_bp | id (مطلوب) | {status, id} |
disable_bp | id (مطلوب) | {status, id} |
| الأداة | المعاملات | النتائج |
|---|
get_captures | — | {count, captures: [{bp_id, expr, timestamp, registers, rip, symbol_at_rip, instruction, stack, context_memory}]} |
clear_captures | — | {status} |
capture_state | — | {timestamp, registers, rip, symbol_at_rip, instruction, disasm_5, stack_at_rsp, call_stack} |
| الأداة | المعاملات | النتائج |
|---|
read_mem | addr (مطلوب), size (الافتراضي 16) | {addr, size, hex, formatted, ascii} |
write_mem | addr (مطلوب), data (مطلوب، سلسلة سداسية عشرية) | {status, addr, bytes_written} |
read_ptr | addr (مطلوب), count (الافتراضي 1) | {addr, values: ["0x..."]} |
poi | addr (مطلوب) | {addr, value} |
read_str | addr (مطلوب), wide (الافتراضي false) | {addr, value, wide} |
dump_mem | addr (مطلوب), count (الافتراضي 8) | {addr, output} |
mem_info | addr (مطلوب) | {addr, info} |
mem_list | — | [region_description_strings] |
| الأداة | المعاملات | النتائج |
|---|
get_regs | — | {rax, rbx, rcx, rdx, rsi, rdi, rbp, rsp, rip, r8–r15, eflags, ...} |
get_reg | name (مطلوب) | {name, value} |
set_reg | name (مطلوب), value (مطلوب) | {status, name, value} |
get_pc | — | {value, symbol, instruction} |
get_sp | — | {value} |
| الأداة | المعاملات | النتائج |
|---|
resolve | name (مطلوب) | {name, addr} أو {name, addr: null, error} |
find_symbols | pattern (مطلوب) | [symbol_strings] |
addr_to_symbol | addr (مطلوب) | {addr, symbol} |
disasm | addr (الافتراضي: RIP الحالي), count (الافتراضي 10) | {addr, output} |
whereami | addr (اختياري، الافتراضي: RIP الحالي) | {description} |
| الأداة | المعاملات | النتائج |
|---|
list_modules | — | [{name, base, size}] |
module_info | name (مطلوب) | {name, entry_point, sections} |
get_exports | name (مطلوب) | [export_strings] |
get_imports | name (مطلوب) | [import_strings] |
| الأداة | المعاملات | النتائج |
|---|
list_threads | — | [thread_description_strings] |
get_thread | — | {current_thread} |
set_thread | id (مطلوب) | {status, thread} |
get_stack | frames (الافتراضي 20) | {frames: [{frame, addr, return_addr, frame_ptr}], count} |
get_teb | — | {addr} |
get_peb | — | {addr} |
| الأداة | المعاملات | النتائج |
|---|
get_handles | — | [handle_description_strings] |
get_bitness | — | {bits} |
raw | cmd (مطلوب) | {output} |