BOOT CHAIN LAB
Lab 3 · detection engineering

Cross-view detection.

A rootkit hides a process by unlinking it from the list the OS walks — but the thing still has to run, so a lower-level view of the system still accounts for it. Enumerate the same thing two ways, diff the results: what the low view sees but the high view doesn't is hidden.

01 — the idea

Two views, one truth

Any list the OS exposes can be tampered with at the layer that produces it. So a defender never trusts one list — they build a second, independent view and compare. A hidden object is a disagreement between the views, and disagreement is something you can state with evidence.

high-level viewThe convenient API every tool uses — a process snapshot, tasklist, ps. Easiest to query, and the easiest for a rootkit to filter.
low-level viewSomething harder to fake that still implies the object exists: the scheduler's thread list, brute-forcing PIDs via open-by-id, scanning kernel memory for the object's signature.
the diffPresent low but absent high → hidden (the finding). Present high but absent low → usually a scan race (the process exited between passes).
02 — run a cross-view diff

Find the hidden process

Two independent enumerations of the same host (sample data). Run the diff: processes in both are accounted for; a PID in the low view with no high-view entry is flagged hidden; a high-only PID is treated as a timing race, not a conviction.

high-level · process snapshot

low-level · thread/PID scan

Run the diff to compare the two views.
03 — with your tools

Cross-view on your stack

macOS / Linux analog

You rarely read kernel memory on a Mac. The same idea becomes cross-source correlation: the process list vs. who actually owns a live socket vs. who Zeek saw send traffic. A process that holds a connection or sends packets but isn't in the baseline process view is the same disagreement.

# three independent views
osquery: processes
osquery: process_open_sockets   # owner of each socket
zeek:    conn.log               # traffic, no process
diff → a talker with no owning process = investigate

in the detection lab

  • The normalizer already joins sockets to processes on proc_key — an unattributed connection is a cross-view gap worth a look.
  • A network talker with no matching process row is the macOS-shaped version of "low view sees it, high view doesn't."
  • A confirmed delta becomes a Vertical case: record both views and the diff as the evidence.
04 — the race is the hard part

Disagreement isn't always hiding

Processes start and exit between your two passes, so a single diff is noisy — a high-only PID is almost always one that just exited, not evidence of anything. The signal is a persistent low-only object across several passes, ideally from views a single tamper can't fake at once. One snapshot raises a question; repetition answers it.

Next: Lab 4 — detecting C2 (beaconing regularity and DNS tunneling), built on the detection lab's R3/R4.