DEFCON2K12 Prequals: gb300 writeup

Written by Franck Michea, 2012-06-05 18:29:07

This articles was originally written for LSE Blog. It was archived here. Check this awesome blog out too!

For this challenge, we had an IP, a port and a password. Like most of the other exercices, it was first waiting for the password and then sent us some stuff. Format of the datas was as follow:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
DD GOTP ATM sckimmer v0.0000001

Sun Jun -9 20:58:58

 4  2  3  1  2  3
 1  8  9  9  6  0
 7  6  0  7  8  4
 0  2  8  0  9  2
 7  3  6  8  6  3
 1  9  4  4  1  7
User entered: 1 4 8 3

The matrix thing was displayed 4 times with only 3 user inputs (linked to the 3 first matrices). We were asked to enter the right input for the last matrix.

While observing what was sent and trying to answer, one of us noticed that by stacking the matrices and the user inputs, we were generating lists of 4 and 3 values respectively. The user inputs lists could be matched with 4 of the matrices lists. The answer could then be obtained from the last value of the four matched lists. Sadly there was a timeout and it was really difficult to find the right answer in time by sight, so we decided to write a python script.

 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
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
#! /usr/bin/env python2

import re
import sys
import socket

sckt = socket.create_connection(('140.197.217.85', 10435))

def discard(message):
    print sckt.recv(len(message) + 1)

COLOR = {'c': '\x1b\[\d+;\d+;\d+m'}
LINE = re.compile(
    '^%(c)s (\d) %(c)s (\d) %(c)s (\d) %(c)s (\d) %(c)s (\d) %(c)s (\d) %(c)s$' % COLOR
)
UINPUT = re.compile('^%(c)sUser entered: (\d) (\d) (\d) (\d) $' % COLOR)

def get_matrix(matrix):
    for nb_line in xrange(6):
        line = sckt.recv(89)
        if len(line) < 89:
            line += sckt.recv(89 - len(line))
        print line
        match = LINE.match(line)
        if match is None:
            sys.exit('Failed to parse number line.')
        else:
            for column in xrange(6):
                matrix[nb_line * 6 + column].append(int(match.group(1 + column)))

def get_user_input(user_input):
    line = sckt.recv(32)
    print line
    match = UINPUT.match(line)
    if match is not None:
        for x in xrange(4):
            user_input[x].append(int(match.group(1 + x)))

sckt.send('5fd78efc6620f6\n')

discard('\x1b[0;37;40m')
discard('DD GOTP ATM skimmer v0.0000001')

for _ in xrange(5): # [1]
    matrix = [[] for _ in xrange(36)]
    user_input = [[] for _ in xrange(4)]
    for x in xrange(4):
        if x != 3:
            discard('Sun Jun-10 20:58:58 2012')
            discard(' ')
        get_matrix(matrix)
        get_user_input(user_input)
        print matrix
        print user_input
        if x != 3: discard(' ')
        else:
            res = [0] * 4
            for it in xrange(4):
                inpt = user_input[it]
                for lst in matrix:
                    if lst[:-1] == inpt:
                        res[it] = lst[-1]
                        break
            result = '%d %d %d %d\n' % (res[0], res[1], res[2], res[3])
            print result,
            sckt.send(result)

After some loops it finally gave something that looked like a menu of a cash machine, the balance of the account, and closed the connection. The balance was the flag: 9238740982570237012935.32.

[1] for here is due to some tests we did to find how many times was necessary to win, but we didn't find it and since we already had the key we moved on after 5 minutes.