Skip to content

WER crash call-path hashing and pre-crash behavior fingerprinting

Windows Error Reporting (WER) records information when applications crash, hang, or trigger certain exceptions. It can provide useful pre-incident telemetry for exploit hunting, unstable payloads, application abuse, and recurring failures.

Two complementary detection paths

WER-centered detection model
WER crash
    |
    +-----------------------------+
    |                             |
    v                             v
Crash call-path signature   Pre-crash behavior
    |                             |
    v                             v
crash_path_hash           behavior/API fingerprint
    |                             |
    +-------------+---------------+
                  |
                  v
           anomaly scoring
  • The crash call-path signature asks: Is this failure path unusual?
  • The behavioral/API fingerprint asks: Was the process doing something unusual immediately before the crash?
  • When both are unusual, confidence and investigative priority should increase.

Neither path makes a crash malicious by itself. Exploitation, injection, shellcode execution, and unstable post-exploitation activity can sometimes leave secondary crash or error artifacts, but ordinary defects, compatibility problems, security tools, and administrative software can do the same.

Collect and retain

WER evidence Why it matters
Process/application name Identifies the crashing workload
Application version Separates vulnerable or unusual builds
Faulting module Locates the component involved
Exception code Distinguishes access violations and other failure classes
Fault offset Helps cluster similar crashes within a build/module
Crash bucket Microsoft's coarse grouping of related failures
Ordered crash call path Captures the function/module path around the failure
WER report identifier Stable case-level identifier for joining report artifacts
Report/bucket identifiers Connect repeated or related crash submissions
Host, user, and time Enables scope, sequence, and prevalence analysis

High-value Windows events

Event ID Log/provider Meaning
1000 Application Error Application fault details
1001 Windows Error Reporting WER report, bucket, and report identifier data
1002 Application Hang Application stopped responding

Event availability and field shape vary by Windows version, application, policy, and collection configuration.

WER report locations

Queued reports
%ProgramData%\Microsoft\Windows\WER\ReportQueue
Archived reports
%ProgramData%\Microsoft\Windows\WER\ReportArchive
Per-user reports
%LOCALAPPDATA%\Microsoft\Windows\WER

WER report identifiers

Preserve the original identifiers before normalization:

Identifier Use
Report Id / report identifier Join event data to a specific report/artifact
Bucket ID / failure bucket Group Windows-classified similar failures
Event name Distinguish crash/hang/report families
Application and module version Prevent false clustering across builds
Exception code and fault offset Refine similarity and triage

Do not treat a WER report ID as a malware identifier. It identifies a report instance; use bucket and normalized crash-path fingerprints for clustering.

Source basis: crash call-path signatures

Tiepolo and Sorensen describe this workflow in Chapter 6 of Advanced Cyber Threat Intelligence and Hunting. Their method creates a compact signature from the top N non-OS frames or canonical function names, then uses it to cluster rare, new, repeated, or cross-host crashes.1

The underlying debugger artifact is an ordered call stack: the nested function and module frames active near the failure. It is not a fingerprint of stack memory. This page calls the normalized output crash_path_signature to keep that distinction explicit.

The source method is:

  1. Remove common operating-system scaffolding such as kernel32.dll and ntdll.dll from the clustering view.
  2. Retain the top N application or library call frames near the fault.
  3. Prefer canonical module!function names when symbols exist.
  4. Otherwise use a stable module-relative offset, not an absolute virtual address.
  5. Lowercase, remove formatting noise, preserve frame order, concatenate, and hash.
  6. Measure signature rarity, recurrence, host diversity, and velocity.

Obtain the actual crash call path

WER event records commonly provide crash metadata, not a complete symbolized call path. The signature pipeline needs a report artifact, dump, or endpoint source that exposes ordered call frames.

Source Use
Application Error and WER events Identify the process, module, exception, offset, report ID, and crash time
Report.wer and WER archive/queue Recover report fields and locate related artifacts
WER LocalDumps or another crash-dump policy Preserve a user-mode dump from which the call path can be reconstructed
EDR or application crash telemetry Use vendor-provided call frames when available
WinDbg/CDB or another symbol-aware parser Extract ordered frames from the dump

Microsoft documents per-application and global LocalDumps configuration under HKLM\SOFTWARE\Microsoft\Windows\Windows Error Reporting\LocalDumps. Scope dump collection to selected applications, set retention limits, protect dump storage, and validate that the chosen dump type contains enough state for call-path reconstruction.

Collection path
WER event
  → report ID and crash metadata
  → Report.wer or dump artifact
  → symbol-aware call-frame extraction
  → ordered frames
  → canonical crash call path
  → crash-path signature

Create the crash-path signature

Keep the crash-path signature focused on the ordered call frames. Store application version, exception code, faulting module, and WER bucket as adjacent fields for filtering or a separate composite cluster key.

Raw frames
  → remove common OS-only frames from the clustering view
  → retain the top N application/library frames
  → canonicalize module!function or module+relative_offset
  → lowercase and remove whitespace
  → join in frame order
  → hash the canonical sequence
Canonical crash-path input
chrome.dll!v8::internal::codestubassembler::callbuiltin>chrome.dll!blink::document::evaluatescript
Reference Python implementation
from hashlib import sha256

COMMON_OS_MODULES = {
    "kernel32.dll",
    "kernelbase.dll",
    "ntdll.dll",
}


def canonical_call_path(frames, top_n=8):
    selected = []
    for raw_frame in frames:
        frame = "".join(raw_frame.lower().split())
        module = frame.split("!", 1)[0].split("+", 1)[0]
        if module in COMMON_OS_MODULES:
            continue
        selected.append(frame)
        if len(selected) == top_n:
            break

    if not selected:
        raise ValueError("no application or library frames remained")
    return ">".join(selected)


canonical = canonical_call_path(frames)
crash_path_hash_full = sha256(canonical.encode("utf-8")).hexdigest()
crash_path_signature = crash_path_hash_full[:24]  # 12-byte display key

The book uses MD5/SHA-1 as examples of fast clustering hashes. SHA-256 or BLAKE2 is a safer modern default with negligible cost at this scale. Store the full digest for collision resolution and use a shorter display key only for analyst convenience.

Do not hash raw debugger output directly. Paths, absolute addresses, symbol decoration, thread headers, and formatting changes make raw text unstable. Keep the raw ordered frames and canonical input beside the signature so the result remains explainable and the normalization can be revised.

Optional composite cluster key
application|application_version|exception_code|faulting_module|crash_path_signature
Field Purpose
wer_report_id Report-instance join key
wer_bucket_id Native WER grouping
crash_path_hash Environment-controlled normalized call-path cluster
crash_path_normalized Explainable hash input
application / application_version Workload/build context
faulting_module / version Fault location
exception_code / fault_offset Crash characteristics
host / user Scope and ownership
first_seen / last_seen / count Prevalence and timeline

Behavioral/API sequence fingerprinting

WER as the temporal anchor

Pre-crash behavioral fingerprint workflow
WER event
  → identify the affected process and crash time
  → retrieve endpoint telemetry immediately preceding the crash
  → normalize relevant API calls or lower-level process actions
  → create a behavioral/API-sequence fingerprint
  → compare historical, host, process, peer-group, and cross-host prevalence

WER does not provide the API-call sequence. This path depends on EDR, ETW, specialized tracing, or other endpoint telemetry with enough visibility to reconstruct the actions preceding the crash. Normalize behavior rather than raw event text so equivalent lower-level actions can cluster despite different providers or API layers.

Higher-risk sequence elements

These operations increase suspicion when they are rare, occur in a meaningful sequence, and are tightly aligned to the crash. None is inherently malicious by itself.

Behavior Focused API examples
Remote process access OpenProcess, NtOpenProcess
Remote memory allocation VirtualAllocEx, NtAllocateVirtualMemory
Writing into another process WriteProcessMemory, NtWriteVirtualMemory
Writable-to-executable or other execution-enabling protection change VirtualProtect, VirtualProtectEx, NtProtectVirtualMemory
Remote thread creation CreateRemoteThread, NtCreateThreadEx
Unbacked or unusual thread start Correlate the start address with module and memory-region metadata
Execution from private or unbacked memory Correlate thread execution with allocation, write, and protection history

Use the High-Risk API Population and Fileless Memory Telemetry pages for deeper collection and population-analysis guidance; this page uses those signals only as pre-crash context.

Detection Ideas

Signals to prototype

  • New or historically unseen WER crash-path signature
  • Rare crash-path signature for a host, process, or peer group
  • Sudden increase in WER/crash frequency on a host
  • Same unusual crash-path signature appearing across multiple hosts
  • New or rare pre-crash behavioral/API fingerprint
  • Same unusual behavioral fingerprint appearing across multiple systems
  • Rare behavior immediately followed by a crash
  • Rare behavior plus one or more high-risk memory/process operations
  • High-risk API/process behavior followed by an unusual WER event
  • New crash signature and new behavioral fingerprint occurring together
  • Temporal clustering of similar crashes or behavioral fingerprints across hosts
  • Significant deviation from a host or peer-group baseline

Conceptual risk progression

Rare behavior
  → more interesting

Rare behavior immediately before a crash
  → higher suspicion

Rare behavior before a crash + high-risk memory/process operation
  → substantially higher suspicion

Rare behavior + crash + high-risk operation + recurrence across hosts
  → high investigative priority

Candidate anomaly features

Crash-path features Behavioral and prevalence features
crash_path_signature_rarity behavior_sequence_rarity
crash_path_signature_age behavior_sequence_age
crash_rate_vs_baseline high_risk_api_count
hosts_seen_with_crash_path hosts_seen_with_sequence
process_prevalence host_prevalence
peer_group_prevalence cross_host_velocity
time_since_first_seen —

This does not need to begin as a machine-learning model. Prototype the joins, windows, normalization, rarity, prevalence, baselines, and false-positive handling in Splunk SPL first. If the signal is useful and the telemetry is dependable, operationalize it through Enterprise Security detections, Splunk UBA custom content, MLTK, or the behavioral-analytics framework appropriate to the environment.

Why this matters for threat hunting

Exploitation and exploit attempts can cause abnormal exceptions, crashes, hangs, faulting instructions, unusual call paths, faulting modules, and report clusters. WER can supply an earlier point in the timeline than detections focused only on post-exploitation behavior.

Most detections emphasize what happens after successful exploitation:

powershell.exe → cmd.exe → process injection → credential access → network callback

WER may preserve evidence of what happened before or during that transition:

Inbound content → parsing/handling → exception or crash → distinct WER crash path

A crash is not proof of exploitation. Its value comes from correlation with process, memory, file, identity, and network telemetry.

WER correlation patterns

WER + Sysmon

WER crash
  → Sysmon 1 Process Create
  → Sysmon 10 ProcessAccess
  → Sysmon 8 CreateRemoteThread
  → Sysmon 3 Network Connection

Pivot next: Process GUID, source/target image, access rights, remote-thread start fields, destination, and timeline gaps.

WER + EDR

Crash or exception
  → abnormal crash call path
  → executable MEM_PRIVATE
  → unbacked thread start
  → injection or shellcode evidence

Pivot next: memory region type/protection, allocation and protection transitions, raw thread start, loaded-module boundaries, and responsible process lineage.

WER + network

Inbound content
  → application parses content
  → crash
  → distinct WER crash path
  → subsequent callback

Pivot next: source session, request/object, DNS, TLS/HTTP metadata, callback process, peer-host prevalence, and whether the callback preceded or followed restart/recovery.

WER + file telemetry

Document or download
  → application opens file
  → crash
  → WER crash path
  → suspicious execution

Pivot next: file origin, Mark-of-the-Web, hash, signer, creating/downloading process, application child processes, and execution across other hosts.

Crash-path signature hunt

The analytical value comes after the hash is created. Group crashes by crash_path_signature, then rank signatures by novelty, rarity, recurrence, host diversity, and rate of appearance.

Minimum aggregation
by application, application_version, crash_path_signature
  count crashes
  count distinct hosts and users
  calculate first_seen and last_seen
  calculate crashes per hour
  retain exception_code, faulting_module, and module_offset

Prioritize:

  • A signature not seen during the baseline window
  • A rare signature appearing on several hosts in a short period
  • Repeated instances on one exposed or high-value host
  • The same signature plus the same exception code, module, or relative offset
  • A crash cluster aligned with common inbound content or web activity
  • A crash cluster followed by unusual process, memory, identity, or network activity

Keep application and module versions in the grouping or filter logic. Patches and software releases can change symbols and offsets without changing security relevance.

A crash is not proof of exploitation. Patch defects, compatibility problems, JIT behavior, and ordinary instability can produce similar evidence.

What to pivot to next

WER report ID → report archive/dump → ordered call frames → normalized crash-path hash
Crash-path hash → other hosts/users → process lineage → file/module provenance
Crash time → DNS/network → authentication → persistence → cloud/application activity

Also pivot to signer/hash, application and module version, document/download origin, EDR memory/thread telemetry, Sysmon 1/3/7/10/11/22/25, and Windows Security events in the same session.

Acting on the telemetry

Finding Action
Common known-benign cluster Baseline with version and signer constraints
Rare unexplained cluster Preserve report/dump and investigate host timeline
Repeated vulnerable-build cluster Patch or mitigate; track residual exposure
Cross-host suspicious cluster Scope enterprise-wide and create a hunt/detection
Missing call-path/report details Improve WER, event, dump, symbol, or EDR collection
Security-control crash Treat visibility loss as a separate incident signal

Operational summary

Collect WER identifiers and crash artifacts, extract symbolized call frames, and create an explainable normalized crash-path signature. Use the same crash time to retrieve preceding endpoint activity and create a normalized behavioral/API fingerprint when telemetry supports it. Baseline each dimension independently, then prioritize rare, repeated, or cross-host combinations without treating WER or high-risk operations as malicious by themselves.

Sources


  1. Gianluca Tiepolo and Dan Sorensen, Advanced Cyber Threat Intelligence and Hunting, first edition, Packt, 2026, Chapter 6, "Correlating crashes and instability to uncover exploitation," supplied EPUB extraction lines 214–307. ↩