Skip to content
All posts
forensicsrevised April 14, 20264 min read

Log forensics and threat hunting for blue-team CTF

Defensive challenges hand you logs and ask what the attacker did. Building a timeline, following the kill chain, and using MITRE ATT&CK as a checklist to turn a pile of events into the story that holds the flag.

Blue-team and DFIR challenges invert the usual CTF: instead of breaking in, you are handed the aftermath - web server logs, Windows event logs, a shell history, a SIEM export - and asked to reconstruct what an attacker did. What was the first foothold? What did they run? What did they take? The flag is a fact buried in the logs: an attacker IP, an exfiltrated filename, the timestamp of compromise, the CVE they used.

The trap is drowning. A realistic log set is tens of thousands of lines, almost all of it normal, and staring at it top to bottom finds nothing. Threat hunting is a discipline for exactly this: reduce, pivot, and reconstruct, using a model of how attacks unfold to know what to look for.

Reduce before you read

The first move is always to shrink the haystack - the same reduction discipline that makes PCAP triage tractable. You cannot read everything, so cut away the normal until the abnormal stands out. Frequency analysis is the workhorse: the attacker's activity is, almost by definition, rare compared to legitimate traffic.

# Which IPs are noisiest, and which are one-offs?
awk '{print $1}' access.log | sort | uniq -c | sort -rn | head
# Rare user-agents are often tools:
awk -F'"' '{print $6}' access.log | sort | uniq -c | sort -n | head
# Non-200 responses cluster around probing and exploitation:
awk '$9!=200{print $1, $7, $9}' access.log | sort | uniq -c | sort -rn | head
Sort-by-count in both directions. The noisiest IP might be a scanner; the single weird user-agent or the one endpoint that 500ed is often the actual attack.

Build the timeline

Once you have a suspect - an IP, a user, a process - the central artifact of any investigation is a timeline, and a disk image or a memory dump contributes rows to the same one: every event involving that entity, in order, across all your log sources. The story of the compromise is chronological, and the flag is usually a specific step in it. Normalise timestamps to one timezone, merge your sources, and sort.

# Pull one attacker IP's full activity, in order:
grep "203.0.113.7" access.log | sort -k4
# The sequence tells the story: recon (many 404s) -> a hit (a 200 on an odd
# path) -> a POST (the exploit) -> requests to a shell -> exfil (a large GET).
A super-timeline tool (Plaso/log2timeline) does this across many artifact types at once, but a sort on one field gets you the shape for a single source fast.

Follow the kill chain

Attacks proceed in stages, and knowing the stages tells you what to look for next once you have found one. If you have identified the initial access, the model predicts execution, persistence, and exfiltration are also in the logs - go find them. MITRE ATT&CK is the detailed version of this: a catalogue of the techniques attackers use, organised by tactic (the 'why'), that doubles as a hunting checklist.

StageWhat it looks like in logs
Initial accessAn exploit attempt that got a 200, a successful login from a new IP, a malicious upload
ExecutionA web server or office process spawning a shell; encoded PowerShell; unusual command lines
PersistenceA new user, a new scheduled task or cron job, a new service, an added SSH key
Privilege escalationA sudo/SUID event, a token-related Windows event, a known local-exploit signature
Collection & exfiltrationA large response, an outbound connection to a new host, a big archive created then read

Map what you find onto these stages and the gaps tell you where to look. Found the exfiltration but not the entry? The entry is earlier in the timeline, before the first suspicious event you have. The kill chain turns 'search everything' into 'search for the specific next thing'.

The specific log sources

  • Web access logs. IP, timestamp, method, path, status, size, user-agent. The size field flags exfiltration; the status field flags probing; the path field carries the payload.
  • Windows Event Logs (EVTX). Event 4624/4625 (logon success/failure), 4688 (process creation), 4720 (user created), 7045 (service installed), and the Sysmon channel if present. Parse with a tool like Chainsaw or EvtxECmd rather than by hand.
  • Shell history / auth logs. .bash_history, /var/log/auth.log, sudo logs - the attacker's commands, sometimes verbatim.
  • PowerShell logs. ScriptBlock logging (Event 4104) records the deobfuscated script, which is where an encoded payload becomes readable.

The method

  1. Reduce: frequency-analyse the logs to surface the rare and the abnormal.
  2. Establish a baseline of normal, so deviations become visible.
  3. Pick a suspect entity - IP, user, process - and pull its full activity.
  4. Build a timeline: merge sources, normalise time, sort.
  5. Map events onto the kill chain / ATT&CK and hunt the stages you have not yet found.
  6. Keep a running list of entities and facts; the flag is the gap in the story.