Lesson 2 of 5 · 25 min read

Writing at L3 and Above — Deliberately Designing Robustness

You’ve seen the L0–L4 rubric. This lesson is about deliberately writing at L3 and above — identifying the behavioral invariants that an attacker can’t change without changing their fundamental technique.


Why Most Rules Land at L1 Without Intent

The path of least resistance when writing a Sigma rule is:

  1. Find a malicious sample
  2. Look at what process it creates and what arguments it uses
  3. Write those into a rule

The result is almost always an L1 rule: it detects this specific tool, with these specific argument strings.

# Typical L1 rule — written from a specific malware sample:
detection:
  selection:
    Image|endswith: '\cobaltstrike.exe'
    CommandLine|contains: '-pipename'
  condition: selection

This fires for exactly this payload configuration. Change the binary name or the pipe name — no alert.

Most rules in the SigmaHQ repository started as L1. That’s not a criticism — they have value as first-line detections for commodity tooling. But a mature detection program needs L3+ coverage as the backbone.


The L3 Design Process

Step 1: Identify the OS primitive the technique requires.

Every attack eventually calls an OS API or generates a system event. Credential dumping from LSASS requires reading another process’s memory — that’s OpenProcess + ReadProcessMemory at the Win32 level. The OS primitive is “a process accessed another process’s memory with read rights.”

Step 2: Find the telemetry that records that primitive.

Sysmon Event 10 (ProcessAccess) records when one process opens a handle to another. TargetImage = the process being accessed. GrantedAccess = the access rights requested.

Step 3: Write the rule against the primitive, not the tool.

logsource:
  product: windows
  category: process_access

detection:
  selection:
    TargetImage|endswith: '\lsass.exe'
    GrantedAccess|contains:
      - '0x1010'   # PROCESS_VM_READ | PROCESS_QUERY_LIMITED_INFORMATION
      - '0x1410'
      - '0x1F0FFF' # PROCESS_ALL_ACCESS
      - '0x143A'
      - '0x40'     # PROCESS_DUP_HANDLE (for some dumping techniques)
  filter_legitimate:
    SourceImage|startswith:
      - 'C:\Windows\System32\'
      - 'C:\Windows\SysWOW64\'
      - 'C:\Program Files\Windows Defender\'
  condition: selection and not filter_legitimate

This fires for Mimikatz, ProcDump, comsvcs.dll, any custom tool, any future tool — because they all require PROCESS_VM_READ on lsass.exe. The evasion path is kernel-mode (bypass Sysmon entirely), which requires a kernel exploit. That’s L3+.


L3 Design Examples Across Techniques

T1059.001 — PowerShell Execution (from L1 to L3)

L1:

detection:
  selection:
    Image|endswith: '\powershell.exe'
    CommandLine|contains: '-EncodedCommand'
  condition: selection

Evaded by: using pwsh.exe, -ec abbreviation, Unicode-encoded argument, invoking via WMI.

L3:

logsource:
  product: windows
  category: ps_script        # PowerShell Event 4104 — Script Block Logging

detection:
  selection:
    ScriptBlockText|contains:
      - 'IEX'
      - 'Invoke-Expression'
      - 'DownloadString'
      - 'FromBase64String'
  condition: selection

Event 4104 records the decoded script block regardless of how PowerShell was invoked or how the command was obfuscated. The attacker cannot obfuscate their way past Script Block Logging — the payload must decode to something executable, and that decoded form is logged.

T1547.001 — Registry Run Key Persistence (from L1 to L3)

L1:

detection:
  selection:
    Image|endswith: '\reg.exe'
    CommandLine|contains:
      - 'SOFTWARE\Microsoft\Windows\CurrentVersion\Run'
  condition: selection

Evaded by: using PowerShell Set-ItemProperty, direct registry API, WMI, any tool that doesn’t call reg.exe.

L3:

logsource:
  product: windows
  category: registry_set     # Sysmon Event 13

detection:
  selection:
    TargetObject|startswith:
      - 'HKLM\Software\Microsoft\Windows\CurrentVersion\Run'
      - 'HKCU\Software\Microsoft\Windows\CurrentVersion\Run'
      - 'HKLM\Software\Microsoft\Windows\CurrentVersion\RunOnce'
  condition: selection

Event 13 fires for ANY process that writes to these registry paths — reg.exe, PowerShell, direct Win32 API, WMI, malware using reflective DLL. The only evasion is using a different persistence key, which means choosing a different sub-technique (HKCU\Environment, scheduled tasks, etc.).


The L1 + L3 Layering Strategy

Don’t choose between L1 and L3. Ship both:

LayerRuleValue
L1 (fast)OriginalFileName = 'mimikatz.exe'Zero FPs, instant detection of commodity tooling
L3 (robust)Any process → LSASS with high access rightsCatches custom tools, renamed binaries, new variants

The L1 rule catches careless attackers without any false positives. The L3 rule catches sophisticated ones at the cost of a tuning phase. Together they cover the attack space from commodity to custom.


Identifying Behavioral Invariants

For any technique, ask: what must be true in the logs regardless of which tool is used?

TechniqueBehavioral InvariantTelemetry
Credential dumping (LSASS)Process accesses lsass.exe with read rightsSysmon Event 10
Registry persistenceA value is written to a Run key pathSysmon Event 13
Network lateral movementOutbound SMB/WinRM from a workstationSysmon Event 3
Defense evasion (delete logs)Event log service stopped OR log clearedWindows Event ID 1102/104
Data exfiltrationLarge outbound transfer to unusual IPNetwork flow data

These invariants form the foundation of L3+ detections. The telemetry column tells you what to enable if you don’t already have it.