Crackme v1.0 by Crudd, cracked by woody

This is a nice crackme for newbies, it's pretty easy to crack. it has 5 different protections. Hardcoded, self checking, name/serial, patch me and a enable me. Let's start with the hardcoded one. Run the file cruddme.exe (in the exe directory in this archive) and press the Hardcoded item in the menu.

Now it displays a edit box with the serial 12345666 in it, so lets just press the "check it" button. Now a messagebox pops up saying "sorry, you suck". Press the OK button. okay ... let's break on messageboxa in softice. Hit ctrl+d and write 'bpx messagebox' without the quotes ... press F5 to get out of sice, now press the check it button again and sice will show again. Press F11 and the "sorry, you suck" message will appear. Just press the OK button again, now sice comes again. you landed here:


:00441AB7 6A00                    push 00000000

* Possible StringData Ref from Code Obj ->"Crudd Me 1. 0"
                                  |
:00441AB9 68341B4400              push 00441B34

* Possible StringData Ref from Code Obj ->"Sorry, you suck"
                                  |
:00441ABE 68441B4400              push 00441B44
:00441AC3 8BC3                    mov eax, ebx
:00441AC5 E83A68FEFF              call 00428304
:00441ACA 50                      push eax

* Reference To: user32.MessageBoxA, Ord:0000h
                                  |
:00441ACB E8044BFCFF              Call 004065D4

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:00441AB5(U)
|
:00441AD0 33C0                    xor eax, eax <----- ** You landed here **

Okay ... so if you scroll up a bit:

:00441A8F 8B45F8                  mov eax, dword ptr [ebp-08]
:00441A92 8B55FC                  mov edx, dword ptr [ebp-04]
:00441A95 E8BE21FCFF              call 00403C58
:00441A9A 751B                    jne 00441AB7
:00441A9C 6A00                    push 00000000

You'll see that it jumps to 441ab7 which here is the bad boy. so what we don't want it to do is jump here. Lets take a look at that call at line 441a95.

:00403C58 53                      push ebx
:00403C59 56                      push esi
:00403C5A 57                      push edi
:00403C5B 89C6                    mov esi, eax
:00403C5D 89D7                    mov edi, edx
:00403C5F 39D0                    cmp eax, edx
:00403C61 0F848F000000            je 00403CF6

It checks if eax is equal to edx, and just before the call it moved [ebp-08] into eax, and [ebp-04] into edx. So my guess would be that the serials is in eax and edx. Run sice again and when sice breaks (via the messagebox) write 'bc*' to clear the break points you've set (bpx messageboxa), now write 'bpx 441a95' so it breaks at the call. Press the "Check it" button again and sice will break. Now write 'd eax' and it will show you this "1235666", okay that's pretty easy to guess what that is ;), write 'd edx' and it will show you your serial. write 'bc*' and press F5 to get out of sice. Now in the edit box write '1235666' and press the Check it button .. did it work ? ofcause it did :) heh next ...

Next is self checking serial. Once again the '12345666' serial is already there, so we just press the check it button. Now a messagebox comes again saying "sorry, you suck" once again ;) So make sice break on messageboxa, and F5 to get out of sice, now press the check it button, and sice will appear. F11, and press the OK button. And you will land here:

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:00441B85(C)
|
:00441B8C 6A00                    push 00000000

* Possible StringData Ref from Code Obj ->"Crudd Me 1. 0"
                                  |
:00441B8E 68341C4400              push 00441C34

* Possible StringData Ref from Code Obj ->"Sorry, you suck"
                                  |
:00441B93 68441C4400              push 00441C44
:00441B98 8BC3                    mov eax, ebx

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:00441B2C(C)
|
:00441B9A E86567FEFF              call 00428304
:00441B9F 50                      push eax

* Reference To: user32.MessageBoxA, Ord:0000h
                                  |
:00441BA0 E82F4AFCFF              Call 004065D4
:00441BA5 EB69                    jmp 00441C10 <--- ** you land here ** !

Scroll up a bit and you'll see this:

:00441B74 E8BB06FEFF              call 00422234
:00441B79 8B45FC                  mov eax, dword ptr [ebp-04]
:00441B7C 0FB600                  movzx eax, byte ptr [eax]
:00441B7F 83E830                  sub eax, 00000030
:00441B82 83F802                  cmp eax, 00000002
:00441B85 7C05                    jl 00441B8C

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:00441B21(C)
|
:00441B87 83F809                  cmp eax, 00000009
:00441B8A 7E1B                    jle 00441BA7

Well that sure looks like something we wanna check ;) so lets break on 441b74 'bpx 441b74' remember to clear the messageboxa break point before this. Press the check it button again, now we're at 441b74. Press F10 to trace the code. After the call at 441b74 it returns eax with the value 8, and our serial is 8 chars long, but that doesn't matter cause it erases the value right after.

At line 441b79 it moves eax to the serials offset, the one that we've wrote. movzx eax, byte ptr [eax] means that it moves the byte at eax's offset into eax, so now eax contains the first character of the serial in hex. The first char was 1, and 1 in hex is 31, so now eax's value is 31. Then it sub eax, 30 meaning eax - 30 and that's 1, so now eax is 1. Now it compares eax with 2, and checks if eax is lower than that. The jl at 441b85 means jump if lower. But it will jump to 441b8c, and that's where the bad messagebox is, so now we know that eax has to be 2 or higher - the first char of the serial has to be 2 or higher.

Press F5 and write 2 as the first char. Press check it again, and trace a little further.. now we're at 441b87 here it compares eax with 9. As we changed the first char to 2, eax is now 2. Now it checks if eax is lower or equal to 9, and 2 is surely lower than 9 so it will jump to 441ba7. okay so far we know that the first char has to be between 2 and 9 to bypass the first "protection".

:00441BA7 8B55FC                  mov edx, dword ptr [ebp-04]
:00441BAA 0FB64402FF              movzx eax, byte ptr [edx+eax-01]
:00441BAF 83E830                  sub eax, 00000030
:00441BB2 85C0                    test eax, eax
:00441BB4 7F05                    jg 00441BBB
:00441BB6 83F809                  cmp eax, 00000009
:00441BB9 7D0B                    jge 00441BC6

Okay now it moves the serials offset into edx, and moves [edx+eax-01] into eax - [offset of serial+2-1]. and that gives us [offset of serial+1] so that would be the next char in our serial. and 2nd char is 2, and 2 in hex is 32, so eax is now 32. Then it says eax - 30, so now eax is 2. Now it checks if eax is 0 and it will jump if it's greater. And since 2 is higher than 0, it will jump to 441bbb.

:00441BBB 8B55FC                  mov edx, dword ptr [ebp-04]
:00441BBE 0FB67402FF              movzx esi, byte ptr [edx+eax-01]
:00441BC3 83EE30                  sub esi, 00000030

* Referenced by a (U)nconditional or (C)onditional Jump at Addresses:
|:00441B4F(C), :00441BB9(C)
|
:00441BC6 8B55FC                  mov edx, dword ptr [ebp-04]
:00441BC9 0FB65432FF              movzx edx, byte ptr [edx+esi-01]
:00441BCE 8B4DFC                  mov ecx, dword ptr [ebp-04]
:00441BD1 0FB64401FF              movzx eax, byte ptr [ecx+eax-01]
:00441BD6 03F0                    add esi, eax
:00441BD8 3BD6                    cmp edx, esi
:00441BDA 751B                    jne 00441BF7

Okay now it will mov the offset of the serial into edx. Then it will move [edx+eax-01] into esi. [offset of serial + 2 - 1] the same as before, esi will have the 2nd char (32). Then esi - 30, so now esi is 2. Once again it will mov the offset of the serial into edx, Then it will move the 2nd char into edx (32). Then it will move the offset of the serial into ecx, and move the 2nd char into eax (32). Now eax is 32, edx is 32 and esi is 2. At line 441bd6 it will add esi to eax - esi = esi + eax (esi = 2 + 32). So now esi is 34. Then it will compare edx to esi (cmp 32 to 34) and jump if it's not equal .. it will jump to the nasty messagebox.

This might seem pretty confusing, but it's really not. if the serial was 23456 then eax=2, esi=(offset+eax-1)-30, edx=offset+esi-1, eax=offset+eax-1. esi+eax. This would be:

eax=first char eax=char number[eax]
esi=char number[eax]
esi-30
edx=char number[esi]
eax=char number[eax]
esi+eax
check if edx is equal to esi

With the serial 23456
eax=2
eax=3
esi=4
edx=5
eax=4
esi+eax=8
check if edx is equal to esi+eax - 5 = 8 ?

So now we know that edx has to be 8, and edx is the 4th char. So the right serial could be 23486, the last number we really don't use, so it would be 2348. Try the serial out, it works :) Next protection

The next protection is a name and serial, and again a name and serial has already been entered. Crudd[TeX] and 12345666. So we just press the check it button, "sorry, you suck" ... okay break on messageboxa and you will land here:

:00441D20 6A00                    push 00000000

* Possible StringData Ref from Code Obj ->"Crudd Me 1. 0"
                                  |
:00441D22 68941D4400              push 00441D94

* Possible StringData Ref from Code Obj ->"Sorry, you suck"
                                  |
:00441D27 68A41D4400              push 00441DA4
:00441D2C 8BC3                    mov eax, ebx
:00441D2E E8D165FEFF              call 00428304
:00441D33 50                      push eax

* Reference To: user32.MessageBoxA, Ord:0000h
                                  |
:00441D34 E89B48FCFF              Call 004065D4

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:00441D1E(U)
|
:00441D39 33C0                    xor eax, eax <--- ** you land here **

So just scroll up a bit to this:

:00441CDD 8B45F8                  mov eax, dword ptr [ebp-08]
:00441CE0 E8631EFCFF              call 00403B48
:00441CE5 8B55F8                  mov edx, dword ptr [ebp-08]
:00441CE8 0FB632                  movzx esi, byte ptr [edx]
:00441CEB 8B55F8                  mov edx, dword ptr [ebp-08]
:00441CEE 0FB65402FF              movzx edx, byte ptr [edx+eax-01]

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:00441C8C(C)
|
:00441CF3 0FAFF2                  imul esi, edx
:00441CF6 0FAFF0                  imul esi, eax
:00441CF9 8B45FC                  mov eax, dword ptr [ebp-04]
:00441CFC E8375DFCFF              call 00407A38
:00441D01 3BF0                    cmp esi, eax
:00441D03 751B                    jne 00441D20

Okay .. first it moves the offset of the name into eax. After the call at 441ce0 it will return the length of the name into eax. Now it moves the offset of the name into edx. moves the byte at edx into esi - moves the first char into esi. The first char is C (67 in decimal). Then it moves the offset of the name into edx again .. hmmm waste ;) then moves the byte at [edx+eax-1] into edx. [offset of name+length of name-1] and that would be the last char of the name which is ']' (93 in decimal). Now it multiplies esi with edx, 67*93 = 6231. and then multiply esi with eax. 6231*10 = 62310.

This means ((first char * last char) * length of name). After this it moves the offset of the serial into eax, and calls a routine that moves the hex of the serial into eax. Then it compares esi to eax, and jumps to the nasty messagebox if it's not equal.

So this is pretty easy, esi has the real serial and eax has our fake serial. So what you can do here is type '? esi' in sice, and it will display esi as a decimal (62310), type '? eax' will display our fake serial. k .. so now all we have to do is write 62310 as the serial. press the check it button, did it work ? cewl. The name woody, w=119, y=121, 119*121=14399 , 14399*lenght = 71995. The serial for woody is 71995. The serial for wkvsy is 71995 too, so it's a bad way to calculate serials. Next protection:

This next protection is the Patch me one. This is the place where we're allowed to patch .. well it's pretty obvious how to crack it, press the patch me menuitem, and a messagebox will appear saying "nop, try again", so we set a breakpoint a messageboxa. and you will land here:

:0044171B 6A00                    push 00000000

* Possible StringData Ref from Code Obj ->"Sorry.  You Suck"
                                  |
:0044171D 6854174400              push 00441754

* Possible StringData Ref from Code Obj ->"Nope.  Try Again."
                                  |
:00441722 6868174400              push 00441768
:00441727 8BC3                    mov eax, ebx
:00441729 E8D66BFEFF              call 00428304
:0044172E 50                      push eax

* Reference To: user32.MessageBoxA, Ord:0000h
                                  |
:0044172F E8A04EFCFF              Call 004065D4
:00441734 5B                      pop ebx <--- ** you land here **
:00441735 C3                      ret

So we scroll up a bit ..:

:00441711 8BD8                    mov ebx, eax
:00441713 B801000000              mov eax, 00000001
:00441718 48                      dec eax
:00441719 751B                    jne 00441736

That was pretty easy! patch line 441719 751B to EB1B so it will always jump no matter what. did it work ? sure it did :) Next...

Okay for menuitems that needs to be enabled, it's pretty easy to patch this, this way: First open the .exe file and search for the string 'Enable me', first it finds the 'Enable me completed, good head job" which is the messagebox it will show when completing this easy crackme. The next will be this:

43 61 70 74-69 6F 6E 06-0A 26 45 6E-61 62 6C 65 ..........Enable
20 4D 65 07-45 6E 61 62-6C 65 64 08-07 4F 6E 43  me.enabled.....

Something like this ... just after the enabled text the hex is 08. Change that to 09, and the Enable me menuitem is enabled. very easy and quick.

There you go ... one crackme down ;)

-wOODY^dRN