CTF Writeups

K17 CTF: In Over My Head, and Still 49th

What it was like playing K17 CTF with Cyber Club when most of the challenges were above my level, and what I picked up anyway.

From September 11 to 13, the Ohio University Cybersecurity Club (Cyber Club) played K17 CTF. We finished 49th in the non-AI division. I’m happy with that, but I want to be upfront about something: this event was above my level. A lot of what I did that weekend was learning things for the first time while the clock was running.

The rules on AI

K17 split teams into an AI division and a non-AI division. We were in the non-AI one. The rules let you use an LLM to explain a concept or remind you of a command, but you couldn’t have it solve the challenge for you. That works out to about how I already try to practice. If I ask “what is a pickle file,” I’m still the one who has to open it and figure out what’s wrong with it.

What I ran into

The first thing that stood out was how many different kinds of knowledge one event can ask for. In a single weekend I saw:

  • A JavaScript reversing challenge where the logic I wanted was inside a module. I kept typing variable names into the browser console and getting ReferenceError back. It took me longer than I’d like to admit to understand why. Things declared inside a module aren’t global, so the console can’t see them just because the page loaded them.
  • A PDF redaction challenge. The “redacted” text had black boxes drawn over it, but the text was still in the file. Drawing a rectangle on top of words doesn’t delete them. Pulling the text out with pypdf shows what’s underneath. It’s a simple idea, and it’s also exactly the mistake real organizations make when they release documents.
  • A Terraria world file (.wld) with tampered header fields. To fix it you had to know what the header is supposed to look like: the magic bytes, the version, the savefile type, and the section pointers that say where each chunk of the world starts. I had never looked at a game save in a hex editor before, so I was learning the format and debugging it at the same time.
  • RSA with leaked dp + dq. I knew RSA at the level of public key, private key and modulus. I didn’t know what dp and dq were (the CRT exponents some implementations use to speed up decryption), so I had to start there.
  • A linear MAC forgery that came down to XOR. If a MAC is linear, you can combine known valid messages and tags to produce a valid tag for a message you never saw signed.
  • A forensics file mixing pickle and XOR, plus a few pwn challenges built on format strings and an arbitrary byte write.

Where my limits were

XOR, pickle and binary file formats are where I felt it most. I understood XOR as an operation, but not what happens when it’s used as a building block in a broken scheme, or how to reason about it when you only have pieces of the data. Pickle I knew only as “Python’s save format.” I didn’t know it was its own little instruction format, or that you shouldn’t just load one you don’t trust. And with the .wld file I could see bytes but couldn’t tell yet which ones mattered.

The pwn challenges were the clearest gap. Format string bugs and arbitrary writes are things I’ve read about, but reading about them and turning one into a working exploit under time pressure are very different skills. That’s going on my list for practice, not something I’m going to pretend I handled.

What I’m taking from it

My usual practice is picoCTF, where the challenges teach one concept at a time. K17 assumed you already had a lot of those concepts and wanted you to combine them, and that’s a big jump. Hitting that wall was useful, because now I know where the gap actually is instead of guessing.

A few things I’m changing because of this weekend:

  1. More time on binary formats. Opening files in xxd, reading a spec, and matching header fields to actual bytes.
  2. Actually working through XOR-based crypto on CryptoHack instead of skimming it.
  3. Starting pwn from the beginning on pwn.college instead of avoiding it because it feels hard.

Placing 49th as a club that’s basically being rebuilt from scratch this year is something I’ll take. And it was a good reminder that the stuff I don’t know yet isn’t a reason to sit an event out.