ScareByte's CrackMe #7
Delphi Cracking
Written by Sphinx


Introduction


Ok. This CrackMe is interesting. It has five tasks to accomplish which includes a nag, password (constant), serial
(user-based), checkboxes and trackbars. They range from easy to hard (especially the last, which includes some FPU). Anyway, onward we go...



Tools required


SoftICE (I used v3.25)
DeDe (I used v1.06)
UnAspack
Hiew


Target's URL

http://crackmes.cjb.net



Essay


Ok. As usual, let's snoop! And from the looks of things this app is packed. And I could tell from experience that it's Aspacked by an older version coz it doesn't have it's own ".aspack" section like the newer ones. Ok, since it's packed
and there are alot of nifty unpackers available, I used UnAspack (subtle isn't it?). After that, we continue to snoop. And
we notice it's coded in Delphi (again, from experience :) So we might as well use DeDe to decompile it for a "better" view. Ok, after processing it with DeDe, we goto the "DCU" tab coz there's where the most useful infos are located. And from
my view, I could see the "crack" unit name. So click it and lo! We can see the events used! There'll be some other events,
but the most important ones are those with SpeedButton?Click (where ? is a # from 1 to 4). And getting add-on infos,
you'll know that they're the "Check" buttons. Anywho, let's go on with our first task.

Task 1: Nag

Ok. We're not yet interested with the above infos (yet), coz the nag ain't got one. So we'll try this instead:

- In SoftICE, type: bpx MessageBoxA [enter]

- Run it then break! We should press F12 to let the nag to be completely drawn (sux!). Then click "Ok" and break!

 You see: (as exported from SoftICE with "CODE OFF")

 ...(some crap)....
 0137:00441CCB CALL 00440D3C
 0137:00441CD0 TEST AL,AL
 0137:00441CD2 JZ 00441CDA ; we'll patch this...
 0137:00441CD4 OR EBX,00100000
 0137:00441CDA XOR ECX,ECX
 0137:00441CDC PUSH EBP
 0137:00441CDD PUSH 00441D59
 0137:00441CE2 PUSH DWORD PTR FS:[ECX]
 0137:00441CE5 MOV FS:[ECX],ESP
 0137:00441CE8 PUSH EBX
 0137:00441CE9 PUSH EDI
 0137:00441CEA PUSH ESI
 0137:00441CEB MOV EAX,[EBP-04]
 0137:00441CEE MOV EAX,[EAX+24]
 0137:00441CF1 PUSH EAX
 0137:00441CF2 CALL USER32!MessageBoxA ; Yep!
 0137:00441CF7 MOV [EBP-08],EAX
 0137:00441CFA XOR EAX,EAX ; ...to let it jump here!

So what I did was I changed that conditional jump at :00441CD2 from a jz 00441CDA to a jmp 00441CFA and voila!
The nag's gone! hehe.. So to make it permanent, we'll patch it in Hiew. Anyway, here's it:

Comparing files CRACKME.BAK and CRACKME.EXE
000410D2: 74 EB
000410D3: 06 26

Task 2: Password

Ok. We'll go back to the SpeedButtons we saw earlier in DeDe. So we should pick one then. But (most) probably,
it's the first one we're after. So we disassemble it. And as I was looking at the snippet, it reminded me of HellForge's W32Dasm CrackMe. Anywho, it just compares the chars of our input to some constants. And I won't include the entire snippet here, coz it's too long. So I'll just present here the ones we're after (and note that the hexcodes were all ripped!)

 * Possible Reference to Control 'Edit1:TEdit' ; yep, the password edit field
 |
 0044C3C7 mov eax, [ebx+$02E8]
 0044C3CD call 00425824
 0044C3D2 mov eax, [ebp-$04]
 0044C3D5 call 00403A74
 0044C3DA cmp eax, +$0C
 These (probably) just checks the length. If it is, the password then must be 12 chars long...

Continuing, we then notice that the next ones are the real compares! Why so? coz by merely looking at the entire
deadlisting (not shown). All of what we're after, have a check before a conditional jump. And here's the summary:

 0044C3F4 cmp byte ptr [eax], $43 ; ("C")
 0044C40E cmp byte ptr [eax+$03], $6F ; ("o")
 0044C429 cmp byte ptr [eax+$08], $6F ; ("o")
 0044C444 cmp byte ptr [eax+$01], $6C ; ("l")
 0044C45F cmp byte ptr [eax+$04], $20 ; (" ")
 0044C47A cmp byte ptr [eax+$0A], $52 ; ("R")
 0044C495 cmp byte ptr [eax+$07], $75 ; ("u")
 0044C4B0 cmp byte ptr [eax+$09], $6E ; ("n")
 0044C4C7 cmp byte ptr [eax+$02], $6E ; ("n")
 0044C4DE cmp byte ptr [eax+$05], $69 ; ("i")
 0044C4F5 cmp byte ptr [eax+$0B], $6E ; ("n")
 0044C50C cmp byte ptr [eax+$06], $67 ; ("g")

Ok. Reading this way spelled Cool Running. But it's not the final code yet. Why? coz it checks for these characters at different locations. But at first, I assumed that [eax] points to the first char, the [eax+$03] to the 4th char and so on. And doing that, we then come up with the (presumably) real password which reads Clno_iguonRn (note that the "_" is really
a space, just to avoid confusion). And now enter that and it'll work! Now onto task 3.

Task 3: Serial

Ok. Let's first see that. Hey! It has an anti-SoftICE trick (coz it says so ;) and notice that the "Check" button has also been
disabled! So we have to "fix" this one first. How? Hmmm.. I've a hunch that it's just like MeltICE only. So first, switch to
any tab other than this.

- In SoftICE, type: bpx CreateFileA [enter]

- Goto the Serial tab then break! Mash F12 first so we'll return to the program's code.

 You see:

 ...(some crap)....
 0137:0044BFB0 PUSH EAX ; before, eax points to "\\.\SICE"
 0137:0044BFB1 CALL KERNEL32!CreateFileA ; check if the VxD is loaded
 0137:0044BFB6 CMP EAX,-01 ; found? (eax is -01 if not, else eax = handle)
 0137:0044BFB9 JNZ 0044BFBF ; yes? jump, else..
 0137:0044BFBB XOR EBX,EBX ; ebx=0 (goodflag)
 0137:0044BFBD JMP 0044BFC1 ; jump to close (why?)
 0137:0044BFBF MOV BL,01 ; ebx=1 (badflag)
 0137:0044BFC1 PUSH EAX ; save handle then..
 0137:0044BFC2 CALL KERNEL32!CloseHandle ; close it
 0137:0044BFC7 XOR EAX,EAX ; clean-up

So what should we do? We could make that only conditional jump to an unconditional jump. But hey! There's one more better thing. Since it opened it, I want it to close it but I also want it to eat a goodflag. But how? We could patch that
mov bl, 1 at :0044BFBF to xor ebx, ebx (goodflag) then close the file afterwards. More elegant? Maybe? Maybe not :)
But since the code is like messed up, so... anyway, here's it:

Comparing files CRACKME.BAK and CRACKME.EXE
0004B3BF: B3 33
0004B3C0: 01 DB

Ok. Back in DeDe and diassemble that SpeedButton2Click. And again, no full snippet here. Now we need to break at
those relevant memory locations. We could use the int3 move or for an easier way, we could use Symbol Loader (yep!).
Ok. On the first break, press F10 just to be sure ;-) Then...

- In SoftICE, type: bpx cs:44C66A [enter]

- Goto the Serial Tab. I registered with Sphinx as name, TRES2000 as the company and 12345 as the serial and hit
  "Check" then break!. And yeah, no need for F12 :-)

 0044C66A mov eax, dword ptr [$44F880] ; after, eax = name offset
 0044C66F call 00403A74 ; strlen(name)
 0044C674 cmp eax, +$06 ; is it <= 6?
 0044C677 jle 0044C76D ; yes? jump badboy, else...
 Hey! I'm a badboy coz mine's only six (sux!). So I changed it to Sphinxter (heh!) then...

 0044C67D mov eax, dword ptr [$44F880] ; name again
 0044C682 call 00403A74 ; strlen again
 0044C687 cmp eax, +$14 ; is it >= 14 (20)?
 0044C68A jnl 0044C76D ; yes? jump, else...
 So we now know that name should be > 6 and < 20 chars...

 0044C690 mov eax, dword ptr [$44F880] ; Deja Vu ;)
 0044C695 call 00403A74 ; mine's eax = 9
 0044C69A test eax, eax ; 0 bah? (what for?)
 0044C69C jle 0044C6B5 ; yes? jump, else...
 0044C69E mov edx, $00000001 ; edx = 1 (initial)
 0044C6A3 mov ecx, [$44F880] ; ecx = name
 0044C6A9 movzx ecx, byte ptr [ecx+edx-$01] ; ecx = 53 ("S")
 0044C6AE add [ebp-$04], ecx ; 1st, [ebp-04] = 0, so now it's 53 (duh!)
 0044C6B1 inc edx ; inc name ptr
 0044C6B2 dec eax ; dec namelen
 0044C6B3 jnz 0044C6A3 ; while eax != 0 loop
 This routine just adds the oridinal values of the name_chars. And mine's 3C5, so [ebp-04] = 3C5

 0044C6B5 mov eax, dword ptr [$44F884] ; after, eax = company
 0044C6BA call 00403A74 ; strlen(company)
 0044C6BF cmp eax, +$02 ; is it <= 2?
 0044C6C2 jle 0044C6DC ; yes? jump, else...
 0044C6C4 mov eax, dword ptr [$44F884] ; same
 0044C6C9 call 00403A74 ; same
 0044C6CE cmp eax, +$08 ; is it >= 8 then?
 0044C6D1 jnl 0044C6DC ; yes? jump, else...
 So we now know that company should be > 2 and < 8 chars. So I change mine to TRES2K.

 0044C6D3 mov eax, [ebp-$04] ; eax = 3C5 (see :0044C6AE)
 0044C6D6 imul eax, eax, $02 ; eax = eax * 2, so eax = 78A (1930 in dec)
 0044C6D9 mov [ebp-$04], eax ; [ebp-04]

Ok. Too long to explain further, so I'll stop here. But to give a hint, my real serial's I Love Cracking and 1930 Girls ;)
D'you dig it? It generates a number from the name only then inserts it between the magic words. And it's case senstive
and that ;) is really included. Yep, task done so onto the next.

Task 4: CheckBoxes

Ok. Back to DeDe. Disassemble the SpeedButton3Click. Btw, this ain't that difficult at all with DeDe's help. Anyway,
just by merely looking at the control names, you'll immediately know what should be checked. And here they are:

* Possible Reference to Control 'cb3:TCheckBox'; #3
* Possible Reference to Control 'cb5:TCheckBox'; #5
* Possible Reference to Control 'cb6:TCheckBox'; #6
* Possible Reference to Control 'cb12:TCheckBox'; #12
* Possible Reference to Control 'cb15:TCheckBox'; #15
* Possible Reference to Control 'cb20:TCheckBox'; #20
* Possible Reference to Control 'cb9:TCheckBox' ; #9
* Possible Reference to Control 'cb11:TCheckBox' ; #11
* Possible Reference to Control 'cb13:TCheckBox' ; #13
* Possible Reference to Control 'cb19:TCheckBox' ; #19

Ok. Now we know what boxes. But to check which one is which, I had to use SoftICE. So again, break anywhere
near these lines using Symbol Loader. Anyway, here's my snapshot:


Ok, task done so onto the next...

Task 5: TrackBars

Ok. This is the hard part of the CrackMe, simply because it includes some FPU. I even went to www.intel.com for explanations on some instructions :-) But I should note the ff. first:

- It's important to have the "floating point stack window" in SoftICE, else you'll be lost, so if you have none, type WF.
- Since they're in float, treat the numbers in the "floating point stack window" as decimal and NOT as hex!
- This is my first FPU, so some of my comments aren't the real way how they work! It's these way as how I see them
  and how I see them fit. So apologies in case you might feel misleaded...
  eg.
  For faddp st(1), st(0): I commented it as st(0) = st(0) + st(1). But in "real life", it should be st(1) = st(1) + st(0)
  then pop. And that pop just places the contents of st(1) to st(0).

Ok. Let's start. After diassembling the last SpeedButton in DeDe, we hit the code similar below (but not fully shown).
But first, I made the trackbars read (starting from left), 12345. And the first few lines (not shown) just stores these #'s seperately in some memory locations. And let's call these input as the usercode. Anyway, here they are:

[ebp-18] = 1 (1st)
[ebp-20] = 2 (2nd)
[ebp-28] = 3 (3rd)
[ebp-30] = 4 (4th)
[ebp-38] = 5 (5th)

Let's just dive from the start of the calcs:

 0044C1F0 fld qword ptr [ebp-$20] ; st(0) = 2 (2nd number)
 0044C1F3 add esp, -$0C
 0044C1F6 fstp tbyte ptr [esp] ; [esp] = st(0)
 0044C1F9 wait
 0044C1FA mov eax, $00000003 ; eax = 3 (counter for the call below)
 0044C1FF call 0041B8F0 ; It goes st(0) = 2 * 2 * 2 = 8 (done 3 times coz counter is 3)
 0044C204 fadd dword ptr [$44C350] ; st(0) = st(0) + 5 (const)
 0044C20A fsqrt ; st(0) = sqrt(st0)
 0044C20C call 00402804 ; st(0) = cos(st0)
 0044C211 fstp tbyte ptr [ebp-$48] ; [ebp-48] = st(0)
 0044C214 wait
 0044C215 fld dword ptr [$44C354] ; st(0) = 1 (const)

Interruption
"fstp" stores a float value to dest then clears st(0) (the src).
"fstp" loads a float value to st(0). But first, move st(0)'s original value to st(1) (if not empty).

 0044C21B fadd qword ptr [ebp-$18] ; st(0) = st(0) + (1st number)
 0044C21E fsqrt ; st(0) = sqrt(st0)
 0044C220 fchs ; change st(0)'s sign (ie. from + to - and vice versa)
 0044C222 fld tbyte ptr [ebp-$48] ; st(0) = value saved from :0044C211
 0044C225 faddp st(1), st(0) ; st(0) = st(0) + st(1)
 0044C227 fstp tbyte ptr [ebp-$54] ; [ebp-54] = st(0)
 0044C22A wait
 0044C22B fld dword ptr [$44C358] ; st0 = 3 (const)
 0044C231 fmul qword ptr [ebp-$28] ; st0 = st0 * (3rd number)
 0044C234 fadd dword ptr [$44C354] ; st0 = st0 + 1 (const)
 0044C23A fldln2 ; st(0) = log(2)
 0044C23C fxch st(0), st(1) ; exchange floating point registers
 0044C23E fyl2x ; st(0) = log(10)
 0044C240 fld tbyte ptr [ebp-$54] ; st(0) = value saved from :0044C227
 0044C243 faddp st(1), st(0) ; st(0) = st(0) + st(1)
 0044C245 fstp tbyte ptr [ebp-$60] ; [ebp-60] = st(0)
 0044C248 wait
 0044C249 fld dword ptr [$44C35C] ; st0 = 2 (const)
 0044C24F fadd qword ptr [ebp-$30] ; st0 = st0 + (4th number)
 0044C252 fsqrt ; st0 = sqrt(st0)
 0044C254 fld tbyte ptr [ebp-$60] ; st0 = value saved from :0044C245
 0044C257 fsubrp st(1), st(0) ; st0 = st0 - st1
 0044C259 fld dword ptr [$44C358] ; st0 = 3 (const)
 0044C25F fmul qword ptr [ebp-$38] ; st0 = st0 * (5th number)
 0044C262 fdiv dword ptr [$44C35C] ; st0 = st0 / 2 (const)
 0044C268 faddp st(1), st(0) ; st0 = st0 + st1
 0044C26A fld tbyte ptr [$44C360] ; st0 = 0.37 (const)
 0044C270 faddp st(1), st(0) ; st0 = st0 + st1
 0044C272 fmul dword ptr [$44C36C] ; st0 = st0 * 1000
 0044C278 fstp qword ptr [ebp-$10] ; [ebp-10] = st(0)
 0044C27B wait
 0044C27C fld qword ptr [ebp-$10] ; st0 = value saved from :0044C278 (mine's 5414.593729279496670000)
 0044C27F call 00402814 ; st(0) = round(st0)
 0044C284 mov [ebp-$68], eax
 0044C287 mov [ebp-$64], edx
 0044C28A fild qword ptr [ebp-$68] ; st(0) = rounded value (mine's 5415)
 0044C28D add esp, -$0C
 0044C290 fstp tbyte ptr [esp] ; [esp] = st(0) (ie. 5145)
 0044C293 wait
 0044C294 lea eax, [ebp-$04]
 0044C297 call 00408204
 0044C29C lea eax, [ebp-$04]
 0044C29F call 0044BF00 ; most important call!

First, let's call that 5415 as magic_value. Then the call above will encrypt this magic_value using a set of xor keys
(based on its length) producing the final usercode. And here's the xor keys I sniffed (heh!):

Length   XOR Key (comment)

    3         82 8E 98 (probably NOT included coz realcode's four chars! See below)
    4         83 89 86 8D (the best option!)
    5         85 85 8F 8F 87 (could be since it just compares the first four)


Ok. Here's the summary of encrypting my 4-lengthed magic_value:

35 ("5") xor 83 = B6
34 ("4") xor 89 = BD
31 ("1") xor 86 = B7
35 ("5") xor 8D = B8

So my final usercode is B6 BD B7 B8. Then we continue to trace...

 0044C2A7 mov edx, $0044C378
 0044C2AC call 00403B84 ; compare usercode (B6 BD B7 B8) with realcode (B5 BA B2 BA)
 0044C2B1 jnz 0044C2EB ; if NOT equal? jump to badboy, else print "Correct"

Ok, think. If I were to know the magic_value of the realcode, I would do these. And I'll also be using the xor keys
for a 4-lengthed magic_value. Yep, and here's it:

B5 xor 83 = 6
BA xor 89 = 3
B2 xor 86 = 4
BA xor 8D = 7

So the magic_value should really have been 6347 to pass. So I need to enter a usercode, which, after those long
calcs above, should result to 6347. But how? Ok. My approach, I brute forced! hehe... I translated the above calcs
into a Pascal program. And after running the brute forcer, I hit this:

User: 14435
Magic: 6347

Ahh, ok. So it's 14435. So if I made the bar read that (starting from left), then hit "Check"... BOOM! It's correct!
Yep, my first FPU crack and I already brute forced ;-) Well, that's it! So I guess I'm kinda done now, later.

Sphinx [sphinxter@edsamail.com.ph]


Final Notes



My Greetz Goes to:



TRES2000
ScareByte




When ever there is a door,
there is an entrance.
And behind an entrance can no secret hide,
when a cracker takes his knowledge for a ride
                                                                               McCodEMaN



ObDuh

The information in this essay is for educational purpose only!
You are only allow to crack, reverse engineer, modify code and debugg programs that you legaly bought and then for personal use only!!
To ignore this warning is a criminell act and can result in lawful actions!

So please note!
I take no responebility for how you use the information in this essay, i take NO responebility for what might happen to you or your computer!
You use this information on your own risk!!









Essay written by Sphinx ŠTRES2000. All Rights Reserved.