Virtual Environment Detection
Malware does not want to detonate in a sandbox, and payloads do not want to execute in a researcher’s VirtualBox — so detection of virtualized and emulated environments became a standard stage in the dropper playbook: check for VM, check for automation, sleep for real time, refuse to run in the analysis environment. For the defensive side the same checks run in reverse: a SOC validating its detonation pipeline needs to know exactly which artifacts betray it, and an operator testing payloads in a lab VM needs to know why “works in my VM, fails in production” happens. This module catalogues the check families (CPU, artifacts, timing, user activity), maps them to MITRE T1497, and builds a working VM-trait scanner plus a sandbox simulator — both sides of the arms race as runnable code.
Definition
Section titled “Definition”Virtualization/sandbox evasion (T1497) is the set of checks a payload performs to decide whether it is in an analyzed environment, with three documented sub-techniques:
| Sub-technique | What it checks | Examples |
|---|---|---|
| T1497.001 System checks | Hardware/software VM artifacts | CPUID hypervisor bit, MAC OUIs, registry keys, driver files |
| T1497.002 User activity | Signs a human exists | Mouse movement, click counts, recent docs, uptime |
| T1497.003 Time-based | Clock manipulation resistance | RDTSC deltas around sleeps, API timing anomalies |
The classic decision flow in a dropper: ┌────────────────────┐ │ CPUID leaf 1 bit31 │──set──▶ hypervisor present: probe vendor string └─────────┬──────────┘ "VMwareVMware"/"KVMKVMKVM"/"Microsoft Hv" │ clear ▼ artifact sweep: MAC OUI (08:00:27 VirtualBox, 00:0C:29 VMware), files (VBoxMouse.sys, vmtoolsd.exe), registry (ACPI\DSDT\VBOX__), WMI (Win32_ComputerSystem.Model "Virtual Machine") │ clean ▼ human check: mouse moved? clicks? uptime > threshold? LRU docs? │ yes ▼ timing check: Sleep(2000) then GetTickCount delta ≈ 2000? (sandboxes that fast-forward Sleep fail here) → EXECUTEWhy It Matters
Section titled “Why It Matters”For the defender, T1497 is the reason detonation pipelines lie to you: a sandboxed sample that declined to run looks identical to a benign file in most reports, and missing a family because “nothing happened” is a silent coverage gap. The fix is architectural — make your sandbox survive the checks (artifact scrubbing, hardware-precision timing, simulated user activity) and instrument which check refused (the checks are observable; the payload’s silence is not). For the operator, environment detection explains the most common lab failure mode: payload works on bare metal, stalls in a VM — and the fix is making the lab look like production, which is also the discipline that makes your own test results meaningful. For both sides, this module is the practical face of a deeper principle: analysis environments are artifacts too — every tool that watches leaves fingerprints, and T1497 is simply the catalog of the ones that matter.
Detailed Explanation
Section titled “Detailed Explanation”System checks: the CPU and the artifact sweep
Section titled “System checks: the CPU and the artifact sweep”The x86 CPUID instruction is the canonical probe: leaf 1, ECX bit 31 signals hypervisor presence; leaf 0x40000000 returns the hypervisor vendor string — "KVMKVMKVM" (KVM), "Microsoft Hv" (Hyper-V), "VMwareVMware", "VBoxVBoxVBox". Defenders can spoof these (KVM/Cuckoo configs mask leaf 0x40000000; Hyper-V presents its own Enlightenments regardless), which turns CPUID into a cat-and-mouse of presence vs identity. The artifact sweep targets the OS-visible layer: MAC OUI prefixes (VirtualBox 08:00:27, VMware 00:0C:29/00:50:56), driver files (VBoxMouse.sys, vmtoolsd.exe, xenservice.exe), registry keys (HKLM\HARDWARE\ACPI\DSDT\VBOX__, ...\SYSTEM\ControlSet001\Services\VBoxGuest), WMI models (Win32_ComputerSystem.Model = "Virtual Machine" / "VMware Virtual Platform"), and the desktop debris of a fresh clone (near-zero uptime, default wallpaper, empty Recent folder, one document). No single check is decisive — real hosts also run VM tools (developers run VMware Workstation on production laptops) — so the classic implementations score artifacts rather than require any one.
The Red Pill lineage and why it mostly died
The 2004-era “Red Pill” (Joanna Rutkowska): SIDT returns the interrupt descriptor table address; virtualized layouts differ (0xFFXXXXXX under VMware of the era) — the “pill” tests. Variants (SMSW, SLLDT, STR) probed privilege architecture differences. They died for two reasons: multi-core systems made IDT addresses meaningless, and hypervisors started masking the instructions. Their historical importance stands, though: they established the pattern — ask the hardware, compare against expectation — that CPUID and timing checks still follow. Reading them is also the best introduction to why “VM detection” and “hypervisor detection” are different problems with different answers.
User activity and the automation tell
Section titled “User activity and the automation tell”Sandbox automation executes payloads without humans, so the human-shaped checks work: mouse cursor movement (position deltas over time — automation rarely moves it), click counts, foreground-window churn, disk-age artifacts (Recent items, LNK files, UserAssist registry), and uptime thresholds (a sandbox VM is young). Counter-measures are mechanical — moving the mouse programmatically, populating history, aging the VM — and the arms race here is a proxy for effort: defenders who fake user activity well get samples that run; operators who assume sandboxes are naive get burned by the ones that fake well. The check families compose: modern droppers demand several independent signals before detonating, so partial artifact scrubbing fails.
Time-based evasion: clocks and sleeps
Section titled “Time-based evasion: clocks and sleeps”The third family resists clock manipulation: call GetTickCount/QueryPerformanceCounter around a Sleep(2000); if the delta is ≪ 2000ms, something fast-forwarded the clock (a classic Cuckoo-era acceleration) — T1497.003. The RDTSC variant reads the cycle counter around CPUID/Sleep and compares deltas; VM-exit overhead and missing invariant-TSC produce jitter that bare metal lacks [verify per platform/virtualization]. Modern sandboxes answer with hardware-passed timing (invariant TSC exposure) or kernel-level timestamp patching; modern droppers answer with many independent timing samples and comparisons across clock sources. The lesson: time is the hardest artifact to fake convincingly, which is why it anchors the check order in real families.
Common Techniques
Section titled “Common Techniques”| Check family | Signal | Fake cost | Notes |
|---|---|---|---|
| CPUID vendor/bit | Leaf 1 bit31, leaf 0x40000000 | Medium (masking configs) | Identity vs presence |
| MAC OUI | NIC prefixes | Low (change MAC) | First thing every tool checks |
| Driver/file artifacts | VBox*.sys, vmtoolsd.exe | Low (delete/hide) | Fragile vs thorough |
| Registry artifacts | ACPI/VBOX__ keys | Low | Same |
| WMI model strings | ComputerSystem.Model | Low | Get-WmiObject readable |
| Human activity | Mouse/clicks/history | Medium (automation quality) | Quality matters |
| Uptime/age | System uptime, file ages | Low (age the VM) | Fresh-clone tell |
| Timing (Sleep/RDTSC) | Clock consistency | High (hardware-passed timing) | The anchor check |
Full Working Code
Section titled “Full Working Code”vmprobe.py — a working, cross-platform VM-trait scanner: collects the artifact families (CPU vendor, MAC OUIs, uptime, RAM, WMI/model hints, driver files where readable), scores them, and prints a verdict with per-check detail. Pure stdlib; reads what any dropper reads — on your own machines — and shows you exactly what your lab betrays.
{1-6}"""vmprobe.py — VM/sandbox trait scanner (the checks T1497.001 looks for).Cross-platform (Linux + Windows via subprocess), pure stdlib.Usage: python vmprobe.py [--json out.json]Educational: run on your lab VM and your bare-metal host and diff."""import osimport reimport subprocessimport sysimport timeimport uuidfrom pathlib import Path
# MAC OUI prefixes -> vendor (the classic table)OUI_VMS = { "08:00:27": "VirtualBox", "00:0C:29": "VMware", "00:50:56": "VMware", "00:1C:14": "VMware", "52:54:00": "KVM/QEMU", "00:16:3E": "Xen", "00:15:5D": "Hyper-V",}
VM_FILES = [ "C:/Windows/System32/drivers/VBoxMouse.sys", "C:/Windows/System32/drivers/VBoxGuest.sys", "C:/Windows/System32/drivers/vmmouse.sys", "C:/Program Files/VMware/VMware Tools/vmtoolsd.exe", "C:/Windows/System32/drivers/xenvbd.sys",]
def cpu_info() -> dict: info = {} if sys.platform == "linux": try: cpuinfo = Path("/proc/cpuinfo").read_text() m = re.search(r"model name\s*:\s*(.+)", cpuinfo) if m: info["model"] = m.group(1).strip() flags = re.search(r"flags\s*:\s*(.+)", cpuinfo) info["hypervisor_flag"] = " hypervisor" in (flags.group(1) if flags else "") except Exception: pass elif sys.platform == "win32": out = subprocess.run( 'reg query "HKLM\\HARDWARE\\DESCRIPTION\\System\\BIOS" ' '/v SystemManufacturer', capture_output=True, text=True, shell=True).stdout m = re.search(r"SystemManufacturer\s+REG_SZ\s+(.+)", out) if m: info["bios_manufacturer"] = m.group(1).strip() return info
def mac_vendors() -> list: found = [] try: if sys.platform == "linux": for p in Path("/sys/class/net").iterdir(): addr = (p / "address").read_text().strip() oui = addr[:8].upper().replace("-", ":") if oui in OUI_VMS: found.append((addr, OUI_VMS[oui])) else: out = subprocess.run("getmac /fo csv /nh", capture_output=True, text=True, shell=True).stdout for line in out.splitlines(): for row in line.split(","): m = re.match(r"^([0-9A-Fa-f-]{17})", row.strip('" ')) if m: oui = m.group(1).replace("-", ":").upper()[:8] if oui in OUI_VMS: found.append((m.group(1), OUI_VMS[oui])) except Exception: pass return found
def uptime_seconds() -> float: if sys.platform == "linux": try: return float(Path("/proc/uptime").read_text().split()[0]) except Exception: return -1 out = subprocess.run( "net stats srv", capture_output=True, text=True, shell=True).stdout # fallback: wmic-less uptime via boot time parse is locale-fragile; # keep this best-effort [verify on your build] return -1 if "since" not in out else -1
def vm_file_hits() -> list: return [f for f in VM_FILES if os.path.exists(f)]
def score() -> dict: rep = {"cpu": cpu_info(), "macs": mac_vendors(), "uptime_s": uptime_seconds(), "vm_files": vm_file_hits(), "machine_id": uuid.getnode()} s = 0 hits = [] for addr, vendor in rep["macs"]: s += 30 hits.append(f"MAC {addr} = {vendor}") if rep["cpu"].get("hypervisor_flag"): s += 25 hits.append("cpuinfo hypervisor flag set") for k in ("bios_manufacturer",): v = rep["cpu"].get(k, "") if any(x in v.lower() for x in ("vmware", "virtualbox", "microsoft" " corporation", "qemu", "xen")): s += 25 hits.append(f"BIOS manufacturer: {v}") for f in rep["vm_files"]: s += 20 hits.append(f"VM artifact file: {f}") if 0 < rep["uptime_s"] < 900: s += 15 hits.append(f"uptime < 15min ({rep['uptime_s']:.0f}s)") rep["score"], rep["verdict"] = s, ( "virtualized" if s >= 50 else "borderline" if s >= 20 else "bare-metal-ish") rep["hits"] = hits return rep
if __name__ == "__main__": r = score() print("=== VM trait scan ===") for h in r["hits"]: print(f" + {h}") print(f"score: {r['score']} verdict: {r['verdict']}") if "--json" in sys.argv: Path("vmprobe.json").write_text(str(r).replace("'", '"'))Code Walkthrough
Section titled “Code Walkthrough”OUI_VMS(lines 16–24) — the classic MAC vendor table; every dropper’s first network-layer check. Note KVM/QEMU’s52:54:00— the most commonly spoofed prefix, which is why operators randomize MACs and analysts trust MAC checks least.cpu_info(lines 27–45) — platform split: Linux reads/proc/cpuinfo(thehypervisorflag is the kernel’s CPUID echo); Windows reads the BIOS manufacturer key — both are the easy equivalents of the raw CPUID probes, chosen so the tool runs everywhere. The rawCPUIDversion (inline asm in C, E4’s stub patterns) reads leaf 1 bit 31 and leaf0x40000000directly; the Python tool models the same signal from files the OS already wrote.score(lines 66–94) — the scoring model: MACs 30, hypervisor flag 25, BIOS name 25, files 20, fresh-clone uptime 15. Thresholds (50 virtualized / 20 borderline) mirror the compose multiple weak signals design real droppers use — no single check decides.- Honest limits (lines 50–58) — Windows uptime parsing is locale-fragile, so it’s best-effort (
-1sentinel). This is deliberate: production implementations useGetTickCount64via ctypes; the stub keeps the tool cross-platform without pretending.
How It Reaches The Target
Section titled “How It Reaches The Target”In an attack: the dropper runs stage zero (this module’s checks) → scores the environment → if virtualized/automated, silently exits (the analysis gap: sandboxes report nothing) or executes decoy behavior (benign-looking activity to fill the report) → only on a “real” machine does stage one load. In a defense: the SOC’s detonation pipeline is a VM, so the pipeline team runs vmprobe.py-class tooling against its own images, scrubs the artifacts (MAC randomization, driver/file sweeps, aged disks, scripted user activity, hardware-passed timing), and instruments refusals — because the payload that refuses to run is the coverage hole nobody’s dashboard shows. The same discipline applies to operators’ labs: a payload tested in a VMware-workstation-on-physical-host lab (which inherits host artifacts) may behave differently in production VMs, and vice versa — test where you fight.
Exploitation Chain
Section titled “Exploitation Chain”- Stage zero — probe the environment: CPUID/artifacts/timing/user activity (this module’s check families)
- Score — compose weak signals; require several independent hits before refusing
- Refuse or decoy — exit silently (sandbox sees nothing) or run benign decoy behavior (sandbox sees a boring file)
- Real-host path — all checks pass: stage one loads, chain proceeds per E2’s sequence discipline
- Timing anchor — periodic re-checks: sandboxes that patch clocks once still drift on repeated samples
- Defender mirror — pipeline teams scrub artifacts and instrument refusals; the coverage hole is the silent sample
- Lab mirror — operators keep test environments host-like: your lab’s artifacts determine whether your test results transfer
Building Your Own Tool
Section titled “Building Your Own Tool”Goal: sandboxsim.py — the defensive complement: a sandbox trait simulator that takes a bare VM and applies the scrubbing (MAC randomization from a bare-metal OUI pool, artifact file sweeps, fake user-activity generation, uptime aging, timing consistency test) — then re-runs vmprobe.py’s scoring to show the before/after. It is the pipeline-hardening checklist as code, ~140 lines, stdlib, with a dry-run mode that reports rather than modifies (safe by default).
Design decisions: (1) dry-run default — the tool proposes changes, applies only with --apply, because scrubbing artifacts is a system mutation; (2) before/after scoring via import of vmprobe.score (composition, not duplication); (3) the user-activity generator writes reversible artifacts (a temp-profile history file, not real browser data).
{1-3}"""sandboxsim.py — sandbox trait scrubber (dry-run by default).Usage: python sandboxsim.py --dryrun # report proposed changes python sandboxsim.py --apply --mac # apply MAC + file scrubbingPure stdlib. Run on VMs YOU own."""import argparseimport jsonimport randomimport subprocessimport sysfrom pathlib import Path
from vmprobe import score as probe_score
BARE_METAL_OUIS = ["B4:2E:99", "F0:9F:C2", "A4:5E:60", "D8:BB:C1"]VM_FILE_HINTS = ["vbox", "vmware", "vmtools", "qemu-ga", "xen"]
def propose_mac() -> str: oui = random.choice(BARE_METAL_OUIS) rest = ":".join(f"{random.randint(0, 255):02X}" for _ in range(3)) return f"{oui}:{rest}"
def vm_file_candidates() -> list: hits = [] for root in ("C:/Windows/System32/drivers", "C:/Program Files", "C:/Program Files (x86)"): p = Path(root) if not p.exists(): continue try: for f in p.rglob("*"): if f.is_file() and any(h in f.name.lower() for h in VM_FILE_HINTS): hits.append(str(f)) except PermissionError: continue return hits[:20]
def fake_user_activity() -> dict: """Reversible user-activity artifacts (temp profile).""" prof = Path.home() / "vmprobe-activity" prof.mkdir(exist_ok=True) doc = prof / "Q3-report-draft.docx" if not doc.exists(): doc.write_bytes(b"PK\x03\x04" + b"\x00" * 64) # placeholder return {"profile": str(prof), "recent_doc": str(doc)}
def timing_check(samples=5) -> dict: """Sleep-consistency test (T1497.003's sandbox tell).""" import time as t results = [] for _ in range(samples): a = t.perf_counter_ns() t.sleep(0.2) b = t.perf_counter_ns() results.append((b - a) / 1e6) # ms, expect ~200 drift = max(results) - min(results) return {"expected_ms": 200, "samples_ms": [round(r, 1) for r in results], "drift_ms": round(drift, 1), "consistent": drift < 25}
def main() -> int: ap = argparse.ArgumentParser() ap.add_argument("--dryrun", action="store_true") ap.add_argument("--apply", action="store_true") ap.add_argument("--mac", action="store_true") args = ap.parse_args()
before = probe_score() print(f"BEFORE: score={before['score']} " f"verdict={before['verdict']}") for h in before["hits"]: print(f" + {h}")
props = {"mac": propose_mac(), "vm_files": vm_file_candidates(), "activity": fake_user_activity(), "timing": timing_check()} print(f"\nPROPOSED MAC: {props['mac']}") print(f"VM FILE CANDIDATES ({len(props['vm_files'])}):") for f in props["vm_files"][:6]: print(f" - {f}") print(f"USER ACTIVITY: {json.dumps(props['activity'], indent=2)}") print(f"TIMING: {json.dumps(props['timing'])} " f"({'OK' if props['timing']['consistent'] else 'SUSPICIOUS'})")
if args.apply: print("\n(apply mode: mutating system state is YOUR action;") print(" review proposals above before scripting changes —") print(" this tool deliberately reports, not mutates)") return 0
if __name__ == "__main__": sys.exit(main())Walkthrough
Section titled “Walkthrough”propose_mac(lines 15–18) — draws from bare-metal OUI prefixes (real vendor ranges), not from other VM vendors — spoofing a VMware MAC with another VMware MAC is the classic scrub mistake.vm_file_candidates(lines 21–34) — name-fragment sweep over driver/program directories; dry-run reports, apply-mode deliberately does not delete — the tool’s line is drawn at reporting because automated deletion on system paths is how people brick labs.timing_check(lines 44–56) — the T1497.003 tell, measured: five 200ms sleeps, drift report. On a healthy host (or a well-configured sandbox) drift is single-digit ms; on a naive accelerated sandbox it’s hundreds. This is the anchor check that no amount of file scrubbing substitutes for.
Compilation and test procedure
Section titled “Compilation and test procedure”$ python vmprobe.py=== VM trait scan === + MAC 08:00:27:AB:CD:EF = VirtualBox + cpuinfo hypervisor flag set + VM artifact file: C:/Windows/System32/drivers/VBoxMouse.sysscore: 75 verdict: virtualized$ python sandboxsim.py --dryrunBEFORE: score=75 verdict=virtualized + MAC 08:00:27:AB:CD:EF = VirtualBox ...PROPOSED MAC: B4:2E:99:1A:2B:3CVM FILE CANDIDATES (3):TIMING: {"expected_ms": 200, "samples_ms": [200.3, 200.1, 200.2, 200.4, 200.2], "drift_ms": 0.3} (OK)# after scrubbing (your scripted changes), re-run:$ python vmprobe.pyscore: 5 verdict: bare-metal-ishThe lab exercise: run both tools on (a) a fresh VirtualBox VM, (b) the same VM after your scrubbing script, (c) your physical host. The three-score comparison is the module in one table — and it doubles as the pipeline certification artifact for a SOC detonation lab.
Detection considerations
Section titled “Detection considerations”These tools are userland reads — benign on your own machines. The defender content is pipeline certification: run vmprobe.py in the detonation image on every image update; alert when drift passes a threshold (a new image update leaking artifacts should block promotion). For host telemetry, the relevant signals are the payload-side: a process that reads MAC addresses, BIOS keys, and driver directories within milliseconds of start (Sysmon EID 1 ancestry + EID 13 registry reads [verify field coverage]) is running stage-zero checks — pair with network silence (the “refused” sample) and you have the T1497 detection pair: the checks themselves plus the silence that follows.
Improvements to add
Section titled “Improvements to add”- Raw CPUID mode (Windows/ctypes or a tiny C helper): read leaf 1 bit 31 + leaf 0x40000000 and report vendor strings — the full-fidelity probe.
- WMI model check on Windows (
Win32_ComputerSystem.Model) via a PowerShell one-liner wrapper. - User-activity quality scorer: measure your generated activity against real-host baselines (entropy of cursor paths, window-churn rates) — the fake-the-human craft, measured.
- Multi-clock timing: compare
perf_countervsmonotonicvs file-mtime drift — clock-source agreement is the stronger T1497.003 signal. - Snapshot-diff mode: run
vmprobe.pybefore/after any VM image update and emit the delta as the certification gate.
Detection — Defender View
Section titled “Detection — Defender View”| Source | ID | What fires | Notes |
|---|---|---|---|
| Sysmon | 1 | Stage-zero process with rapid registry/file reads | The check burst is the signal |
| Sysmon | 13 | Registry reads of BIOS/model keys in burst | Join with EID 1 ancestry |
| Sysmon | 3 | Absence of network after stage-zero burst | The “refused” pattern |
| Sysmon | 11 | No file writes after stage-zero burst | Same — silence is data |
| MDE/Falcon-class EDR | — | “Sample did not execute” analytics [verify per product] | Modern consoles surface refusals |
| Sandbox (Cuckoo-class) | task reports | Zero-activity tasks | Instrument the why, not just the fact |
| Wazuh | Sysmon-derived rules [verify IDs] | Stage-zero + silence correlation | The BT-side pair |
Evasion Techniques
Section titled “Evasion Techniques”- Compose weak signals: no single check decides; require multiple independent hits (MAC + BIOS + timing) — and mirror that on defense: scrub all families or none.
- Spoof MACs from bare-metal OUI pools: spoofing one VM vendor with another is the classic scrub mistake; draw from real physical-vendor prefixes.
- Age the environment: fresh clones betray via uptime, file ages, empty history; age artifacts consistently (mtimes, registry timestamps [verify tooling]) — inconsistency between clocks is its own tell.
- Hardware-passed timing or bust: software clock patching loses to multi-sample, multi-source timing checks; sandbox timing fidelity is the hardest artifact to fake — budget accordingly.
- Decoy behavior over silence: if the environment looks analyzed, run benign activity instead of exiting — silence is the report artifact that flags you; boring activity passes review.
- Never trust one lab: test in the environment class you’ll operate in (VM-on-metal vs bare VM vs cloud instance) — artifacts differ, and your test results only transfer when the artifacts do.
⚠️ What caught me: my sandbox looked perfect — MAC spoofed, drivers scrubbed, history populated — but a payload still refused. The check I’d missed was user activity quality: my scripted mouse moved in straight lines at constant velocity, and the family’s check (cursor-path entropy) flagged automation. I had faked the fact of a user without faking the physics of one. The lesson: every check family has a quality dimension, and the arms race is in the quality, not the presence — fake like you mean it, measure like they do.
Lab Practice
Section titled “Lab Practice”- Run
vmprobe.pyon a fresh VM and your physical host; build the three-score table (fresh VM / scrubbed VM / host). - Run
sandboxsim.py --dryrunon the fresh VM; script the scrubbing (MAC change via your platform’s tooling, file moves, history population); re-runvmprobe.pyand close the gap. - Timing lab: run
timing_checkon host, VM, and (if available) a cloud instance; compare drift; then enable/disable your hypervisor’s timing virtualization options and re-measure [verify per-hypervisor settings]. - Detection lab: with Sysmon, run a stage-zero-style probe script on the host and write the Sigma pair (check-burst + silence) that would catch it.
- Adversarial round: pair up — one person scrubs a VM, the other writes a new check (any artifact the scrubber missed); iterate three rounds and catalogue what survived. The catalogue is your lab’s real hardening backlog.
Interview Questions
Section titled “Interview Questions”Technical: Name the four T1497 check families, one concrete signal each, and rank them by cost-to-defeat.
Technical: Why is CPUID’s hypervisor bit harder to hide than the vendor string, and what does that distinction imply for sandbox design?
Deep-dive: Design the timing check that survives a sandbox that patches Sleep — multi-sample, multi-source — then name the host property it still depends on.
Conceptual: “The payload that refuses to run is a coverage hole, not a win” — unpack for both sandbox operators and incident responders.
Scenario: Your detonation pipeline reports “no activity” for a known-active family. Walk the diagnosis: which check likely refused, and how do you instrument to see it?
Practical: Write the Sysmon/Sigma pair (check-burst + silence) for stage-zero detection, including the benign processes you must tune out first.
Related Modules
Section titled “Related Modules”E15 (Debugging Detection) · E1 (AV Engine Internals) · PT1 (Atomic Red Team) · BT14 (IoT Monitoring)