Unbacked call trace process access
A process opened a handle to another process, and the call came from memory that is NOT backed by any file on disk (CallTrace=UNKNOWN(0x…)).
What it detects
A process opened a handle to another process, and the call came from memory that is NOT backed by any file on disk (CallTrace=UNKNOWN(0x…)).
Every legitimate API call originates inside a loaded module, so Sysmon can name the DLL and offset for each frame. UNKNOWN means the calling code exists only in memory — manually mapped, reflectively loaded, or plain shellcode. That is the defining property of in-memory execution, and it is what makes this one of the very few high-fidelity injection signals available from logs alone.
It also survives the evasions that defeat name-based rules. The attacker can rename their binary, sign it, run it from Program Files, and hollow a trusted process — none of which changes the fact that the call frame has no file behind it.
MITRE ATT&CK mapping
False positives and triage
A small number of legitimate technologies produce unbacked frames: .NET's JIT compiler, some anti-cheat and DRM layers, a few endpoint-security agents that hook by design, and certain debuggers/profilers. Baseline those on the host before treating this as universal.
Its false-positive rate is NOT measured: the benign benchmark corpus contains no Sysmon data, so the .NET-JIT caveat above is judgement rather than evidence. On the attack corpus it fires on 21 of 278 captures, which is consistent with injection being a technique used inside many tactics rather than a rule that is too wide — but confirm against your own estate before trusting the severity.
To confirm: read SourceImage and TargetImage together. A .NET application touching itself is JIT; anything reaching into lsass.exe, explorer.exe or another user's process is not. Check GrantedAccess — 0x1F0FFF/0x1FFFFF is full control and 0x1010/0x1410 is the read-memory pattern used for credential theft. Then find how the source process started: an unbacked call trace from something launched by a script host, an Office application, or a binary in a user-writable directory is an intrusion, not a profiler.
The rule
Declarative YAML read by the detection engine — data, never executed. Confidence 90%. Source: rules/windows/unbacked_call_trace_process_access.yaml, licensed under the Apache License 2.0.
id: windows.injection.unbacked_call_trace_process_access
version: 1.0.0
status: stable
severity: critical
confidence: 0.9
platforms: [windows]
mitre_techniques: [T1055, T1620]
description: |
A process opened a handle to another process, and the call came from memory that is
NOT backed by any file on disk (`CallTrace=UNKNOWN(0x…)`).
Every legitimate API call originates inside a loaded module, so Sysmon can name the
DLL and offset for each frame. `UNKNOWN` means the calling code exists only in
memory — manually mapped, reflectively loaded, or plain shellcode. That is the
defining property of in-memory execution, and it is what makes this one of the very
few high-fidelity injection signals available from logs alone.
It also survives the evasions that defeat name-based rules. The attacker can rename
their binary, sign it, run it from `Program Files`, and hollow a trusted process —
none of which changes the fact that the call frame has no file behind it.
match:
event_action: process_access
raw_message_contains_any:
- 'CallTrace=UNKNOWN'
- '|UNKNOWN('
correlation_keys: [hostname, user_name]
false_positive_guidance: |
A small number of legitimate technologies produce unbacked frames: .NET's JIT
compiler, some anti-cheat and DRM layers, a few endpoint-security agents that hook
by design, and certain debuggers/profilers. Baseline those on the host before
treating this as universal.
Its false-positive rate is NOT measured: the benign benchmark corpus contains no
Sysmon data, so the .NET-JIT caveat above is judgement rather than evidence. On the
attack corpus it fires on 21 of 278 captures, which is consistent with injection
being a technique used inside many tactics rather than a rule that is too wide —
but confirm against your own estate before trusting the severity.
To confirm: read `SourceImage` and `TargetImage` together. A .NET application
touching itself is JIT; anything reaching into `lsass.exe`, `explorer.exe` or
another user's process is not. Check `GrantedAccess` — `0x1F0FFF`/`0x1FFFFF` is
full control and `0x1010`/`0x1410` is the read-memory pattern used for credential
theft. Then find how the source process started: an unbacked call trace from
something launched by a script host, an Office application, or a binary in a
user-writable directory is an intrusion, not a profiler.
Related detections
Run this rule on your own logs — offline
KIROSEC runs this rule and the rest of the library over Windows, Linux, macOS and cloud audit logs on the analyst's own machine. Every alert links to the events that raised it, and nothing leaves the device.
