New 2 Cracking
~~~~~~~~~~~~~~

Tutorial Type  : Tutorial
Tutorial Topic : FaNt0m's 6th Crackme (keyfile)
Written by     : ParaBytes (the one and only :)))
Date           : Jan. 31th, 2002.
Music          : Bob Marley, Natural Mystic Track #15
Utilities      : W32Dasm/Notepad/Some basic math knowledge (VERY BASIC !)
Remarks        : The Crackme can be found in http://fant0m.cjb.net
                 The Notepad can be found with Windows, but any other editor can be usefull...

Prologue :
----------

ok, my 2nd tutorial on fant0m's crackmes today (the 1st was Keygen Injection ;p)
lets see what are we dealing with,
keyfile protection, really ?
ok, lets check it out....

Chapter I - "The Check" :
-------------------------

open up, hmmm, Key file not found!
well, i know, i have no keyfiles in the area, so lets dasm it with w32dasm...

open up the sdr (string data reference), select the bad boy message,
scroll up a bit, you see 

* Possible StringData Ref from Data Obj ->"keyfile.dat"   <-----------------------------\
                                  |                                                     |
:004010F3 6817304000              push 00403017                  // push the file name -/

* Reference To: KERNEL32.CreateFileA, Ord:0032h
                                  |
:004010F8 E8BD000000              Call 004011BA                  // CreateFileA (file is present ?)
:004010FD A388304000              mov dword ptr [00403088], eax  // move the File Handle into mem
:00401102 83F8FF                  cmp eax, FFFFFFFF              // eax=-1 ?
:00401105 7514                    jne 0040111B                   // if not, then file is here, jmp 

before we continue, let me explain the createfile thing,
if you check the other pushes you'll see that the computer will try to createfile,
if the return value is -1 (FFFFFFFFh) the file is not exist, so you cant use it...
(further help on CreateFileA you can find in win32.hlp and MSDN Files, i dont know much
 about files stuff, just the basics...)

ok, we can learn that,
keyfile is called keyfile.dat
and the file handle is stored into 00403088h as memory address...

lets roll into the jump and assume that keyfile is present...

ok, we see :

:0040111B 6A00                    push 00000000                // NULL Parameter, Ignored.
:0040111D 6896304000              push 00403096                // Address of the file
:00401122 6A0A                    push 0000000A                // Read 10 bytes into the file
:00401124 688C304000              push 0040308C                // Address of bytes we read
:00401129 FF3588304000            push dword ptr [00403088]    // File Handle

* Reference To: KERNEL32.ReadFile, Ord:01FDh
                                  |
:0040112F E898000000              Call 004011CC                // Call to ReadFile
:00401134 83F800                  cmp eax, 00000000            // if return <> 0
:00401137 7515                    jne 0040114E                 // jump... else, you can see yourself

so,

  
 BOOL ReadFile( 
  
     HANDLE    hFile ,    	                 // handle of file to read     
     LPVOID    lpBuffer ,    	                 // address of buffer that receives data      
     DWORD    nNumberOfBytesToRead ,    	 // number of bytes to read     
     LPDWORD    lpNumberOfBytesRead ,    	 // address of number of bytes read     
     LPOVERLAPPED    lpOverlapped      	         // address of structure for data     
    );    	    
 
so the last in was the file handle,
before it was the memory address of the current keyfile,
very important, write that thing on a paper...

Chapter II - "Surprises !" :
----------------------------

roll into the jump and assume the read went fine
"well surprise surprise !" (fat bastard, austin powers II)

:0040114E 8D158C304000            lea edx, dword ptr [0040308C]         // set the start of file
:00401154 83C205                  add edx, 00000005                     // 5th byte from start
:00401157 803A31                  cmp byte ptr [edx], 31                // that byte=31h (1 ascii) ?
:0040115A 7510                    jne 0040116C                          // if not, go there ---------\
:0040115C 83C203                  add edx, 00000003                     // 3 more bytes              |
:0040115F 803A33                  cmp byte ptr [edx], 33                // that byte=33h (3 ascii) ? |
:00401162 7508                    jne 0040116C                          // if not, go there ---------|
:00401164 42                      inc edx                               // next byte                 |
:00401165 803A30                  cmp byte ptr [edx], 30                // this byte=30h (0 ascii) ? |
:00401168 7402                    je 0040116C                           // if does, go there --------|
:0040116A EB15                    jmp 00401181                          // go over badboy message    |
                                                                                                     |
* Referenced by a (U)nconditional or (C)onditional Jump at Addresses:                                |
|:0040115A(C), :00401162(C), :00401168(C)                               // got here, 3 jump <--------/
|
:0040116C 6A10                    push 00000010                         

* Possible StringData Ref from Data Obj ->"Error!"
                                  |
:0040116E 6823304000              push 00403023                         // push strings

* Possible StringData Ref from Data Obj ->"Invalid key!"
                                  |
:00401173 6852304000              push 00403052                         // push strings
:00401178 6A00                    push 00000000                         

* Reference To: USER32.MessageBoxA, Ord:01BBh
                                  |
:0040117A E82F000000              Call 004011AE                         // show messagebox
:0040117F EB15                    jmp 00401196                          // go over goodboy message

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:0040116A(U)                                                           // start of good boy mesage
|
:00401181 6A40                    push 00000040                         

* Possible StringData Ref from Data Obj ->"Correct!!!"
                                  |
:00401183 6876304000              push 00403076                         // push string

* Possible StringData Ref from Data Obj ->"Correct key! Good job!"
                                  |
:00401188 685F304000              push 0040305F                         // push string
:0040118D 6A00                    push 00000000                         

* Reference To: USER32.MessageBoxA, Ord:01BBh
                                  |
:0040118F E81A000000              Call 004011AE                         // you know this one :)
:00401194 EB00                    jmp 00401196                          // goto next instrution (ignored)

well, we can we learn ?

lets set the file into array of bytes called a, so a[i] will be byte i, it will make it easier..

a[5]     == '1'
a[5+3=8] == '3'
a[8+1=9] <> '0'

so, open up the editor you selected, insert :
111113333
and save as keyfile.dat (the file name, go look on the tutorial start ;p)

but, behold, the keyfile is invalid !!!!
godamnit ! the son of a bi**h !!! we hate him !!!
WRONG ! we dont !!!
many people never noticed but there is something called Byte-Zero, its the 1st byte that people
tend to ignore, when edx got the file data, he didnt got it as the byte-before-data-starts
he got it on the 1st byte of data,
so to fix it, we need to add 1 byte to each selected char, so
0111113333 will do the job !
change, save, check, be happy !!!

a keyfile, fully working !!!!
we can create a keyfile generator, we know that the array is 10 bytes read, so its useless to write more
we can do, array of random numbers
but, its gonna be like this,

Chapter III - "Why its have to end ?!?!?" :
-------------------------------------------

(pascal/delphi code)
(data is array of 10 chars)
Randomize
data[0] := Chr(Random[10]+$30);
data[1] := Chr(Random[10]+$30);
data[2] := Chr(Random[10]+$30);
data[3] := Chr(Random[10]+$30);
data[4] := Chr(Random[10]+$30);
data[5] := Chr(Random[10]+$30);
data[6] := Chr($31);
data[7] := Chr(Random[10]+$30);
data[8] := Chr(Random[10]+$30);
data[9] := Chr($33);
data[10]:= Chr(Random[9]+$31); (* never be 0, but can be anything *)

do it, save it as text file named keyfile.dat, and you done..

Epilogue :
----------

This keyfile protection was, to be honest, lame, real keyfiles always check for sum of keyfile/
decryption of code in keyfile, and the size, 
but since keyfiles is not easy for newbies (i never learnt it well) i guess this is
an excellent crackme, so keep on the good work !

People that i greet :
---------------------

FaNt0m, Invoker, PhANt0m, ThrawN, iNSiGHT Crew, tKC, krobar, other publisher,
GodsJiva, sinny, Dawai, URSoft, Borland (Inprise), #New2Cracking ppl, Anvile, death,
ThE-SAiNt, DR '0ld $c#00l' ppl (you know yourself ;p), Kwazy Webbit, people who read this,
GogaMoga, dCe, PhoX, necrotoad, DarkMoon, Bob Marley & The Wrailers, all the tutorials writers,
some .nl dudes (they are many many names, so i wont mention anyone, except the guy i mentioned already),
and more and more and more and more (etc..)

Getting in Touch With Me :
--------------------------

E-Mail : Lewsers@Hotmail.com
IRC    : EFNet / #New2Cracking
Here ;p

as i said, New 2 Cracking site is down atm, but soon, 
we will have a new one, i will make you know :)

ParaBytes, Shake-Spear !

