Keygenning Crackme by sghetti
 
Tracing the code

TOOLS USED : W32Dasm, Soft-Ice, Hexeditor
DIFFICULTY : 1/10

Load the crackme in Wdasm, soon we find the call with the serial calculation :

  00401523 68A8504100 push 004150A8
* Referenced by a (U)nconditional or (C)onditional Jump at Address:004014B2(C)
00401528 E857360000 call 00404B84
0040152D 83C410 add esp, 00000010
00401530 E803000000 call 00401538 ;Serial routine
00401535 C9 leave
00401536 C3 ret


Serial Routine :
---------------

   00401538 55           push ebp
00401539 89E5 mov ebp, esp
0040153B 81EC98040000 sub esp, 00000498
00401541 A000604100 mov al, byte ptr [00416000]
00401546 8845FF mov byte ptr [ebp-01], al
00401549 A001604100 mov al, byte ptr [00416001]
0040154E 8845FE mov byte ptr [ebp-02], al
00401551 A002604100 mov al, byte ptr [00416002]


...
very long, but very easy algorithm
...

   004041CC 89D0         mov eax, edx
004041CE 034594 add eax, dword ptr [ebp-6C]
004041D1 89C2 mov edx, eax
004041D3 035590 add edx, dword ptr [ebp-70]
004041D6 8B458C mov eax, dword ptr [ebp-74]
004041D9 01D0 add eax, edx
004041DB A314604100 mov dword ptr [00416014], eax
004041E0 E803000000 call 004041E8 ; correct-serial routine
004041E5 C9 leave
004041E6 C3 ret

As you noticed I skipped the very long algo, it's very easy to understand. It checks every letter for it's value and does a simple calculation accordingly. Everybody should notice that only lower cases are processed ! What does that mean? If we enter our name in capitals, the serial will always be the same (when the name has the same length). Let's check this out..:

DETTEN = 8263
XXXXX = 8263 too :-)
MUTTEN = 8263 :-)

Point proven ! No need to write a keygen, just enter your name in capital! But we will make an internal keygen anyway :-)

Correct-Serial Routine :
------------------------

   004041E8 55           push ebp
004041E9 89E5 mov ebp, esp
004041EB 83EC08 sub esp, 00000008
004041EE A118604100 mov eax, dword ptr [00416018] ; your serial
004041F3 3B0514604100 cmp eax, dword ptr [00416014] ; correct serial
004041F9 7507 jne 00404202 ; If not correct, badguy
004041FB E830000000 call 00404230 ; Goodguy message
00404200 EB12 jmp 00404214 ; Leave

* Referenced by a (U)nconditional or (C)onditional Jump at Address: 004041F9(C)

00404202 A118604100 mov eax, dword ptr [00416018]
00404207 3B0514604100 cmp eax, dword ptr [00416014] ; check again
0040420D 7405 je 00404214 ; if correct, leave
0040420F E850000000 call 00404264 ; Badguy message routine

* Referenced by a (U)nconditional or (C)onditional Jump at Addresses: 00404200(U), 0040420D(C)

00404214 C9 leave
00404215 C3 ret

 

Check address 416014 to know the correct serial for your name. eg Detten : 8968
So now you know your serial, the only thing left to do is keygen it...

Make the internal keygen


We want to display the correct serial, instead of the badguy message. Unfortunatly the program does not use winapi's. (It's a dosbox, noticed : ))
First let's have a look at the badguy-message routine (call 00404264) :

   00404264 55           push ebp
00404265 89E5 mov ebp, esp
00404267 83EC08 sub esp, 00000008
0040426A 83C4F8 add esp, FFFFFFF8
0040426D 684D424000 push 0040424D ; push badguy-message
00404272 6828504100 push 00415028
00404277 E88C120000 call 00405508 ; display message
0040427C 83C410 add esp, 00000010
0040427F E890D1FFFF call 00401414
00404284 C9 leave

It's obvious, all we have to do is change the content of the parameter at address 0040426D. Now it contains "Incorrect Serial"
The correct serial is placed in address 00416014 as we saw before. This address contains our correct serial in hex (an int) . Before we can output the serial, we will have to convert the hex value to ascii values.
We will need some space for this, so we change the push 0040424D to JMP 00414C7C

At address 414C7C we have a gap of 186 bytes of free space. (Find this in your hexeditor, or use a specialised tool)
Now we have jumped to the free space, and we have to convert the hex to dec and to ascii-values. Next, we have to push it on the stack, and jump back to address 404272 for the display of the serial.

I coded it like this :

; serial = 416014
; badguystring = 40424D
-----------------------------------------------------------------------------------------
pushad
mov eax, [serial]
mov ebp, badguystring+2
xor ecx, ecx
mov esi, 0Ah

more: ; This routine converts hex to dec
cdq
idiv esi
imul edx, ebx
imul ebx, 10h
inc ecx
add edi, edx
cmp eax, 0
jnz more

mov eax, edi; Now eax contains the serial in decimals.
mov word ptr [ebp+ecx], 000Ah ; Here we add a return, and a null to terminate the string.
mov esi, 10h

next: ; This routine converts dec to ascii
cdq
idiv esi
add dl, 30h
dec ecx
mov [ebp+ecx], dl
cmp eax, 0
jnz next
popad
push badguystring ; We push the serial on the stack
jmp 404272 ; And jump back to where we left.
-----------------------------------------------------------------------------------------

Patching the code


Ok, that is all very easy, but how are we going to add this to the program?

I prefer to use Softice for this. Load the crackme in the Symbol Loader, and let it break at address 0040426D. typ 'a' and press enter.
We can change the code now. Change it in 'jmp 414C7C'

Take the jump, and we land at the free space, typ 'a' again, and enter the above code. (Of course you have to replace the variables by their addresses.) Execute the code you just entered to see if it works. It should work :)

Now dump the code to disk, or write down the opcodes of ur code (d 414C7C). Then paste them in the crackme with your Hexeditor.
Run the keygen...

Enter a name eg Detten
Enter a serial eg 1

OUTPUT : 8968

It works ! You have made an internal keygen. Congrats! :-)
If you have questions about this tutorial or remarks, mail me at Detn@hotmail.com

Greetings,

Detten
Detn@hotmail.com

www.biw-reversing.cjb.net