Crash triage
TL;DR: Turn a crash dump into an answer to two questions — which bug class is this, and is it exploitable — using
!analyze -v, register/disassembly context, page-heap, and a few WinDbg helpers.
What it is
A workflow for taking a crash artefact (user-mode .dmp, kernel MEMORY.DMP, or a live debugger break) and producing: bug class (OOB-W, UAF, type confusion, null deref, integer underflow), root-cause function, and a first-cut exploitability call. Triage discards uninteresting crashes quickly so fuzzing effort flows back into the corpus.
Preconditions / where it applies
- Reproducible crash with a saved input or a dump.
- Symbols available (Microsoft public symbol server
srv*c:\sym*https://msdl.microsoft.com/download/symbols). - For heap bugs: page-heap (
gflags /p /enable target.exe /full) so the bug fires at the corruption site instead of much later.
Technique
Open the dump.
1
2
3
windbg -z crash.dmp
.sympath SRV*c:\sym*https://msdl.microsoft.com/download/symbols
.reload /f
Headline command.
1
!analyze -v
The summary lists EXCEPTION_CODE, FAULTING_IP, BUCKET_ID and a heuristic exploitability score. Treat the score as a hint, never as proof.
Look at the actual fault site.
r— registers at fault. Look for attacker-controlled values in RIP, RAX, RCX.u @rip/ub @rip— disassemble around the crash; identify the instruction class (write through register, indirect call, vtable deref).dps @rsp L20— stack walk and search for return addresses outside expected modules.kb— call stack with parameters.
Heap bugs.
- With page-heap on, the crash fires on the guard page directly adjacent to the corrupted allocation;
!heap -p -a <addr>shows the allocation stack. !address <addr>tells you region type (heap, stack, image, mapped file).
Kernel crashes.
!analyze -vplus!pool <addr>,!process 0 0,!irql,!locks.!verifierif Driver Verifier is on — its sub-codes (0xC4,0xC9,0xCB) name the driver bug class.
Classification rules of thumb.
- Write-through-pointer with attacker-influenced destination → likely exploitable.
- Indirect call/jump through tainted register → exploitable modulo CFG/cfg-cet-kernel.
- Read from
NULLor from a non-canonical address with no attacker influence on the source → usually not. - Stack canary
__report_gsfailure→ overflow happened but mitigations caught it; still useful as a coarse bug locator.
De-duplicating fuzzer output. Hash on (BUCKET_ID, last-3 stack frames) and triage one representative per bucket.
Detection and defence
- WER (Windows Error Reporting) collects mini-dumps centrally; mining them surfaces in-the-wild crashes attackers also see.
- Driver Verifier in production-like test rings catches many kernel bugs before release.
- Address sanitizer-style mitigations (page heap, Application Verifier) should be on for any fuzz target.
References
- WinDbg !analyze docs — official command reference
- Microsoft: Driver Verifier flags — verifier sub-codes
- Tim Misiak — WinDbg tips — modern dump-triage workflow
See also: kernel-debugging-with-windbg, mona-py, fuzzing-windows-drivers.