Windows Event Log Forensics: Building Evidence from Logs
Theory
Prerequisites
- DFA-K003: NTFS Forensics
- COA-K003: Windows Event Log Investigation (recommended)
Why This Lesson Matters
Registry artefacts tell you what was installed. Memory artefacts tell you what was running. Event logs tell you what happened and when. Combined, the three paint a complete picture. This lesson focuses on event logs from a forensics perspective — not alert triage (that is the COA path) but evidence extraction: how to parse EVTX files offline, build a timeline, detect log tampering, and present log-based evidence in a report.
1. EVTX File Format
Windows event logs are stored in binary .evtx format. They are not plain text — they require parsing.
Location on disk:
C:WindowsSystem32winevtLogsSecurity.evtx
C:WindowsSystem32winevtLogsSystem.evtx
C:WindowsSystem32winevtLogsApplication.evtx
C:WindowsSystem32winevtLogsMicrosoft-Windows-Sysmon%4Operational.evtx
From a forensic image (extract then parse):
icat -o 2048 disk.img <inode_of_Security.evtx> > Security.evtx
2. Parsing EVTX Offline
2.1 Python-evtx / evtxdump
# Convert EVTX to XML (readable text)
python3 -m evtx.evtxdump Security.evtx > Security.xml
# Then grep for event IDs
grep -A 20 "<EventID>4624</EventID>" Security.xml | head -60
2.2 Eric Zimmerman's EvtxECmd
# Parse to CSV (Windows tool, runs under Wine on Linux)
EvtxECmd.exe -f Security.evtx --csv /cases/IR-001/ --csvf security_parsed.csv
# The CSV contains every event with all fields expanded — easy to filter in Excel or pandas
import pandas as pd
df = pd.read_csv("security_parsed.csv")
logons = df[df["EventId"] == 4624][["TimeCreated","UserName","IpAddress","LogonType"]]
print(logons.sort_values("TimeCreated"))
2.3 Chainsaw (Hunt Rules Against EVTX)
Chainsaw applies Sigma rules directly to EVTX files — fast triage without a SIEM.
# Hunt against all EVTX files in a directory
chainsaw hunt /cases/IR-001/evtx_export/
--sigma rules/sigma/
--mapping mappings/sigma-event-logs-all.yml
--output /cases/IR-001/chainsaw_results.json
# Rules will flag: brute force patterns, lateral movement, persistence, credential dumping
3. Key Forensic Event Sequences
Event logs tell stories. The story is in the sequence, not individual events.
3.1 Account Compromise Sequence
14:30:02 4625 Failed logon × 47 (same source IP, rapid succession)
14:30:48 4624 Successful logon LogonType=3, IpAddress=185.220.101.5
14:30:49 4672 Special privileges SeDebugPrivilege assigned
↑ the account has admin rights
Reading this sequence: SSH brute force → success → admin session established.
3.2 Lateral Movement Sequence
14:31:15 4624 LogonType=3 TargetUser=Administrator IpAddress=10.0.0.42
LogonProcess=NtLmSsp ← NTLM = PtH
14:31:20 5140 Network share accessed: \SRV-001ADMIN$
14:31:25 5145 Share object accessed: file on ADMIN$
NTLM logon to a server from a workstation using Administrator = Pass-the-Hash lateral movement.
3.3 Persistence Installation Sequence
14:32:41 7045 (System) New service: WindowsUpdateHelper
ImagePath: C:UsersPublicupdate.exe
14:32:42 4697 (Security) Service installed (confirmation)
14:32:43 Sysmon 1 update.exe executes (parent: services.exe)
Three-event chain: service installed → service confirmed → service executed.
4. Detecting Log Tampering
Attackers erase their tracks by:
- Clearing individual event logs: wevtutil cl Security
- Disabling the event log service
- Deleting specific events (rare — requires direct EVTX manipulation)
Indicators of log clearing:
| Evidence | Meaning |
|---|---|
| Event 1102 in Security log | Security audit log was cleared |
| Event 104 in System log | System log was cleared |
| EVTX file has unusually small size or recent creation time | Log was recently cleared |
| Gap in event record numbers | Events were deleted (record numbers are sequential) |
# Check for gaps in Security log record numbers (Python)
python3 << 'PYEOF'
import evtx
parser = evtx.PyEvtxParser("Security.evtx")
prev_record_id = None
for record in parser.records():
rid = record["data"]["System"]["EventRecordID"]
if prev_record_id and rid != prev_record_id + 1:
print(f"GAP: missing records {prev_record_id+1} to {rid-1}")
prev_record_id = rid
PYEOF
5. Correlating Across Log Sources
Single-source analysis is weak. Cross-source correlation is powerful.
Timeline built from three sources:
auth.log (Linux WS-042):
14:30:48 Accepted SSH from 185.220.101.5 as alice
security.evtx (Windows SRV-001):
14:31:15 4624 Type 3: Administrator logged in from 10.0.0.42
14:32:41 7045: Service WindowsUpdateHelper installed
sysmon.evtx (SRV-001):
14:31:02 Event 1: powershell.exe -EncodedCommand JABm...
14:31:15 Event 3: powershell.exe → 185.220.101.5:443
14:33:02 Event 11: C:inetpubwwwrootuploadssh3ll.php created
Combined narrative:
14:30:48 — Attacker SSH's into Linux WS-042 as alice
14:31:02 — Runs encoded PowerShell (downloads next stage)
14:31:15 — C2 connection established; uses WS-042 to PtH into SRV-001
14:32:41 — Installs persistence on SRV-001
14:33:02 — Deploys web shell on SRV-001's web server
6. Common Mistakes
Mistake 1: Using local time instead of UTC. Windows Event logs store timestamps in UTC internally but some tools display them in local time. Always verify the timezone setting of your analysis tool and report in UTC.
Mistake 2: Treating an empty log as evidence of innocence. An empty Security log on a system that should have weeks of events means the log was cleared. Event 1102 confirms it; the absence of Event 1102 means the clearing predates the EVTX or used a direct-manipulation technique.
Mistake 3: Not exporting all channels. Security and System logs are obvious. Do not forget: Sysmon (if deployed), PowerShell/Operational, WMI Activity, Task Scheduler, and RemoteDesktopServices-RdpCoreTS.
7. Practice Exercises
-
An EVTX export shows Security log events jump from Record ID 8823 directly to 9100. What does this mean? What event ID would confirm the cause?
-
Build a two-sentence forensic narrative from this sequence:
4624 Type 10 from 203.0.113.5 at 03:12 UTC→4672 SeDebugPrivilege at 03:12 UTC→7045 new service "WindowsHelper" at 03:13 UTC. -
You have security.evtx from a server. You want to find all Type 3 logons that used NTLM (NtLmSsp). Write a pandas one-liner that filters the EvtxECmd CSV output for these events.
8. Lab
Assessment mode: quiz
6 questions: interpret provided event sequences, identify log tampering indicators, select the correct EVTX channel for described investigation goals, and match Event IDs to their forensic significance.
9. Framework Alignment
| Framework | Role | Competency | Confidence |
|---|---|---|---|
| CCSSF-DFA | Digital Forensics Analyst | Event log forensics and timeline construction | High |
| CCSSF-CIR | Cyber Incident Responder | Evidence-based incident timeline | High |
| NICE 2.2.0 | Digital Forensics (INV-FOR-002) | K0119 — Log analysis for forensic purposes | High |
10. Further Reading
- EvtxECmd (Eric Zimmerman) — https://ericzimmerman.github.io — Best offline EVTX parser
- Chainsaw — https://github.com/WithSecureLabs/chainsaw — Sigma-based EVTX hunter
- Windows Event Log Encyclopedia — https://ultimatewindowssecurity.com — Every Event ID explained with examples
Learning Objectives
["Parse an EVTX file offline using python-evtx or EvtxECmd and filter for at least three specific Event IDs relevant to a described investigation scenario", "Identify a log tampering event by detecting a gap in event record numbers or finding Event 1102/104, and explain what the attacker likely used to clear the log", "Build a four-event forensic narrative across two EVTX channels (Security and Sysmon) that describes initial access, execution, lateral movement, and persistence in UTC timestamps"]
Lesson Outline
Prerequisites → Why this matters → EVTX format and offline parsing (python-evtx, EvtxECmd, Chainsaw) → Key forensic event sequences (compromise, lateral movement, persistence) → Detecting log tampering (indicators, record number gaps) → Cross-source correlation (worked timeline example) → Common mistakes → Practice exercises → Quiz lab → Framework alignment → Further reading