pine.space
← Back to blog

2024-10-14

Huntress CTF 2024: warmup write-ups

A few of the challenges I solved at the Huntress CTF 2024. None of these are hard, but each has a clean trick worth remembering.

Matryoshka QR

The challenge hands you a QR code. Scan it and you don't get a flag — you get the bytes of a PNG (the \x89PNG header gives it away), which is itself another QR code. Save the bytes, open the image, scan the smaller code inside for the flag.

The QR code supplied by the challenge
qrcode.png — scanning it yields PNG bytes, not a flag
The smaller QR code hidden inside
inner_qrcode.png — the nested code that holds the flag

You can do the extraction by hand, but Python makes it tidy:

from PIL import Image
import io

inner_data = b"\x89PNG\r\n\x1a\n..."  # the bytes decoded from the outer QR
inner_image = Image.open(io.BytesIO(inner_data))
inner_image.save('inner_qrcode.png')

Cattle

The attached file is a wall of ms and os. Searched around and it turned out to be COW, an esoteric language whose entire instruction set is variations on "moo." An online COW interpreter runs it and prints the flag.

The COW source code
The 'code' — MOO, moO, mOo and friends

Whamazon

A little shop where the flag costs $10,000,000,000 and you start with $50. Easy to overthink.

The Whamazon shop menu with a $50 balance
$50 to spend; the flag is item 7

The store multiplies quantity by unit price and subtracts that from your balance — but it never checks that the quantity is positive.

Buying one apple for three dollars
Cost = quantity × price, subtracted from the wallet

Buy a negative number of something and the subtraction becomes an addition. Your balance balloons.

Buying a negative quantity of video games to inflate the balance
−5×10²¹ video games later, the wallet is very full

Now the flag is affordable, and it's waiting in your inventory.

The inventory listing showing the flag
The flag, bought and paid for

Finder's Fee

SSH in and user can't read finder's home directory.

Listing /home shows finder's directory is unreadable
Permission denied on /home/finder

But /bin links to /usr/bin, and there the find binary has its SGID bit set (rwxr-sr-x root finder) — so find runs with the finder group's permissions.

The find binary with its SGID bit set to the finder group
find is SGID finder

find will happily list a directory you couldn't otherwise read:

Using find to list the contents of finder's home directory
flag.txt, now visible

Its -exec flag then runs a command per result:

bash
find /home/finder/ -name flag.txt -exec cat {} \;
find -exec cat printing the flag
-exec cat runs as the finder group and prints the flag

Any SGID/SUID binary that can read files or spawn processes is a privilege-escalation primitive — find is one of the friendliest.