13 min read
Team RAMROD wins again - back-to-back token.wtf champs! This post details my experiences with the token.wtf CTF contest at THOTCON 0xA on May 3rd and 4th, 2019.
There are lot of really interesting talks and other things to see and do at the conference, but I always find doing the token.wtf contest to be time well-spent. It's both easy to get into, and it covers so many disciplines that anyone can feel like a 1337 H4x0r by the closing ceremonies. Maybe next year I'll get to some of those talks, though...
Stage 0 - Freebie
Some effort is required to get your team registered and tokens submitted, so this sanity check is helpful. Once you claim this freebie token, you can be sure that all of your admin work is done. Back at THOTCON 0x7, we spent some time writing scripts to register, submit tokens, and check the scoreboard. Fortunately, they haven't changed how the contest works, and we don't have to worry about this each year.
Each token gets hashed and combined with the stage number to create the url of the next stage.
echo -n '<token-goes-here>' | sha256sum
Stage 1 - :gun::zipper_mouth_face::flag-it:
An image was posted to the token.wtf Twitter page...
Examining the file, it's clear that there's more to it than just the image itself. Running
strings yields a lot of printable ascii you wouldn't expect in a jpg, and
hexdump shows significant data AFTER the
FF D9 end-of-jpg magic number.
The emojis in the image itself seem to suggest that it's a zip file and that we should "gUN ZIP IT". Attempting to unzip doesn't error, but it does require a passphrase to get the hidden files out. Trying some of the more reasonable text from our
strings output as passphrases, we finally extract what we're looking for - a text file with a flag.
hexdump ambiguous.jpg | grep 'ff d9' strings ambiguous.jpg | awk 'length>10'
Stage 2 - Happy Hunting
Watching the network console of the browser, we notice it's requesting 4 different images in a loop. The images are numbers -
011. Sure looks like an IP (ignoring the leading 0's), but there's nothing on port 80. Maybe it's the IP of a multiplayer Quake server we need to connect to in-game? It is. Maybe there's no password required? Yeah, right!
After reading way too much about the Quake 3 console and trying to dump configs, browse the filesystem, and enable special cheats, we were almost out of ideas. Viewing source on the original page, however, yields this:
// serverpass: EndgameSpoiler
Of course. :facepalm: Joining the server at that IP with the password puts you into a game with a handful of suspiciously named bots.
Noob Slayer69, the rest are obviously what we're looking for. After a little bit of trial and error with the ordering, we're on our way with the next flag.
Stage 3 - Quiz Time
An obvious IP address and port is given as the clue for this stage:
0x03 dot 0x0E dot 0x7C dot 0x62 colon 0x539. After conversion, hitting
220.127.116.11:1337 in the browser yields the following:
18.104.22.168:1337/2 404's, and
22.214.171.124:1337?answer=2 doesn't work either. Instead of guessing paths or what format to POST, we connected with telnet. Responding to the
1+1 prompt with
2 here gets us a new question:
1+2. Answering correctly again gets another question, and after 11 questions the whole quiz repeats. We decided to script it, and some quick googling suggested expect.
#!/usr/bin/expect spawn telnet 126.96.36.199 1337 expect 1+1 send "2\r" expect 1+2 send "3\r" expect 1-1 send "0\r" ...
After the script rips through a handful of iterations of the quiz, the server spits out something about being good at math and produces a flag.
Stage 4 - From Russia with Love
We're only given a link to the following YouTube video:
The title and description of the video aren't helpful. The transcript is somewhat wrong and most definitely incomplete, and it eventually even devolves into a rickroll. After slowing the video and listening extra closely, you can hear an overlayed audio track of somebody saying Russian letters/numbers. Time to go learn some Russian. After several translation efforts, including a few by a fluent speaker, we had enough to play "GUID Mastermind" with the puzzle creator and figure out the flag.
Getting the full flag took significantly longer than expected (this was a third of the way into day 2 at this point), and it caused some reshuffling of the later stages to be necessary.
We noticed somebody on the scoreboard with an odd number of points. Since we knew each flag was worth 10, something was up. Our investigation led us to a table of chocolates, some of which were edible, some not. The game: "Chocolate/Not-Chocolate". Pick up a "chocolate", and put it in your mouth - it's as simple as that. Mine unfortunately turned out to be a chocolate-covered package of mints. Landon enjoyed a chocolate-covered plastic dinosaur. There were some real chocolates too, and the flag-containing winner turned out to be a chocolate-covered Oreo with a tiny slip of paper inside.
A+++ would Chocolate/Not-chocolate again
Stage 5 - :gift::gift::gift:
The generous folks at the token.wtf table gave us a puzzle to put together. We completed it relatively quickly, and here's the finished product:
To prevent anybody else from sneaking a peek, we took this photo and quickly destroyed the evidence. It was only after returning the disassembled puzzle that we converted the binary to ascii and found an unfortunate phrase.
After completing the puzzle a second time (and painstakingly flipping it), we could almost make out a QR code, written in nearly impossible to see ink. We took several photos with different lightings and angles, and we messed with levels/curves/saturation/contrast/etc in GIMP. We got close, but it wasn't good enough. After experimenting a bit more with different lightings, a nearby blacklight saved the day - it was glow-in-the-dark paint and lit up nicely.
The QR gave us another site to visit http://4z8r.token.wtf, and hitting it in the browser yielded the following message:
you didnt say the magic number - 23423
We threw the number on the end of the path and tried again, which produced yet another number. After some trial and error, we figured out that the new number is the port of the next request to make, and the "magic number" was the path. It went on and on...
http://4z8r.token.wtf/ - say the magic number - 23423 http://4z8r.token.wtf/23423 - 2217 http://4z8r.token.wtf:2217 - say the magic number - 6559 http://4z8r.token.wtf:2217/6559 - 3776 http://4z8r.token.wtf:3776 - say the magic number - 11276 ...
This continued for a long time - longer than I'd like to admit. I thought I might be able to get to the bottom of it manually, but luckily Landon came through with some quick Python. Eventually, a flag was returned.
Stage 6 - Warp Zone
This stage was unfortunately skipped due to Stage 4 being unexpectedly time-consuming for all teams.
Stage 7 - The Plot Thickens
Because of the aforementiond time contraints, stages 7, 8, and 9 were combined and presented as different options for stage 7. We were told we could choose any, but each path had a flag worth 10 points - so why not attempt them all?
Part A - Eight Oh Too Eleven
Our new friend Claude worked this one. Hopefully he's willing to contribute to the post!
Part B - Forensics Examination
We were given access to a stack of 7 100mb zip disks and a zip drive.
Being a forensics challenge, I figured a good first start would be to make images of them. After
dd ing them to my disk (at a speed not seen since 1995), it was time to figure out what to do with them.
My first thought was that 7 x 100 = 700 mb = the capacity of a CD - I should concatenate all the images together and mount it as an disk image or maybe a bootable LiveCD. It was a decent guess, actually, but unfortunately not completely correct.
file on any of the images tells us it's of type
EWF/Expert Witness/EnCase image file format.
I'd used EnCase before. I remembered that it's used to forensically image a disk, and it had an option to split the image into multiple pieces. My original guess was correct, I'd have to merge these files together. Before I could continue along this path, though, I had to find out what order the images belonged in.
Looking at the picture of the disks, it might be completely obvious to those familiar with electronics. Each was labeled with a bunch of colors, resembling the bands on resistors. Renaming the disk images
disk.E0[1-7], using resistor values for ordering, was a success. Running
ewfverify confirmed this, and it was time to mount it.
ewfmount capable of mounting these files, and that too worked like a charm.
Unfortunately, this is when time ran out for the whole contest. I did follow up to find out how the rest was supposed to go. Inside the mounted EWF file was a filesystem. On the filesystem, there was a git repo in the home directory. In the git history for that repo, there was a commit mentioning the removal of the flag. Reverting/showing that commit would've given it up. Bummer - I was almost there!
Part C - GradeCom Enterprise
So that's the story of our 81 points - 8 flags and a chocolate. The 3-way tie for 2nd place all had 61 points, so they were all working on Stage 7, as well.
A few of these were our alt accounts - testing things out, playing mind games, etc
If you'd like to take a look at some of these challenges, here's the token.wtf page for all stages. I can't promise that everything will still be live (I'm not hosting), but it's all live at the time of this writing.
THOTCON and the token.wtf challenge are always a good time. Whether you go to talks, hang out in a room all day solving puzzles like us, or some combination of both - you won't be disappointed. And if you're not sure how to get started with the CTF, just walk up and ask someone what they're working on. Come sit down with us, your reigning champs, Team RAMROD!