crackme 11 keygen

crackme 11 ui :
image1

you need input username and password.

decompile code

1
2
3
4
5
6
7
8
9
10
11
0040127D   .  BF 06214000   mov edi,crcme1.00402106                  ;  ASCII "testabc"
00401282 . 33DB xor ebx,ebx
00401284 . 33C0 xor eax,eax
00401286 > 8A1F mov bl,byte ptr ds:[edi]
00401288 . 80FB 20 cmp bl,0x20 ; 0x20 space
0040128B . 0F82 95000000 jb crcme1.00401326
00401291 . 03C3 add eax,ebx
00401293 . 47 inc edi
00401294 . 803F 00 cmp byte ptr ds:[edi],0x0
00401297 .^ 75 ED jnz short crcme1.00401286

bl is the lower part of ebx
rewrite it as python code:

1
2
3
4
5
6
7
8
9
10
edi = username
ebx = eax = i = 0
while i < len(edi):
ebx = edi[i]
if ebx < 0x20:
jump
eax += ebx
i += 1
if edi[i] == 0x0:
jump

continue

1
2
3
00401299   .  C1C0 03       rol eax,0x3
0040129C . 35 A5150500 xor eax,0x515A5
004012A1 . 50 push eax

python

1
2
3
eax <<= 3 #  000002E6 for testabc
eax ^= 0x515A5
temp = eax # push eax to stack for username `testabc`, I got `eax = 00050295`

continue, asm code

1
2
3
4
004012A2   .  33C0          xor eax,eax
004012A4 . 33DB xor ebx,ebx
004012A6 . 33FF xor edi,edi
004012A8 . BE 2E214000 mov esi,crcme1.0040212E ; ASCII "123456"

python code:

1
2
eax = ebx = edi = 0
esi = password # 123456 is my input

asm

1
2
3
4
5
6
7
8
9
10
11
12
13
14
004012AD   > /B8 0A000000   mov eax,0xA
004012B2 . |8A1E mov bl,byte ptr ds:[esi]
004012B4 . |85DB test ebx,ebx
004012B6 . |74 15 je short crcme1.004012CD
004012B8 . |80FB 30 cmp bl,0x30 ; check if it is 0
004012BB . |72 69 jb short crcme1.00401326
004012BD . |80FB 39 cmp bl,0x39 ; check if it is 9
004012C0 . |7F 64 jg short crcme1.00401326
004012C2 . |83EB 30 sub ebx,0x30
004012C5 . |0FAFF8 imul edi,eax
004012C8 . |03FB add edi,ebx
004012CA . |46 inc esi ; crcme1.0040212E
004012CB .^\EB E0 jmp short crcme1.004012AD

interpret as python

1
2
3
4
5
6
7
8
eax = 0xA
while i < len(esi):
ebx = esi[i]
if ebx < 0 or ebx > 9:
jump
edi = edi * 10 + ebx. # 0xA is 10
i += 1

asm

1
2
3
4
5
6
7
8
004012CD   > \81F7 CA870000 xor edi,0x87CA
004012D3 . 8BDF mov ebx,edi
004012D5 . 58 pop eax ; 00050295
004012D6 . 03C3 add eax,ebx
004012D8 . 35 E7970700 xor eax,0x797E7
004012DD . 85C0 test eax,eax
004012DF 75 45 jnz short crcme1.00401326

python

1
2
3
4
5
6
7
8
9
edi ^= 0x87CA
ebx = edi
eax = temp
eax += ebx
eax ^= 0x797E7
if eax == 0:
jump
else:
succeed

we can see, this app check both username and password , password and username must have some relationship, let’s revese engineer the relationship
at line 5, and 6, final result of eax must be 0x797E7 , at line 3 we know eax has value of temp , which is calcuated by f(username) so we get

1
2
3
0x797E7 - temp = f(password) ^0x87CA
=>
f(password) = 0x87CA ^(0x797E7 - temp)

write keygen as such:

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
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(int argc, char *argv[] )
{
/* if(argc != 3) { */
/* printf("Usage: %s <username> <password>\n", argv[0]); */
/* } */
/* char *username = argv[1]; */
/* char *password = argv[2]; */

/* printf("Username: %s\n", username); */
/* printf("Password: %s\n", password); */


char username[100];
printf("Enter username: ");
scanf("%99s", username);
printf("you entered: %s\n", username);

size_t username_len = strlen(username);
if(username_len < 5)
{
printf("username is too short");
return 1;

}

int32_t eax = 0;
for(size_t i = 0; i < username_len; i++)
{
int c = username[i];
if( c < 0x20 )
{
printf("invalid characters\n");
return 1;
}
eax += c;
}
eax <<= 3;
eax ^= 0x515A5;

int32_t password = 0x87CA^(0x797E7-eax);

printf("keygen code: %d\n",password);
return 0;

}

generate the output as such:

1
2
3
4
~/github/algorithm-practice/crackme (master ✗) ./crack11.out
Enter username: testabc
you entered: testabc
keygen code: 135832

test it: image2
looks good!