Contribute  :  Web Resources  :  Past Polls  :  Site Statistics  :  Downloads  :  Forum  
    BiW ReversingThe challenge is yours    
 Welcome to BiW Reversing
 Tuesday, September 28 2021 @ 04:14 AM CEST

Reversing the algo in Phox Crackme 5


TutorialsLevel : newbie

Reversing a simple algorithm that seems to need bruting at first sight.

Find the crackme here : attachment.

We have to find a valid serial for the crackme.
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 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 arg_0 = dword ptr 8
00401159 arg_4 = dword ptr 0Ch
00401159 arg_8 = dword ptr 10h
00401159 arg_C = dword ptr 14h
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 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 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 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
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 ; S U B R O U T I N E
0040120B ; Attributes: bp-based frame
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 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'

The Solution

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 ;-)
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 in a couple of minutes.

If you have questions, or remarks abou this tutorial, feel free to post a comment here, or post on our forum.

Detten (at) reversing (dot) be

What's Related

Story Options

Reversing the algo in Phox Crackme 5 | 0 comments | Create New Account
The following comments are owned by whomever posted them. This site is not responsible for what they say.
 Copyright © 2021 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