Uncategorized

Watchlist CTF 2026: How I Ran a DFIR CTF Alone

September 23, 2026
Black terminal-style banner in the Watchlist CTF colours: headline Watchlist CTF 2026, The Making. A builder sits at a laptop inside a Person of Interest style target box tagged Subject: Admin, Status: Relevant, with ten call-outs flying in: 756 users, 431 teams, 24 challenges, Cowrie honeypot, Cloudflare Workers, systemd watchdog, 03:00 AM cron fix, 56% played solo, Razgovor 12 solves, 9 tied at 5560

24 hours · 756 users · 431 teams · 24 challenges · 6 categories · run solo, start to finish.

The Beginning

I was a CTF player in my younger days, focusing on forensics and miscellaneous challenges. Incidentally, those forensics and miscellaneous challenges also helped me a lot in my professional career. With 17 years in the corporate world handling InfoSec challenges and the last 8 years supporting XposedOrNot as its founder.

This is how WATCHLIST CTF began: a 24-hour, DFIR-flavoured CTF that opened on 19 September 2026 at 03:30 UTC and closed at the same time the next day.

There were two challenges I wanted to attempt in this CTF:

  1. Can we run a global CTF as a one-man team?
  2. Can we run it differently than the usual CTFs we see regularly?

Those were my seed ideas, and since I do not have the needed knowledge or experience in web, pwn, or crypto, those three were ruled out. Now comes the main issue: how do we run a CTF with only a forensics focus, and that’s when I realised a CTF closer to DFIR may help.

The next challenge is making it interesting for the participants.

In our earlier days of CTF participation, many competitions used to run monotonously with no flavor or theme.

However, there were some; even their front-end design was very unique, interesting, and captivating, and it made a very positive impression on players like us.

So for sure I wanted a theme, and the search continued.

Finally settled on Person of Interest, with each episode an investigation, and it fit our requirements well, not to mention the fact that I am a die-hard fan, and it also allowed me to pay my tributes in my own way.

Challenge Categories

Now that the theme and direction were visible, the next choice was the categories. Forensics was a given, so the search widened from there, and trivia and OSINT became obvious quite quickly. Trivia is primarily the board entry, and OSINT sits close to DFIR anyway.

Also added Recon, as it’s always the first part of any incident at the beginning.

That didn’t look sufficient, and we wanted to add a bit of a lab exercise. Where’s the fun if every challenge can be solved from a desk with scripts and nothing has to be done by hand on a live box? Hence, a lab was introduced.

Finally, while deciding the categories, I deliberated on adding one not seen in existing CTFs: a POI category built on the theme. The idea is to solve an individual investigation and then move it level by level. In hindsight, this category was well received by the participants, and even in feedback, this category was highlighted in a positive way.

That ends our search with Trivia, Forensics, OSINT, POI, Recon, and Lab.

Category Challenges Points What it covers
Forensics 6 1525 Disk images, memory captures, documents, and logs. Recover what was deleted, covered, or overwritten.
Lab 5 1250 Hands-on targets: live hosts, packet captures, and full disk images to walk through.
OSINT 3 750 Open-source intelligence: metadata, public records, archives and flight data.
Recon 2 450 Reconnaissance against live infrastructure: certificates, repositories and provenance trails.
Trivia 3 235 Short warm-up and sign-off questions.
PoI 3 800 The Person of Interest story arc. Three linked challenges, one case.
Hidden 2 550 Off-board bonus challenges. Not listed on the scoreboard, found by players who looked where they were not told to.

Infrastructure

One thing was clear: the build and infra will be fuelled by Python scripts for sure. Python has been a very trusted and supportive one in my projects, and I used it extensively in XposedOrNot. The entire backend operations and API run 100% on it, and hence I wanted to continue in that trend.

Been a Linux user for a long time, and hence that would also be the base of all challenges, be it creation or the solution end. That’s also one of the reasons there were no Windows-related challenges in this entire event. Maybe some day in the future.

A couple of topics I wanted to cover: file forensics, memory forensics, SSH honeypot analysis, cross-cloud correlation log analysis, recovering tampered documents, and a few more.

Since we are playing in the POI theme, it is better to get a domain, Northernlights, and hence you would have seen that domain in play.

Constraints & Challenges

A couple of things I wanted to keep in mind are to avoid disturbing the players and not get into firefighting mode.

As such, what we planned and what we got is completely different, as one challenge conked off for the first few hours even with all these precautions.

Second one, wanted to bring in a bit of analysis: be it manual or automatic, string search should ideally not give the strings. Care was taken on that front.

A fair amount of internal checks and balances on the availability of the services for hosts that were serving these challenges. Be it a virtual machine or a Cloudflare Worker, it was monitored round the clock, literally.

Proud to say that, for a first-time CTF host, the uptime got a lot of appreciation from players, in the feedback form and on CTFtime.

The live side of things ran on a mix of a single VPS and Cloudflare’s free tier. Every challenge ran in its own container, so one going down couldn’t take the others with it.

A few services had to stay up and answer requests in real time rather than just sit there as static files: the flag endpoint behind Razgovor, a little HTCPCP toy server for the RFC 2324 trivia question, and the Cowrie SSH honeypot for the beginner persistence-hunting challenge.

Each of these ran as its own systemd service with a watchdog cron checking on it, because losing one of these mid-event was exactly the kind of firefighting I was trying to avoid.

A few other pieces (the canary check-in behind Trap Street, the C2 simulation, and the relay behind the final challenge) were built as Cloudflare Workers instead, which meant one less server for me to babysit at 3 am.

The Cowrie honeypot deserves its own mention. It wasn’t spun up for the weekend and torn down after. It ran live and caught real attack traffic well before and after the event, which is part of what made the logs behind Trap Street feel authentic instead of staged, and it ran for almost two months continuously.

On the Forensics track specifically, I tried to make sure no two challenges taught the same lesson twice: recovering a deleted-but-recoverable file, spotting a tampered document, telling signal from noise in a pile of honeypot logs, pulling something out of a memory dump, and finally correlating logs across three different clouds that don’t talk to each other.

Each one had to teach something the others didn’t.

The two hidden bonus challenges never got hints; on purpose, finding them was the actual puzzle. And by the numbers, the difficulty curve came out close to what I was hoping for: the warm-up challenges were solved by 75-81% of scoring teams, tapering all the way down to under 17% at the hard end.

Razgovor turned out to be the single hardest challenge of the event, with only 12 of the 213 scoring teams, 5.6%, cracking it.

Playtesting

I ran this in passes rather than all at once: a blind playthrough about 11 days before launch, a full soak test after that, and a final smoke test the night before the event went live, with notes for each pass kept separately.

Every challenge also had its own solver script that I ran against the actual shipped artifact right before launch, independent of the design doc, just to catch anything that had drifted.

That process is what caught a couple of nasty little bugs before they became live-event problems: an Office document library that was quietly stamping the build time into file metadata, and gzip embedding wall-clock time into archive headers.

Left alone, either one would have silently changed the flag on every rebuild. Pinning the timestamps fixed both.

Challenges

# Category Title Points Files Solution
F100 Forensics Carter’s Note 100 488e9231c060b7c7.zip walkthrough
F200 Forensics Shadow Box 200 20769767962808ed.pdf walkthrough
F250 Forensics Trap Street 250 98e5b6c288ba3672.tar.gz walkthrough
F275 Forensics Dead Drop 275 F275-dead-drop.img walkthrough
F300 Forensics Tmpfs 300 F300-tmpfs.7z walkthrough
F400 Forensics Mirror Sites 400 a093033e707206da.tar.gz walkthrough
L100 Lab Reduced Footprint 100 none (live target) walkthrough
L200 Lab Signal 200 5dde59ee766dcf93.pcap walkthrough
L250 Lab Checkpoint 250 3d44a3e47901c9c1.tar.gz walkthrough
L300 Lab Legion 300 a342e7530aec5e66.pcap walkthrough
L400 Lab Mission Creep 400 L400-mission-creep.7z walkthrough
O100 OSINT Cadence 100 7ac6142bb8e8c0ea.docx walkthrough
O350 OSINT Manifest 350 74fbd4e07ff56e85.tar.gz walkthrough
O300 OSINT Aletheia 300 none (live target) walkthrough
R150 Recon Ghosts 150 none (live target) walkthrough
R300 Recon Razgovor 300 none (live target) walkthrough
T10 Trivia Check-In 10 none (live target) walkthrough
T100 Trivia Satoshi 100 none (live target) walkthrough
T125 Trivia RFC 2324 125 none (live target) walkthrough
P100 PoI Pilot 100 1f97c207100afb1e.zip walkthrough
P250 PoI Witness 250 26bf84684d31d6f7.zip walkthrough
P450 PoI Endgame 450 3b6a10347800c543.zip walkthrough
B200 Lab (hidden) Bad Code 200 none (live target) walkthrough
B350 Forensics (hidden) Contingency 350 none (live target) walkthrough

Solve counts by challenge

Horizontal bar chart of solve counts per challenge out of about 213 scoring teams: Satoshi 171 at the top down to Razgovor 12 at the bottom

Participants and Metrics

We had a surprisingly large number of registrations and participation for a first-time CTF. Thank you to all who participated and solved challenges.

One note on the numbers below: the stats page says 25 challenges, and the solve chart has a Debrief bar. Debrief wasn’t a challenge; it was the feedback form, worth nothing on the board. 24 were the real ones.

CTFd scoreboard screenshot: score-over-time lines for the top 10 teams and the table showing nine teams tied on 5560 points
CTFd statistics panel: 756 users, 431 teams, 2375 IPs, 5560 points, 25 challenges, most solved Satoshi 171, least solved Razgovor 12

Registration & team growth

Line chart of registrations and teams over the event, from 403 users and 223 teams before the start to 756 users and 431 teams at the end

The headline numbers were nice. What actually surprised me was how many people showed up alone. 119 of the 213 scoring teams, just under 56%, were solo players.

I hadn’t planned around that assumption either way, but it says something about a DFIR-themed CTF. Forensics is more of a one-person-at-a-desk skill than web or pwn, where teams naturally split the work.

Team size distribution

Bar chart of team sizes across 213 scoring teams: 119 solo, 29 pairs, 27 threes, 16 fours, 9 fives, 11 sixes, 2 sevens

The score curve told its own story too. Nine teams finished tied at the max score, 5560, sorted purely by who reached it first, per the closing announcement’s tiebreak rule.

Below that cluster, the drop was steep. Median score across all 213 scoring teams was 1835, less than a third of max, and that’s the shape I wanted. A determined newcomer could get somewhere on the board, and the top stayed hard to reach.

Score distribution

Bar chart of final scores across 213 scoring teams: 1 under 100, 88 between 100 and 999, 48 between 1000 and 2999, 59 between 3000 and 4999, 17 at 5000 or more

Lessons Learnt

Running this as one person, first time out, meant a few things slipped through that I’d fix immediately if I did this again.

The biggest content gap: every technical challenge ended up Linux, cloud, or protocol-based. Not a single one touched Windows artifacts. Nothing on the registry, Event Logs, $MFT, or Prefetch.

That’s a real gap against the DFIR label, since Windows endpoint forensics is most of what real-world DFIR work actually looks like.

Related to that, nothing exercised true multi-source timeline reconstruction, the kind you’d do with plaso or log2timeline across filesystem, logs, registry, and memory together. Mirror Sites (F400) gets close with its cross-cloud correlation, but it’s hand-correlating a handful of known events, not building a timeline from scratch.

That’s my priority build for Year 2.

On infrastructure, a few things I’d lock in from day one instead of retrofitting mid-build: elastic IPs on every instance (I chased IP drift more than once), watchdog crons as part of the deployment runbook rather than an afterthought, and centralized logging so I’m not scrambling to pull logs off a VM before shutting it down.

A late security pass, about 40 hours before the event, caught real issues that should’ve been caught at build time: rate limiting keyed to a spoofable value instead of the real connection IP, a single-threaded service that needed to handle concurrent requests, a flag sitting in source instead of a secret store. None of these were exploited live, but they’re now a standing checklist I run per-challenge, not a pre-event scramble.

On content, the boss challenge was still untested on a clean VM three days before launch, and I ended up swapping it out for a lighter challenge at the last minute. Year 2 rule: anything VM-based gets built and OVA-tested by day 60, not day 110.

Acknowledgments

This was a one-man build, start to finish, so there’s no team to thank behind the scenes.

The thanks here go to the players. 756 of you showed up for a first-time event with no track record behind it, stuck with it through a rough patch of infra trouble in the early hours, and gave feedback that was honest, not just polite.

That’s what makes a first year worth running again.

Closing Note & What’s Next

For a first year, run alone, I’m genuinely happy with how this landed. But there’s a long list of things to fix, and the Lessons Learnt section above is only part of it.

Year 2 has to be better: more Windows/endpoint coverage, infrastructure that doesn’t need me awake at 3 am fixing a cron job, and outreach that starts weeks earlier instead of scrambling in the final stretch.

If you played this year, thank you again. If you didn’t, there’s a Year 2 coming, and I intend to make it worth showing up for.

Get alerted when your email shows up in a new breach. Set up free breach alerts, it takes two minutes.


Check out some of our posts for you.

Discover more from Data Breach Insights

Subscribe now to keep reading and get access to the full archive.

Continue reading