Cracking the Hotline SW Client v1.2 and Server v1.0 b8

by douby

Target: Hotline SW Client v1.2 and Server v1.0 b8
Difficulty: Medium
Tools used: SoftIce
Date: 13-03-'99
Section: Other reverse engineering essays
 

Essay

One of the problems with cracking hotline is that it doesn't have any api input
calls to hook on. When entering name & serial hooking on calls like GetDlgItemTextA,
GetWindowTextA or even hmemcpy won't work. So how are we going to locate the
protection scheme if we can't hook on api input calls ?

The CreateWindowExA method.

The solution to this problem is using the CreateWindowExA method. By hooking
the CreateWindowExA api function soft-ice will pop up every time a window is
created. So if the protection scheme window is created SI will hopefully pop
up somewhere in/before the protection scheme code. The entire protection
scheme method is probably located in a single call. So if SI pops up, the only
thing we'll have to do to locate the protection scheme call is press the F12
button until we're back in hotline. Press the cancel button, et voila back in
softice and right after the protection scheme call. Now ain't that great = )
This method works for both the hotline server and client.

Using this method with the hotline client will get you here:


:00403B14 8B4DCC mov ecx, dword ptr [ebp-34]
:00403B17 E824320000 call 00406D40 ;protection scheme
:00403B1C E98F000000 jmp 00403BB0

Ok so let's disable the bpx on CreateWindowExA and put one on :00403b17, open
the about box, click on the unlock button and .... Back in softice!! Ok let's
trace into this function. Press F10 until we're back in hotline. Hmm let's put
some text in the name box and .... Back in soft-ice. Start pressing F10 again
until you're back in HL enter the rest of your name. Now start typing some kind
of false serial. Wow! Back in SI again. Press f10 till you're back in HL. Enter
the rest of your false serial and press unlock. Back in SI again. Ok this is the
code where the REAL protecion starts.

We could put some breakpoints on our name and serial but since the program may copy
our name/serial a lot of times to different memory locations it may be a boring
exercise. So let's just step over functions/compares and see what happens.

Using this method you'll soon get to a cmp with 0eh=14d. Let's see what it does


:00406E05 80BD90FBFFFF0E cmp byte ptr [ebp+FFFFFB90], 0E
; if serial length < 0e get the hell out of here else continue
:00406E0C 0F853E030000 jne 00407150
:00406E12 8D95E4FBFFFF lea edx, dword ptr [ebp+FFFFFBE4]
:00406E18 8995E0FBFFFF mov dword ptr [ebp+FFFFFBE0], edx
:00406E1E 8B95E0FBFFFF mov edx, dword ptr [ebp+FFFFFBE0]
:00406E24 FF85E0FBFFFF inc dword ptr [ebp+FFFFFBE0]
:00406E2A C60241 mov byte ptr [edx], 41
:00406E2D 8B95E0FBFFFF mov edx, dword ptr [ebp+FFFFFBE0]
:00406E33 FF85E0FBFFFF inc dword ptr [ebp+FFFFFBE0]
:00406E39 C60248 mov byte ptr [edx], 48
:00406E3C 0FB605B8E34700 movzx eax, byte ptr [0047E3B8]

In the code following the serial length check the program sets some values for
creating some kind of compare value by using these values and the entered name. We
will get back to these values later.

Now just step & trace until you get here.


:00406ECF BA00000000 mov edx, 00000000
:00406ED4 8995D8FBFFFF mov dword ptr [ebp+FFFFFBD8], edx
:00406EDA 8B95D8FBFFFF mov edx, dword ptr [ebp+FFFFFBD8]
:00406EE0 6BD21A imul edx, 0000001A
:00406EE3 8995D8FBFFFF mov dword ptr [ebp+FFFFFBD8], edx
:00406EE9 8B95E0FBFFFF mov edx, dword ptr [ebp+FFFFFBE0]
:00406EEF 0FB65206 movzx edx, byte ptr [edx+06]
;get letter #7 from serial
:00406EF3 83C2BF add edx, FFFFFFBF ;subs 41h from letter
:00406EF6 0195D8FBFFFF add dword ptr [ebp+FFFFFBD8], edx
;add result to mem location
:00406EFC 8B95D8FBFFFF mov edx, dword ptr [ebp+FFFFFBD8]
;move result in edx
:00406F02 6BD21A imul edx, 0000001A ;imul with 1ah
:00406F05 8995D8FBFFFF mov dword ptr [ebp+FFFFFBD8], edx
;store result
:00406F0B 8B95E0FBFFFF mov edx, dword ptr [ebp+FFFFFBE0]
:00406F11 0FB65205 movzx edx, byte ptr [edx+05]
;get letter #6 from serial
:00406F15 83C2BF add edx, FFFFFFBF ;subs 41h from letter
:00406F18 0195D8FBFFFF add dword ptr [ebp+FFFFFBD8], edx
;add result to mem location
:00406F1E 8B95D8FBFFFF mov edx, dword ptr [ebp+FFFFFBD8]
;move result in edx
:00406F24 6BD21A imul edx, 0000001A ;imul with 1ah
:00406F27 8995D8FBFFFF mov dword ptr [ebp+FFFFFBD8], edx
;store result
:00406F2D 8B95E0FBFFFF mov edx, dword ptr [ebp+FFFFFBE0]
:00406F33 0FB65204 movzx edx, byte ptr [edx+04]
;etc....
:00406F37 83C2BF add edx, FFFFFFBF
:00406F3A 0195D8FBFFFF add dword ptr [ebp+FFFFFBD8], edx
:00406F40 8B95D8FBFFFF mov edx, dword ptr [ebp+FFFFFBD8]
:00406F46 6BD21A imul edx, 0000001A
:00406F49 8995D8FBFFFF mov dword ptr [ebp+FFFFFBD8], edx
:00406F4F 8B95E0FBFFFF mov edx, dword ptr [ebp+FFFFFBE0]
:00406F55 0FB65203 movzx edx, byte ptr [edx+03]
:00406F59 83C2BF add edx, FFFFFFBF
:00406F5C 0195D8FBFFFF add dword ptr [ebp+FFFFFBD8], edx
:00406F62 8B95D8FBFFFF mov edx, dword ptr [ebp+FFFFFBD8]
:00406F68 6BD21A imul edx, 0000001A
:00406F6B 8995D8FBFFFF mov dword ptr [ebp+FFFFFBD8], edx
:00406F71 8B95E0FBFFFF mov edx, dword ptr [ebp+FFFFFBE0]
:00406F77 0FB65202 movzx edx, byte ptr [edx+02]
:00406F7B 83C2BF add edx, FFFFFFBF
:00406F7E 0195D8FBFFFF add dword ptr [ebp+FFFFFBD8], edx
:00406F84 8B95D8FBFFFF mov edx, dword ptr [ebp+FFFFFBD8]
:00406F8A 6BD21A imul edx, 0000001A
:00406F8D 8995D8FBFFFF mov dword ptr [ebp+FFFFFBD8], edx
:00406F93 8B95E0FBFFFF mov edx, dword ptr [ebp+FFFFFBE0]
:00406F99 0FB65201 movzx edx, byte ptr [edx+01]
:00406F9D 83C2BF add edx, FFFFFFBF
:00406FA0 0195D8FBFFFF add dword ptr [ebp+FFFFFBD8], edx
:00406FA6 8B95D8FBFFFF mov edx, dword ptr [ebp+FFFFFBD8]
:00406FAC 6BD21A imul edx, 0000001A
:00406FAF 8995D8FBFFFF mov dword ptr [ebp+FFFFFBD8], edx
:00406FB5 8B95E0FBFFFF mov edx, dword ptr [ebp+FFFFFBE0]
:00406FBB 0FB612 movzx edx, byte ptr [edx]
:00406FBE 83C2BF add edx, FFFFFFBF
:00406FC1 0195D8FBFFFF add dword ptr [ebp+FFFFFBD8], edx
:00406FC7 6AFE push FFFFFFFE
:00406FC9 8B85DCFBFFFF mov eax, dword ptr [ebp+FFFFFBDC]
:00406FCF 50 push eax
:00406FD0 8D85E4FBFFFF lea eax, dword ptr [ebp+FFFFFBE4]
:00406FD6 50 push eax
:00406FD7 E8D42D0300 call 00439DB0
:00406FDC 83C40C add esp, 0000000C
:00406FDF 3985D8FBFFFF cmp dword ptr [ebp+FFFFFBD8], eax
;cmp serial value w/ name
;value
:00406FE5 0F8565010000 jne 00407150

If you study the code you will see the first 7 characters of the serial are used
to create a value. This value is compared with a value created using the previousely
set values. Let's say our serial looks something like this:

ABCDEFGHIJKLMN

In the code before the call at 00406fd7 the following mathimatical operations are
being used on the serial (#A represents the uni-code of A(=41h)):

((((((((#G-41H)*1AH + (#F-41H))*1AH + (#E-41H))*1AH + (#D-41H))*1AH +
(#C-41H))*1AH + (#B-41H))*1AH + (#A-41H)) = X

If (X == value created using our name) then the first part of our serial is valid
else wrong serial.

So if we copy the code used for making the name value and if we are able to "substract"
the right serial out of this name value we've got the first part of the serial!

Hmmm let's take another look at the formula above. If X - (#A-41H) = Y then Y mod 1ah
must be 0. Becoz of the (- 41H) and the (* 1AH) a valid serial will probably only contain
uppercase chars, that means #A must be a value between 0 and 19H.

Using this knowledge we could create an algorythm using backtracking that will "substract"
the right serial out of the given name value. It looks something like this:


String getSerial(long a, String s){
if(a==0 && s.length()==7) return s;
else if(s.length()>6||((s.length()<5)&&(a<26))) return null;
else {
for (int i=0;i<26;i++){
if((a-i)%26==0){
s=getSerial((a-i)/26,s+(char)(i+65));
if(s!=null) return s;
}
}
}
return null;
}

Param: a = name value, s = serial

We can use this function to substract the first part of the serial out of the name value
but what about the second part ???

Well let's take a look at the rest of the code:


:00407003 8D9590FBFFFF lea edx, dword ptr [ebp+FFFFFB90]
:00407009 83C208 add edx, 00000008
:0040700C 8995E0FBFFFF mov dword ptr [ebp+FFFFFBE0], edx
:00407012 BA00000000 mov edx, 00000000
:00407017 8995D8FBFFFF mov dword ptr [ebp+FFFFFBD8], edx
:0040701D 8B95D8FBFFFF mov edx, dword ptr [ebp+FFFFFBD8]
:00407023 6BD21A imul edx, 0000001A
:00407026 8995D8FBFFFF mov dword ptr [ebp+FFFFFBD8], edx
:0040702C 8B95E0FBFFFF mov edx, dword ptr [ebp+FFFFFBE0]
:00407032 0FB65206 movzx edx, byte ptr [edx+06]
:00407036 83C2BF add edx, FFFFFFBF
:00407039 0195D8FBFFFF add dword ptr [ebp+FFFFFBD8], edx
:0040703F 8B95D8FBFFFF mov edx, dword ptr [ebp+FFFFFBD8]
:00407045 6BD21A imul edx, 0000001A
:00407048 8995D8FBFFFF mov dword ptr [ebp+FFFFFBD8], edx
:0040704E 8B95E0FBFFFF mov edx, dword ptr [ebp+FFFFFBE0]
:00407054 0FB65205 movzx edx, byte ptr [edx+05]
:00407058 83C2BF add edx, FFFFFFBF
:0040705B 0195D8FBFFFF add dword ptr [ebp+FFFFFBD8], edx
:00407061 8B95D8FBFFFF mov edx, dword ptr [ebp+FFFFFBD8]
:00407067 6BD21A imul edx, 0000001A
:0040706A 8995D8FBFFFF mov dword ptr [ebp+FFFFFBD8], edx
:00407070 8B95E0FBFFFF mov edx, dword ptr [ebp+FFFFFBE0]
:00407076 0FB65204 movzx edx, byte ptr [edx+04]
:0040707A 83C2BF add edx, FFFFFFBF
:0040707D 0195D8FBFFFF add dword ptr [ebp+FFFFFBD8], edx
:00407083 8B95D8FBFFFF mov edx, dword ptr [ebp+FFFFFBD8]
:00407089 6BD21A imul edx, 0000001A
:0040708C 8995D8FBFFFF mov dword ptr [ebp+FFFFFBD8], edx
:00407092 8B95E0FBFFFF mov edx, dword ptr [ebp+FFFFFBE0]
:00407098 0FB65203 movzx edx, byte ptr [edx+03]
:0040709C 83C2BF add edx, FFFFFFBF
:0040709F 0195D8FBFFFF add dword ptr [ebp+FFFFFBD8], edx
:004070A5 8B95D8FBFFFF mov edx, dword ptr [ebp+FFFFFBD8]
:004070AB 6BD21A imul edx, 0000001A
:004070AE 8995D8FBFFFF mov dword ptr [ebp+FFFFFBD8], edx
:004070B4 8B95E0FBFFFF mov edx, dword ptr [ebp+FFFFFBE0]
:004070BA 0FB65202 movzx edx, byte ptr [edx+02]
:004070BE 83C2BF add edx, FFFFFFBF
:004070C1 0195D8FBFFFF add dword ptr [ebp+FFFFFBD8], edx
:004070C7 8B95D8FBFFFF mov edx, dword ptr [ebp+FFFFFBD8]
:004070CD 6BD21A imul edx, 0000001A
:004070D0 8995D8FBFFFF mov dword ptr [ebp+FFFFFBD8], edx
:004070D6 8B95E0FBFFFF mov edx, dword ptr [ebp+FFFFFBE0]
:004070DC 0FB65201 movzx edx, byte ptr [edx+01]
:004070E0 83C2BF add edx, FFFFFFBF
:004070E3 0195D8FBFFFF add dword ptr [ebp+FFFFFBD8], edx
:004070E9 8B95D8FBFFFF mov edx, dword ptr [ebp+FFFFFBD8]
:004070EF 6BD21A imul edx, 0000001A
:004070F2 8995D8FBFFFF mov dword ptr [ebp+FFFFFBD8], edx
:004070F8 8B95E0FBFFFF mov edx, dword ptr [ebp+FFFFFBE0]
:004070FE 0FB612 movzx edx, byte ptr [edx]
:00407101 83C2BF add edx, FFFFFFBF
:00407104 0195D8FBFFFF add dword ptr [ebp+FFFFFBD8], edx
:0040710A 6A02 push 00000002
:0040710C 8B85DCFBFFFF mov eax, dword ptr [ebp+FFFFFBDC]
:00407112 50 push eax
:00407113 8D85E4FBFFFF lea eax, dword ptr [ebp+FFFFFBE4]
:00407119 50 push eax
:0040711A E8F12C0300 call 00439E10
:0040711F 83C40C add esp, 0000000C
:00407122 3985D8FBFFFF cmp dword ptr [ebp+FFFFFBD8], eax ;cmp serial value
;w/ name value
:00407128 7526 jne 00407150

HEY!!! It's almost the same. But instead of the first 7 chars the last 7 chars
of the serial are used. So we can use the same algorythm to substract the last
part of the serial out of the SECOND name value.

Okay so now we know what algorhytm to use to substract the right serial out off the name
codes. But how can we create these name codes ?

Well that's pretty easy study the call that creates these name values and just copy the
code. You will see this call uses a table to create the name serials so you'll have to
copy the table too. The call also uses the values set at the beginning of the protection
scheme to create the name value. As you will see the only difference between the hotline
server and client are these values set at beginning of the protection scheme.

Now you've got all the information you need to crack these babies. Good luck to you amigo.

Well that's all folks. I'm sorry i didn't explain the creating of the name values :-(
But hey see it as an exercise and try to figure it out for yourself.

For questions/suggestions/remarks/etc. email me at douby_(at)hotmail(dot)com or visit
the #dread channel on efnet.

Greetz go out to everyone of Faith2000, Rvl & Ecolove.

 

Disclaimer notice

DREAD is NOT responsible for any abuse of the information we provide. Members of DREAD don't crack to get programs registered. As a matter of fact, we don't crack at all, since we are reverse engineers. Our only objective is to further our knowledge. If you want to use a program you reversed, you have to buy it!

 
This essay is © copyright 2000 by douby.