home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Hackers Toolkit v2.0
/
Hackers_Toolkit_v2.0.iso
/
HTML
/
archive
/
Texts
/
cracking
/
odin-ct151.txt
< prev
next >
Wrap
Text File
|
1999-11-04
|
19KB
|
469 lines
odin's_________ _______ ______ _____________
____\ /____\ /________\ /____| /_____/_______ _________
/ _____/ _____/ __ ___/ '____/ / | \ _____/___
/ | \ || | | | \ . \ | | | \__ /
\_____ \___| \____ |____ \___| \___|____| |_____ |
|_______/ <hook> `----' |_____/ |______/ |____| |_____|
tutorial v1.51
Cracking/Patching SoftArt's Deskey v1.02.010
X. TABLE OF CONTENTS
1. FOREWARDS
2. INTRODUCTION
3. TOOLS USED FOR THIS
4. THE CRACKING STARTS
5. MAKING A PATCH
6. THE URL'S
1. Forewards
Welcome. So how come you're interested in reading this tutorial?
Perhaps you think cracking is cool and seems easy, and that cracking
is a way to be famous on the internet today. Well, if you think like
this please stop reading now. Why? Mainly because most crackers don't
crack because they think it's "cool." and want to be famous. Cracking
is something they actually do because they think its a great thing to
spend their precious time on, believe it or not. Most crackers, not to
say all, also code in one or several computer languages.
On the other hand if you're very interested in how computers work
internally, and you like to program in languages like Pascal, C++ and
Assembler, then I believe this tutorial is worth reading for people
such as you, and you might even learn something from it.
If you're the third category, you've been learning cracking for some
time now and read every little article about cracking you can get,
then this tutorial also is very good to read. You can always learn
something that you didn't know before. Even I can learn things I
didn't know by listening to others and reading various text files.
To become a cracker will take several years. And to become a good
cracker will take even longer. The key to success is practice and, in
my point of view, learning and listening to other crackers.
I'll skip the most things about how SoftICE works because there are
several good tutorials out about that. One is Exact's SoftICE
tutorial, very good and recommended reading.
2. Introduction
This text files purpose is to show and hopefully learn you how to
patch away a time limit of a program. The program we will use is
SoftArt's Deskey. It isn't necessary to patch this program because you
can also enter a registration code in the registry to get the program
to work fully, but then you have to write a keymaker because the code
depends on the Windows name and company (the one you enter when you
installed Windows 95). So we're going to do it the lazy way and patch
it. There are of course other ways to do this crack.
3. Tools you will need for this
(1) SoftICE 2.0/3.0, of course, our beloved debugger.
(2) Ultra Edit or another good hex editor.
(3) A patch generator, or if you write the patch yourself as I do.
4. The cracking starts
Ok, let's begin with removing the semicolon from the user32.dll and
kernel32.dll lines in SOFTICE.DAT if you haven't done so already.
Now let's do some detective work, by checking the Deskey help file.
You'll notice that this program will stop working after 60 minutes.
This limit is what we're going to remove. There are a few possible
solutions for the programmer to obtain this limit. To check which
functions the program use, let's test the approach Qapla used in his
tutorial:
Start the explorer and press the right mouse button on the Deskey exe
file. Now choose Quick-View. You'll notice all the calls the program
uses and which dll's store the code for the calls. When you look at
them, you'll notice some interesting functions.
Import Table
...
KERNEL32.dll
Ordinal Function Name
... ...
008f FreeLibrary
0188 MultiByteToWideChar
011d GetSystemTime <----- Interesting
00e4 GetLocalTime <----- Interesting
025d lstrcmpiA
00ca GetDateFormatA
... ...
USER32.dll
Ordinal Function Name
... ...
00ec GetDlgItemTextA
007d DefWindowProcA
01fe SetTimer <----- Interesting
01a2 PostMessageA
0224 TrackPopupMenu
01b8 RemoveMenu
... ...
Ok, as you see I'm interested in 3 different calls. We can try to see
if the program uses KERNEL32!GetSystemTime(); and
KERNEL32!GetLocalTime();. Enter SoftICE and put a breakpoint on these
two. Enable them just when you're about to start the program. If you
do it before, you risc to break on these calls used by another
program. So just before you start Deskey, enable these.
Now you started it and program pops up in the traybar. Nothing
happens. Oh well, then we can exclude these ones. Actually a cracker
might have excluded them from the beginning and tried some other calls
first. Why? Probably because a programmer usually uses these calls if
the program has a 30-day limit, not a 60-minutes one.
We have one left to test, USER32!SetTimer();. Exit Deskey and put a
breakpoint on SetTimer(); just before you start Deskey.
Finally, SoftICE detected the use of this function by Deskey. Press
F11. It should look something like this now:
.
.
.
0137:0040397F 833D1890400000 CMP DWORD PTR [00409018], 00
0137:00403986 7409 JZ 00403991
0137:00403988 833D1C90400000 CMP DWORD PTR [0040901C], 00
0137:0040398F 7421 JZ 004039B2
0137:00403991 6A00 PUSH 00
0137:00403993 A128904000 MOV EAX,[00409028]
0137:00403998 6880EE3600 PUSH 0036EE80
0137:0040399D 6834120000 PUSH 00001234
0137:004039A2 50 PUSH EAX
0137:004039A3 FF158CB44000 CALL [USER32!SetTimerA] <-- you're here
0137:004039A9 8BBC24AC060000 MOV EDI,[ESP+000006AC]
0137:004039B0 EB12 JMP 004039C4
0137:004039A9 8BBC24AC060000 MOV EDI,[ESP+000006AC]
0137:004039B0 EB09 JMP 004039C4
0137:004039A9 8BBC24AC060000 MOV EDI,[ESP+000006AC]
0137:004039B0 EB07 JMP 004039CB
.
.
.
Let's check the SetTimerA function in our we-cant-be-without-it API
guide:
The SetTimer function creates a timer with the specified time-out value.
UINT SetTimer(
HWND hwnd, // handle of window for timer messages
UINT idTimer, // timer identifier
UINT uTimeout, // time-out value
TIMERPROC tmprc // address of timer procedure
);
.
.
.
uTimeout
Specifies the time-out value, in milliseconds.
.
.
.
Aha, let's check on the code again:
0137:00403991 6A00 PUSH 00 <-- tmprc
0137:00403993 A128904000 MOV EAX,[00409028] <-- pushed later
0137:00403998 6880EE3600 PUSH 0036EE80 <-- uTimeout
0137:0040399D 6834120000 PUSH 00001234 <-- idTimer
0137:004039A2 50 PUSH EAX <-- HWND
0137:004039A3 FF158CB44000 CALL [USER32!SetTimerA] <-- you're here
Hmm, very interesting indeed, let's check the value 0036EE80 in the
SoftICE debugger:
:? 36ee80
0036EE80 0003600000 "6»╟"
An even and nice value. And if you read further in the API help file
you'll notice that the uTimeout should be in milliseconds. 1 second is
1000 milliseconds. Let's do some calculating:
3600000/1000=3600 seconds.
60 seconds*60 minutes=3600 seconds, which is 1 hour
We've found the right one! This call creates a timer which will be
checked when the program process the WM_TIMER message from Windows.
The WM_TIMER message is sent when 1 hour has past. Let's check the API
reference once more:
WM_TIMER
wTimerID = wParam; // timer identifier
tmprc = (TIMERPROC *) lParam; // address of timer callback
The WM_TIMER message is posted to the installing thread's message
queue or sent to the appropriate TimerProc callback function after
each interval specified in the SetTimer function used to install a
timer.
.
.
.
So now we know where he creates the timer. If you remove this
SetTimer(); call the WM_TIMER message will never be sent, resulting in
that the 60 minute limit will be REMOVED!! Let's take a look at this
example code below:
SetTimer(hwnd, idTimer, 0x36EE80, tmprc);
^-- hex value
WM_TIMER: { <-- this structure is reached when
PostQuitMessage(0); the hex value above reach 0. If
^-- will exit the program the timer never is set this
} structure wont be reached.
This is very simple to understand, I hope :-).
So perhaps you think, "hey, let's NOP away the whole structure"
(for those of you not familiar with NOP: it means NO OPERATION
and are very commonly used when patching. The computer will do
nothing when it executes this instruction.)
Nono stop! Don't NOP away the whole call. Well first of all a good
rule when patching is that, never alter the code more then you
actually need. It looks nice (who'll notice anyway), and it decreases
the chance of program crash due to doing something stupid. So how
should we do instead? Well let's check that code once more:
.
.
.
0137:0040397F 833D1890400000 CMP DWORD PTR [00409018], 00
0137:00403986 7409 JZ 00403991
0137:00403988 833D1C90400000 CMP DWORD PTR [0040901C], 00
0137:0040398F 7421 JZ 004039B2
0137:00403991 6A00 PUSH 00
0137:00403993 A128904000 MOV EAX,[00409028]
0137:00403998 6880EE3600 PUSH 0036EE80
0137:0040399D 6834120000 PUSH 00001234
0137:004039A2 50 PUSH EAX
0137:004039A3 FF158CB44000 CALL [USER32!SetTimerA] <-- you're here
0137:004039A9 8BBC24AC060000 MOV EDI,[ESP+000006AC]
0137:004039B0 EB12 JMP 004039C4
0137:004039A9 8BBC24AC060000 MOV EDI,[ESP+000006AC]
0137:004039B0 EB09 JMP 004039C4
0137:004039A9 8BBC24AC060000 MOV EDI,[ESP+000006AC]
0137:004039B0 EB07 JMP 004039CB
.
.
.
The CMP (compare) instructions above seems very interesting.
As you might notice, the one at 00403986 will jump to 00403991 and
start the timer. If you check the JZ at 0040398F it will go to
004039B2 and therefor jump over the timer, resulting in that there
will be no time limit. So to solve this simple problem just change the
JZ 00403991 at 00403986 to JMP 004039B2 instead. Like this:
0137:00403986 7409 JZ 00403991
---> to --->
0137:00403986 EB2A JMP 004039B2
Now let's apply the patch to the exe file. Load up your favorite hex
editor. In this case I'll use Ultra Edit. Now load the exe file.
Choose search and enter the following bytes: 68 80 EE 36 00.
So why do we search after these? Well that's very easy. Check the code
once again:
0137:00403993 A128904000 MOV EAX,[00409028]
0137:00403998 6880EE3600 PUSH 0036EE80 <--- this one
0137:0040399D 6834120000 PUSH 00001234
As you see these bytes stands for the instruction PUSH 0036EE80.
"Uhu, I don't have those cryptic numbers to the left of my
instructions!!". Well that's easy to fix. Just write 'code on' and
you'll see these cryptic numbers, also known as OPerand codes.
"Why didn't you search 83 3D 18 90 40 00 00 for example?". Well that's
because I know the ones we searched for only exists one time in the
exe file. The one mentioned above (83 3D...) exists several times, so
you cannot actually know which of those to use, if you don't check the
surrounding bytes that is. Always do "search next" so you are sure
that that byte combination doesn't exist somewhere else in the file.
Now let's change the bytes needed. Some bytes above '68 80 EE 36 00'
you will find '74 09' which is the JZ 00403991 instruction. This is
the two bytes we want to change. So how do you know which numbers to
actually change to? That's also easy. In the debugger when you're
looking at the code just use the 'a' command. Like This:
0137:0040397F 833D1890400000 CMP DWORD PTR [00409018], 00
0137:00403986 7409 JZ 00403991
0137:00403988 833D1C90400000 CMP DWORD PTR [0040901C], 00
----------------------------------------^ code window ^ -----
:a 00403986 JMP 004039B2
----------------------------------------^ prompt ^-----------
This will change the instruction at 00403986 and a new code will pop
up, EB2A. So this is the code you want to change for the 7409 one.
Remember, that if you use the 'a' command it will not change the code
permanently, only temporary. That's why we have to use a hex editor.
So go to the '74 09' bytes and change it to 'EB 2A'.
Now save the exe file, voila! That's it. Now start the program up and
test if it works. If SoftICE doesn't break on SetTimer(); it probably
worked. If it does, read this all again :-).
One thing has to be said also. If you for example want to change a
instruction with the opcode 'C1 E1 10' (3 bytes) to a instruction that
only has a 2 byte opcode, for example '0B D1', you have to NOP away
the last byte. NOP has the hex value 90.
Like this:
C1 E1 10 becomes ---> 0B D1 90
SHL ECX, 10 becomes ---> OR EDX, ECX <- 0B D1
NOP <- 90
As you see I change the F3 to 90 and therefore put the instruction NOP
there. If you didn't do this the chance of a program crash would be
98%.
That's all. To patch is very simple, but to find the bytes to change
is harder. Remember that the byte combination can exist somewhere else
so check the surrounding bytes.
5. Making the patch
Now it's time to make this patch available to the public. To write
something like "uhu change the bytes at blabla to blabla" doesn't look
that good, does it? So now it's time to make a exe file that changes
those bytes asap so the user don't have to use Ultra Edit every time.
I've included a program in Pascal done for this task. There are also
several good patch generators.
One for Windows 95, that I strongly recommend, is Qapla's PatchIt '97.
It's fast and nice interface (happy now Qapla :-)
To convert this program to C++ should be easy. You have to know one
more thing to make a patch, where the bytes are located in the file.
This is called "offset.", to check the offset just go to the bytes you
changed, and look at the status bar in Ultra Edit, it should say the
offset (pos) in hex.
I did the patch in Turbo Pascal 7, most would probably do it in Asm
:). Anyway, here is the patch:
---------------------------------------------------------------------
---------------------------------------------------------------------
Program Patcher;
Uses Crt;
Const offset : Longint = $2D86; { $ means a hex value }
bytes : Byte = 2;
len : Longint = 51200; { file length }
orgbytes : Array[1..2] Of Byte = ($74, $09);
newbytes : Array[1..2] Of Byte = ($EB, $2A);
{---------------------------------------------------------}
filename : String[12] = 'DESKEY.EXE';
errnof : String[43] = ' ERROR: File DESKEY.EXE was not found.';
errver : String[36] = ' ERROR: File size is not correct.';
errpch : String[36] = ' ERROR: File seems to be patched.';
msgdon : String[21] = ' Patch successful!';
ask : String[26] = ' Continue anyway? (Y/N)';
Procedure message(message : String);
Begin
WriteLn;
WriteLn(message);
Halt;
End;
Procedure patchfile;
Var fil : File Of Byte;
teck : Byte;
n : Byte;
ch : Char;
Begin
Assign(fil, filename);
{$I-}
Reset(fil);
{$I+}
If (Not(IOResult=0)) Then message(errnof);
If (Not(FileSize(fil)=len)) Then
Begin
WriteLn;
WriteLn(errver);
WriteLn(ask);
Repeat Until Keypressed;
ch:=ReadKey;
If Upcase(ch)='N' Then Halt;
End;
Seek(fil, offset);
For n:=1 To bytes Do
Begin
Read(fil, teck);
If (Not(teck=orgbytes[n])) Then message(errpch);
End;
Seek(fil, offset);
For n:=1 To bytes Do Write(fil, newbytes[n]);
Close(fil);
WriteLn;
WriteLn(msgdon);
Halt;
End;
Begin
WriteLn;
WriteLn(' SoftArts Deskey v1.02.010 Patch');
WriteLn(' By ODIN / RBS^TFT^PIE in 1997');
patchfile;
End.
---------------------------------------------------------------------
---------------------------------------------------------------------
Some final words.
Take some programs and play with patching them in various ways. This
gives you experience, and hopefully you'll become a better cracker.
Thanks to Qapla, kOUGER, Hook and Tgunner for help while making this
tutorial.
A special greeting goes to ED!SON.
6. THE URL'S
My E-Mail : cracking@usa.net
SoftArts Deskey v1.02.010 : http://www.spiresoft.com
Ultra Edit vX : http://www.windows95.com/apps/