Intro
Yet another Delphi proggie from GenoCide, I am beginning to enjoy them. Now this one is very, very interesting for several reasons. First of all it asks us to patch it to enable a button, and contains anti-patching type code, including checking its image and corrupted routines..... cool! :).
Target
The crackme is just a picture with a greyed button, and we just need to enable it. Now actually enabling the button is easy! It is sorting the program out and getting it to work without crashing afterwards that is going to entertain us!
Analysis
First of all we unpack the program, and I always call the unpacked version something else, leaving the original intact. This proves of value later on when we see that the program does in fact check the file size of its disk image 'gncrk17.exe' is still low, obviously to see if it has been unpacked. This doesnt come into play though with the methods I use. OK, the first thing we find in the file, using a hex editor to check out the resources, etc:
0000000754427574 746F6E0742757474 ....TButton.Butt 6F6E31044C656674 021003546F700328 on1.Left...Top.( 0105576964746802 4B06486569676874 ..Width.K.Height 0219074361707469 6F6E0609436C6F73 ...Caption..Clos 65206D652107456E 61626C6564080854 e me!.Enabled..T 61624F7264657202 00074F6E436C6963 abOrder...OnClic 6B070C427574746F 6E31436C69636B00 k..Button1Click. |
A wealth of information about the button.... in fact it has the caption 'Close me!' when we run the crackme, and these are its starting details. We have its position - top, left, width, height, taborder, routine called for the event 'onclick' and of course that it is enabled. We need to remove this, and I just chose a one byte patch to extend the length of the caption(its length is the byte before it) to take in the bytes used by 'Enabled'+length before+value after. So I added 9 to the caption length. It makes the button look crap, but what the hell.....it is now enabled. Click it and crash! lovely. |
We now need to look at the program a bit, and although Delphi programs can be very verbose they do leave some nice pieces behind for us to trace. Take a look at the following, from the code segment:
s_Panel1: 1000:0042b318 0650616e656c31 ds "Panel1" 1000:0042b31f e0 db e0 1000:0042b320 01 db 01 1000:0042b321 00 db 00 1000:0042b322 00 db 00 1000:0042b323 01 db 01 1000:0042b324 00 db 00 s_Image1: 1000:0042b325 06496d61676531 ds "Image1" 1000:0042b32c e4 db e4 1000:0042b32d 01 db 01 1000:0042b32e 00 db 00 1000:0042b32f 00 db 00 1000:0042b330 02 db 02 1000:0042b331 00 db 00 s_Button1: 1000:0042b332 07427574746f6e31 ds "Button1" 1000:0042b33a 03 db 03 1000:0042b33b 00 db 00 1000:0042b33c 12 db 12 1000:0042b33d 00 db 00 1000:0042b33e f4b34200 dd offset 42b3f4h s_FormDestroy: 1000:0042b342 0b466f726d44657374.. ds "FormDestroy" 1000:0042b34e 13 db 13 1000:0042b34f 00 db 00 1000:0042b350 48b44200 dd offset 42b448h s_Button1Click: 1000:0042b354 0c427574746f6e3143.. ds "Button1Click" 1000:0042b361 11 db 11 1000:0042b362 00 db 00 1000:0042b363 58b44200 dd offset 42b458h s_FormCreate: 1000:0042b367 0a466f726d43726561.. ds "FormCreate" s_TForm1: 1000:0042b372 0654466f726d31 ds "TForm1" 1000:0042b379 03 db 03 1000:0042b37a 00 db 00 1000:0042b37b b49e4200 dd offset 429eb4h 1000:0042b37f f4984200 dd offset 4298f4h 1000:0042b383 98904200 dd offset 429098h 1000:0042b387 90 db 90 1000:0042b388 8cb34200 dd offset 42b38ch ; XREFS First: 1000:0042b388 Number : 1 1000:0042b38c 07 db 07 s_TForm1: 1000:0042b38d 0654466f726d31 ds "TForm1" 1000:0042b394 8cb24200 dd offset 42b28ch 1000:0042b398 1c194200 dd offset 42191ch 1000:0042b39c 3b db 3b ;';' 1000:0042b39d 00 db 00 s_main: 1000:0042b39e 046d61696e ds "main" 1000:0042b3a3 00 db 00 1000:0042b3a4 00 db 00 1000:0042b3a5 8d db 8d 1000:0042b3a6 40 db 40 ;'@' 1000:0042b3a7 00 db 00 ; XREFS First: 1000:0042b448 Number : 2 |
Now this might look bad in some disassemblers which might try and treat it as code, and so you need to choose your tools accordingly. This tells us a lot. Best of all it gives us the three routines: FormCreate, Button1Click and FormDestroy for the main form, and the address of each of them (how nice). Lets take a look at each. |
;***************************************************************** ; formcreate ;***************************************************************** ; XREFS First: 1000:0042b363 Number : 1 1000:0042b458 55 push ebp 1000:0042b459 8bec mov ebp, esp 1000:0042b45b 81c4a8feffff add esp, fffffea8h 1000:0042b461 8d85a8feffff lea eax, [ebp-158h] 1000:0042b467 8b15b0584000 mov edx, [4058b0h] 1000:0042b46d e88a87fdff call 403bfch 1000:0042b472 33c0 xor eax, eax 1000:0042b474 55 push ebp 1000:0042b475 68d0b44200 push offset 42b4d0h 1000:0042b47a 64ff30 push dword ptr fs:[eax] 1000:0042b47d 648920 mov fs:[eax], esp 1000:0042b480 8d8da8feffff lea ecx, [ebp-158h] 1000:0042b486 ba3f000000 mov edx, 3fh 1000:0042b48b b8e4b44200 mov eax, s_gencrk_exe 1000:0042b490 e85fb2fdff call 4066f4h 1000:0042b495 8d85a8feffff lea eax, [ebp-158h] 1000:0042b49b e8a0b2fdff call 406740h 1000:0042b4a0 81bdacfeffffe0220200 cmp dword ptr [ebp-154h], 222e0h 1000:0042b4aa 7e05 jle 42b4b1h 1000:0042b4ac e8f7feffff call 42b3a8h ; XREFS First: 1000:0042b4aa Number : 1 1000:0042b4b1 33c0 xor eax, eax 1000:0042b4b3 5a pop edx 1000:0042b4b4 59 pop ecx 1000:0042b4b5 59 pop ecx 1000:0042b4b6 648910 mov fs:[eax], edx 1000:0042b4b9 68d7b44200 push offset 42b4d7h ; XREFS First: 1000:0042b4d5 Number : 1 1000:0042b4be 8d85a8feffff lea eax, [ebp-158h] 1000:0042b4c4 8b15b0584000 mov edx, [4058b0h] 1000:0042b4ca e8f587fdff call 403cc4h 1000:0042b4cf c3 ret ; XREFS First: 1000:0042b475 Number : 1 1000:0042b4d0 e9ff7afdff jmp 402fd4h 1000:0042b4d5 ebe7 jmp 42b4beh ; XREFS First: 1000:0042b4b9 Number : 1 1000:0042b4d7 8be5 mov esp, ebp 1000:0042b4d9 5d pop ebp 1000:0042b4da c3 ret |
Notice the cmp 222e0h in this routine, it is the filelength trap that I mentioned earlier. But since it tests gencrk17.exe, and we havent changed that file, it doesnt matter. |
;***************************************************************** ; formdestroy ;***************************************************************** ; XREFS First: 1000:0042b33e Number : 1 1000:0042b3f4 6a00 push 00h 1000:0042b3f6 6808b44200 push offset s_Just_a_reminder_ 1000:0042b3fb 681cb44200 push offset s_Enable_the_button___send_me_the_solu 1000:0042b400 6a00 push 00h 1000:0042b402 e811a2fdff call _MessageBoxA 1000:0042b407 c3 ret s_Just_a_reminder_: ; XREFS First: 1000:0042b3f6 Number : 1 1000:0042b408 4a7573742061207265.. ds "Just a reminder." 1000:0042b419 00 db 00 1000:0042b41a 00 db 00 1000:0042b41b 00 db 00 s_Enable_the_button___send_me_the_solu: ; XREFS First: 1000:0042b3fb Number : 1 1000:0042b41c 456e61626c65207468.. ds "Enable the button & send me the solution ;)" |
This is just the reminder and will always be shown, we could bypass it if we wanted to but I chose not to. |
;***************************************************************** ; button1click ;***************************************************************** ; XREFS First: 1000:0042b350 Number : 1 1000:0042b448 e85bffffff call 42b3a8h 1000:0042b44d a10cd74200 mov eax, [42d70ch] 1000:0042b452 e80db0ffff call 426464h 1000:0042b457 c3 ret |
And this is the culprit of our problems. We note that it calls a routine in close proximity at the start, 42b3a8h, and this warrants further attention. |
;***************************************************************** ; our interesting routine from button1click ;***************************************************************** ; XREFS First: 1000:0042b448 Number : 2 1000:0042b3a8 55 push ebp 1000:0042b3a9 8bec mov ebp, esp 1000:0042b3ab 6a00 push 00h ; XREFS First: 1000:0042b3c3 Number : 1 1000:0042b3ad 33c5 xor eax, ebp 1000:0042b3af 55 push ebp 1000:0042b3b0 68deb34500 push 45b3deh 1000:0042b3b5 26ff7007 push dword ptr es:[eax+07h] 1000:0042b3b9 896006 mov [eax+06h], esp 1000:0042b3bc 45 inc ebp 1000:0042b3bd fc cld 1000:0042b3be baf0b34200 mov edx, 42b3f0h 1000:0042b3c3 e8e5ffffff call 42b3adh 1000:0042b3c8 33c0 xor eax, eax 1000:0042b3ca 5a pop edx 1000:0042b3cb 59 pop ecx 1000:0042b3cc 59 pop ecx 1000:0042b3cd 648910 mov fs:[eax], edx 1000:0042b3d0 68e5b34200 push 42b3e5h ; XREFS First: 1000:0042b3e3 Number : 1 1000:0042b3d5 8d45fc lea eax, [ebp-04h] 1000:0042b3d8 e85381fdff call 403530h 1000:0042b3dd c3 ret 1000:0042b3de e9f17bfdff jmp 402fd4h 1000:0042b3e3 ebf0 jmp 42b3d5h 1000:0042b3e5 59 pop ecx 1000:0042b3e6 5d pop ebp 1000:0042b3e7 c3 ret |
This is it, the culprit. It's pretty obviously fake, just take a look at the push dword ptr es:[ax+07h] !, and of course the recursive call leading to a quick crash. hmmmmmm. I decided on a one byte patch for this in the end. The byte ? Oh, yeah... the address of the button1click routine, i added 5 to it to bypass the call to this routine (so 48h becomes 4dh). The end result ? Job done :) |
Conclusions
This crackme was quite interesting although most people would probably find it quite hard, although the hardest part for most people will probably be understanding how Delphi compiles programs. Once you have grasped that the rest is easy ;)
{Cronos}