Files
John Smith e80adf7de0 feat: re-winedbg MCP server for headless Windows-binary debugging from Linux/macOS
Adds the 10th MCP server to the RE-AI plugin. re-winedbg drives the
winedbg gdbserver (a debugger shim that ships with Wine) plus a GDB
client subprocess so an AI agent can attach to a Windows .exe and
observe its behavior at runtime.

Highlights
- 19 vendor-neutral tools: check_winedbg, launch_under_wine,
  start_winedbg_gdbserver, attach_winedbg_gdbserver, the 14 standard
  debug primitives (set_breakpoint / remove_breakpoint /
  continue_execution / step_into / step_over / step_out /
  read_registers / write_register / read_memory / write_memory /
  info_modules / info_threads / backtrace), and gef_trace_breakpoint.
- set_breakpoint accepts <module>+0x<RVA> targets and resolves them
  via a per-module base-address cache populated from
  info sharedlibrary on first attach.
- gef_trace_breakpoint is the structured replacement for the
  manual 'commands N; silent; printf ...; continue; end' workaround
  re-vm-reverse/SKILL.md:67 had been doing by hand.
- Reuses re-gdb's GDBSession for the gdb-client side. New CLI
  parsers (gdb_text.py) turn info sharedlibrary / info registers /
  stopped events into structured dicts.
- Each session gets its own WINEPREFIX under
  ~/.cache/re-ai-wine/<session>/ — the global ~/.wine is never
  touched, and end_session refuses to wineserver -k any prefix
  outside that cache root.

Install + manifest
- install.sh gets a best-effort wine + winedbg install path
  (apt / dnf / brew), opt-out via RE_AI_SKIP_WINE=1. install.bat
  discovers wine / winedbg and warns the user that re-winedbg
  requires WSL on Windows hosts.
- scripts/check_deps.py gains check_wine() + a dependency row.
- .mcp.json adds the 10th server entry with CLAUDE_PLUGIN_ROOT and
  env defaults for WINEDBG_PATH / WINE_PATH / WINESERVER_PATH.
- verify.sh + verify.bat bump 9 -> 10 servers.

Tests
- tests/test_plugin_manifest.py gains test_mcp_json_includes_re_winedbg.
- tests/test_servers_import.py adds the re-winedbg row to the
  parametrized expected-tools list.
- tests/test_re_winedbg.py is new: 7 soft-skip tests covering
  check_winedbg, the GDB-CLI parsers, the wineserver-kill safety
  guard, and a launch_under_wine smoke test (skipped without
  RE_AI_WIN32_FIXTURE).
- All existing tests continue to pass (48 passed, 27 skipped;
  2 pre-existing Triton/z3 failures unrelated to this change).
- tests/test_no_vendor_leakage.py still passes 14/14.

Skills
- re-dynamic-analysis gains a 'Windows .exe on Linux (via Wine +
  winedbg)' workflow section. Frontmatter unchanged (description
  is still 318 chars).
- re-vm-reverse Stage 4 now uses re-winedbg.gef_trace_breakpoint on
  Windows targets; the old step_count loop is retained as the
  Linux-ELF fallback. The Limitations bullet at the old line 139
  is updated to match.

Other
- .claude-plugin/plugin.json and root pyproject.toml bumped to 2.4.0.
- CHANGELOG.md gains a 2.4.0 entry.
- docs/MCP_SERVERS.md (working-tree only) gains a full re-winedbg
  section with the tool table, install command, per-session-prefix
  behavior, and end-to-end example.

Vendor neutrality: no commercial anti-tamper product, publisher,
or game title appears in any shipped file. The new strings
(winedbg / wine / wineserver / WINEDBG_PATH / WINE_PATH /
WINESERVER_PATH / WINEPREFIX / re-winedbg) are tool / env-var /
server-slug identifiers.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-05 13:28:03 -04:00

52 lines
2.1 KiB
Batchfile

@echo off
REM RE-AI plugin verifier (Windows). Smoke tests the install.
setlocal EnableDelayedExpansion
set "PLUGIN_ROOT=%~dp0"
if "%PLUGIN_ROOT:~-1%"=="\" set "PLUGIN_ROOT=%PLUGIN_ROOT:~0,-1%"
if exist "%PLUGIN_ROOT%\.venv-re-ai\Scripts\activate.bat" (
call "%PLUGIN_ROOT%\.venv-re-ai\Scripts\activate.bat"
set "PYTHON_BIN=python"
echo ^(using venv^)
) else (
set "PYTHON_BIN=python"
)
set "PASS=0"
set "FAIL=0"
echo === RE-AI verify ===
REM Manifest sanity
echo . plugin.json is valid JSON
"%PYTHON_BIN%" -c "import json; json.load(open('%PLUGIN_ROOT%\.claude-plugin\plugin.json'))"
if errorlevel 1 ( set "FAIL=1" ) else ( set /a "PASS+=1" & echo PASS )
echo . .mcp.json is valid JSON
"%PYTHON_BIN%" -c "import json; json.load(open('%PLUGIN_ROOT%\.mcp.json'))"
if errorlevel 1 ( set "FAIL=1" ) else ( set /a "PASS+=1" & echo PASS )
echo . plugin.json has 'name' field
"%PYTHON_BIN%" -c "import json; assert 'name' in json.load(open('%PLUGIN_ROOT%\.claude-plugin\plugin.json'))"
if errorlevel 1 ( set "FAIL=1" ) else ( set /a "PASS+=1" & echo PASS )
echo . .mcp.json declares 10 servers with the 8 originals + re-il2cpp + re-winedbg
"%PYTHON_BIN%" -c "import json; d=json.load(open('%PLUGIN_ROOT%\.mcp.json'))['mcpServers']; originals={'re-rizin','re-capa','re-lief','re-llm-decompile','re-mitm2swagger','re-kaitai','re-gdb','re-triton'}; assert len(d)==10 and originals.issubset(d) and 're-il2cpp' in d and 're-winedbg' in d, d"
if errorlevel 1 ( set "FAIL=1" ) else ( set /a "PASS+=1" & echo PASS )
if exist "%PLUGIN_ROOT%\tests" (
"%PYTHON_BIN%" -m pytest -q "%PLUGIN_ROOT%\tests\test_skills_frontmatter.py" >nul 2>&1
if errorlevel 1 ( set "FAIL=1" ) else ( set /a "PASS+=1" & echo test_skills_frontmatter.py PASS )
"%PYTHON_BIN%" -m pytest -q "%PLUGIN_ROOT%\tests\test_plugin_manifest.py" >nul 2>&1
if errorlevel 1 ( set "FAIL=1" ) else ( set /a "PASS+=1" & echo test_plugin_manifest.py PASS )
)
echo.
echo Passed: %PASS%
echo Failed: %FAIL%
if "%FAIL%"=="0" ( echo All checks passed. ) else ( echo Some checks failed. )
exit /b %FAIL%
endlocal