Introduction

This is an old protection, dating back to 1997. Why do I mention about "a sweet memory" below?. Well, nothing special actually. I remember that this was the first commercial program which I brutally cracked (patching!) when I was almost a total newbie. Back then, I had even written a more_than_lame_&_basically_doesn't_explain_anything patching tutorial (included here actually :-) )and now, I strike back again at the same target (5th August 2000) with a key generator.

Darts 95 v1.0 & v1.1 (a sweet memory)

Hello, welcome to my first tutorial. I am ManKind, a newbie who would like to share my newly acquired cracking skills with other newbies. Thanks for reading. Contact me at mankind001@bigfoot.com.

Disclaimer

This tutorial is created just for educational purposes, the author will not bear any responsibilities upon any damages or law breaking charges caused by reading this file. Please forgive me if my narration is not clear as English is not my native language.


Tools

W32Dasm 8.93.
Hiew 6.0/6.04.
Darts 95 v1.0 (try to get it from software sites or DarkFlare's site which is at http://www.esoterica.pt/delphi-pt).
Darts 95 v1.1 http://ourworld.compuserve.com/homepages/djogon/d95.html.

Darts 95 v1.0

Now try the Darts 95 game, you will notice that the unregistered version allows you to play for 99 times before it stops functioning. Now try to enter regisration information (click file and new game), enter anything in those empty spaces and click register now. A message box will appear saying 'incorrect name or password'. So now we want to fix that. Follow these step by step actions.

1). Open up W32Dasm and then click the first button under the Disassembly text.
2). Choose Darts95 in the 'select file to disassemble' box and click open.
3). Now it should start disassembling (while waiting go get some snacks and drinks).
4). Click on the second last button (String Data Reference).
5). Then search for this string "REGISTRED" (it is "registred" and not "registered") and double click on it.
6). Close the data string reference window and you should see this line with a blue line :-

:0042F348 BA08F54200  MOV EDX,0042F508

Now scroll up a little until you see this :-

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
:0042F31D(C), :0042F322(C)

Anything after this is useless. Now note down the two numbers which are 0042F31D and 0042F322.

7). Click Shift and F12 together and type in 0042F31D in the 'Code Offset[hex]' spaces and click OK. You will be brought here with a green line :-

:0042F31D 7E0F        JLE 0042F32E

Now see the status bar (at the lowest point of W32Dasm) and you will see this :-

Line:107398 Pg 1279 of 1318 Code Data @:0042F31D @Offset 0002E71D in File : Darts95.exe

Write down the number after the offset (0002E71D).

8). Now press Shift and F12 again and type in 0042F322, press OK. You will be here with a green line on it :-

:0042F322 7D0A        JGE 0042F32E

Again note down the offset which is 002E722.

9). Now exit W32Dasm and open Hiew. Choose the Darts95.exe file and press enter. Then press enter twice when you see some weird text. After that press F5 and type in the first offset which is 0002E71D and you will be here :-

:0042F31D:7E0F        JLE .00042F32E <-- Change the 7E0F to 7D0F by pressing F3.

-->:0042F31D: 7D0F    JGE .00042F32E <-- New.

Press F9 to update/save and proceed to the next step.

Type the second offset (0002E722) and you will be here:-

:0042F322:7D0F	      JGE .00042F32E <-- Change the 7D0F to 7E0F (refer to step 9).

Now we have cracked it. You should try your Darts95 to see whether it works. Click 'new game' and a new game should start without the nag (registration screen and the XX time left). Thats it, you cracked Darts95. Congratulations. Note :- After examining it again I realized that we just have to patch the second offset (0002E722) to make it registered. Sorry for making you do extra work.

Darts 95 v1.1

Start Darts 95. There is not any registration drop-down menu. Let's try to start a new game (F2). The registration screen will pop up, enabling you to enter your name and password and it also tells you how many times more you can play the game. Enter some fake registration information into the edit fields so that we can pass both the name and password length check (if any) before we reach the CORE (or the heart or the main part) of the password calculation (some sort of calculation but not bound to numbers only). Go into SoftICE and set a breakpoint on hmemcpy.

Leave SoftICE, press the Register Now button, SoftICE will pop up, press F5 once so that our password will be read into the memory, then SoftICE will pop up again, press F11 once and F12 11 times to go back to the good code below :-

:0042E4AC CMP DWORD PTR [EBP-18], 0 <-- check if serial was entered.
:0042E4B0 JNE 0042E4C1 <-- good_boy jump.
:0042E4C1 LEA EDX, DWORD PTR [EBP-14]
:0042E4C4 MOV EAX, DWORD PTR [EBP-04]
:0042E4C7 MOV EAX, DWORD PTR [EAX+1D0]
:0042E4CD CALL 00411CF0
:0042E4D2 MOV EAX, DWORD PTR [EBP-14] <-- move name to eax.
:0042E4D5 LEA EDX, DWORD PTR [EBP-08]
:0042E4D8 CALL 004054F4 <-- uppercase name.
:0042E4DD MOV EAX, DWORD PTR [EBP-08] <-- move uppercased name to eax.
:0042E4E0 CALL 004033FC <-- get length of name.
:0042E4E5 XOR ESI, ESI
:0042E4E7 MOV ECX, EAX <-- move eax (length of name) into ecx.
:0042E4E9 TEST ECX, ECX
:0042E4EB JLE 0042E517
:0042E4ED MOV EAX, 1

<-- The main calculation routine starts here -->

:0042E4F2 MOV EDX, DWORD PTR [EBP-08] <-- move uppercased name to edx.
:0042E4F5 MOV DL, BYTE PTR [EDX+EAX-1] <-- get the first byte of name into dl.
:0042E4F9 AND EDX, 0FF <-- and it with 255 decimal.
:0042E4FF MOV EBX, EDX <-- move ebx to edx.
:0042E501 IMUL EBX, EDX <-- multiply ebx with edx.
:0042E504 ADD ESI, EBX <-- add ebx to esi.
:0042E506 MOV EBX, EDX <-- move ebx to edx.
:0042E508 SAR EBX, 1 <-- shift arithmetic right ebx by 1.
:0042E50A JNS 0042E50F <-- jump if not signed to 0042E50F.
:0042E50C ADC EBX, 0 <-- add with carry ebx with 0.
:0042E50F ADD ESI, EBX <-- add ebx to esi.
:0042E511 SUB ESI, EDX <-- minus edx from esi.
:0042E513 INC EAX <-- increment eax (position of name).
:0042E514 DEC ECX <-- decrement ecx.
:0042E515 JNE 0042E4F2 <-- jump if not zero.

<-- End of loop -->

I wonder why I didn't trace further into the above piece of code when I was a total newbie. Probably at that time I was already satisfied if I could patch it (frankly, I didn't think of fishing a serial or keygenning!). With the above listing, it is not very hard to create a keygen. Below is the source I coded in Turbo Pascal. I compile it with Turbo Pascal v7.0 but it should compile on older versions or any other compatible compilers. As you might see, I am a bad coder, so, if you could optimize the following source in any way possible, then by all means, do it!.

Program keygen ; { program heading }
uses crt ; { uses clause, similar to #include directive in c++ }

var { variable declaration }
 temp1, i, name1, name4, temp2, temp3, temp5 : longint ;
 name2, name3, temp, temp4 : string ;

begin 
 clrscr ; { clear the screen }
 Writeln('Darts 95 v1.1 KeyGen by ManKind') ; { intro }
 Writeln('===============================') ; { part of intro }
 Write('Name: ') ; { input for name }
 Readln(name2) ; { assign inputed name into string variable name2 }
 if Length(name2) > 0 then { only calculate if name is inputed }
 begin
  { uppercase all the chars of name }
  for i := 1 to Length(name2) do
   begin
    name3 := name3 + Upcase(Chr(Ord(name2[i]))) ;
   end ;

  { main calculation here }
  for i := 1 to Length(name2) do { loop all chars of name }
   begin
    name4 := Ord(name3[i]) ; { name4 = ascii of current char of name }
    name4 := name4 and 255 ; { originally -> and edx, 000000FF }
    temp3 := name4 ; { assign value of name4 into temp3 }
    name4 := name4 * name4 ; { originally -> imul ebx, edx }
    temp2 := temp2 + name4 ; { originally -> add esi, ebx }
    temp5 := temp3 div 2 ; { originally -> sar ebx, 1 }
{ sar src, 1 actually dividess src with 2, check asm manual for more info}
    temp2 := temp2 + temp5 ; { originally -> add esi, ebx }
    temp2 := temp2 - temp3 ; { originally -> sub esi, edx }
   end ;

  Write('Password: ') ; { output the password }
  Writeln(temp2) ; { same as above }
  Readln { exit to dos when the user press Enter }
 end
 else { if name's length is less than 1, then ask the user to try again }
  begin
   Writeln('Invalid name! Please try again!') ; { bad_boy message }
   Readln
  end ;
end.

I can actually end this essay here, but I would like to examine this game's protection a little more. Let's see where this game keeps its registration and usage limit information. I see a suspicious string "Pharse.dll" in the dead listing right after the part where the real serial is compared to fake serial, examine it and it turns out to be the thing we are looking for. Below are some contents of that file which indicate whether you are registered or not and how many uses you are still entitled to (note :don't view it in text editor, hex edit it and all numbers involved below are in hexadecimal ) :-

pharse.dll's content after you register with a real serial :- B4000000

pharse.dll's content when you are unregistered and the registration screen tells you that you still have 99 uses left (this actually means that at the first run of that program, its content of pharse.dll is 63000000) :- 62000000

pharse.dll's content when you are unregistered and the registration screen tells you that you still have 98 uses left :- 61000000

You should understand how the usage limit protection works now (the number of uses left and registration status depend on the first byte of the file). However, there's some bug, I think. If you change the first byte into anything larger than 63, you will be registered and if you change the zeros(0) after the first byte into something else, you will be registered too!. Well, if only the author is still around, fix this bug. This is all for now. Hope you enjoyed this tutorial. As usual, contact me if I made any mistakes, give me your feedback, comments, suggestions and opinions and my way of presenting it.


Thanks to : +ORC, +HCU, Sandman, HarvestR, tKC, ytc_, Punisher, Kwai_Lo, TORN@DO, CrackZ, cLUSTER, LaZaRuS, mISTER fANATIC, yes123, WhizKiD, Volatility, ACiD BuRN, Eternal Bliss, R!SC, Kwazy Webbit, +Mammon, MisterE, Shadow, ^tCM^, WaJ, egis, Borna Janes, CyberBlade, josephCo, Kathras, tsehp, Predator, AB4DS, douby, Steinowitz, Lord Soth, Latigo, Lucifer48, Mercution, NeuRaL_NoiSE, Fravia+, [dshadow], yAtEs, Duelist, Alpine, flag eRRatum, Nitrus, +Frog's Print, Muad`Dib, Acid_Cool_178, Iczelion, Razzia, Warezpup, Bomber Monkey, XMen and other crackers, individuals and organisations who have helped me, either directly or indirectly..

Service for ManKind
ManKind
mankind001@bigfoot.com