	  Ŀ
	                                                              Ŀ
	    
	          
	          
	                                               
	                                               
	                                   
	                                   
	                                   
	                                                
	                                                
	                       
	                       
	                 
	                                                                  
	                                                                  
	                         
	                 p r o u d l y     p r e s e n t s                
	                         
	                                                                  
	Ŀ                                            www.tscube.cjb.net
	  


                      ͻ
                         Tutorial for LobiX's crackme #2.1   
                      ͼ



Ŀ
1.Intro 


I really love these smalls WIN32ASM crackmes. This one features :

1) Anti SICE protection
2) Anti BPX protection
3) A few tricks

Maybe there is a BPX detection, but I don't really care because I usually use 'BPM <address> X'
instead of 'BPX <address>' (i.e the debug registers are used instead of placing a 'INT 3' in
the middle of the code).



Ŀ
2. Disabling the Anti SICE protection 


	2.1. the first protection
	

It's easy to find, because you can see it as soon as SICE pops on the entrypoint :

//******************** Program Entry Point ********
:00401000 892514324000            mov dword ptr [00403214], esp
:00401006 68BA134000              push 004013BA

* Reference To: KERNEL32.SetUnhandledExceptionFilter, Ord:026Ah
                                  |
:0040100B E814060000              Call 00401624
:00401010 BD4B484342              mov ebp, 4243484B -> 'BCHK'
:00401015 B804000000              mov eax, 00000004
:0040101A CC                      int 03
:0040101B 6A00                    push 00000000

* Reference To: KERNEL32.ExitProcess, Ord:0075h
                                  |
:0040101D E8F0050000              Call 00401612


hehe, this SICE detection is clever, because it mixes 2 things :

1) a classic 'BCHK' detection
2) SEH (read the documentation on Iczelion's site for more details)

If SICE is loaded, then the 'INT 3' makes him think the crackme seeks for the signature of
BoundsChecker... so he doesn't care of the SEH and continues execution at @41101D (Exitprocess)

Usually, this detection is used like this (code extracted from Frogsice documentation) :

mov     ebp, 04243484Bh        ; 'BCHK'
mov     ax, 04h
int     3       
cmp     al,4
jnz     SoftICE_Detected

In the crackme, there is no test after the 'INT 3' because you CAN'T land at @41101D if SICE
is not there ! 
=> If SICE is not loaded, 'INT 3' raises an exception and the crackme continues execution at 
@4013BA (address of exception filter function)

To patch this SICE detection, we just have to remove the 'BCHK' detection... for example by
replacing the 'mov ebp, 4243484B' with 'int 3'


	2.2. Second protection 
	

This protection is also used in Crunch v1.0

:004012F0 0F010D18324000          sidt [00403218]
:004012F7 A11A324000              mov eax, dword ptr [0040321A]
:004012FC 83C008                  add eax, 00000008
:004012FF 8B18                    mov ebx, dword ptr [eax]
:00401301 83C010                  add eax, 00000010
:00401304 8B00                    mov eax, dword ptr [eax]
:00401306 25FFFF0000              and eax, 0000FFFF
:0040130B 81E3FFFF0000            and ebx, 0000FFFF
:00401311 2BC3                    sub eax, ebx
:00401313 83F81E                  cmp eax, 0000001E
:00401316 7507                    jne 0040131F -> we change this to 'JMP 40131F'
:00401318 C6050732400001          mov byte ptr [00403207], 01 -> SICE detected

For more details, I suggest you have a look at 'bang.zip' by R!SC
(you can find it at protools.cjb.net)



Ŀ
3. The fake serial check 


Yeah, there is a fake serial check... looks like LobiX wants to play with us ;)

When you click on the 'OK' button, the following code is executed :


* Referenced by a CALL at Address:
|:00401568   
|
:00401320 68B7134000              push 004013B7
:00401325 68A9134000              push 004013A9
:0040132A 803D0832400001          cmp byte ptr [00403208], 01 -> not important
:00401331 7471                    je 004013A4 -> exit process

:00401333 E8C3FEFFFF              call 004011FB => EAX= strlen(serial) when you return from here

:00401338 C1C804                  ror eax, 04
:0040133B 48                      dec eax
:0040133C C1C004                  rol eax, 04
:0040133F 83C002                  add eax, 00000002
:00401342 C1C804                  ror eax, 04
:00401345 48                      dec eax
:00401346 7408                    je 00401350 -> go to genuine_serial_check_routine if EAX=0

:00401348 8D0555134000            lea eax, dword ptr [00401355]
:0040134E FFE0                    jmp eax -> go to fake_serial_check_routine


Here is the fake_serial_check_routine :


:0040136E 33C9                    xor ecx, ecx
:00401370 8D351E324000            lea esi, dword ptr [0040321E] -> serial

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:00401389(U)
|
:00401376 83F910                  cmp ecx, 00000010 -> we loop 4 times
:00401379 7410                    je 0040138B
:0040137B 8B0431                  mov eax, dword ptr [ecx+esi]
:0040137E 0381E7314000            add eax, dword ptr [ecx+004031E7] -> a array of 4 DWORD
:00401384 7523                    jne 004013A9
:00401386 83C104                  add ecx, 00000004
:00401389 EBEB                    jmp 00401376

I won't give you the 'fake serial' because there is a funny surprise for you if you find it ;) 



Ŀ
4. The real serial check routine 


	4.1. the correct length of the serial
	

EAX = strlen(serial)
:00401338 C1C804                  ror eax, 04
:0040133B 48                      dec eax
:0040133C C1C004                  rol eax, 04
:0040133F 83C002                  add eax, 00000002
:00401342 C1C804                  ror eax, 04
:00401345 48                      dec eax
:00401346 7408                    je 00401350 -> go to genuine_serial_check_routine if EAX=0

you'll notice that these instructions can easily be reversed :
ROR <=> ROL
DEC <=> INC
ADD <=> SUB

The final value of EAX must be 0... here is the 'inversion' :

xor eax,eax // this is the result we want (EAX=0)
inc eax
rol eax,4
sub eax,2
ror eax,4
inc eax
rol eax,4

=> we found that strlen(serial)=30


	4.2. The serial check routine
	

The serial check routine starts at @4010B8 and ends at @401168... and it's really a pain to
reverse... for an example, look at this :

:004010DA 33C9                    xor ecx, ecx
:004010DC 33C0                    xor eax, eax
:004010DE 8A5E1D                  mov bl, byte ptr [esi+1D]
:004010E1 83F9F1                  cmp ecx, FFFFFFF1
:004010E4 7416                    je 004010FC
:004010E6 F7D9                    neg ecx
:004010E8 301C31                  xor byte ptr [ecx+esi], bl
:004010EB 8A0431                  mov al, byte ptr [ecx+esi]
:004010EE F7D9                    neg ecx 
:004010F0 8A5C311C                mov bl, byte ptr [ecx+esi+1C]
:004010F4 D2C0                    rol al, cl
:004010F6 3044311D                xor byte ptr [ecx+esi+1D], al
:004010FA E2E5                    loop 004010E1

BUT, there is a weak point - a huge hole to be exact - in the crackme protection... because we
can crack this baby in a few seconds without having to reverse anything.

note : this is not a bug, it's just to make cracking easier ;)


Look at the last part of the serial check routine :

(EDI points to the serial we entered)
:00401112 B8BD8D9E9C              mov eax, 9C9E8DBD
:00401117 0107                    add dword ptr [edi], eax
:00401119 75F1                    jne 0040110C -> fuck off
:0040111B B86B4D6520              mov eax, 20654D6B
:00401120 294704                  sub dword ptr [edi+04], eax
:00401123 75E7                    jne 0040110C -> fuck off
:00401125 B8CED1CFDF              mov eax, DFCFD1CE
:0040112A 014708                  add dword ptr [edi+08], eax
:0040112D 75DD                    jne 0040110C -> fuck off
:0040112F 8B470C                  mov eax, dword ptr [edi+0C]
:00401132 3D6279204C              cmp eax, 4C207962
:00401137 75D3                    jne 0040110C -> fuck off
:00401139 B8919D96A7              mov eax, A7969D91
:0040113E 014710                  add dword ptr [edi+10], eax
:00401141 75C9                    jne 0040110C -> fuck off
:00401143 B8E0A4BC8D              mov eax, 8DBCA4E0
:00401148 014714                  add dword ptr [edi+14], eax
:0040114B 75BF                    jne 0040110C -> fuck off
:0040114D B89F9C94AF              mov eax, AF949C9F
:00401152 014718                  add dword ptr [edi+18], eax
:00401155 75B5                    jne 0040110C -> fuck off
:00401157 66B8B4A2                mov ax, A2B4
:0040115B 6601471C                add word ptr [edi+1C], ax
:0040115F 75AB                    jne 0040110C -> fuck off
:00401161 33C9                    xor ecx, ecx
* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:00401174(U)
|
:00401163 83F910                  cmp ecx, 00000010
:00401166 740E                    je 00401176
[WE ARE REGISTERED IF WE LAND HERE]


This last part takes the 30 bytes of our serial (the 30 ASCII values in fact) and simply does a 
few checks to see if they're correct.

This is basic ASM stuff, if you don't get it, here is an example :

Let's say our serial is "ABCDEFGHIJKLMNOPQRSTUVWXYZ1234"
The 30 ASCII values are 0x41 0x42 0x43 0x44 etc...
first check : 0x44434241 + 0x9C9E8DBD != 0x00 => not registered !

If you still don't get, there is nothing more I can do for you ;)


	4.3. The serial
	

Well, there are just a few operations to do :

first part of serial   : 0x00 - 0x9C9E8DBD = 0x63617243
second part of serial  : 0x00 + 0x20654D6B = 0x20654D6B
third part of serial   : 0x00 - 0xDFCFD1CE = 0x20302E32
fourth part of serial  : 0x4C207962
fifth part of serial   : 0x00 - 0xA7969D91 = 0x5869626F
sixth part of serial   : 0x00 - 0x8DBCA4E0 = 0x72435B20
seventh part of serial : 0x00 - 0xAF949C9F = 0x506B6361
eigth part of serial   : 0x00 - 0xA2B4 =     0x5D4C

The ASCII values of the serial are :

0x43 0x72 0x61 0x63 0x6B 0x4D 0x65 0x20 0x32 0x2E 0x30 0x20 0x62 0x79 0x20 0x4C 0x6F 0x62 0x69 0x58 0x20 0x5B 0x43 0x72 0x61 0x63 0x6B 0x50 0x4C 0x5D
'C'  'r'  'a'  'c'  'k'  'M'  'e'  ' '  '2'  '.'  '0'  ' '  'b'  'y'  ' '  'L'  'o'  'b'  'i'  'X'  ' '  '['  'C'  'r'  'a'  'c'  'k'  'P'  'L'  ']'

=>  "CrackMe 2.0 by LobiX [CrackPL]"

hum... it look like LobiX updated the crackme version without updating the serial ;)


Ŀ
5. Outro 


I discovered the polish scene a few months ago and I can tell you these guys are really good :)

    ________     _______     _______
   /__   __/\   /  ____/\   /  ____/\
   \_/  /\_\/  /  /\___\/  /  /\___\/
    /  / /    /  /_/_     /  / / 
   /  / /    /____  /\   /  / /
  /  / /     \___/ / /  /  / /
 /  / /     ____/ / /  /  /_/_
/  / /     /_____/ /  /______/\
\__\/      \_____\/   \______\/ 14/07/2000 (allons enfants de la patrie...)

www.tscube.cjb.net

