CSAW CTF 2013 - Reversing 400 - Keygenme

Monday, September 23, 2013 » csaw, ctf, stratum auhuur

Reversing 400 challenge of CSAW CTF 2013

Description

keygenm32.elf implements a vm in C++, mangling a given username string and then comparing the result to two tokens, supplied via the command line. If they match, it prints a smiley, if not a sad smiley. The descriptive text points us to an ip:port, where usernames are given repeatedly for which we are supposed to find the two tokens that makes the binary happy. The approach was to use the binary to mangle the username given and then reverse the tokens from the vms calculation. This can be done by observing the arguments passed to the check function in gdb. From there on, we can reverse the tokens by xoring one half with 0x31333337 and the other by rearranging the individual bytes.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
#!/usr/bin/env python

import sys
import subprocess
import struct
import socket

HOST = "128.238.66.219"
PORT = 14549
command="./get_numbers.sh"
def mangle(T6, T7):
    T6^=0x31333337
    tmp = struct.pack(">I", T7)
    T7, = struct.unpack(">I", "".join(tmp[i] for i in [1, 2, 0, 3]))
    return T6, T7

def unmangle(T6, T7):
    T6^=0x31333337
    tmp = struct.pack(">I", T7)
    T7, = struct.unpack(">I", "".join(tmp[i] for i in [2, 0, 1, 3]))
    return T6, T7


sock = socket.socket()
sock.connect((HOST, PORT))
sock.recv(256)
while True:
    data = sock.recv(256)
    print data
    username = data.strip()[-32:]
    numbers = subprocess.check_output([command, username]).strip().split(' ')
    t6, t7 = unmangle(int(numbers[0]), int(numbers[1]))
    sock.sendall("%d %d\n" % (t6, t7))
    print sock.recv(1024)
sock.close()

get_numbers.sh is a shellscript, wrapping gdb in such a way that it prints out the contents of the T6 and T7 registers of the vm after the execution. These are the numbers which will get compared to the mangled tokens. The gdbscript looks like this:

1
2
3
4
5
6
7
b *0x0804a125
command
x/2uw $esp
c
end
run
quit

It can be invoked like this: gdb --quiet -x gdbscript --args keygenme32.elf [username] 123 123