GenoCide Crackme 16 [Gandalf]

by

{Cronos}

Intro

GenoCide seem to like packing their crackmes with UPX it appears, I can't think why personally. Why do they want to hide the code ? So you just unpack it..... Anyway, it's a Delphi program swollen beyond all proportions :) and 90% of the code that is there is ignorable. It is full of bloat for class type initialisation and type and error checking and it's easy to get lost in a debugger tracing through seemingly endless calls to a library stringlength type function. After a while cracking Delphi apps you become familiar and learn to ignore it for the best part. Delphi however does leave some nice remnants in memory which enable you to start cracking Delphi apps faster :).

Target

The crackme says you just need a serial and presents you with a box for a name and four spinners with which to enter a serial number. I note that there is a reg.dat file with the crackme but I didn't find a use for it, perhaps it is just for some obscurity ? A red herring ? Oh well, I cracked it first and realised there was this file later :).

Analysis

It's not difficult to find the relevant part of the program, with the success messages in, and not far away is some code which stands out due to its use of some values and some maths involving idiv's. In the disassembly of the program I have just shown the mainly relevant parts of the code, in a more relevant order for me to talk about.
success_messages:
;                                                 XREFS First: 1000:00437b8f Number : 1
1000:00437ea0 6a00                 push   00h
1000:00437ea2 68b47e4300           push   offset s_Success_
1000:00437ea7 68c07e4300           push   offset s_Hey__Man__you_did_it__You_cracked_my
1000:00437eac 6a00                 push   00h
1000:00437eae e831dbfcff           call   _MessageBoxA
1000:00437eb3 c3                   ret    
s_Success_:
;                                                 XREFS First: 1000:00437ea2 Number : 1
1000:00437eb4 537563636573732100   ds     "Success!"
1000:00437ebd 00                   db     00
1000:00437ebe 00                   db     00
1000:00437ebf 00                   db     00
s_Hey__Man__you_did_it__You_cracked_my:
;                                                 XREFS First: 1000:00437ea7 Number : 1
1000:00437ec0 4865792c204d616e2c.. ds     "Hey, Man, you did it!You "
					  "cracked my little proggie.AAAAH! :("
Here is the first part we spot, although browsing through the code would soon reveal the second part below, which contains the serial code we are looking for.
1000:00437c02 8b45fc               mov    eax, [ebp-04h]
1000:00437c05 e86ebdfcff           call   403978h
1000:00437c0a 83f805               cmp    eax, 05h		; length >=5 ?
1000:00437c0d 0f8caf000000         jl     437cc2h
1000:00437c13 8b45fc               mov    eax, [ebp-04h]
1000:00437c16 0fb600               movzx  eax, [eax]		; first character
1000:00437c19 b90a000000           mov    ecx, 0ah		; divide by 10
1000:00437c1e 99                   cdq    
1000:00437c1f f7f9                 idiv   ecx
1000:00437c21 a32ca74300           mov    [43a72ch], eax	; save result
1000:00437c26 8b45fc               mov    eax, [ebp-04h]
1000:00437c29 0fb64002             movzx  eax, [eax+02h]	; third character
1000:00437c2d b90a000000           mov    ecx, 0ah
1000:00437c32 99                   cdq    
1000:00437c33 f7f9                 idiv   ecx			; divide by 10
1000:00437c35 a330a74300           mov    [43a730h], eax	; save
1000:00437c3a 8b45fc               mov    eax, [ebp-04h]
1000:00437c3d 0fb64003             movzx  eax, [eax+03h]	; fourth character
1000:00437c41 b90a000000           mov    ecx, 0ah
1000:00437c46 99                   cdq    
1000:00437c47 f7f9                 idiv   ecx			; divide by 10
1000:00437c49 a334a74300           mov    [43a734h], eax	; save
1000:00437c4e 8b45fc               mov    eax, [ebp-04h]
1000:00437c51 0fb64004             movzx  eax, [eax+04h]	; fifth character
1000:00437c55 b90a000000           mov    ecx, 0ah
1000:00437c5a 99                   cdq    
1000:00437c5b f7f9                 idiv   ecx			; divide by 10
1000:00437c5d a338a74300           mov    [43a738h], eax	; save
1000:00437c62 be01000000           mov    esi, 01h
1000:00437c67 bb2ca74300           mov    ebx, offset 43a72ch
;                                                 XREFS First: 1000:00437c94 Number : 1
1000:00437c6c 8d55f8               lea    edx, [ebp-08h]
1000:00437c6f 8b03                 mov    eax, [ebx]
1000:00437c71 e88aecfcff           call   406900h
1000:00437c76 8b45f8               mov    eax, [ebp-08h]
1000:00437c79 e8fabcfcff           call   403978h
1000:00437c7e 48                   dec    eax
1000:00437c7f 740c                 jz     437c8dh
1000:00437c81 8b03                 mov    eax, [ebx]		; just check to see if any
1000:00437c83 b90a000000           mov    ecx, 0ah		; are more than 10
1000:00437c88 99                   cdq    			; in which case we divide again
1000:00437c89 f7f9                 idiv   ecx
1000:00437c8b 8903                 mov    [ebx], eax
;                                                 XREFS First: 1000:00437c7f Number : 1
1000:00437c8d 46                   inc    esi
1000:00437c8e 83c304               add    ebx, 04h
1000:00437c91 83fe05               cmp    esi, 05h
1000:00437c94 75d6                 jnz    437c6ch
1000:00437c96 be01000000           mov    esi, 01h
1000:00437c9b b82ca74300           mov    eax, offset 43a72ch	; now check it
1000:00437ca0 ba3ca74300           mov    edx, offset 43a73ch	; to spinner settings
;                                                 XREFS First: 1000:00437cbe Number : 1
1000:00437ca5 8b0a                 mov    ecx, [edx]
1000:00437ca7 3b08                 cmp    ecx, [eax]
1000:00437ca9 7407                 jz     437cb2h
1000:00437cab b901000000           mov    ecx, 01h
1000:00437cb0 eb15                 jmp    437cc7h
;                                                 XREFS First: 1000:00437ca9 Number : 1
1000:00437cb2 33c9                 xor    ecx, ecx
1000:00437cb4 46                   inc    esi
1000:00437cb5 83c204               add    edx, 04h
1000:00437cb8 83c004               add    eax, 04h
1000:00437cbb 83fe05               cmp    esi, 05h
1000:00437cbe 75e5                 jnz    437ca5h
1000:00437cc0 eb05                 jmp    437cc7h
;                                                 XREFS First: 1000:00437c0d Number : 1
1000:00437cc2 b901000000           mov    ecx, 01h
;                                                 XREFS First: 1000:00437cb0 Number : 2
1000:00437cc7 85c9                 test   ecx, ecx
1000:00437cc9 7514                 jnz    437cdfh
1000:00437ccb a128a74300           mov    eax, [43a728h]
1000:00437cd0 8b80e0010000         mov    eax, [eax+1e0h]
1000:00437cd6 b201                 mov    dl, 01h
1000:00437cd8 e87b54feff           call   41d158h
1000:00437cdd eb12                 jmp    437cf1h
This is the majority of a subroutine which starts with typical Delphi instance code and ends with typical Delphi exit code. You can see the regular mov ecx,0ah followed by cdq followed by idiv ecx. In depth this is taking some characters from the name we input (offsets 0,2,3,4 so 'Cronos' uses 'Cono'). For each digit we take the Ascii value and divide by 10 to produce a set of figures. We then check if any are more than 9 and if they are we divide them again by 10. The result is four digits (and we have four spinners which go from 0 to 9 :)). These four digits are the code we need to set. Simple. So for 'Cronos' we use 'Cono' which is 67,111,110,111 and we are just taking the first digit of each, or '6111' which is the code to set on the spinners.

In fact this is the sort of place I would enter 'aaaaaa' as the code and see if it matched any of '0000' to '9999', which of course it does ('9999').

And so there you have it, name:Cronos, serial:6111.

Conclusions

This crackme was quite easy, the hardest part for most people will probably be understanding how Delphi compiles programs.

{Cronos}