t0ad_k3yg3n
13 April, 2018
t0ad_k3yg3n is a crackme imported from crackmes.de, with a difficulty level of 1 in C/C++. The aim is to create a keygen to generate valid passwords.
The main function we are interested in is the one that starts at 0x4006fd
,
which we can find by seeing all the printed strings, such as “< T0AD K4YG3N >”.
To begin with, we see that the function writes 0x202020
… to three buffers.
0x20 is the space character in ASCII, so these are likely character buffers.
Later down the line, this is confirmed.
Here we see a function call to scanf()
that reads from STDIN to rbp-0x50
,
one of the buffers from earlier. Before this, “Username: “ is printed, so this
must be the buffer for our username. We can rename it in our disassembler.
rbp-0x50
=username
This section initialises a value rbp-0x60
to 0. It then checks if this value
is 8, and jumps to 400785
if it’s less than or equal. At the end of this
section, it is incremented by 1. Clearly, rbp-0x60
is a loop variable.
rbp-0x60
=i
The body of this loop is simple. It takes our username buffer and goes through
every character to check if it is 0x20 - space. If it is, it jumps to 400798
,
where it prints “Access Denied.” and leaves. Since the buffer was initially set
to spaces, if any remain (or the user input contains a space), then the program
exits. As a result, the user input must be exactly 7 characters long, plus the
newline to make 8 characters.
Another user input from STDIN, this time to rbp-0x40
. This time, it’s the
password.
rbp-0x40
=password
The process of generating the correct password from the username starts here.
The byte rbp-0x4f
is grabbed into eax. Since the username
buffer is at
rbp-0x50
, rbp-0x4f
is the second character of the username input
(username[1]
). Through some twiddling, this value is copied to edx, where it
is multiplied by 0x56 and bit shifted to the right by 8. The copy in eax is
rotated to the right by 7. The value in edx is copied to ecx, and the value in
eax is subtracted from it. This is saved to rbp-0x64
, which we will name
magic
for lack of a better term.
rbp-0x64
=magic
= ((username[1] * 0x56) » 8) - (username[1] » 7)
Using the same logic as last time, we have another loop variable at rbp-0x5c
.
rbp-0x5c
=i2
This loop once again goes over the username
buffer, placing the character at
username[i2]
into eax. It then XORs this value with magic
, and ANDs the
result of this with 0x3c. This value is saved to rbp-0x54
, a temporary value
we will come back to later.
rbp-0x54
=temp
= (username[i2] ^ magic) & 0x3c
The value in temp
is added to 0x30, and this value is stored in our third
buffer rbp-0x30
plus i2
. We will later see that this buffer is used to
contain the real password.
rbp-0x30
=real_password
real_password[i2]
=temp
+ 0x30
temp
is then retrieved from memory, and added to itself twice. This is the
same as multiplying by three. The result is saved back into magic
.
magic
=temp
* 3
This loop continues over the entire username
buffer, and the end result is
thus the target password. This loop, and the initial magic
value, is
therefore the algorithm to recreate within our keygen.
There is one final loop in the code, that simply checks the user-supplied
password
buffer with the generated real_password
. If they match, the user
is granted access, otherwise they are not.
The final keygen code is as follows