The deadlisting is very short, and easy to understand. Usually, I start
looking at the DialogBox MessageLoop :
00401159 sub_401159 proc near ; DATA XREF: start+16o 00401159 00401159 arg_0 = dword ptr 8 00401159 arg_4 = dword ptr 0Ch 00401159 arg_8 = dword ptr 10h 00401159 arg_C = dword ptr 14h 00401159 00401159 enter 0, 0 0040115D push ebx 0040115E push edi 0040115F push esi 00401160 cmp [ebp+arg_4], 111h ; WM_COMMAND 00401167 jz short loc_40118B ; Check button pressed? 00401169 cmp [ebp+arg_4], 2 ; WM_DESTROY 0040116D jz loc_4011F8 00401173 push [ebp+arg_C] 00401176 push [ebp+arg_8] 00401179 push [ebp+arg_4] 0040117C push [ebp+arg_0] 0040117F call j_DefWindowProcA 00401184 pop esi 00401185 pop edi 00401186 pop ebx 00401187 leave 00401188 retn 10h 0040118B ; ---------------------------------------------------------------------------
If we press the Check-button we take the jump at line 00401167h. To the
following code :
0040118B loc_40118B: ; CODE XREF: sub_401159+Ej 0040118B cmp [ebp+arg_8], 20h ; Check button pressed? 0040118F jnz short loc_4011EF 00401191 push 28h 00401193 push offset Serial ; Serial Buffer 00401198 push ds:dword_40204C 0040119E call j_GetWindowTextA ; Get serial 004011A3 push ds:dword_402044 004011A9 call sub_40120B ; Calculate Hash 004011AE cmp eax, 1 ; Flag ok? 004011B1 jnz short loc_4011D1 ; If not, jump badguy 004011B3 push 30h 004011B5 push offset aGoodForU ; "Good For U!" 004011BA push offset aUDidIt ; "U Did It!!" 004011BF push ds:dword_402048 004011C5 call j_MessageBoxA ; Good guy Message 004011CA pop esi 004011CB pop edi 004011CC pop ebx 004011CD leave 004011CE retn 10h 004011D1 ; --------------------------------------------------------------------------- 004011D1 004011D1 loc_4011D1: ; CODE XREF: sub_401159+58j 004011D1 push 30h 004011D3 push offset asc_402098 ; "=)" 004011D8 push offset aWrongSN ; "Wrong S/N#" 004011DD push ds:dword_402048 004011E3 call j_MessageBoxA ; Bad Guy Message 004011E8 pop esi 004011E9 pop edi 004011EA pop ebx 004011EB leave 004011EC retn 10h 004011EF ; --------------------------------------------------------------------------- 004011EF 004011EF loc_4011EF: ; CODE XREF: sub_401159+36j 004011EF xor eax, eax 004011F1 pop esi 004011F2 pop edi 004011F3 pop ebx 004011F4 leave 004011F5 retn 10h 004011F8 ; --------------------------------------------------------------------------- 004011F8 004011F8 loc_4011F8: ; CODE XREF: sub_401159+14j 004011F8 push 0 004011FA call j_PostQuitMessage ; Quit 004011FF mov eax, 0 00401204 pop esi 00401205 pop edi 00401206 pop ebx 00401207 leave 00401208 retn 10h 00401208 sub_401159 endp 00401208
If the Check-button is pressed, the Serial is read with GetDlgItemTextA.
And a Call is executed to make the hash and check it. If the Call returns
a 1 in eax the goodguy message is displayed, otherwise the badguy message
is displayed. So the answer for this crackme should be in that Call :
0040120B 0040120B ; ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦ S U B R O U T I N E ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦ 0040120B 0040120B ; Attributes: bp-based frame 0040120B 0040120B sub_40120B proc near ; CODE XREF: sub_401159+50p 0040120B enter 0, 0 0040120F push ebx 00401210 push edx 00401211 xor eax, eax 00401213 mov eax, offset Serial 00401218 cmp byte ptr [eax], 0 ; end of serial ? 0040121B jz short loc_40127D ; if yes, jump 0040121D xor ebx, ebx ; zero out 0040121F xor edx, edx ; zero out 00401221 00401221 loc_401221: ; CODE XREF: sub_40120B+21j 00401221 mov bl, [eax] ; Move current serial char to ebx 00401223 rol ebx, 8 ; ROL serial, 8 00401226 add edx, ebx ; Calculate hash in edx 00401228 inc eax ; point to next char 00401229 cmp byte ptr [eax], 0 ; end of serial ? 0040122C jnz short loc_401221 ; if yes, jump 0040122E push edx ; push hash 0040122F push offset unk_402054 00401234 push offset unk_4020BF 00401239 call j_wsprintfA ; convert to ascii 0040123E mov ebx, offset unk_4020BF 00401243 ; compare hash with '8DCAF368'
00401243 cmp byte ptr [ebx], 38h ; '8' 00401246 jnz short loc_40127D 00401248 cmp byte ptr [ebx+1], 44h ; 'D' 0040124C jnz short loc_40127D 0040124E cmp byte ptr [ebx+2], 43h ; 'C' 00401252 jnz short loc_40127D 00401254 cmp byte ptr [ebx+3], 41h ; 'A' 00401258 jnz short loc_40127D 0040125A cmp byte ptr [ebx+4], 46h ; 'F' 0040125E jnz short loc_40127D 00401260 cmp byte ptr [ebx+5], 33h ; '3' 00401264 jnz short loc_40127D 00401266 cmp byte ptr [ebx+6], 36h ; '6' 0040126A jnz short loc_40127D 0040126C cmp byte ptr [ebx+7], 38h ; '8' 00401270 jnz short loc_40127D 00401272 mov eax, 1 ; Set Flag if correct 00401277 pop edx 00401278 pop ebx 00401279 leave 0040127A retn 4 0040127D ; ---------------------------------------------------------------------------
This happens in the call :
First a hash is calculated from our serial. The algo to do this, is very
simple :
ROL Serial, 8
ADD Hash, Serial
This is done till all chars are processed.
The second part of the Crackme transforms the hash (DWORD in edx) to
an ASCII string. (with API wsprintfA)
Then the third part compares the ascii formated DWORD with '8DCAF368'
|
What do we know so far?
Hashvalue = '8DCAF368'
Hashing Algo =
ROL Serial, 8
ADD Hash, Serial
The question that remains is : Can we find a serial without bruting?
The hashvalue is a 32-bit value (stored in EDX).
After every char that is processed, we shift the previous bytes 8 bits
to the left.
if we process more than 4 chars, we will only find the solution by bruting
it, because
when the fourth char is processed (4 * 8 bit = 32 bit), the ROL overwrites
the first byte (by adding 5th char to it)+-.
So if we want to solve this without bruting, we will need a 4 char serial.
If you don't completely understand how I come to this conclusion,
then you should step through the algo with softice a couple of times.
For a 4 chars long serial we have the following scheme after the 4 chars
have been processed :
FIRST CHAR = 00 00 01 00
+ SECOND CHAR = 00 01 02 00 + THIRD CHAR = 01 02 03 00 + FOURTH CHAR = 02 03 04 01
-----------
EDX = HASH = 8D CA F3 68
Char 1 = 68h = 'h'
Char 2 = 8Dh - 68h = 25h = '%'
Char 3 = CAh - 68h - 25h = 3Dh = "="
Char 4 = F3h - 68h - 25h - 3Dh = 29h = ')'
Try this serial ' h%=) ' , it works! We solved the crackme without bruting
;-) |