code hacking, zen coding

NDH2k12 Public Wargame – Crackme Bukkake Writeup

Simple crackme.

After a bit of reversing in IDA:

.text:08048F3C                 mov     eax, [ebp+password]
.text:08048F3F                 mov     [esp+4], eax
.text:08048F43                 lea     eax, [ebp+candidateHash]
.text:08048F46                 mov     [esp], eax
.text:08048F49                 call    WhatisIt
.text:08048F4E                 lea     eax, [ebp+validHash]
.text:08048F51                 mov     [esp+4], eax
.text:08048F55                 lea     eax, [ebp+candidateHash]
.text:08048F58                 mov     [esp], eax
.text:08048F5B                 call    ccc
.text:08048F60                 test    eax, eax
.text:08048F62                 jz      short loc_8048F7B
.text:08048F64                 mov     eax, [ebp+password]
.text:08048F67                 mov     [esp+4], eax
.text:08048F6B                 lea     eax, (aTheHashIsS - 80E605Ch)[ebx] ; "The hash is %s\n"
.text:08048F71                 mov     [esp], eax
.text:08048F74                 call    printf

ccc function is a simple memcmp. Function WhatisIt is the core of this crackme. It uses 2 tables to transform the password in a bytearray that is compared to a valid bytearray stored inside the binary.

Simple bruteforcer:

#!/usr/bin/env python

import string

valid = [ 3, 35, 31, 35, 5, 3, 8, 7, 31, 4, 5, 32, 33, 7, 31, 5, 33, 5, 4, 29, 34, 30, 31, 38, 37, 31, 30, 33, 36, 6, 36, 37 ]

print "len valid=", len(valid)

keyData1 = [ 10,  9,  1, 16, 19, 23, 13,  8,  7,  3, 14, 17, 22, 12,  6, 21, 25,  5, 20, 15, 18, 11, 24,  2,  4,  0, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36]
keyData2 = [ 90, 67, 88, 74, 89, 82, 79, 73, 72, 66, 65, 86, 78, 71, 75, 84, 68, 76, 85, 69, 83, 80, 77, 70, 87, 81, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57 ]

print "len keyData1=", len(keyData1)
print "len keyData2=", len(keyData2)

password = []

charset = string.ascii_lowercase + string.ascii_uppercase + string.digits

v = 0
while v < 32:
  for char in charset:
    t = ord(char)
    for i in range(32):
      for j in range(36):
        if (keyData2[j] == t):
          for k in range(36):
            b = keyData1[k]
            if (b == j):
              c = k + 3

              if valid[v] == c:
                print "v=", v, "t=", t, "VALID"
                password.append(t)
                print "".join(map(chr, password))
                v+=1
$ python bukkake.py
len valid= 32
len keyData1= 37
len keyData2= 36
v= 0 t= 65 VALID
A
v= 1 t= 54 VALID
A6
v= 2 t= 50 VALID
A62
v= 3 t= 54 VALID
A626
v= 4 t= 67 VALID
A626C
v= 5 t= 65 VALID
A626CA
v= 6 t= 70 VALID
A626CAF
v= 7 t= 69 VALID
A626CAFE
v= 8 t= 50 VALID
A626CAFE2
v= 9 t= 66 VALID
A626CAFE2B
v= 10 t= 67 VALID
A626CAFE2BC
v= 11 t= 51 VALID
A626CAFE2BC3
v= 12 t= 52 VALID
A626CAFE2BC34
v= 13 t= 69 VALID
A626CAFE2BC34E
v= 14 t= 50 VALID
A626CAFE2BC34E2
v= 15 t= 67 VALID
A626CAFE2BC34E2C
v= 16 t= 52 VALID
A626CAFE2BC34E2C4
v= 17 t= 67 VALID
A626CAFE2BC34E2C4C
v= 18 t= 66 VALID
A626CAFE2BC34E2C4CB
v= 19 t= 48 VALID
A626CAFE2BC34E2C4CB0
v= 20 t= 53 VALID
A626CAFE2BC34E2C4CB05
v= 21 t= 49 VALID
A626CAFE2BC34E2C4CB051
v= 22 t= 50 VALID
A626CAFE2BC34E2C4CB0512
v= 23 t= 57 VALID
A626CAFE2BC34E2C4CB05129
v= 24 t= 56 VALID
A626CAFE2BC34E2C4CB051298
v= 25 t= 50 VALID
A626CAFE2BC34E2C4CB0512982
v= 26 t= 49 VALID
A626CAFE2BC34E2C4CB05129821
v= 27 t= 52 VALID
A626CAFE2BC34E2C4CB051298214
v= 28 t= 55 VALID
A626CAFE2BC34E2C4CB0512982147
v= 29 t= 68 VALID
A626CAFE2BC34E2C4CB0512982147D
v= 30 t= 55 VALID
A626CAFE2BC34E2C4CB0512982147D7
v= 31 t= 56 VALID
A626CAFE2BC34E2C4CB0512982147D78

$ ./crackme A626CAFE2BC34E2C4CB0512982147D78
The hash is A626CAFE2BC34E2C4CB0512982147D78

Note: yes, the algorithm can be reversed and the solution is then a simple oneliner, I didn’t catch that last night.

Share