## crackme analysis

Posted by Paul Bobby on July 10, 2009

I’ve finished my analysis of the crackme I’ve been talking about for the last couple of posts. The userid-to-serial manipulation is accomplished using Complex numbers.

The crackme is split in to three parts:

- Userid manipulation
- Serial Code manipulation
- Complex number arithmetic against the manipulated Serial Code and manipulated Userid

Userid Manipulation is in four parts

- Sum the ordinal values of each character in the userid – this value is used in a complex number (c6.real)
- The imaginery part of this complex number is (c6.real-1)*3
- Iterate through the userid as follows
- EAX=0x12345678
- for x in userid:
- eax = eax XOR x
- rotate EAX left 5 times

- Create a complex number out of two parts of the processed userid
- userid_complex.real = (EAX / 31337) AND 0xFFF
- userid_complex.imag = EAX % 31337

The following Python code accomplishes the UserID Manipulation:

1: #

2: #Process the raw Userid in four steps

3: #

4: #userid munge part1

` 5: userid2 = 0;`

6: for x in userid:

` 7: userid2 += ord(x);`

` 8: userid_munge1 = userid2`

` 9:`

10: #userid munge part2

` 11: userid2 = (userid2-1) * 3;`

` 12: userid_munge2 = userid2`

` 13:`

14: #Userid munge part3

` 15: EAX = 0x12345678`

` 16: useridList = []`

17: for x in userid:

` 18: useridList.append(ord(x))`

` 19: useridList.append(0)`

20: for EDX in useridList:

21: EAX = EAX ^ EDX #XOR EAX,EDX

22: for y in range(5): #ROL EAX,5

` 23: EAX *= 2`

24: if EAX > 0xffffffff:

` 25: EAX -= 0x100000000`

` 26: EAX += 1`

` 27:`

28: #Userid munge part4

29: #Divide EAX by 0x7a69, or 31337 base10 🙂

30: EDX = EAX % 0x7a69 #EDX contains remainder from a DIV

` 31: EAX = EAX / 0x7a69`

` 32: EAX = EAX & 0xfff`

Serial Code Manipulation

The crackme reads in a serial code, 36bytes in length. The code is manipulated by

- Bytes 9,18,27,36 are reset to 0
- Each byte in the serial number is converted
- ord(byte) – 0x30
- shift the result left 4 times

` 1: def processRawSerial(rawSerial):`

` 2: EAX = 0`

3: for x in rawSerial:

` 4: y = ord(x) - 0x30`

5: if y > 0x0A:

` 6: y = y - 7`

7: EAX = EAX * 16 #SHL EAX, 4

8: if EAX > 0xffffffff:

` 9: EAX = EAX & 0xFFFFFFFF`

` 10: EAX = EAX | y`

11: return EAX

This function is used to produce four parts of the serial number: serial1 through serial4

`Complex Numbers against the Serial Code and Userid`

Python has builtin support for Complex numbers, making the following calculations very easy. Isn’t it interesting that I had a harder time coding Rotates and Shifts than I did complex arithmetic.

A series of complex number calculations are performed using the Serial Code. A series of complex number calculations are performed using the Userid. The outcome should be equal if you are using a valid Serial Code. Here are both processes.

- c3_real = 0
- c3_imag = 0x4e21
- c1 = (serial1+1J*serial2)
- c2 = (serial3+1J*serial4)
- c6 = (userid_munge1+1J*userid_munge2)
- uc = (userid1+1J*userid2)
- Loop:
- add 3 to c3_real
- subtract 2 from c3_imag
- c3 = (c3_real+1J*c3_imag)
- # Compute the serial number complex arithmetic
- sc1 = c3 * c3
- sc2 = c1 * c3
- c4 = sc1 + sc2
- c4 = c4 + c2
- # Compute the userid complex arithmetic
- sc1 = c3 + c6
- sc2 = c3 + uc
- c5 = sc1 * sc2
- if c5 != c4 then exit #wrong serial
- repeat the loop 6666 times

And that’s it. What follows will be the keygen.

## Leave a Reply