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:
- Can we run a global CTF as a one-man team?
- 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

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.


Registration & team growth

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

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

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.
- How Big Is a Data Breach?
- Watchlist CTF 2026: How I Ran a DFIR CTF Alone
- 5 Things in a Data Breach Worse Than a Leaked Password
- Domain Breach Check by API: Verify Once, Pull the Report Anytime
- Password Managers, From Someone Who Reads Breach Dumps
- 516 Breaches Leaked Passwords. 56% Stored Them Badly.





