During this weekend’s TUCTF competition, I encountered the woo, woo2 and woo2-fixed challenges. These are all variants of a specific challenge: the poorly oriented data type.
At face value, all of these challenges appear to be the same, presenting the following menu:
Part 1: Finding the Secret Menu Option:
The first thing I do is load woo into IDA Pro, and look for interesting functions. Immediately, the “l33tH4x0r” and “pwnMe” functions stand out. A quick xref check reveals nothing 0n “l33tH4x0r”, but “pwnMe” gets a hit from what appears to be the main menu function
From here, we can tell that this is option number 0x1337 (or “4919” at the prompt).
From here, we can dive a bit deeper into the pwnMe function: it looks like a relatively straightforward “loader” function: it looks up a structure (presumably a bear), checks if a given field is ‘3’, then calls another field.
A little bit of debugging with GDB quickly reveals the structure:
15 minutes later, we have a reasonable idea of what we need to do:
[target_ptr] [name] [type] [dunno whocares] [\x00\x00\x00\x00\xAA\xBB\xCC\xBB] [\x41\x41\x41\x41\x41\x41\x41\x41]  [dunno whocares]
Part 2: Making an Exploit
The way to exploit this vulnerability is to create a bear object, with a type of “3”, and a name which overflows into the target_ptr field, with the address of the “l33tH4x0r” function (which prints the flag). Then, go back to the main menu and trigger the hidden menu option of “4919”.
There’s one further trick to bypass before we can do this: the “bear” object only has types 1 to 2 – fortunately, the 4919 secret function does not check the actual type of object, so we fake it with a Tiger entry.
Unfortunately, I forgot to screencap the exploit during the CTF, but here’s the exploit:
#!/usr/bin/python # print "4" # print "0" print "2" print "3" print "\xDD\x08\x40\x00\x00\x00\x00\x00" print "4919"
Pipe that through stdin, and Bob’s your uncle:
Woo2 is the same as the woo exercise, except the application will forbid you from creating a bear of type 3. Fortunately, our previous exploit did not depend on this, so we could simply re-use it with a modified “win” offset, for a glorious second flag.
Correction: after the CTF, I realized that the woo did not enforce the bear.type != 3 check, where woo2 did. Welp, free internet points for me.
Woo2_fixed introduces a slight variation on this exploit: the pwnMe function now checks the “bearOffset” (which starts at -1), and ensures that it is not -1:
We can check that this is incremented when we create an object: so we simply create 2 fake bear objects, remove 1 of them, and overwrite it with a “tiger” object (which becomes “Object 1”, which bearOffset correctly points to).
The modified exploit is as follows:
#!/usr/bin/python print "3" print "1" print "dicks" # fake bear 1 print "3" print "1" print "dicks" # fake bear 2 print "4" print "1" # delete fake bear 2 print "2" # payload "bear" 2 :) print "3" print "\x0D\x09\x40\x00\x00\x00\x00\x00" print "4919"
And that’s an easy 250 (?) points:
Thanks TUCTF for putting together these challenges. I think woo2 and woo2_final were scored too highly with respect to woo, but they were definitely fun (and a good excuse for me to write up this type of memory corruption vulnerability).