The biggest event of the robot year is happening this week! Robot invitations are cool in that they are just a password that validates at the door. We acquired the validator to be used. Can you find an invitation for us in time?
In this challenge we’re given an ELF binary which asks for a password. Disassembly in IDA quickly shows what the mess is all about – function pointers, lots of them.
The use of so many function pointers makes reversing the application a little bit more involved, so it might take some extra time to find the interesting bits: a simple virtual machine which takes a brainfuck-like program as input, operating on the entered key.
While examining the program in a disassembler, we note a call to ptrace (2), used to detect the presence of a debugger. Depending on the result it will load a different set of VM instructions; this is something we need to take into account when debugging the program. Also we note it appears to check the length of our password – it should be 29 characters.
The virtual machine appears to have four different operations, two shifts (left, right), an increment instruction and a xor operation. No further investigation into the operations was performed as the xor operation is a prime candidate used in a key/password verification algorithm.
We’ve used gdb‘s scripting functionality to log all VM operations, especially the operands of the xor operation. In addition to this the ptrace-based antidebug check is patched to ensure the right VM program is executed. The full script is attached to the bottom of this post.
The debug trace tells us every byte of our password is xorred with a ‘key byte’ and compared against 0x61. This means we can recover a given byte of our password by xorring the ‘key byte’ with 0x61. The gdb script below does exactly this, and also substitutes each input character with the correct value, so the VM program doesn’t terminate after checking the first password char (which would be incorrect).
Grabbing the key using some shell magic:
$ gdb -x mess.gdb mess <<< `python -c "print 'a'*29"` | grep KEYB | cut -d ' ' -f2 | tr -d '\n' ar3n't_funct10n_p01nt3rs_fun
For reference, the ‘correct’ key when the ‘antidebug’ VM program is run: d3bugg3rs_ar3_just_t00_us3ful
printf "inc %08x\n", *(int)($esp+8)
printf "shr %08x\n", *(int)($esp+8)
printf "shl %08x\n", *(int)($esp+8)
printf "xor %08x ^ %08x == %08x\n", *(char*)*(int)($ebp+0x08), $edx, $eax
# fixup input and print key byte
printf "KEYBYTE: %c\n", ($eax ^ 0x61)
set *(char*)($ebp - 0x04) = ($eax ^ 0x61)
# antidebug patch
set *(short*)0x08048E41 = 0x32eb