Contribute  :  Web Resources  :  Past Polls  :  Site Statistics  :  Downloads  :  Forum  
    BiW ReversingThe challenge is yours    
 Welcome to BiW Reversing
 Friday, April 03 2020 @ 06:17 AM CEST

Reversing Phox 7 crackme


TutorialsLevel : beginner

Patching a crackme to reveal the inputbox, and writing a small bruter to find the wanted password.

Find the crackme here = attachment

We have to find a valid serial for the crackme. But there is more ;-)
It's not packed, so we should be able to solve this with only a deadlisting.

So, disassemble it with IDA, or WDasm



The code

The deadlisting of crackme 7 is very simular with the one from crackme5.1. So again let's start with the DialogMessageLoop :

00401189                 enter   0, 0
0040118D push ebx
0040118E push edi
0040118F push esi
00401190 cmp [ebp+arg_4], 111h ; WM_COMMAND
00401197 jz short loc_4011BB
00401199 cmp [ebp+arg_4], 2 ; WM_DESTROY
0040119D jz loc_40125C
004011A3 push [ebp+arg_C]
004011A6 push [ebp+arg_8]
004011A9 push [ebp+arg_4]
004011AC push [ebp+arg_0]
004011AF call j_DefWindowProcA ; Pass on Message to next thread
004011B4 pop esi
004011B5 pop edi
004011B6 pop ebx
004011B7 leave
004011B8 retn 10h
004011BB ; ---------------------------------------------------------------------------
004011BB loc_4011BB: ; CODE XREF: sub_401189+Ej
004011BB cmp [ebp+arg_8], 20h ; Button pressed ?
004011BF jnz loc_401253
004011C5 push ds:EditHandle
004011CB call j_GetWindowTextLengthA ; Get Serial Length
004011D0 cmp eax, 0 ; If not zero
004011D3 jnz short loc_401235 ; jump badguy
004011D5 xor eax, eax ; zero out
004011D7 push 28h ; Max length
004011D9 push offset unk_40209C ; pointer 2 Serial Buffer
004011DE push ds:HiddenEditHandle
004011E4 call j_GetWindowTextA ; Get Serial
004011E9 push ds:hInstance
004011EF call sub_40126F ; Make and Check Hash
004011F4 cmp eax, 1 ; Check return flag
004011F7 jnz short loc_401217
004011F9 push 30h
004011FB push offset aBeaten ; "*BEATEN*"
00401200 push offset aMumble ; "*mumble*"
00401205 push ds:hWndDialogBox
0040120B call j_MessageBoxA ; Goodguy Message
00401210 pop esi
00401211 pop edi
00401212 pop ebx
00401213 leave
00401214 retn 10h
00401217 ; ---------------------------------------------------------------------------
00401217 loc_401217: ; CODE XREF: sub_401189+6Ej
00401217 push 30h
00401219 push offset a8i ; ">8I"
0040121E push offset aHaha___wrongSN ; "*HAHA*...Wrong S/N#"
00401223 push ds:hWndDialogBox
00401229 call j_MessageBoxA ; BadGuy Message
0040122E pop esi
0040122F pop edi
00401230 pop ebx
00401231 leave
00401232 retn 10h
00401235 ; ---------------------------------------------------------------------------
00401235 loc_401235: ; CODE XREF: sub_401189+4Aj
00401235 push 30h
00401237 push offset aEdit___ ; "Edit..."
0040123C push offset aHeySonnyBoy___ ; "Hey sonny boy...not even close"
00401241 push ds:hWndDialogBox
00401247 call j_MessageBoxA ; You filled in the wrong EditBox Message
0040124C pop esi
0040124D pop edi
0040124E pop ebx
0040124F leave
00401250 retn 10h
00401253 ; ---------------------------------------------------------------------------

What happens in the main Dialog messageloop? :

If we press the 'check' button, the proggy first checks if we entered nothing in the EditBox. If we have entered someting, we jump to the 'Hey sonny boy...' MessageBox. So it's clear we cannot enter something there.

Next the Serial is moved to a buffer. If you look closely, you should notice that the EditBox which the serial is read from is another one than the previous checked one! How can this be? There is only one EditBox in the crackme... We'll check this out in a minute ;-)

When the serial is read, a call is executed where the hash is calculated and checked. EAX is set to 1 when equal.

Ok, now let's check out the missing EditBox first! As there are now resources present in the crackme, they have to be build at runtime. Let's check the beginning of our deadlisting :

00401000                 public start
00401000 start proc near
00401000 push 0
00401002 call j_GetModuleHandleA
00401007 mov ds:hInstance, eax
0040100C mov ds:dword_402000, 4003h
00401016 mov ds:dword_402004, offset sub_401189
00401020 mov ds:dword_402008, 0
0040102A mov ds:dword_40200C, 0
00401034 mov eax, ds:hInstance
00401039 mov ds:dword_402010, eax
0040103E push 7F04h
00401043 push 0
00401045 call j_LoadIconA ; Load Icon
0040104A mov ds:dword_402014, eax
0040104F push 7F00h
00401054 push 0
00401056 call j_LoadCursorA ; Load Cursor
0040105B mov ds:dword_402018, eax
00401060 mov ds:dword_40201C, 0Bh
0040106A mov ds:dword_402020, 0
00401074 mov ds:dword_402024, offset aAsmclass ; "ASMClass"
0040107E push offset dword_402000
00401083 call j_RegisterClassA ; Register Class to Windows
00401088 push 0
0040108A push ds:hInstance
00401090 push 0
00401092 push 0
00401094 push 69h ; height
00401096 push 0D2h
0040109B push 8000h
004010A0 push 8000h
004010A5 push 104B0000h
004010AA push offset aPhoxSeventhCra ; "PhoX Seventh CrackMe!"
004010AF push offset aAsmclass ; "ASMClass"
004010B4 push 0
004010B6 call j_CreateWindowExA ; Create DialogBox
004010BB mov ds:hWndDialogBox, eax
004010C0 push 0
004010C2 push ds:hInstance
004010C8 push 10h
004010CA push ds:hWndDialogBox
004010D0 push 0 ; Editbox with heigth
004010D0 ; and width 0 ??
004010D2 push 0
004010D4 push 19h ; y
004010D6 push 0Fh ; x
004010D8 push 50800000h
004010DD push 0
004010DF push offset aEdit ; "Edit"
004010E4 push 0
004010E6 call j_CreateWindowExA ; Create hidden EditBox
004010EB mov ds:HiddenEditHandle, eax
004010F0 push 0
004010F2 push ds:hInstance
004010F8 push 10h
004010FA push ds:hWndDialogBox
00401100 push 12h ; height
00401102 push 0A0h ; width
00401107 push 5 ; y
00401109 push 0Fh ; x
0040110B push 50800000h ; dwStyle
00401110 push 0
00401112 push offset aEdit ; ClassName
00401117 push 0
00401119 call j_CreateWindowExA ; Create EditBox
0040111E mov ds:EditHandle, eax
00401123 push 0
00401125 push ds:hInstance
0040112B push 20h
0040112D push ds:hWndDialogBox
00401133 push 14h
00401135 push 2Eh
00401137 push 2Dh
00401139 push 41h
0040113B push 50800001h
00401140 push offset aOk ; "Ok"
00401145 push offset aButton ; "Button"
0040114A push 0
0040114C call j_CreateWindowExA ; Create OK-Button
00401151 mov ds:dword_402054, eax

Indeed, as you can see after the DialogBox setting up, we have 2 editboxes...but the first one has nohight/width! (in blue) Which makes it invisible of course.
But as we already saw in the messageLoop, it's the invisible editbox that is used to read the serial. So, first step : Patch the width and heigth.

push 0 -> push 12h (height)
Opcode : 6A00 ->6A12
push 0 -> push 50h (width)
Opcode : 6A00 -> 6A50

If you restart the crackme, it should have 2 editboxes now :-)
Let's continue and have a look at the hashing Call :

0040126F ;  S U B R O U T I N E 
0040126F ; Attributes: bp-based frame
0040126F sub_40126F proc near ; CODE XREF: sub_401189+66p
0040126F enter 0, 0
00401273 push ebx
00401274 push edx
00401275 push ds:HiddenEditHandle
0040127B call j_GetWindowTextLengthA ; Get Serial Length
00401280 mov ecx, eax ; move SLen to ecx
00401282 xor eax, eax ; zero out
00401284 mov eax, offset unk_40209C ; pointer to Serial Buffer
00401289 cmp byte ptr [eax], 0 ; End of Serial String ?
0040128C jz short loc_4012F8 ; If so, jump
0040128E xor ebx, ebx ; zero out
00401290 xor edx, edx ; zero out
00401292 loc_401292: ; CODE XREF: sub_40126F+36j
00401292 mov bl, [eax] ; Current Char to bl
00401294 push ecx ; push SLen
00401295 xor cl, bl ; SLen ^ Char
00401297 ror ebx, cl ; ROR ebx, SLen
00401299 rol ecx, 3 ; ROL SLen, 3
0040129C shl ebx, cl ; SHL ebx, SLen
0040129E pop ecx ; pop SLen
0040129F add edx, ebx ; EDX += EBX
004012A1 inc eax ; pointer ++
004012A2 cmp byte ptr [eax], 0 ; End of Serial String ?
004012A5 jnz short loc_401292 ; If not, loop on...
004012A7 push edx ; push Hash
004012A8 push offset unk_402058
004012AD push offset unk_4020B5
004012B2 call j_wsprintfA ; Convert serial to ascii
004012B7 xor ebx, ebx
004012B9 mov ebx, offset unk_4020B5 ; Move ascii string of Hash in ebx
004012BE cmp byte ptr [ebx], 44h
004012C1 jnz short loc_4012F8
004012C3 cmp byte ptr [ebx+1], 33h
004012C7 jnz short loc_4012F8
004012C9 cmp byte ptr [ebx+2], 46h
004012CD jnz short loc_4012F8
004012CF cmp byte ptr [ebx+3], 38h
004012D3 jnz short loc_4012F8
004012D5 cmp byte ptr [ebx+4], 42h
004012D9 jnz short loc_4012F8
004012DB cmp byte ptr [ebx+5], 31h
004012DF jnz short loc_4012F8
004012E1 cmp byte ptr [ebx+6], 30h
004012E5 jnz short loc_4012F8
004012E7 cmp byte ptr [ebx+7], 43h
004012EB jnz short loc_4012F8 ; Serial hash = 'D3F8B10C' ?
004012ED mov eax, 1 ; if yes, set return flag to TRUE
004012F2 pop edx
004012F3 pop ebx
004012F4 leave
004012F5 retn 4
004012F8 ; ---------------------------------------------------------------------------

I think this Call is pretty straightforward. The small algo that is used here, needs bruting to be solved.
We don't know the keylength too, but that's no problem. If we look closely to the hash value, we can 'calculate' that
the serial should be a least 6 chars.
Another thing I prefer to know is the Char Range, but we don't know it...let's assume 30h - 7Ah
The hash value should be 'D3F8B10C', so we have everything we need.
The only 2 vars used in the algo are Serial = TestString and Serial Length = SLen

This is my bruting algo :

.WHILE byte ptr [TestString]  
  .WHILE byte ptr [TestString+1]   
    .WHILE byte ptr [TestString+2]    
      .WHILE byte ptr [TestString+3]     
        .WHILE byte ptr [TestString+4]      
          .WHILE byte ptr [TestString+5] 

         mov ecx, [SLen]
         mov eax, offset TestString
         xor ebx, ebx
         xor edx, edx 
loop_on :
         mov bl, [eax]
         push ecx
         xor cl, bl
         ror ebx, cl
         rol ecx, 3
         shl ebx, cl
         pop ecx
         add edx, ebx
         inc eax
         cmp byte ptr [eax], 00h
         jnz loop_on 
         cmp edx, 0D3F8B10Ch
         jz found_it
         inc byte ptr [TestString+5]
       inc byte ptr [TestString+4]
       mov byte ptr [TestString+5],30h
     inc byte ptr [TestString+3]
     mov byte ptr [TestString+4],30h
   inc byte ptr [TestString+2]
   mov byte ptr [TestString+3],30h
  inc byte ptr [TestString+1]
  mov byte ptr [TestString+2],30h
 inc byte ptr [TestString]
 mov byte ptr [TestString+1],30h

found_it :
invoke SetDlgItemText,hWnd,IDC_EDIT,ADDR TestString 
After a couple of minutes we find the following serial = "2XDrvB"

Enter it in the second EditBox, and we get the goodguy message :-)

Final notes

This crackme is very well coded, so there are no problems to understand the code.
The algo is very easy, so a valid serial can be found easily, the only little trick in this crackme is that the editbox that is used, is hidden.

So a little 2 bytes patch is required first.

If you have questions, or remarks abou this tutorial, feel free to post a comment, or ask on the BiW forum.


What's Related

Story Options

Reversing Phox 7 crackme | 2 comments | Create New Account
The following comments are owned by whomever posted them. This site is not responsible for what they say.
Reversing Phox 7 crackme
Authored by: TDC on Sunday, July 03 2005 @ 03:14 PM CEST
hey, where do I have to input that bruting in a ASM file? can someone gimme an example? thanks :D

:: The world is yours! ::

 Copyright © 2020 BiW Reversing
 All trademarks and copyrights on this page are owned by their respective owners.
Powered By Geeklog 
Created this page in 0.78 seconds