Inspiration
I built a forensics game for an earlier hackathon and got hooked on how real
attacks show up in server logs. Every SSH break-in leaves a trail in
/var/log/auth.log, but it's thousands of near-identical lines that no human
reads. I wanted to turn that wall of text into the actual story of what an
attacker did.
What it does
You drop in a raw SSH auth.log and Killchain reconstructs the attack as a
timeline. It groups events by attacker IP and walks the kill chain: scanning,
brute force, the login that finally worked, sudo to root, and any backdoor
account they created. It scores each attacker from 0 to 100, tags every step
with its MITRE ATT&CK technique, and writes a plain-English summary like
"198.51.100.7 ran 70 failed logins, broke in as admin, escalated to root, and
created the user backup1."
How I built it (and how I used Python)
Everything is the Python standard library. No pip installs, no frameworks.
returns each log line into a structured event.- Six detectors find the behaviors: brute force, username enumeration, breach,
privilege escalation, persistence, and scanning. The brute-force detector uses
a sliding window with
collections.deque. - A correlator groups findings per attacker and scores how far they got. I used
enum.IntEnumso "how deep did they reach" is justmax(). http.serverruns a drag-and-drop web app and renders a self-contained HTML report with no external files.- A scenario generator builds six different randomized attacks so I can test the engine on something new every run.
I wrote 17 unittest tests covering the parser, every detector, and a
round-trip where the generator makes a known attack and the pipeline has to
recover it exactly.
Challenges I ran into
The hardest one: sudo and useradd lines have no source IP. They're local
actions, so I couldn't link privilege escalation or a new backdoor account to
the attacker by address. I solved it by tying those events back to the breach
using the username, host, and time window. That one join is what turns a pile of
log lines into a single attacker's story.
A smaller bug: sshd logs an invalid login twice, once as "Invalid user" and once as "Failed password," so my brute-force counts were doubled until I counted only one of them.
And making the demo safe: a random attack generator could roll a scenario the detectors miss, which would show "attack detected, zero findings" in front of a judge. I fixed the structure of every scenario and only randomized the surface (IPs, usernames, timing), then wrote a test that every attack type still detects correctly across 60 random seeds.
What I learned
How syslog actually formats SSH events, how to write real detection rules
instead of just grepping, sliding-window detection, and that the interesting
part of forensics is correlation, not pattern matching. I also learned that
Python removed the cgi module in 3.13, which is why I send file uploads as raw
text instead of form data.
What's next
IPv6 support, more detectors (off-hours logins, impossible travel), and correlating several log sources into one timeline.
Built With
- css
- html
- http.server
- javascript
- mitre-att&ck
- python
- regex
- standard-library
- unittest

Log in or sign up for Devpost to join the conversation.