About this tutorial:
Tutorial:Total reversing of Darts 95 v1.1(A sweet memory)

Target:Darts 95 1.1(http://ourworld.compuserve.com/homepages/djogon/d95.html)

Tools:SoftICE 3.2x, W32Dasm 8.9x, HIEW 6.1x

Date:5th August 2000

Descriptions&Comments:This is an old protection, dating back to 1997, but, with a brief look, I can confidently say that its name/serial and time-limit protections are considered quite good back in that time mentioned. Why do I mention about "a sweet memory"? Well, nothing special actually. I remember that this was the first few commercial programs which I brutally crack(patching!) when I was almost a total newbie. Back then, I had even written a more_than_lame_&_basically_doesnt_explain_anything patching tutorial and now, when I have the ability, I strike back again at the same target and needless to say, quite successfully beat it up...

Protections:Name/serial, 99 uses limit, nag

Disclaimer:This file is used for educational purposes only. Any misuse of the information presented here is not my responsibility.

Copyright information:This tutorial is copyright © ManKind

Starting words:
Hello,welcome to my tutorial. I am ManKind, a newbie in cracking who want to share my cracking skills with other newbies. Contact me at mankind001@bigfoot.com


The process:
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). I enter the following fake information(the first line for 'Your Name:' edit field and second line for 'Password:' edit field):

ManKind
23199981

Go into SoftICE and set a breakpoint on hmemcpy API function like below:

bpx 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 codes below:

:0042E4AC 837DE800                cmp dword ptr [ebp-18], 00000000 <-- check if our serial is entered
:0042E4B0 750F                    jne 0042E4C1 <-- good_boy jump

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:0042E499(C)
|

* Possible StringData Ref from Code Obj ->"Please enter both - Name and Password!"
                                  |
:0042E4B2 B85CE64200              mov eax, 0042E65C
:0042E4B7 E804A6FFFF              call 00428AC0
:0042E4BC E957010000              jmp 0042E618
I told you to put in the fake registration info earlier on, didn't I? And if you do according to what I say, you will jump to good_boy below:
* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:0042E4B0(C)
|
:0042E4C1 8D55EC                  lea edx, dword ptr [ebp-14]
:0042E4C4 8B45FC                  mov eax, dword ptr [ebp-04]
:0042E4C7 8B80D0010000            mov eax, dword ptr [eax+000001D0]
:0042E4CD E81E38FEFF              call 00411CF0
:0042E4D2 8B45EC                  mov eax, dword ptr [ebp-14] <-- move name to eax
:0042E4D5 8D55F8                  lea edx, dword ptr [ebp-08]
:0042E4D8 E81770FDFF              call 004054F4 <-- uppercase name
:0042E4DD 8B45F8                  mov eax, dword ptr [ebp-08] <-- move uppercased name to eax
:0042E4E0 E8174FFDFF              call 004033FC <-- get length of name
:0042E4E5 33F6                    xor esi, esi
:0042E4E7 8BC8                    mov ecx, <--move eax(length of name) into ecx
:0042E4E9 85C9                    test ecx, ecx 
:0042E4EB 7E2A                    jle 0042E517 
:0042E4ED B801000000              mov eax, 00000001

<-- The main calculation routine starts here -->
<-- From line 0042E4F2 to 0042E514 is a loop, it loops for as many times as the length of name -->

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:0042E515(C)
|
:0042E4F2 8B55F8                  mov edx, dword ptr [ebp-08] <-- move uppercased name to edx
:0042E4F5 8A5402FF                mov dl, byte ptr [edx+eax-01] <-- get the first byte of name into dl
:0042E4F9 81E2FF000000            and edx, 000000FF <-- add it with 255 decimal
:0042E4FF 8BDA                    mov ebx, edx <-- move edx to ebx
:0042E501 0FAFDA                  imul ebx, edx <-- multiply ebx with edx
:0042E504 03F3                    add esi, ebx <-- add ebx to esi
:0042E506 8BDA                    mov ebx, edx <-- move ebx to edx
:0042E508 D1FB                    sar ebx, 1 <-- shift arithmetic right ebx by 1
:0042E50A 7903                    jns 0042E50F <-- jump if not signed to 0042E50F
:0042E50C 83D300                  adc ebx, 00000000 <-- add with carry ebx with 0

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:0042E50A(C)
|
:0042E50F 03F3                    add esi, ebx <-- add ebx to esi
:0042E511 2BF2                    sub esi, edx <-- minus edx from esi
:0042E513 40                      inc eax <-- increment eax(position of name)
:0042E514 49                      dec ecx <-- decrement ecx
:0042E515 75DB                    jne 0042E4F2 <-- jump if not zero

<-- End of loop -->
<-- End of important code, the rest is just useless moving of real serial and comparing it with your fake serial -->
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 am 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 of a keygen I coded in Turbo Pascal. I compile it with my Turbo Pascal v7.0 but it should compile on older versions of Turbo Pascal or any other compatible compilers. As you might have known, 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 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 and update(hehe, its gameplay is good) please....

This is all for now. Hope you are satisfied with this tutorial. As usual, contact me if I make any mistake, give me your feedback, comments, suggestions and opinions about this tutorial and my way of presenting it.

Extra notes:
A very interesting protection, at least, it was, in year 1997, I think. Though quite easy for many of us now, it shall serve as a good learning and entertainment target for some newbies out there(and gamers, hehe). Hope this is not too lame and at least taught you a little new thing(assuming you are newbie)...


Ending:
Thanks and greetz 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(Death), 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, llama and other crackers, individuals and organisations who have helped me, either directly or indirectly.

Service for Mankind
ManKind
mankind001@bigfoot.com