--- name: vuln-hunter description: Hunt for vulnerabilities in a running debuggee by analyzing imports/exports, triaging attack surface, and iteratively testing for bugs with PoC generation. allowed-tools: mcp__x64dbg__list_sessions, mcp__x64dbg__connect_to_session, mcp__x64dbg__get_debugger_status, mcp__x64dbg__read_memory, mcp__x64dbg__get_register, mcp__x64dbg__get_all_registers, mcp__x64dbg__set_register, mcp__x64dbg__disassemble, mcp__x64dbg__set_breakpoint, mcp__x64dbg__clear_breakpoint, mcp__x64dbg__list_breakpoints, mcp__x64dbg__step_over, mcp__x64dbg__step_into, mcp__x64dbg__go, mcp__x64dbg__pause, mcp__x64dbg__run_to_return, mcp__x64dbg__set_comment, mcp__x64dbg__set_label, mcp__x64dbg__get_symbol, mcp__x64dbg__get_label, mcp__x64dbg__eval_expression, mcp__x64dbg__execute_command, mcp__x64dbg__refresh_gui, mcp__x64dbg__get_memory_map, mcp__x64dbg__trace_over, mcp__x64dbg__trace_into, mcp__x64dbg__write_memory, mcp__x64dbg__allocate_memory, mcp__x64dbg__assemble, mcp__x64dbg__get_latest_event, mcp__x64dbg__wait_for_event, mcp__x64dbg__start_session, mcp__x64dbg__terminate_session, mcp__x64dbg__disconnect, AskUserQuestion, Bash, Read, Write, Skill --- # vuln-hunter Hunt for vulnerabilities in a running debuggee. Performs import/export reconnaissance, triages attack surface by I/O context, then iteratively tests for bugs (buffer overflows, integer wraps, logic flaws, etc.) and builds proof-of-concept exploits. ## Prerequisites - The target program must be loaded in x64dbg and paused (at entrypoint or a function of interest) - Be conservative with the context window — disassemble on demand, read memory on demand, do not dump large regions speculatively ## Instructions ### 1. Connect and verify state Confirm the debugger is connected and the debuggee is paused: 1. Call `mcp__x64dbg__get_debugger_status` — verify status is `paused` 2. If running, call `mcp__x64dbg__pause` 3. Call `mcp__x64dbg__get_register` for `rip` (64-bit) or `eip` (32-bit) to determine bitness and current location 4. Call `mcp__x64dbg__get_memory_map` to get an overview of loaded modules Note the main module name and base address for subsequent steps. IF the debuggee looks packed (e.g., entry point is in a non-standard section, imports look obfuscated, or YARA signatures match known packers), run the `/find-oep` skill first to unpack and find the real entry point. ### 2. Reconnaissance — imports and exports The goal is to identify all program entry points that handle external (attacker-controllable) input. #### 2a. Enumerate imports and exports Use the LIEF-based enumeration script to parse the PE's imports, exports, and security features: ``` Bash("python ${SKILL_DIR}/enum_imports.py --output imports.json") ``` **Packed binaries**: LIEF parses the on-disk PE, so packed binaries will show only the packer's minimal IAT (e.g. `GetProcAddress`, `LoadLibraryA`). For packed targets: 1. Unpack first (e.g. via `/find-oep`) 2. Take a `/state-snapshot` to dump all memory to disk 3. Re-run the script with `--snapshot-dir --base ` to parse the resolved IAT from the memory dump instead Read the output and the generated JSON. Categorize each import by I/O context: | Category | Example APIs | |---|---| | **Network** | `recv`, `recvfrom`, `WSARecv`, `InternetReadFile`, `HttpQueryInfo`, `WinHttpReadData`, `getaddrinfo` | | **File** | `ReadFile`, `CreateFileA/W`, `fread`, `fgets`, `MapViewOfFile`, `NtReadFile`, `mmioOpen`, `mmioRead` | | **Registry** | `RegQueryValueExA/W`, `RegGetValueA/W`, `RegEnumValueA/W` | | **Environment** | `GetEnvironmentVariableA/W`, `getenv` | | **Command line** | `GetCommandLineA/W`, `CommandLineToArgvW` | | **Clipboard / UI** | `GetClipboardData`, `GetWindowTextA/W`, `GetDlgItemTextA/W` | | **IPC / Pipes** | `ReadFile` on pipe handles, `PeekNamedPipe`, `TransactNamedPipe` | | **Memory / String** | `memcpy`, `strcpy`, `strcat`, `sprintf`, `wcscat`, `lstrcpyA/W`, `MultiByteToWideChar` — these are sinks, not sources, but are critical for buffer overflow detection | | **Allocation** | `malloc`, `HeapAlloc`, `VirtualAlloc`, `LocalAlloc`, `GlobalAlloc` — track buffer sizes | Also note dangerous formatting/conversion functions: `sprintf`, `vsprintf`, `swprintf`, `sscanf`, `atoi`, `atol`, `strtol` — these may be involved in format string or integer conversion bugs. Exports indicate externally callable interfaces (DLL entry points, COM interfaces, etc.) that may accept untrusted input. #### 2c. Find cross-references to I/O functions For each interesting import identified above, find where it is called in the main module. **Preferred approach — IAT byte-pattern search via Python/LIEF**: The most reliable way to find xrefs is to search the `.text` section for byte patterns that reference IAT entries. This works even when the debugger's `findcalls` command fails or returns incomplete results. Write and run an inline Python script: ```python import lief, struct binary = lief.parse("") disk_base = binary.optional_header.imagebase # e.g. 0x400000 runtime_base = # e.g. 0x160000 rebase = runtime_base - disk_base # Get .text section bytes text = [s for s in binary.sections if s.name == '.text'][0] text_data = bytes(text.content) text_va = disk_base + text.virtual_address # For each import, compute IAT VA using DISK base (not runtime base!) for imp in binary.imports: for entry in imp.entries: disk_iat_va = disk_base + entry.iat_address # Search for FF 15 (call dword ptr [IAT]) — direct callers pattern_call = b'\xff\x15' + struct.pack(' (jmp dword ptr [IAT]) — thunk stub pattern_jmp = b'\xff\x25' + struct.pack(' callers of the thunk if thunk_found: thunk_disk = thunk_runtime - rebase for i in range(len(text_data) - 4): if text_data[i] == 0xE8: rel32 = struct.unpack('") ``` Record each call site address. These are the **xrefs** — the primary targets for triage. **Important**: Be selective. Focus on the most security-relevant imports first (network inputs, file reads, string copies). Do not enumerate xrefs for every import — that would bloat the context. ### 3. Triage areas of interest For each xref group (organized by I/O function), evaluate the surrounding context: 1. **Disassemble** 30–50 instructions around each call site using `mcp__x64dbg__disassemble` 2. **Identify the containing function** — look for the function prologue (push rbp/ebp; mov rsp/esp pattern or similar) and note the function's start address 3. **Consider the actor** — who provides the input? - Remote attacker (network) → highest risk - Local attacker (file, registry, environment) → medium risk - Authenticated user (UI, clipboard) → lower risk but still relevant 4. **Consider the sink** — where does the input end up? - Fixed-size stack buffer → stack overflow potential - Heap buffer with unchecked size → heap overflow potential - Format string argument → format string vulnerability - Integer used in allocation size → integer overflow/wraparound - Used in control flow decision → logic flaw potential 5. **Label** each triaged function with a descriptive name via `mcp__x64dbg__set_label` (e.g., `vuln_candidate_recv_handler`, `vuln_candidate_file_parser`) 6. **Comment** each call site with a brief risk note via `mcp__x64dbg__set_comment` After triaging, present the ranked list to the user: ``` ## Triaged Attack Surface | Rank | Address | Function | I/O Source | Sink | Risk | |------|---------|----------|------------|------|------| | 1 | 0x... | ... | Network | Stack buffer | High | | 2 | 0x... | ... | File | Heap alloc | Medium | | ... | ... | ... | ... | ... | ... | ``` Ask the user via `AskUserQuestion`: "Here is the triaged attack surface. Which targets should I investigate? (all / specific ranks / let me choose)" ### 4. Bug hunting (iterative) For each selected target, perform the following loop. **Do one target at a time** to stay focused and conserve context. #### 4a. Deep analysis of the target function 1. Disassemble the full function (from prologue to retn) using `mcp__x64dbg__disassemble` 2. If the function is complex (>100 instructions), use `/decompile` via `Skill("decompile")` for a higher-level view 3. Identify: - **Buffer sizes** — look for `sub rsp, N` (stack frame), `push N` / `mov ecx, N` before `HeapAlloc`/`malloc`, static `.data`/`.bss` buffers - **Length checks** — are sizes validated before copy? Look for `cmp`, `ja`/`jb` guards - **Integer arithmetic** — addition/multiplication on sizes before allocation (wrapping potential). Look for `add`, `imul`, `shl` on values derived from input - **Loop bounds** — are they controlled by attacker input? - **Format strings** — is user input passed as format argument (first arg) to `sprintf`/`printf` family? - **Logic flaws** — off-by-one in comparisons, signed/unsigned confusion (`jl` vs `jb`), TOCTOU patterns - **Side effects** — does the function write to global state, file, or registry based on unchecked input? #### 4b. Formulate a hypothesis Based on the analysis, describe the suspected vulnerability: - **Type**: buffer overflow, integer overflow, format string, use-after-free, logic flaw, etc. - **Trigger**: what input triggers it (e.g., "a `recv` buffer > 256 bytes when the stack buffer is 256") - **Impact**: what happens if triggered (crash, code execution, info leak, etc.) Present the hypothesis to the user. #### 4c. Prepare instrumentation Set up the debugger to observe the target code path: 1. Set a breakpoint at the function entry via `mcp__x64dbg__set_breakpoint` 2. Set breakpoints at key points: the dangerous call (e.g., `strcpy`), the length check (if any), the return 3. If fine-grained observation is needed, use `/tracealyzer` via `Skill("tracealyzer")` to trace through the function #### 4d. Generate a test input Create an input that should trigger the suspected bug. Use `Bash` to write a Python script that generates the payload: - For network targets: a Python socket script that sends crafted data - For file targets: a Python script that writes a crafted file to disk - For other I/O: an appropriate delivery mechanism The test input should be **diagnostic first** — use recognizable patterns (e.g., `"A" * 300` for overflow, `"%x" * 20` for format string) to confirm the bug before refining to a PoC. Write the script to `./exploits/test_.py`. #### 4e. Trigger and observe 1. Tell the user what input to provide, or if the test script can deliver it automatically, run it via `Bash` 2. Call `mcp__x64dbg__go` to resume execution 3. Wait for a breakpoint hit or exception via `mcp__x64dbg__wait_for_event` or `mcp__x64dbg__get_debugger_status` 4. When paused: - Read registers via `mcp__x64dbg__get_all_registers` - Read the stack and relevant buffers via `mcp__x64dbg__read_memory` - Disassemble at the current location via `mcp__x64dbg__disassemble` - Check if the hypothesis is confirmed (e.g., buffer overwritten past boundary, EIP/RIP control, crash at expected location) 5. Document findings with comments and labels #### 4f. Assess result - **Bug confirmed**: proceed to PoC development (step 5) - **Bug not triggered**: refine the hypothesis or input, revisit the analysis. Consider: - Was the code path actually reached? Check if breakpoints were hit - Are there additional checks that prevent the bug? - Is the input being transformed before reaching the sink? - **Program crashed unexpectedly**: analyze the crash context. If the target needs restarting: - Use `mcp__x64dbg__execute_command("InitDebug")` to restart, or - Ask the user to restart the target if needed - Re-apply breakpoints and instrumentation Repeat steps 4a–4f for each target until bugs are found or all targets are exhausted. ### 5. Proof-of-concept development (iterative) For each confirmed bug, develop a PoC that demonstrates impact. #### 5a. Design the PoC Plan a PoC that demonstrates a meaningful impact: - **Crash PoC** (minimum): input that reliably crashes the target - **Info leak PoC**: input that causes the target to reveal memory contents - **Code execution PoC**: input that achieves a small demonstration — e.g., spawning `calc.exe`, writing a marker file, or connecting back to a listener Consider the target's mitigations: - ASLR, DEP/NX, stack cookies, CFG — check with `mcp__x64dbg__get_memory_map` (look at page protections) and examine the binary's PE headers - Adjust PoC strategy based on mitigations present #### 5b. Write the PoC script Write a Python PoC script to `./exploits/poc_.py`. The script should: - Be self-contained and well-commented - Include a description of the vulnerability at the top - Generate the exploit payload - Deliver it to the target (network send, file write, etc.) - Print status messages so the user can follow along #### 5c. Test the PoC 1. Ensure the target is running and instrumented (breakpoints at key locations) 2. Run the PoC script via `Bash` (or ask the user to trigger it if manual interaction is required) 3. Observe the result in the debugger 4. If the PoC fails: - Analyze why (wrong offset, mitigation blocked it, timing issue, etc.) - Refine the payload and retry - If the target crashed, restart it (see step 4f) 5. If the PoC succeeds: - Document the full exploitation chain - Capture relevant register/memory state as evidence Repeat steps 5a–5c until the PoC is reliable or the user decides to move on. ### 6. Report generation Ask via `AskUserQuestion`: "Would you like a markdown vulnerability report?" If yes, read the report template at `${CLAUDE_PLUGIN_ROOT}/skills/vuln-hunter/report_template.md` and fill in every section based on findings. Write the completed report to `./reports/vuln_report_.md` via `Write`. Omit table rows or sections that have no findings, but preserve the overall structure.