Challenge: Warmer Up · CTF: DalCTF 2026 · Category: Forensics · Difficulty: Easy
TL;DR
The “challenge file” is the CTF’s own rules PDF. The flag is sitting in plain text as the very last line of the document. Open the PDF, scroll to the bottom (or run pdftotext), and read the rules like the author begged you to:
| |
That’s the whole thing. But let’s do it properly, because “it’s just plain text” is the conclusion — not something you know going in.
The setup
The challenge name is Warmer Up and the description is a cheeky “What, the rules again?”. The provided file is rules1.pdf — the same rules document handed out at the start of the event. The category tag is forensics, and the joke writes itself: the author is daring you to actually read the rules instead of skimming past them to get to the “real” challenges.
This is a classic CTF tradition. Almost every event hides a freebie flag somewhere in the rules, the welcome message, or the Discord topic. They’re worth a few easy points and they reward the one habit every competitor should have: read everything carefully.
But I didn’t know it was a freebie when I started. A 50-point forensics tag on a PDF could just as easily mean carved data after EOF, an embedded file, a stego’d image, or a malicious /OpenAction. So I treated it like any other PDF forensics target.
Step 1 — Identify the file
First, confirm what we’re actually holding:
| |
A ~53 KB PDF, version 1.5. Nothing weird yet. On to the standard forensics passes.
Step 2 — Look for the easy win (strings + flag grep)
The fastest possible check — grep the raw bytes for anything flag-shaped:
| |
Nothing. That’s expected — the actual page text in a PDF lives inside compressed (FlateDecode/zlib) streams, so strings on the raw file won’t surface readable body text. This is the #1 reason people get stuck on PDF challenges: they run strings, see nothing, and assume the flag is deeply hidden, when in reality it’s just compressed plain text.
Step 3 — Map the structure with binwalk
| |
| |
Dozens of zlib streams. At first glance this looks suspicious (“why so many embedded blobs?!”), but this is completely normal for a PDF — each text object, font subset, and content stream gets its own Flate-compressed object. This is a structural artifact, not a hiding spot. Don’t get nerd-sniped into carving forty font tables.
Step 4 — Metadata
| |
| |
Interesting little tells here, but nothing secret:
Title: rules.md— the source was a Markdown file.Creator: HeadlessChrome— this PDF was generated by “printing” the rendered Markdown to PDF via headless Chrome.
Translation: someone wrote rules.md, rendered it in a browser, and printed it. The flag, if it’s text, will be in the document body, not in some exotic structure. That points us straight at the rendered text.
Step 5 — Just read the document
This is the move people skip. Decompress the streams and dump the actual text:
| |
The output is exactly what you’d expect from a rules sheet — welcome blurb, in-person vs. online brackets, prizes, logistics, and the rules list:
| |
And then, after the AI Policy section, the document signs off:
| |
There it is — the final line of the entire document:
| |
The flag literally reads “did you read them?” — a perfect punchline for a challenge whose description is “What, the rules again?”
Step 6 — Due diligence (ruling out the rabbit holes)
Even after finding the flag, it’s worth a 30-second sanity check to confirm there isn’t a second, harder flag hidden elsewhere — and to confirm the PDF is benign.
Appended data after EOF? A common PDF trick is stashing a ZIP or image after the %%EOF marker.
| |
The last %%EOF is at offset 54261; the file is 54267 bytes. That’s only 6 trailing bytes — just a newline/whitespace. Nothing carved onto the end.
Active / embedded content? PDFs can carry JavaScript, embedded files, or auto-run actions.
| |
No /JavaScript, no /EmbeddedFile, no /OpenAction, no /Launch. The PDF is clean — it’s purely a rendered document with no hidden payload.
Confirmed: one flag, in plain sight, at the bottom of the rules.
Lessons / takeaways
- Read the rules. Actually read them. This is the entire moral of the challenge, and it generalizes: in CTFs (and pentests), the intro material, READMEs, and “boring” docs frequently hide the win.
stringson a PDF tells you almost nothing about its text. PDF body text is Flate-compressed inside stream objects. Reach forpdftotext,mutool, orpdf-parserto read content — notstrings.- Don’t get nerd-sniped by structure. Forty zlib streams in a PDF is normal (fonts + content objects), not forty hidden files. Know what “normal” looks like so you can spot what isn’t.
- Metadata is a free hint.
Title: rules.md+Creator: HeadlessChromeimmediately told us this was Markdown → browser → PDF, meaning the payload was plain rendered text, not an exotic embed. - Finish with a quick EOF + active-content check. Even a freebie deserves a 30-second confirmation that you didn’t miss a second flag and that the file is safe to open.
A perfect warm-up. Or, as the author put it: DONT SLOP. 🐙
Flag: dalctf{d1d_y0u_r34d_th3m?}