crash_monitor is a small Rust tool for monitoring a Windows program while it is being fuzzed. It attaches as a debugger, captures a memory dump when it observes an access violation, and exposes crash status to an external fuzzer over TCP.

The project keeps input generation and process monitoring separate. The fuzzer sends test cases; Crash Monitor watches what happens inside the target process.

Why monitor the process?

A network fuzzer can observe a timeout or a dropped connection, but those symptoms do not explain whether the target hit an access violation, exited normally, or simply stopped responding. A debugger can provide a more specific signal, along with the process state needed for investigation.

Crash Monitor focuses on that instrumentation layer. It does not generate test cases or determine whether a crash is exploitable. It records access-violation events and gives the fuzzer a way to notice them.

The debugger loop

The implementation uses Rust’s Windows bindings and the Win32 debugging API. In src/main.rs, the main loop:

  1. Starts the target executable supplied at the prompt.
  2. Attaches with DebugActiveProcess.
  3. Receives events through WaitForDebugEvent, tracking thread handles and exception information.
  4. On EXCEPTION_ACCESS_VIOLATION, updates the shared crash counters and attempts to write a dump.
  5. Detaches, attempts to terminate the target, and starts another monitoring cycle.

A separate thread serves the TCP status endpoint. The debugger and server share an Arc<CrashStatus> containing atomic counters, so the fuzzer can query status without directly participating in the debug-event loop.

Capturing crash dumps

When an access violation arrives, the monitor requests the faulting thread’s context and calls MiniDumpWriteDump with MiniDumpWithFullMemory and MiniDumpWithHandleData. The intention is to preserve more than a single exception address: the dump can be opened in a debugger to inspect memory and execution state.

Dump filenames encode the crash counter, exception code, access type, and exception address:

crash_{counter}_{exception_code}_{access_type}_{address}.dmp

The access type is derived from the exception record and labelled read, write, or dep. The dep label corresponds to an execute-access violation. These labels help with initial triage; they are not an exploitability classification or a deduplication scheme.

Connecting to boofuzz

The status server listens on TCP port 4444. On connection, it writes the decimal crash-status counter as text. The bundled boofuzz_fuzzer.py implements a custom BaseMonitor: after sending a test case, its post_send callback connects to the monitor and reads the response.

The example treats the exact response b"1" as a crash and returns False to boofuzz. Other responses return True. Crash Monitor’s own outer loop handles starting the target again; the example’s custom monitor does not configure separate start or stop callbacks.

The included target is Vulnserver. For a same-machine lab, the example’s target and monitor addresses can be set to loopback:

RHOST, RPORT = "127.0.0.1", 9999
M_RHOST, M_RPORT = "127.0.0.1", 4444

The monitor binds to 0.0.0.0:4444, not just loopback, and the status endpoint has no authentication. Restrict access with the lab network or host firewall; do not expose it to the internet.

Building and running

The repository documents a 32-bit Windows MSVC build using the nightly Rust toolchain. From a Windows environment with the required Rust and MSVC build tools:

rustup toolchain install nightly-i686-pc-windows-msvc
git clone https://github.com/talha/crash_monitor
cd crash_monitor
cargo +nightly-i686-pc-windows-msvc build --release

Run the monitor in an elevated PowerShell session, as documented in the repository:

.\target\release\crash_monitor.exe

At the process-path prompt, supply the target executable, for example C:\lab\vulnserver.exe. Configure the addresses in the supplied Python example, then start boofuzz:

py -3 -m pip install boofuzz==0.4.1
py -3 boofuzz_fuzzer.py

These commands reflect the repository’s documented setup, not a new compatibility test against current Windows or Rust releases. The project uses older dependency versions; consult the source and build output when reproducing it on a newer environment.

Scope and limitations

  • 32-bit Windows only. The published implementation does not provide x64 debugging support.
  • Access violations, not every failure. Other exception types and process exits do not use the same crash-reporting path. The handler also does not distinguish first-chance from second-chance access violations.
  • Simple status synchronization. The server resets the status counter after serving it and sleeps for three seconds when the reported value is 1. There is no per-test-case identifier or acknowledgement protocol. Polling timing matters, and the counter is not a durable event queue.
  • Crash capture, not crash triage. The tool does not minimize inputs, deduplicate root causes, or establish exploitability. Retain the corresponding fuzzer inputs and investigate the dumps separately.

The useful boundary is small: observe an access violation, preserve state for analysis, and let an external fuzzer know that an event occurred. The repository includes the Rust monitor, the boofuzz example, and screenshots of the workflow.

Source and references