Skip to content

Process (kernel process ETW)

This source records process starts, process exits and executable image (module) loads from the Windows kernel. FreeDR uses it as the process lineage backbone. Every other source takes its actor_* columns from the live process state this source maintains.

Collector ID freedr.kernel-process-etw
Windows mechanism Classic kernel providers in the shared ETW system logger session FreeDR-Unified
Hunt events view, event_type IN ('process.start','process.exit','image.load')
Rule SQL source name kernel_process_etw
Hot table kernel_process_etw_v6
Code crates/freedr-collect-process

ETW providers

Provider GUID Kernel flag Opcodes used
Process {3D6FA8D0-FE05-11D0-9DDA-00C04FD7BA7C} 1 (process) 1 Start, 2 End, 3 DC_START (rundown), 4 DC_END
Image {2CB15D1D-5FC1-11D2-ABE1-00A0C911F518} 4 (image load) 10 Load, 3 DC_START (rundown)
Thread {3D6FA8D1-FE05-11D0-9DDA-00C04FD7BA7C} 2 (thread) 1–4. Used only to attribute other sources' events to a process. Never stored.

Raw events pass through a 256 MiB maximum lifecycle ring (see ring buffers) and two decode workers.

Event types

event_type Recorded when Main fields
process.start Process created, or already running at session start (rundown) pid, parent_pid, session_id, user_sid, user_name, image_path, command_line, parent lineage
process.exit Process ended pid, image_path, exit_code, actor lineage
image.load EXE/DLL mapped into a process pid, image_path, image_base, actor lineage

The source drops thread start and stop and image unload before storage. They are counted only (lifecycle_thread_start, lifecycle_thread_stop, lifecycle_image_unload).

Columns

Column Notes
pid, parent_pid, session_id parent_pid 0 is stored as NULL
user_sid Token SID as S-1-… (start only)
user_name DOMAIN\name looked up when the event is collected. Display only. A 1,024-entry cache is used.
image_path Full DOS path (see below)
command_line Up to 64 KiB (start only)
image_base image.load only
exit_code process.exit only
is_rundown true = the process or image already existed when the session started. The time is the snapshot time, not the real start time.
parent_image_path, parent_command_line, parent_start_at, grandparent_image_path Lineage from FreeDR's live process state, on process.start
actor_image_path, actor_command_line, actor_start_at, actor_user_sid, actor_user_name The process the event belongs to, on process.exit / image.load

This source does not capture integrity level, token elevation, file hashes or signatures. Hashes and signatures come from the Artifacts source, which process.start and image.load paths trigger.

Full image path on process.start

The kernel start event carries only a short, possibly truncated image name. FreeDR binds it to the full path from the matching image load:

  • The match must happen within 2 seconds, with at most 1,024 pending starts (2 MiB).
  • The names must match case-insensitively. When the kernel name is 14 or more characters (EPROCESS truncation), the full path need only start with it.
  • If no match arrives (timeout, process exit, PID reuse, session restart, limit reached), the start is stored with the short name.
  • NT device paths (\Device\HarddiskVolumeN\…, \SystemRoot\, \??\) are converted to drive-letter paths. Paths that cannot be mapped are kept verbatim.
  • Pending starts are lost if the agent crashes.

Noise controls and dedupe

Control Effect
System32 DLL filter image.load of %SystemRoot%\System32\*.dll is dropped. If the drive mapping is ambiguous, nothing is dropped.
Per-process image dedupe Repeated loads of the same path (same size, checksum and timestamp) in the same process instance are dropped. The ASLR base is ignored. Limits: 65,536 images, 16 MiB, 65,536 processes. Above the limit, events are kept.
Event ID dedupe event_id is a UUIDv5 over the event content. The writer suppresses duplicate IDs.

There are no ADR-0028 measured exclusions for this source.

Startup inventory

  • ETW rundown emits process.start and image.load rows with is_rundown = true for everything already running.
  • A Toolhelp32 snapshot (up to 262,144 processes) at each session start seeds the in-memory actor and lineage state only. It writes no rows.

Health counters

Shared ETW decode (TDH) counters, for example schema_not_found, required_property_missing, malformed_or_truncated_payload, cache_capacity_exhausted, plus ring and loss counters (see Storage & health), and the three lifecycle_* counters above.

Verification status

The design documents for start-image binding (ADR-0065) and user SID capture (ADR-0053) list native Windows qualification as pending.