This is a really easy crackme for Windows which I solved in no more than 5 minutes. I have chosen this one to make a simple tutorial for those who are starting with Reverse Engineering so here we go.
You can see the original crackme page here.
The rules from the author are:
1. NO PATCHING
2. Find Serial
3. Write Keygen
4. 😉 Enjoy
Let’s execute the program and type some name/serial to see what’s going on:
Okay, we can see the ‘Bad Boy’ message so let’s open the exe file with IDA and look for that string. Once found we can get all its references by pressing Ctrl+X and see where in the code it is being used.
As you can see in the flow chart, there is a loop making some calculations and after that, the bad/good boy decission is taken. We could patch the jump so that we always get the Good Boy but the first rule was ‘no patching’ so we have to find out how the program works to write a keygen. So let’s focus in the inputs of the loop and the loop itself. As you can see below there are some calls to GetDlgItemTextA function which will get the strings from the DialogBox with the name / serial we have entered.
mov esi, ds:GetDlgItemTextA
push [ebp+hMem] ; lpString
push 3E8h ; nIDDlgItem
push [ebp+hDlg] ; hDlg
call esi ; GetDlgItemTextA <- Get the Name into hMem
push [ebp+nMaxCount] ; nMaxCount
push [ebp+arg_C] ; lpString
push edi ; nIDDlgItem
push [ebp+hDlg] ; hDlg
call esi ; GetDlgItemTextA <- Get the serial into arg_C
Once the program has loaded our strings it’s going to make some calculations inside a loop:
; arg_4 holds the 0x1908 value
; ebx contains the length of our name
loc_4010CC:
mov ecx, [ebp+hMem]
mov edx, [ebp+arg_4]
add edx, ebx ; edx+= name_length
movsx ecx, byte ptr [eax+ecx] ; ecx = name[i]
imul ecx, edx ; ecx = ecx * edx;
inc eax ; i++;
mov [ebp+arg_4], ecx
cmp eax, ebx ; i == name_length?
jl short loc_4010CC ; no -> loop
When this simple algorithm’s finished it’s got its output at arg_4 variable. Let’s see the next piece of code to see what our program does with it:
push [ebp+arg_C] ; char *
call _atoi
pop ecx ; eax = atoi(input_serial)
mov ecx, [ebp+arg_4] ; get our computed value
push 0 ; uType
xor ecx, 0A9F9FAh ; value ^= 0xA9F9FA;
cmp ecx, eax ; do they match?
jnz short BadBoy ; no -> bad boy
push offset aGoodBoy ; "Good Boy!"
push offset aTerimaKasihKer ; "Terima kasih kerana mencuba"
jmp short loc_401111
Simple. The computed value is XOR’ed with 0xA9F9FA and then it is compared with the atoi() of the serial. If both values match then we get the good boy. Putting this all together we can now write a valid keygen for this program. Here it is the C source code of the simple keygen I wrote:
int main(int argc, char **argv)
{
int namelength, i, serial=0x1908;
char *name = argv[1];
if(argc!=2)
{
printf("Usage: %s n",argv[0]);
exit(1);
}
namelength=strlen(name);
if(namelength < 5)
{
printf("Name must be at least 5 characters longn");
exit(1);
}
for(i=0;i<namelength;i++)
{
serial+=namelength;
serial*=name[i];
}
serial^=0xA9F9FA;
printf("Serial: %dn",serial);
return 1;
}
daniel@gargamel:~/crackme2$./keygen_cme2 daniel
Serial: -1860565822
daniel@gargamel:~/crackme2$./keygen_cme2 535246756
Serial: 1791915272
Done!
This is an easy and good one for your first steps at RE because it’s got no protections and you have to reverse a simple algorithm.
Hope you found this article useful.
Regards,
Daniel