Mastering Sysmon: A Practical Guide to Windows Threat Hunting

Standard Windows Security Event Logs leave massive blind spots. While Event ID 4688 tracks basic process creation, it misses critical context like CLI argument variations, parent-child process anomalies, dynamic DLL loading, and direct LSASS memory access. If an attacker injects code into a benign process or dumps credentials using Mimikatz, stock Windows logging often fails to capture the actionable telemetry you need.
That is where System Monitor (Sysmon)—part of the Microsoft Sysinternals suite—comes in. Sysmon acts as a lightweight background service and device driver that monitors system activity and logs detailed events directly to the Windows Event Log.
In this guide, we will step beyond basic installation and cover how to configure Sysmon for threat hunting, analyze high-value Event IDs, and detect common adversary tactics.
Setting Up Sysmon with a Custom Config
Installing Sysmon with default settings logs almost everything, creating massive disk space overhead and logging noise. To make Sysmon useful for threat hunting, you must pair it with a tailored XML configuration file.
A great starting point for any lab or production baseline is SwiftOnSecurity’s public Sysmon config, but understanding how to write and tweak custom rules is essential.
Installation Command
To install Sysmon with a specified configuration file:
sysmon64.exe -i -i c:\sysmon\sysmon-config.xml
To update an existing configuration on the fly without rebooting or restarting the service manually:
sysmon64.exe -c c:\sysmon\sysmon-config-updated.xml
Key XML Architecture
Sysmon configs use an include/exclude schema. For example, if you want to explicitly log process creation while excluding known noise (like backgroundTaskHost.exe), your configuration block looks like this:
<Sysmon schemaversion="4.90">
<EventFiltering>
<RuleGroup name="Process Creation Filters" groupRelation="or">
<ProcessCreate onmatch="exclude">
<Image condition="is">C:\Windows\System32\backgroundTaskHost.exe</Image>
</ProcessCreate>
</RuleGroup>
</EventFiltering>
</Sysmon>
Rule of thumb: Include broadly, exclude precisely. Exclude only binaries whose hashes and signers you trust, or noise that is predictable and high-volume.
The Top 4 Sysmon Event IDs Every Hunter Needs
While Sysmon provides nearly 30 event types, these four form the backbone of host-based threat detection:
1. Event ID 1: Process Creation
Captures detailed telemetry for newly spawned processes, including full command-line arguments, parent process details, user context, and file hashes (MD5, SHA256, IMPHASH).
- What to hunt for: Unexpected parent-child relationships (e.g.,
cmd.exeorpowershell.exespawned byw3wp.exeorwinword.exe).
2. Event ID 3: Network Connection
Maps network sockets to the specific process executable that opened them, including destination IP, port, and resolved hostname.
- What to hunt for: Unsigned or non-standard binaries making outbound connections over ports 443, 80, or non-standard high ports (Command and Control C2 traffic).
3. Event ID 7: Image Loaded
Tracks when a process loads a module (DLL). High logging overhead, but invaluable for specialized hunting.
- What to hunt for: Known dual-use DLLs like
clr.dll(indicates execution of .NET code inside non-.NET processes) or side-loading untrusted DLLs from non-standard directories.
4. Event ID 10: ProcessAccess
Fires when a process opens a handle to another process with specific memory access rights.
- What to hunt for: Processes opening handles to
lsass.exewith0x1410or0x1F0FFFaccess masks—a prime indicator of credential dumping tools like Mimikatz or ProcDump.
Real-World Threat Hunting Scenarios
Let’s apply these Event IDs to detect two classic attack patterns.
Scenario 1: Detecting LSASS Credential Dumping (Event ID 10)
When adversaries attempt to extract plaintext passwords or NTLM hashes from memory, they target the Local Security Authority Subsystem Service (lsass.exe).
To alert on this behavior, ensure your Sysmon config includes a dedicated filter for ProcessAccess to lsass.exe:
<ProcessAccess onmatch="include">
<TargetImage condition="is">C:\Windows\System32\lsass.exe</TargetImage>
</ProcessAccess>
When a tool like Mimikatz or custom C# code attempts to dump memory, Sysmon logs Event ID 10 in Microsoft-Windows-Sysmon/Operational:
- SourceImage:
C:\Users\Public\Downloads\unknown_binary.exe - TargetImage:
C:\Windows\System32\lsass.exe - GrantedAccess:
0x1F0FFF(PROCESS_ALL_ACCESS)
Red Flag: Benign software rarely requires PROCESS_ALL_ACCESS or PROCESS_VM_READ (0x0010) rights to LSASS. Any non-system process requesting full access privileges warrants an immediate containment workflow.
Scenario 2: Catching Command & Control via Web Shell (Event ID 1)
Imagine a web server running Internet Information Services (IIS). If an attacker exploits a remote code execution vulnerability and uploads a web shell, command execution will run under the IIS worker process (w3wp.exe).
By analyzing Sysmon Event ID 1 logs, you can spot anomalous execution lines like:
- ParentImage:
C:\Windows\System32\inetsrv\w3wp.exe - Image:
C:\Windows\System32\cmd.exe - CommandLine:
cmd.exe /c whoami /priv
Normal web applications rarely spawn direct Windows command shells. A simple rule alerting on w3wp.exe, httpd.exe, or nginx.exe spawning shell processes will catch early stage post-exploitation attempts.
Efficient Threat Hunting with PowerShell
You do not need a fully deployed SIEM to start querying Sysmon logs today. You can perform rapid analysis directly from PowerShell using Get-WinEvent.
Querying for Suspect LSASS Access
Run this script to retrieve all recent non-system processes attempting access to LSASS:
$SysmonLog = 'Microsoft-Windows-Sysmon/Operational'
$LSASSAccessEvents = Get-WinEvent -FilterHashtable @{
LogName = $SysmonLog
ID = 10
} | Where-Object {
$_.Message -match "TargetImage:.*lsass\.exe" -and
$_.Message -notmatch "SourceImage:.*(svchost|msmpeng|csrss)\.exe"
}
$LSASSAccessEvents | Select-Object TimeCreated, Id, Message | Format-List
Extracting Unique Parent-Child Process Relationships
To rapidly map execution patterns across a host:
Get-WinEvent -FilterHashtable @{ LogName = 'Microsoft-Windows-Sysmon/Operational'; ID = 1 } -MaxEvents 200 |
ForEach-Object {
$xml = [xml]$_.ToXml()
$data = $xml.Event.EventData.Data
[PSCustomObject]@{
TimeCreated = $_.TimeCreated
Parent = ($data | Where-Object {$_.Name -eq 'ParentImage'}).'#text'
Child = ($data | Where-Object {$_.Name -eq 'Image'}).'#text'
CommandLine = ($data | Where-Object {$_.Name -eq 'CommandLine'}).'#text'
}
} | Format-Table -AutoSize
Next Steps for Your Lab
To lock down your Sysmon skills:
- Spin up a Windows VM with Sysmon installed.
- Apply a modular configuration like SwiftOnSecurity or Olaf Hartong’s
sysmon-modular. - Run adversary simulation tools (like Atomic Red Team) to trigger test alerts.
- Examine the resulting Sysmon log entries and refine your filters to minimize false positives while retaining visibility.
Photo by Florian Olivo on Unsplash.