Solve Crackme#14 by ZeroCoder
 
Intro

In this tutorial, we are going to crack Crackme#14 by ZeroCoder. It's one of the shortest crackmes I've ever seen. But that doesn't mean it's an easy one!

TOOLS USED : SoftIce
DIFFICULTY : 4/10

Trace the code...

Load the crackme...
It displays a MessageBox with the message "please register..." Then the program terminates.

Interesting...let's load this crackme in SoftIce :

00401000 BE22104000 mov esi, 00401022 ; <= Entry point
00401005 BF47584D43 mov edi, 434D5847
* Referenced by a (U)nconditional or (C)onditional Jump at Address: 00401020(U)

; This is the decrypt part, and execution part in one!
0040100A AD lodsd ; Load [esi] in eax 0040100B 8BC8 mov ecx, eax ; Move counter in ecx 0040100D AD lodsd ; Load [esi] in eax 0040100E D3C7 rol edi, cl ; Rotate edi left cl times 00401010 33C7 xor eax, edi ; Xor eax with edi 00401012 03F8 add edi, eax ; add eax to edi 00401014 50 push eax ; push decrypted parameter 00401015 E2F6 loop 0040100D ; if ecx!=0 goto 40100D 00401017 58 pop eax ; pop eax again to correct the stack 00401018 FFD0 call eax ; call decrypted dword (points to import) 0040101A 58 pop eax ; pop 0 0040101B 03F0 add esi, eax ; add 0 to esi 0040101D AD lodsd ; Load [esi] in eax 0040101E 03F8 add edi, eax ; Add eax to edi 00401020 EBE8 jmp 0040100A ; jump back

Lodsd loads the dword esi points to, in eax. Next the pointer in esi is increased with 4 (points to next dword)

Notice that the above code is made with only two loops. The Big loop only moves a value in ecx (not encrypted), The small loop runs until ecx = 0, and decrypts the dword values below, and pushes them on the stack. When ecx = 0, the last push is popped again, and is called. (call eax).
Also notice that edi and eax are the only values needed to decrypt the following datablock.

This is the datablock that is decrypted :

03 00 00 00 3A C2 6A 1A E8 08 AB 69 72 01 16 D3 10 DA E9 E5 06 00 00 00 AE 20 FF 5F 8B 15 E4 FF BF 40 01 FE E0 25 4C F4 7B 98 30 D1 59 20 21 A2 44 2E 48 52 03 00 00 00 4F 7F 4B A7 3E FD 2D 9D D5 EA 1B 3A 53 53 55 52 3A E5 1F 64


The colored bytes are not encrypted. The red dwords are the values that are loaded in ecx. The brown dwords are added to edi (address 40101E). All the white dwords are crypted parameters and pointers to the imported functions.


Now that we know that, we can easily find out what the crackme does :

First '3' is loaded in ecx, then the next 3 dwords are decrypted and executed (just trace the loop to see) :

1) push 0
2) push 0
3) Call GetModuleHandle

Then '6' is loaded in ecx :

1) push 0
2) push 40
3) push 402000 (MessageBox Caption)
4) push 40201F <= This is the value we want to change! (MessageBox Text)
5) push 0
6) Call MessageBoxA

Next '3' is loaded in ecx :

1) push 0
2) push 0
3) Call ExitProcess

This last API ends the crackme of course :)

Now the only interesting one, is the MessageBoxA. We want to change the 'Please Register...' message.
Check the date section of the crackme (starts at 402000) :

         
00402000 63 72 61 63 6B 6D 65 20 crackme  => Caption of MessageBox
00402008 76 31 34 2E 30 20 62 79 v14.0 by
00402010 20 5A 65 72 6F 43 6F 64 ZeroCod
00402018 65 72 2F 2F 58 47 00 70 er//XG.p => MessageBox text (40201F)
00402020 6C 65 61 73 65 20 72 65 lease re
00402028 67 69 73 74 65 72 2E 2E gister..
00402030 2E 00 72 65 67 69 73 74 ..regist => We would like this string better as 
00402038 72 65 64 21 00 00 00 00 red!....    MessageBox text :) (402032)
00402040 00 00 00 00 00 00 00 00 ........



Ok, now we know what we have to do! Only question that remains, how?
Patching the code

We could try to change the dword that is responsible for the push 40201F. How? simple :

           |    1      |     2     |     3     |    4      |
06 00 00 00 AE 20 FF 5F 8B 15 E4 FF BF 40 01 FE E0 25 4C F4 

|    5     |     6     |     
7B 98 30 D1 59 20 21 A2 44 2E 48 52
       
       
The blue dword is the encrypted equivalent for 40201F :

F44C25E0 XOR EDI ( F40C05FF ) = 0040201F

So if you want to change the result to 402032, do this :

00402032 XOR EDI ( F40C05FF ) = F44C2DCD


If you think that just changing this dword will solve the crackme, then you are wrong! Take a look at the decrypting code again.

At address 00401012 the value of eax is added to edi. What does that mean?

We already know that edi is used for decrypting the dwords. So, if we change eax, then edi will change too! And the rest of the code will be fucked up...

That leaves us with 2 solutions:

- Adjust the following dwords too, so that they give the right parameters again. This is easy here, because the encryption algorithm is very simple...

- We can add some code of our own, that only interferes when the push 40201F is about to be pushed, then we change it, push it, and restore the original value.

As the second solution is a bigger challenge, we will do it that way :)

Step in SoftIce till you are in the place where the 4 dword of the MessageBox is loaded in eax (=F44C25E0)
Next we change the code so we jump to an empty part (there is space enough), and at the free space, we change the value in eax, push it, restore the value, and jump back.
The code we lose by putting the jump, we will reproduce in our own code :

 

0040100D AD           lodsd
0040100E D3C7         rol edi, cl
00401010 E9A1000000   jmp 004010B6       ; Jump to own code
* Referenced by a (U)nconditional or (C)onditional Jump at Address: 004010C8(U)

00401015 E2F6         loop 0040100D 


Own code :
------------
004010B6 33C7         xor eax, edi       ; Remake original code
004010B8 03F8         add edi, eax       ; Remake original code
004010BA 81FF1E264CF4 cmp edi, F44C261E  ; if edi = F44C261E, we are at the 4th 
004010C0 7505         jne 004010C7       ; push of the MessageBox Call
004010C2 0513000000   add eax, 00000013  ; then : change 40201F to 402032
* Referenced by a (U)nconditional or (C)onditional Jump at Address: 004010C0(C)
         
004010C7 50           push eax           ; Remake original code
004010C8 E948FFFFFF   jmp 00401015       ; jump back to original code



A very simple patch...
If the value in edi is not the one we are looking for, the code is executed like before we patched.
If edi is what we are looking for, then we add 13h to eax (so it is 402032 then). Next we push it on the stack, and jump back.

Shouldn't we restore the original value back in eax? Nope! Because when we jump back, the next dword is loaded in eax, so it doesn't matter!

I prefer to use softice to patch the code in realtime, execute it (to see that it works), and dump it to disk. Of course, you can do it manually too, it's your choice ;)

There! We have patched the crackme...If we run it, it says 'Registered!'



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

back to tutorials