2267 lines
88 KiB
Plaintext
2267 lines
88 KiB
Plaintext
|
|
The Cracking Manual
|
|
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
|
|
Written By The Cyborg - April 3, 1992
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Disclaimer
|
|
The author of this text shall hold no liability for special,
|
|
incidental, or consequential damages arising out of or
|
|
resulting from the use/misuse of the information in this
|
|
file.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
The Cracking Manual
|
|
|
|
|
|
|
|
INTRODUCTION
|
|
|
|
Introduction
|
|
------------
|
|
Welcome to the wonderful world of cracking. What is
|
|
cracking? If you don't know and you're reading this, ask
|
|
yourself why? Anyway, cracking is the art of removing copy
|
|
protected coding from programs. Why do this? In recent
|
|
years, software companies have been fighting to keep copy
|
|
protection in their software to avoid their work to be
|
|
illegally copied. Users feel that such copy protection is
|
|
ridiculous in that it violate their own rights to make
|
|
backups of their sometimes expensive investments.
|
|
Whichever side you may favor, this manual will go into
|
|
some detail on removing copy protection from programs. If
|
|
you feel offended by this, then I would suggest you stop
|
|
here. Please note, I do not endorse cracking for the illegal
|
|
copying of software. Please take into consideration the hard
|
|
work and effort of many programmers to make the software.
|
|
Illegal copying would only increase prices on software for
|
|
all people. Use this manual with discretion as I place into
|
|
your trust and judgement with the following knowledge.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Page 1
|
|
|
|
|
|
|
|
|
|
|
|
The Cracking Manual
|
|
|
|
|
|
|
|
WHAT YOU WILL NEED
|
|
|
|
What You Will Need
|
|
------------------
|
|
Like all programming, cracking is the debugging stage of
|
|
software development. It is the most tedious and hectic part
|
|
of programming as you shall see. However, unlike software
|
|
development, you are given no source code, only the machine
|
|
level code commonly called machine language. Cracking
|
|
demands patience. No patience, no cracking.
|
|
Before we begin, you will need certain tools. These
|
|
include:
|
|
|
|
- A decent computer. By this, I mean at minimum a 286
|
|
computer with 2 or more megs of RAM. A 386 is the
|
|
ideal since it can load a debugger into usable memory.
|
|
- A source level debugger (eg. Turbo Debugger)
|
|
- A low level debugger (eg. DEBUG)
|
|
- An assembler system (eg. MASM, LINK, EXE2BIN)
|
|
- A hex dumping program (eg. Norton Utilities)
|
|
|
|
The source level debugger is what you will try to be using
|
|
most of the time. It provides many features that are a
|
|
convenience to the cracker, such as interrupt redirection.
|
|
Become comfortable with its features. However, in some
|
|
instances, the source level debugger may not be suitable for
|
|
cracking huge games since the debugger itself may take up too
|
|
much memory. In such a case, a low level debugger must be
|
|
used since their memory usage may be considered negligible.
|
|
This manual will focus on its use.
|
|
The assembler package will be used in the creation of
|
|
the famed loaders, which provide the cracker with dynamic
|
|
memory alterations without changing the original program.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Page 2
|
|
|
|
|
|
|
|
|
|
|
|
The Cracking Manual
|
|
|
|
|
|
|
|
CRASH COURSE IN ASSEMBLY LANGUAGE
|
|
|
|
Crash Course in Assembly Language
|
|
---------------------------------
|
|
If you are already well familiar with the assembly
|
|
language, you may wish to skip this section. Cracking
|
|
demands the knowledge of assembly language. If you wish to
|
|
become a "serious" cracker, you might like to read up more
|
|
about this fascinating language. This section will only give
|
|
you enough info for intermediate level cracking.
|
|
At this point, you should familiarize yourself with
|
|
DEBUG and its commands as we will be using them shortly.
|
|
|
|
Registers
|
|
---------
|
|
One of the neato things that you will be fooling around
|
|
most often with are called the registers. Registers are like
|
|
variables (such as in BASIC) that are located within the CPU
|
|
itself. These registers may hold a positive integer from 0
|
|
to 255 or from 0 to 65535. They can also hold negative
|
|
integers from -128 to 127 or from -32768 to 32767. The
|
|
registers are given names as follows:
|
|
|
|
AX => accumulator - this register is most commonly used
|
|
for mathematical or I/O operations
|
|
BX => base - this register is used commonly as a base or
|
|
a pointer register (we'll talk more about this
|
|
later)
|
|
CX => count - used commonly for counting instructions
|
|
such as loops
|
|
DX => displacement - much like the base register
|
|
|
|
The registers stated above are considered general purpose
|
|
registers, since they can basically be used to store whatever
|
|
the user wants. Let's try putting some number in these
|
|
registers. Type in "R {enter}". You should see a bunch of
|
|
info, of which are four of the above mentioned registers.
|
|
Now, type in "RAX {enter}". Then type in a number like
|
|
8FABh. Type in "R" again and noticed how the accumulator
|
|
(AX) has change its number.
|
|
These general purpose registers can also be "split" in
|
|
half into its higher and lower order components. Instead of
|
|
having one register AX, you can have two registers, AH and
|
|
AL. Note however that while you have a range of 0 to FFFFh
|
|
for AX, you will now have a range of 0 to FF for AH and AL.
|
|
You cannot change these directly in debug, but be aware that
|
|
programs will use it. If AX contains 0A4Ch, then AH will
|
|
contain 0Ah and AL will contain 4Ch.
|
|
The following are called the segment registers:
|
|
|
|
CS => code segment - the block of memory where the code
|
|
(instructions are located)
|
|
DS => data segment - the block of memory where data can
|
|
be accessed. In block move operations in which
|
|
|
|
|
|
Page 3
|
|
|
|
|
|
|
|
|
|
|
|
The Cracking Manual
|
|
|
|
|
|
|
|
huge blocks of memory are moved, this is commonly
|
|
the segment in which the CPU reads from.
|
|
ES => extra segment - also another data segment. In
|
|
block move operations in which huge blocks of
|
|
memory are moved, this is commonly the segment in
|
|
which the CPU writes to.
|
|
SS => stack segment - this is the block of memory in
|
|
which the CPU uses to store return addresses from
|
|
subroutines. (more on this later)
|
|
|
|
In introductory level of cracking, we don't mess around with
|
|
these registers. Later, we will see how we can use these to
|
|
trick a program into thinking other things, but that's later.
|
|
You can also change these registers in debug. Type in "RCS
|
|
{enter}". Then enter "0 {enter}" and notice how the CS
|
|
register changed.
|
|
There are other registers that we use to see what the
|
|
program is doing. These registers can also be change in
|
|
debug. Included are the following:
|
|
|
|
SI => source index - this register is used in
|
|
conjunction with block move instructions. This is
|
|
a pointer within a segment (usually DS) that is
|
|
read from by the CPU.
|
|
DI => destination index - this register is also used in
|
|
conjunction with block move instructions. This is
|
|
a pointer within a segment (usually ES) that is
|
|
written to by the CPU.
|
|
BP => base pointer - a pointer used commonly with the
|
|
stack segment
|
|
SP => stack pointer - another pointer used commonly with
|
|
the stack segment (this one, you don't touch)
|
|
|
|
By now, you may probably be confused about this
|
|
segment/pointer bit. Here is an analogy that my straighten
|
|
things out.
|
|
Pretend you are in kindergarden learning to read. There
|
|
are four black boards surrounding the room. These black
|
|
boards are like SEGMENTS. Let's pretend the front blackboard
|
|
is the code segment (CS). The teacher has written some
|
|
instructions on pronunciation rules. This is what the
|
|
students refer to when they try to pronounce words. In a
|
|
program, this is what the CPU refers to when it follows
|
|
directions.
|
|
Okay, now the teacher has gone to the blackboard on the
|
|
left of the classroom. We will call this board the data
|
|
segment (DS). The teacher has also written a set of words on
|
|
the board. Then she uses a wooden stick or a POINTER to
|
|
point to a word. Let's pretend this stick is the source
|
|
index (SI). She points to the word "their". Now, the
|
|
students look at the front blackboard (CS) to see how to
|
|
pronounce the word and they say "their".
|
|
Now, the instructor wants the students to learn how to
|
|
write. She points the stick to the word "apple". The
|
|
|
|
|
|
Page 4
|
|
|
|
|
|
|
|
|
|
|
|
The Cracking Manual
|
|
|
|
|
|
|
|
students pronounce the word. Then she goes to the blackboard
|
|
on the right. We shall call this one the extra segment (ES).
|
|
She then uses her finger as a different POINTER and points to
|
|
a location on the board where Mary Jane will write "apple".
|
|
That's basically what segments and pointers are.
|
|
Segments are the blackboards and pointers are the teacher's
|
|
stick (we're not talking sexually here) or finger.
|
|
One last important register is the flags register.
|
|
These registers control how certain instruction work, such as
|
|
the conditional jumps (in BASIC, they are like IF-THEN's).
|
|
They are stored as bits (0's or 1's) in the flags register.
|
|
We will most often use:
|
|
|
|
zero => ZR/NZ (zero/not zero) - tells you whether an
|
|
instruction (such as subtraction) yielded a zero
|
|
as an answer
|
|
sign => NG/PL (negative/positive) - tells you whether an
|
|
instruction yielded a positive or negative
|
|
number
|
|
carry => CY/NC (carry/no carry) - tells you whether an
|
|
instruction needed to carry a bit (like in
|
|
addition, you carry a number over to the next
|
|
digit). Various system (BIOS) functions use
|
|
this flag to denote an error.
|
|
direction => DN/UP (decrement/increment) - tells a block
|
|
instruction to either move forward or backwards
|
|
in reads and writes
|
|
|
|
Try changing some of these bits. Type in "RF {enter}". Then
|
|
type in "DN {enter}" to change the direction flag to its
|
|
decrement position.
|
|
|
|
The Instructions
|
|
----------------
|
|
|
|
MOV - move
|
|
----------
|
|
Now we get to the actual instructions or commands that
|
|
the CPU will use. The first instruction you will see most
|
|
often is the move instruction. Its form is
|
|
MOV {destination},{source}. Let's try programming now. Exit
|
|
(q) and reenter debug again. Now, type in "A {enter}". You
|
|
will see a bunch of number to the left. You can think of
|
|
these as line numbers. Now type in "MOV AX,7A7A {enter}".
|
|
Then type "MOV DX,AX" and so on until your program looks
|
|
similar to the one below: (type "U 100" to see)
|
|
|
|
xxxx:0100 B8A77A MOV AX,7AA7
|
|
xxxx:0103 89C2 MOV DX,AX
|
|
xxxx:0105 B90000 MOV CX,0000
|
|
xxxx:0108 88D1 MOV CL,DL
|
|
xxxx:010A 890E0005 MOV [0500],CX
|
|
xxxx:010E 8B160005 MOV DX,[0500]
|
|
xxxx:0112 BB0200 MOV BX,0002
|
|
|
|
|
|
Page 5
|
|
|
|
|
|
|
|
|
|
|
|
The Cracking Manual
|
|
|
|
|
|
|
|
xxxx:0115 26A30005 MOV ES:[0500],AX
|
|
|
|
Press enter again until you see the "-" prompt again. You
|
|
are ready to run your first program. Type "R {enter}" and
|
|
note the values of the general purpose registers. Then type
|
|
in "T {enter}". Debug will automatically display the
|
|
registers after the execution of the instruction. What is in
|
|
the AX register? It should be 7AA7h. Now, "T" again. What
|
|
is in the DX register? It should also be 7AA7h. Trace again
|
|
using "T" and note that CX should be 0 if it was not already.
|
|
Trace again and note what is in the CX register. It should
|
|
be 00A7h. Now trace another step. What is this instruction
|
|
doing? It is now moving the contents of CX into memory
|
|
location 500h in the data segment (DS). Dump the memory by
|
|
typing in "D 500". The first two two-digit numbers should be
|
|
the same as in the CX register. But wait a minute you say.
|
|
They are not the same. They are backwards. Instead of
|
|
00A7h, it is A700h. This is important. The CPU stores 16
|
|
bit numbers in memory backwards to allow for faster access.
|
|
For 8 bit numbers, it is the same. Now, continue tracing.
|
|
This instruction is moving the memory contents of address
|
|
500h into the DX register. DX should be 00A7h, the same as
|
|
CX regardless of how it looked in memory. The next trace
|
|
should be nothing new. The next trace again moves the
|
|
contents of a register into memory. But notice it is using
|
|
the BX register as a displacement. That means it adds the
|
|
contents of BX and 500h to get the address, which turns out
|
|
to be 502h. But also not the "ES:" in front of the address.
|
|
This additional statement tells the CPU to use the extra
|
|
segment (ES) rather than the data segment (DS which is the
|
|
default). Now dump address 502h by entering "D ES:502" and
|
|
you should see A77Ah, which is backwards from 7AA7h.
|
|
|
|
CMP/J? - compare/conditional jump
|
|
---------------------------------
|
|
Another instruction you will see quite often is the CMP
|
|
or compare instruction. This instruction compares the two
|
|
"variables" and changes the flags register accordingly. The
|
|
source and destination operands are the same as those for the
|
|
move instruction.
|
|
Let's consider an example in which the AX register holds
|
|
21 and the BX register holds 22. Then "CMP AX,BX" is
|
|
performed. The compare instruction is like a subtraction
|
|
instruction, but it doesn't change the contents of the AX
|
|
register. So, when 22 is subtracted from 21, the answer will
|
|
be -1, but we will never see the answer, only the flags which
|
|
have resulted from the operation. Number 21 is less than 22,
|
|
so the carry flag and the sign flag should be set. Just
|
|
remember that when the carry flag is set, the first number is
|
|
less than the second number. The same is true for the sign
|
|
flag. Why have two flags if they tell us the same thing?
|
|
This is more complicated and you should not concern yourself
|
|
with it. It requires knowledge of hexadecimal arithmetic,
|
|
the denotation of signed and unsigned integers.
|
|
|
|
|
|
Page 6
|
|
|
|
|
|
|
|
|
|
|
|
The Cracking Manual
|
|
|
|
|
|
|
|
So, now that we have done the compare instruction, there
|
|
will most likely be a conditional jump instruction after. If
|
|
we wanted to jump if AX is less than BX (which it is), then
|
|
there would be an instruction like "JB 200". This
|
|
instruction says Jump if Below to instruction 200h. What
|
|
about if we wanted to jump if AX is greater than BX. Then we
|
|
might have "JA 200". This is read Jump if Above to
|
|
instruction 200. What about AX equal to BX. We would then
|
|
have "JZ 200" or "JE 200". (Please note that the previous
|
|
instructions are synonymous.) This is read Jump if Equal to
|
|
instruction 200h. Here are the jumps you will most likely
|
|
encounter:
|
|
|
|
Mnemonic Flag(s) Checked Description
|
|
-------------------------------------------------------------
|
|
JB/JNAE CF=1 Jump if below/not above or
|
|
equal (unsigned)
|
|
JAE/JNB CF=0 Jump if above or equal/not
|
|
above (unsigned)
|
|
JBE/JNA CF=1 or ZF=1 Jump if below or equal/not
|
|
above (unsigned)
|
|
JE/JZ ZF=1 Jump if equal/zero
|
|
JNE/JNZ ZF=0 Jump if not equal/not zero
|
|
JL/JNGE SF not equal Jump if less/not greater or
|
|
to OF equal (signed)
|
|
JGE/JNL SF=OF Jump if greater or equal/not
|
|
less (signed)
|
|
JLE/JNG ZF=1 or SF Jump is less or equal/not
|
|
not equal OF greater (signed)
|
|
JG/JNLE ZF=0 or SF=OF Jump if greater/not less or
|
|
equal (signed)
|
|
JS SF=1 Jump if sign
|
|
JNS SF=0 Jump if no sign
|
|
JC CF=1 Jump if carry
|
|
JNC CF=0 Jump if no carry
|
|
JO OF=1 Jump if overflow
|
|
JNO OF=0 Jump if not overflow
|
|
JP/JPE PF=1 Jump if parity/parity even
|
|
JNP/JPO PF=0 Jump if no parity/parity odd
|
|
|
|
There are all the possible combinations of conditional jumps
|
|
that you will encounter. I realize that we have not
|
|
discussed some of the flags such as overflow or parity, but
|
|
be aware that they exist and programs sometimes use them.
|
|
|
|
JMP - jump
|
|
----------
|
|
This instruction does what it suggests. It jumps too
|
|
different sections of code. Several forms of the jump
|
|
instruction include:
|
|
|
|
2E0B:0208 EBF6 JMP 0200
|
|
2E0B:020A 3EFF24 JMP DWORD PTR DS:[SI]
|
|
|
|
|
|
|
|
Page 7
|
|
|
|
|
|
|
|
|
|
|
|
The Cracking Manual
|
|
|
|
|
|
|
|
The first instruction jumps to an address within the segment.
|
|
The latter instruction jumps to an address pointed to by ds:
|
|
si. The DWORD says that this will be a far jump, a jump to a
|
|
different segment (a different blackboard). So, if the
|
|
double word that is pointed to by ds:si contains 1000:0040h,
|
|
then, the instruction will jump to 1000:0040h whereas the
|
|
previous jump instruction will jump within the current
|
|
segment (or blackboard).
|
|
|
|
CALL - procedural transfer
|
|
--------------------------
|
|
This instruction is the baby that you will be carefully
|
|
watching out for most often. This instruction calls another
|
|
procedure and upon it's completion, will return to calling
|
|
address. For example, consider the following block of code:
|
|
|
|
2E0B:1002 E8BB46 CALL 56C0
|
|
2E0B:1005 7209 JB 1010
|
|
2E0B:1007 0C00 OR AL,00
|
|
|
|
The first line calls another procedure at "line number"
|
|
56C0h. Upon its completion, the instruction pointer will
|
|
point to the second line. Note that there is a "JC"
|
|
instruction. Remember that programs often use the carry flag
|
|
to signal errors. If the call instruction called a copy
|
|
protection instruction and you entered a wrong code or
|
|
something, it may return with the carry flag set. The next
|
|
instruction would then jump if there was an error to an
|
|
exiting procedure.
|
|
Note, this is a near call. A program can also have far
|
|
calls just like jumps.
|
|
|
|
INT - generate an interrupt
|
|
---------------------------
|
|
This instruction is much like the call instruction. It
|
|
also transfers control to another procedure. However, the
|
|
number after the INT instruction does not point to an
|
|
address. Instead, it is a number pointing to an address that
|
|
is located in something called an interrupt vector. You will
|
|
commonly see "INT 10", "INT 21", "INT 13". Just know (for
|
|
now) that they are like calls to procedures.
|
|
|
|
LODSB/LODSW/STOSB/STOSW - load/store a byte/word
|
|
------------------------------------------------
|
|
These instructions either load in or store a byte or a
|
|
word to or from memory. The DS:SI register pair points to
|
|
the source data. These are the registers the CPU will use
|
|
when reading from memory using the LODS instruction. The
|
|
AX/AL register will hold the number to either read from or
|
|
write to the memory. So, if DS:SI points to a byte which is
|
|
maybe 60, then a "LODSB" instruction will load in the number
|
|
60 into the AL register. A LODSB or STOSB will use the AL
|
|
register while the LODSW or STOSW will use the AX register.
|
|
The STOS writes whatever is in the AX/AL register to the
|
|
|
|
|
|
Page 8
|
|
|
|
|
|
|
|
|
|
|
|
The Cracking Manual
|
|
|
|
|
|
|
|
memory pointed to by ES:DI. So, if ES:DI points to 100:102h
|
|
and if AL held 50, then the byte at 100:102h will hold 50.
|
|
After the instruction is finished, the CPU will either
|
|
increment or decrement SI or DI according to the status of
|
|
the direction flag. So, if SI was 100h and a "LODSW"
|
|
instruction was performed with a cleared direction flag
|
|
(forward), the SI will now point to 102h.
|
|
|
|
MOVSB/MOVSW - copies a byte/word from source to destination
|
|
-----------------------------------------------------------
|
|
This instruction gets a byte or a word from the data
|
|
pointed to by DS:SI and copies it to the data pointed to by
|
|
the ES:DI address. When the instruction is finished, SI and
|
|
DI will be incremented or decremented accordingly with the
|
|
status of the direction flag. So, if DS:SI pointed to a byte
|
|
with the number 30, a "MOVSB" instruction would copy into the
|
|
byte pointed to by ES:DI the number 30.
|
|
|
|
REP - repeat
|
|
------------
|
|
The REP instruction in front of a MOVS/LODS/STOS would
|
|
cause the MOVS/LODS/STOS instruction to be repeated for a
|
|
number of times specified in the CX register. So, if CX
|
|
contained 5, then "REP STOSB" would store whatever was in the
|
|
AL register into the byte pointed to by ES:DI five times,
|
|
increasing DI each time.
|
|
|
|
LOOP - looping
|
|
--------------
|
|
The LOOP instruction repeats a block of instructions for
|
|
a certain number of times. This number will be held in the
|
|
CX register. Each time we reach this instruction, the CPU
|
|
will decrement the CX register and jump to a specified
|
|
instruction until CX becomes zero. This instruction looks
|
|
like "LOOP 1A00" where the number indicates the instruction
|
|
address to loop to.
|
|
|
|
Arithmetic Operators
|
|
--------------------
|
|
Arithmetic instructions allow you to perform various
|
|
arithmetic function of data. "ADD" and "SUB" work the same
|
|
way as "MOV" instructions do in that it subtracts whatever is
|
|
in the source register from the destination register and
|
|
stores it in the destination register.
|
|
The "MUL" and "DIV" instructions are a bit more
|
|
complicated and they are not used as intensively as the "ADD"
|
|
or "SUB" since they are slow, so we will not talk about them.
|
|
There are also a multitude of other instructions that
|
|
you should familiarize yourself with if you are thinking of
|
|
becoming a serious cracker. The instructions given above are
|
|
only the BARE minimum that you need. There is no way around
|
|
learning assembly for better cracking.
|
|
|
|
|
|
|
|
|
|
Page 9
|
|
|
|
|
|
|
|
|
|
|
|
The Cracking Manual
|
|
|
|
|
|
|
|
THE CRACKING
|
|
|
|
The Cracking
|
|
------------
|
|
Now the fun stuff begins. First, we must discuss the
|
|
different forms of copy protection schemes. They are
|
|
basically divided into the disk based and manual based copy
|
|
protection schemes.
|
|
With disk based schemes, the software often reads from
|
|
specific sectors on a disk to determine the disk's validity.
|
|
How can this be done? When you perform a disk format, the
|
|
disk is formatted with specific sector sizes. Once the
|
|
sector size changes, DOS cannot recognize it, thinking that
|
|
it is a bad sector. Since this looks like a bad sector, a
|
|
simple DISKCOPY will not work in copying such disks.
|
|
Interrupt 13h (the assembly mnemonic is INT 13) was commonly
|
|
used to handle such copy protections. It is now very rare to
|
|
encounter the once famed INT 13h copy protection method
|
|
nowadays since it was quite easy to defeat. Any professional
|
|
commercial software will often use their own custom based
|
|
disk I/O routines. This involves intimate access to I/O
|
|
ports using IN and OUT instructions. This is beyond the
|
|
scope of the first release of this manual. However, if you
|
|
are lucky, the I/O functions might be called from a "CALL"
|
|
instruction in which case you may defeat the protection
|
|
without much difficulty. Another disk based scheme used to
|
|
denote legality of software is used during the installation
|
|
process of the software. With certain programs, when you
|
|
install it, it copies the files into the hard drive. But it
|
|
also sets a specific sector in the hard drive so that the
|
|
program can recognize it. This is also similar to diskette
|
|
copy protections, but can be defeated in much the same way.
|
|
Thank goodness that disk based copy protections are
|
|
almost completely out of the software industry. However, a
|
|
sometimes more difficult copy protection scheme has arisen
|
|
that may sometimes prove to be even more difficult to crack.
|
|
These schemes are commonly known as the doc checks in which
|
|
the user must have a copy of the manual to bypass the
|
|
protection. With programs compiled as true assembly (you can
|
|
call then "normal" programs), these protections are not too
|
|
bad to trace through and crack. With programs that run
|
|
scripts (such as Sierra games), this can he a real chore
|
|
however. Why? It is because it is like running a program
|
|
within a program. You just have to be very very patient in
|
|
this case, carefully tracing through the instructions.
|
|
As if these copy protection schemes weren't enough,
|
|
software companies have also added trace inhibition schemes
|
|
to their code. What does this mean? This means that you
|
|
will have a hell of a time trying to trace through code.
|
|
However, if you know how these things work, it should not be
|
|
too much of a problem.
|
|
Run-time compression/decompression and
|
|
encryption/decryption of files also make changes to the
|
|
program difficult. In this case, the loader sure comes in
|
|
|
|
|
|
Page 10
|
|
|
|
|
|
|
|
|
|
|
|
The Cracking Manual
|
|
|
|
|
|
|
|
handy. Also, when the data within the file changes due to
|
|
overlays, loaders are also good to use.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Page 11
|
|
|
|
|
|
|
|
|
|
|
|
The Cracking Manual
|
|
|
|
|
|
|
|
DISK BASED COPY PROTECTIONS
|
|
|
|
Disk Based Copy Protection
|
|
--------------------------
|
|
Since disk based copy protection schemes are rarely
|
|
used, we will not go into great depth in its discussion.
|
|
|
|
INT 13h
|
|
-------
|
|
I have previously mentioned that INT 13h copy protection
|
|
schemes are hardly ever used anymore. Nevertheless, it would
|
|
be good practice for the beginner to learn how to defeat the
|
|
code. You will most likely see INT 13h used with function 2,
|
|
read sector. This means that:
|
|
|
|
AH => will contain the number 2 (function 2)
|
|
AL => the number of sectors to read in. This is
|
|
commonly only 1 since you just want to check a few
|
|
sectors for disk validity.
|
|
CH => will contain the cylinder number
|
|
CL => will contain the sector number
|
|
DH => will contain the head number
|
|
DL => will contain the drive number
|
|
00h - 7Fh for floppies
|
|
80h - FFh for fixed disks
|
|
ES:BX => will point to the address into which the data
|
|
read from the disk will be written to
|
|
|
|
Upon the return for this interrupt, if the carry flag is
|
|
set, that means that the program could not read the sector,
|
|
and therefore the disk is valid. If the carry flag is clear,
|
|
that meant that INT 13h could read the sector properly and so
|
|
the disk would be bad in the eyes of the program, thinking it
|
|
was a copied disk.
|
|
Okay, now that we know to look for INT 13h in the
|
|
program code, we can begin tracing. First, we must know the
|
|
difference between debug's "T" and "P". "T" is the trace
|
|
instruction, which tells it to follow instructions step by
|
|
step. That also means that in LOOP or REP instruction, the
|
|
trace will patiently go through the loop until finished.
|
|
Also, during CALL instructions, trace will go into the call
|
|
and execute the instructions pointed to by the call
|
|
instruction. The "P" command is similar to the "T" but with
|
|
the difference in that it traces over instructions. That
|
|
means that if it encounter a LOOP or REP, it will quickly
|
|
finish up the loop and point to the next instruction. With a
|
|
CALL, the "P" (proceed) will not go into the subroutine.
|
|
Instead, it will just execute the procedure, then point to
|
|
the next instruction.
|
|
Okay, before you start tracing for hours through a
|
|
program, you must first notice when and where the copy
|
|
protection appears. Run the program in DOS first and make
|
|
careful note of when things happen. You might see an intro
|
|
screen, then the music pops up, then the menu comes out.
|
|
|
|
|
|
Page 12
|
|
|
|
|
|
|
|
|
|
|
|
The Cracking Manual
|
|
|
|
|
|
|
|
Notice this so you will know where you are in the program.
|
|
Once you have done that, you can begin debugging the
|
|
program. Whenever you start out with a program, you use "P"
|
|
to trace through the program. Be patient as this might take
|
|
a while. While you are tracing, watch out for CALLs and
|
|
INTerrupts. When you are just about to execute the step, try
|
|
to remember the segment and offset of the instruction. The
|
|
segment is the number to the left of the colon while the
|
|
offset is the number to the right. As you continue tracing
|
|
through the program, you will find that the screen might
|
|
blank and display the intro screen or something like that.
|
|
This is a good sign and it tells you that you are headed in
|
|
the right direction. Start slowing down when you feel that
|
|
you are near to the copy protection.
|
|
|
|
Situation 1 - Exit from copy protected CALL
|
|
-------------------------------------------
|
|
Oops, you have traced over a call that accessed drive A.
|
|
Unfortunately, you also exited the program. That's good.
|
|
You have just narrowed down the location of the copy
|
|
protection code. Now I hope you remembered the address of
|
|
that CALL. If not, you gotta start all over to find it.
|
|
Anyway, restart the program now. Now Go to that instruction
|
|
by "G {segment:address}".
|
|
Did something go wrong? Did the computer freeze or
|
|
something? It is most likely that this is an overlay or
|
|
encrypted code or something that caused the code at that
|
|
location to change. In this case, you will have to remember
|
|
the addresses of various instructions along the way.
|
|
Instructions that you want to take note of are far calls (if
|
|
you remember, calls with a segment:offset address as their
|
|
operand). You don't have to do this for every call. As you
|
|
crack more and more, you will get the hang of which
|
|
instructions to keep track of.
|
|
Okay, let's assume you have gotten back into the
|
|
location of the code again. It is a CALL instruction that
|
|
will access the disk drive. At this point, try skipping the
|
|
CALL instruction. To do this, type in "RIP {enter}". Then
|
|
type in the address of the next instruction. Then execute
|
|
the do or die instruction, "G". If the program runs fine
|
|
without asking for the copy protection, congratulations! You
|
|
have cracked the program.
|
|
If the program freezes or does something weird, restart
|
|
the program and trace back to the suspected copy protected
|
|
location. Now use the "T" command once and start using "P"
|
|
again. Remember to write down the address of that CALL
|
|
instruction you just traced into so you can come back to it
|
|
quickly. As you keep tracing, using the above procedures,
|
|
pretend you eventually come up to an INT 13h instruction.
|
|
See what it does by tracing over it. Make sure you have a
|
|
disk in drive A too. If there was no error, force an error
|
|
by turning on the carry flag and proceeding. With INT 13h
|
|
copy protections, this should be sufficient to crack the
|
|
program.
|
|
|
|
|
|
Page 13
|
|
|
|
|
|
|
|
|
|
|
|
The Cracking Manual
|
|
|
|
|
|
|
|
Situation 2 - Return from copy protected CALL
|
|
---------------------------------------------
|
|
Okay, the CALL that you just traced over accessed the
|
|
disk drive, but it didn't kick you out. Keep on proceeding
|
|
and this point. If there is an instruction that causes you
|
|
to jump because of a carry flag, try fooling around with this
|
|
carry flag and see how the program reacts. INT 13h copy
|
|
protections are usually simple enough for you to just change
|
|
the carry flag to allow the program to bypass the copy
|
|
protection.
|
|
|
|
Access to the Hard Drive
|
|
------------------------
|
|
The cracking for installation software is also the same
|
|
as cracking for the INT 13h. You just keep tracing until you
|
|
see some disk activity. At that point, you try messing
|
|
around with some of the conditional jumps to see what
|
|
happens. If you have the original program, you should run it
|
|
also to see the differences between the valid and invalid
|
|
copies.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Page 14
|
|
|
|
|
|
|
|
|
|
|
|
The Cracking Manual
|
|
|
|
|
|
|
|
DOC CHECK COPY PROTECTIONS
|
|
|
|
Doc Check Copy Protections
|
|
--------------------------
|
|
Okay, we have just quickly scanned over disk based copy
|
|
protections because they are rarely used nowadays. Doc
|
|
checks will be discussed in greater detail for the rest of
|
|
this manual.
|
|
Unlike the disk based protections, which are based on
|
|
hardware identification, doc checks are based on software
|
|
identification. Therefore, the only information that will
|
|
indicate that a copy protection is happening is the screen,
|
|
unlike the whirr of the disk drive. The moral, watch the
|
|
screen. Because this copy protection is software based, it
|
|
will be more of a challenge to trace, but of course, that is
|
|
the "fun" part of cracking.
|
|
|
|
The Basics
|
|
----------
|
|
Make sure you have the COMPLETE version of the program
|
|
you are about to crack. When you do, run the program in DOS.
|
|
While the program is loading, take note of exactly what goes
|
|
on with the screens, sounds, etc. Here is what you might
|
|
want to note:
|
|
|
|
1) What comes up first? Is it a standard text output
|
|
that asks you for the type of graphics adaptor you
|
|
have, the number of joysticks, the sound card?
|
|
2) When does the intro screen come up? Is it after the
|
|
music starts? After the copyright notice? After
|
|
the text prompt for the graphics mode you will be
|
|
operating in?
|
|
3) What happens now? An animated sequence that brings
|
|
you through the beginning plot of a game? If so,
|
|
can you press a key and escape from it?
|
|
4) Now what? Is there a main menu? When you start the
|
|
game by selecting the "START GAME" option from the
|
|
menu, does the copy protection come up immediately?
|
|
5) If it doesn't come up immediately, when does it come
|
|
up?
|
|
6) Does the copy protection only appear when you are
|
|
playing the game, or does it come up also when you
|
|
select "CHANGE OPTIONS" from the main menu?
|
|
|
|
Obviously, these questions are merely prompts for you to
|
|
follow. Use your own mind in discovering what to take note
|
|
of. There are no set rules for cracking. It is a puzzle
|
|
that you must use your mind on.
|
|
Okay, once you have run the program, go into your
|
|
debugger (in our case, DEBUG) and load up the program. One
|
|
tip to use when you first start out programming is to use the
|
|
"P" command to trace through code. As you become a more
|
|
advanced cracker, you might start seeing patterns in coding.
|
|
These patterns are characteristic of high level programming
|
|
|
|
|
|
Page 15
|
|
|
|
|
|
|
|
|
|
|
|
The Cracking Manual
|
|
|
|
|
|
|
|
languages (Pascal, C, etc.) and are usually the
|
|
initialization code for the rest of the program. Use "P" for
|
|
each instruction, one at a time. Be patient as this might
|
|
take a while.
|
|
Okay, you have been tracing for some time now and
|
|
finally, you notice something happen. The screen might have
|
|
blanked or maybe a message prompting you to enter the
|
|
graphics mode may have popped up. Was this what you have
|
|
noted before? It should be and you can assure yourself that
|
|
you are headed in the right direction. As you keep tracing
|
|
programs, you notice that CALLs usually do something
|
|
significant. A CALL might clear the screen or sound some
|
|
music. When it does something rad like this, write down its
|
|
address as the segment:offset pair. The segment is the
|
|
number to the left of the colon while the offset is the
|
|
number to the right of the colon. Don't be a dork and set a
|
|
breakpoint there. Write it down on paper or something. We
|
|
will see later on why breakpoints fail miserably in the cool
|
|
wares.
|
|
Why take note of these instructions? As you trace
|
|
deeper and deeper into programs, the coding often loads up
|
|
overlays or maybe decompresses code to the memory location
|
|
that you have just traced over. Therefore, if you set a
|
|
breakpoint there, or execute a "G" instruction to that
|
|
address, you will fuck up the program and cause your computer
|
|
to freeze. We will see why when we examine how breakpoints
|
|
and single stepping works.
|
|
Also, while you are tracing using "P", mentally remember
|
|
the addresses of the CALLs. That way, if you trace over a
|
|
call that brought you immediately to the copy protection, you
|
|
won't have to retrace the code again. You don't have to
|
|
write down all of the addresses, of course, just remember one
|
|
at a time and write them down if they do anything
|
|
significant.
|
|
|
|
Code Guards Through Keyword Entry
|
|
---------------------------------
|
|
Okay, you know that the copy protection is one in which
|
|
the program waits for you to type in a keyword that you have
|
|
to look up in the manual or something. Here are then
|
|
following steps you should take.
|
|
|
|
Situation 1 - Return from a copy protected CALL
|
|
-----------------------------------------------
|
|
When a copy protection coding reveals itself on the
|
|
screen, you can have a situation in which you are returned to
|
|
the debugger, waiting for the next instruction to be
|
|
executed. Now, suppose that the CALL asked you to enter a
|
|
code. You entered an incorrect code and were returned to the
|
|
debugger, but you have not exited the program. Make sure
|
|
that you have previously recorded the address of this CALL.
|
|
Now, you can do two things, (1) you can try skipping over the
|
|
CALL, (2) you can trace on further. As you become more
|
|
experienced, you will be able to better decide. As one with
|
|
|
|
|
|
Page 16
|
|
|
|
|
|
|
|
|
|
|
|
The Cracking Manual
|
|
|
|
|
|
|
|
experience, however, I can say that 90% of the time, you will
|
|
have to trace further on, but hey, you might get lucky.
|
|
For now, let's say you are lazy and decide that you want
|
|
to skip over the call to see what happens. To do this, you
|
|
must restart the program. Then trace your way back to the
|
|
CALL where the copy protection was located. Use "G
|
|
{segment:offset}" to do this. If, for some reason, the
|
|
computer freezes when you do this, you will have to use "G"
|
|
followed by the addresses of the CALLs that you have noted
|
|
down to be significant. If that doesn't work, resort to
|
|
retracing the code over again. As you become more
|
|
experienced, you will find that you rarely have to retrace
|
|
the entire code since you can "feel" what is going on. Okay,
|
|
now that you are at the location of the CALL, this is the
|
|
time to skip over the instruction. To do this, enter "RIP"
|
|
and then the address of the next instruction's address. Now
|
|
enter the "G" command and see what happens. If the program
|
|
runs just fine, you've cracked the program. If the program
|
|
kicks you out or crashes, you have to do some more tracing.
|
|
Okay, so you've decided to continue tracing from the
|
|
point of the copy protection. There are usually a bunch of
|
|
CMP and J? CMPS? instructions after the call. This point on
|
|
is the difficulty of cracking for a beginner since you don't
|
|
know what the fuck is going on. All those compares and jumps
|
|
don't mean shit to you are you are about to pass out in
|
|
frustration. Don't distress, here are a few tips I can give
|
|
you. If these don't work, you gotta find out your own
|
|
solutions to the problem.
|
|
Okay, in all probability, the CALL that you just traced
|
|
over was acting as a read string procedure (like BASIC's
|
|
INPUT). That means somewhere in the computer's memory, there
|
|
lies the code that you typed in and the code that you were
|
|
supposed to have typed in. What this would mean is that the
|
|
code after the CALL will do some sort of string comparison.
|
|
Look out for these. It might be hidden inside another CALL
|
|
if you're lucky. In such a case, does the program kick you
|
|
out? If it does, you have to trace into the call using "T"
|
|
to see what is going on. Okay, the string comparison will
|
|
most likely take the form of some kind of loop. Maybe "REP
|
|
CMPSB" or "LOOP". In the case of the REP CMPSB, there might
|
|
be a JZ/JNZ or JCXZ/JECXZ that follows it. When strings
|
|
match, the CX register will be zero. If CX is not zero, the
|
|
strings are not the same and the conditional jump will
|
|
probably jump to an exit routine. All you have to do is to
|
|
change the status of the zero flag. Then, try out the "G"
|
|
instruction. If it still didn't work, start over and do some
|
|
more tracing. If the string compare is not of the REP form,
|
|
there will be some kind of loop that will check between two
|
|
memory locations. In such a case, you will just have to
|
|
become accustomed to realizing that the code is a string
|
|
compare. There is no standard code for this. If you know
|
|
you have entered a wrong code, trace through the loop and see
|
|
where in the loop you are thrown out of the loop. At this
|
|
point, you can go back to it, change some flags to make sure
|
|
|
|
|
|
Page 17
|
|
|
|
|
|
|
|
|
|
|
|
The Cracking Manual
|
|
|
|
|
|
|
|
you stay in the loop. When you exit through a different
|
|
location, you have probably bypassed the code and now, you
|
|
can enter "G" to see what happens.
|
|
|
|
Situation 2 - Exit from a copy protected CALL
|
|
---------------------------------------------
|
|
When a copy protection coding reveals itself on the
|
|
screen, you can have a situation in which you are not
|
|
returned to the debugger, instead, causing you to exit the
|
|
program. In this case, you have to restart the program and
|
|
trace into the CALL using "T". After that, you can start
|
|
using "P" again to uncover the location of the code. You
|
|
will most likely encounter a condition that will resemble
|
|
situation 1. Follow its instructions.
|
|
|
|
Shortcuts For Keyword Entry Protections
|
|
---------------------------------------
|
|
With keyword entry systems, you might be lucky to have
|
|
the codes stuck somewhere into file in its
|
|
uncompressed/unencrypted form. This means that you can "see"
|
|
the keywords in its ASCII format. This case is cool because
|
|
you won't have to do any tracing to crack the program. All
|
|
you have to do is to dump the contents of the files to find
|
|
something that looks like a keyword. (Always backup the file
|
|
that you are about to alter.) When you have found such a
|
|
file and the location of the codes, all you have to do now is
|
|
to change the codes to values that you know. For example,
|
|
one code might call for you to enter "PIRATE". It's a bitch
|
|
if you don't know the code. But if you change the code to
|
|
your name or something else you will never forget ("CYBORG"),
|
|
then you'd be set.
|
|
However, in most instances, you can't simple just type
|
|
over the old code with your new code. In high level
|
|
languages, these codes are stored as strings. In 'C',
|
|
strings are stored in their ASCII equivalent. They are then
|
|
terminated with a NULL character (this is a 0). In Pascal,
|
|
the lengths of the strings are first stored in the first
|
|
position. Then, the ASCII is stored.
|
|
|
|
NULL Terminated Strings
|
|
-----------------------
|
|
So, if you see zeros after the codes, this is a NULL
|
|
terminated string. Now, start at the beginning of the string
|
|
and enter your code. Then, enter the '0'. Make sure your
|
|
string is less than the original string since 'C' refers to
|
|
these strings also with pointers.
|
|
|
|
Pre-Length Indentifier
|
|
----------------------
|
|
If you see numbers before strings, enter your own code.
|
|
Then change the length of the code appropriately. Make sure
|
|
you do not exceed the length of the original string.
|
|
|
|
|
|
|
|
|
|
Page 18
|
|
|
|
|
|
|
|
|
|
|
|
The Cracking Manual
|
|
|
|
|
|
|
|
Code Guards Through Pointed Icons
|
|
---------------------------------
|
|
We have a case where we do not type in keywords.
|
|
Rather, we must use a pointer device such as the cursor keys
|
|
on the keyboard, the mouse, or joystick. These protections
|
|
are a bit more complicated since there are no strings to
|
|
compare against. Rather, the input will be a number stored
|
|
in memory or a register. This is what makes this copy
|
|
protection more difficult to crack. We have to hunt through
|
|
code to find out which compare instruction is the key.
|
|
What you have to do is to find the general location of
|
|
the copy protection code as before. Then, instead of typing
|
|
in the keyword, you select the icon. Like before, you must
|
|
step slowly through the code and go until the program JUST
|
|
STOPS asking you for the code. For example:
|
|
|
|
2E0B:0000 E8740E CALL 0E77
|
|
2E0B:0003 38D0 CMP AL,DL
|
|
2E0B:0005 7569 JNZ 0070
|
|
2E0B:0007 CB RETF
|
|
|
|
You might decide to trace over the call at address xxxx:0000.
|
|
But then, you see that the screen displayed the icons and you
|
|
got to select the code. Then, the procedure does some disk
|
|
activity and you return to address xxxx:0003. If you see
|
|
something happen after you have just finished entering the
|
|
code or if it is slow in returning you to debug, then,
|
|
some code must have been performed before you returned. In
|
|
this case, you must trace into the CALL to see what has
|
|
happened. If not, there is still a small probability that
|
|
there were some instructions that formatted the code you
|
|
entered and saved it to a memory location. (We'll talk about
|
|
multiple doc checks later.)
|
|
Realize that most of the programs that you will be
|
|
cracking have been programed by C or some other high level
|
|
language. These languages often use the stack (SS:SP) to
|
|
pass parameters (variables) or to create local variables for
|
|
a procedure's use. Most likely, you will see compares to
|
|
data contained within the stack such as "CMP AX,WORD PTR
|
|
[BP+10]" or "MOV DX,WORD PTR [BP+10]". This is what you hope
|
|
to find, although not always the case. If you do see some
|
|
access via the stack using the BP register as a pointer, you
|
|
may have something there. Then, all you would have to do is
|
|
to mess around the flags register (most likely, JZ/JE will be
|
|
used) at the compare instruction.
|
|
|
|
Multiple Doc Checks
|
|
-------------------
|
|
There are some wares that invoke multiple doc checks,
|
|
doc checks that pop up either systematically or randomly. In
|
|
addition, there could also be two types of this protection.
|
|
The doc check could be a similar type (eg. typing the code
|
|
found on page...) or they could be different (eg. typing in
|
|
the code on page... then select the correct icon), although
|
|
|
|
|
|
Page 19
|
|
|
|
|
|
|
|
|
|
|
|
The Cracking Manual
|
|
|
|
|
|
|
|
the latter is more rarely used due to its extensive memory
|
|
usage.
|
|
|
|
Situation 1 - Similar doc checks
|
|
--------------------------------
|
|
Cracking multiple doc checks that are similar is just
|
|
like cracking with just one doc check. The procedure to
|
|
trace is still the same. Keep Proceeding until you come up
|
|
to the CALL that contains the copy protection. Just use the
|
|
sequences mentioned above. When you are absolutely positive
|
|
that the call contains the copy protection (skip the CALL and
|
|
see what happens; if the protection has been bypassed but
|
|
appears at other times, you got something), here is what you
|
|
do.
|
|
|
|
1) Note what type of CALL it was. Near if the operand
|
|
(number after the CALL) was a four digit number or
|
|
far if the operand contained the segment:offset
|
|
pair.
|
|
2) Trace INTO the call.
|
|
3) At the first instruction, note the address inside
|
|
the CALL.
|
|
4) Then, type in "A" then the address of that very
|
|
first instruction.
|
|
5) If there was a near call performed, now type in
|
|
"RETN", otherwise, type in "RETF".
|
|
6) Now run the program ("G") and see what happens.
|
|
|
|
If this call was definitely the copy protection, you should
|
|
have bypassed the copy protection completely. Otherwise, you
|
|
might have a case like situation 2.
|
|
|
|
Situation 2 - Different doc check types
|
|
---------------------------------------
|
|
Again, cracking multiple doc checks are like cracking
|
|
single doc checks. You follow the same procedures until you
|
|
come up to a copy protected location. Then, you would trace
|
|
into the code as explained in situation 1 just to make sure
|
|
that the code is not called up again. Different doc checks
|
|
are a bitch to do because you have to manually keep tracing
|
|
until you find each one to effectively rid yourself of the
|
|
copy protection. There is not sure way of getting rid of all
|
|
the doc checks any other way. But luckily, there are very
|
|
few wares out there like this. Remember, the more the
|
|
company shoves into the program's memory, the more money it's
|
|
gonna cost them.
|
|
|
|
Of course, I cannot cover every single type of doc check
|
|
since there are too many of them. You'd just have to use
|
|
your own imagination to solve some of them.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Page 20
|
|
|
|
|
|
|
|
|
|
|
|
The Cracking Manual
|
|
|
|
|
|
|
|
SPECIAL SITUATIONS
|
|
|
|
Special Situations
|
|
------------------
|
|
What all crackers are faced with at one time or another
|
|
are situations that call for intuitive thinking to overcome
|
|
the barrier. Remember, there is no one sure way of cracking.
|
|
|
|
INT 3 - Problems During Tracing
|
|
-------------------------------
|
|
Sometimes, when you start cracking, you just find your
|
|
instruction pointer messing up. You keep tracing and
|
|
tracing, then your computer freezes. But then, when you type
|
|
"G" at the beginning of the program, it works just fine.
|
|
What is happening here? There are several things that the
|
|
program could do to impede tracing. Unless you have a
|
|
hardware debugger, you have to settle in for more primitive,
|
|
intuitive methods. First, we have to find out how a software
|
|
debugger works.
|
|
I now introduce you to INT 3 and INT 1. They are the
|
|
breakpoint and single stepping interrupts respectively. We
|
|
will be looking at INT 3 the most.
|
|
What happens when you set breakpoints? Well, here is
|
|
what the debugger does. At the address you have specified,
|
|
the debugger will read in the byte at that address and store
|
|
it somewhere else in its own memory. This byte is part of
|
|
the whole instruction located at that address. For example,
|
|
if there was an "INT 13" at that location, the machine
|
|
language equivalent will be CD13h. Debug will read in the
|
|
first byte, CDh, and save it in memory. The CDh will then be
|
|
replaced by INT 3 (CCh). So, the code will now look like
|
|
CC13h in machine language. When you unassemble this at the
|
|
address, you will see "INT 3" (the instruction only takes up
|
|
one byte) and some gibberish after that. So, when the CPU
|
|
comes up to this address, it will encounter INT 3 and will
|
|
return control to the debugger. The debugger then replaces
|
|
the INT 3 with the CDh byte used before.
|
|
With single stepping, the same thing occurs. Debug will
|
|
also insert the INT 3 instruction at the instruction after
|
|
the one you are about to execute. Then, internally, a "G"
|
|
instruction is performed until it reaches the INT 3, at which
|
|
point, the byte will be replaced and everything will be cool.
|
|
|
|
Use of INT 3 to Call Up Other Interrupts
|
|
----------------------------------------
|
|
This INT 3 deal seems to be cool, working in many
|
|
situations. But what if the software vendor reprograms INT 3
|
|
to point to an INT 21? Many programs use INT 21 to access
|
|
DOS functions like reading a file, etc. There would be a
|
|
conflict now as the program uses INT 3 to call up DOS while
|
|
debug wants to use INT 3 for its breakpoints. There is also
|
|
another problem. INT 21 uses two bytes (CD21h) while INT 3
|
|
uses only one byte (CCh). Therefore, you cannot replace INT
|
|
3 with the INT 21.
|
|
|
|
|
|
Page 21
|
|
|
|
|
|
|
|
|
|
|
|
The Cracking Manual
|
|
|
|
|
|
|
|
Also, INT 3 could be reprogrammed so that everytime it
|
|
is used, the program will just exit to its higher process.
|
|
So everytime you single step, you will be kicked out of the
|
|
program.
|
|
|
|
Parity Errors with INT 3
|
|
------------------------
|
|
The tough copy protections use the change of memory to
|
|
obstruct tracing. Examine the code below:
|
|
|
|
2E0B:0500 FC CLD
|
|
2E0B:0501 B80000 MOV AX,0000
|
|
2E0B:0504 BB0000 MOV BX,0000
|
|
2E0B:0507 BE0005 MOV SI,0500
|
|
2E0B:050A BF0010 MOV DI,1000
|
|
2E0B:050D B90005 MOV CX,0500
|
|
2E0B:0510 AC LODSB
|
|
2E0B:0511 345A XOR AL,5A ;'Z'
|
|
2E0B:0513 01C3 ADD BX,AX
|
|
2E0B:0515 AA STOSB
|
|
2E0B:0516 E2F8 LOOP 0510
|
|
2E0B:0518 3B1E0043 CMP BX,[4300]
|
|
2E0B:051C 7403 JZ 0521
|
|
2E0B:051E E9EF2A JMP 3010
|
|
2E0B:0521 D1E0 SHL AX,1
|
|
|
|
Notice what the program is doing. It is performing a simple
|
|
decryption of a block of code from address 500h and putting
|
|
it in address 1000h. In addition, there is a checksum being
|
|
performed at address . The program is adding all those bytes
|
|
up, then comparing the number with some other number (a
|
|
checksum value) in memory at address 4300h. So what you may
|
|
say. When the program is run without any set breakpoints,
|
|
the program will run fine. But when you start tracing
|
|
through the code, or putting a breakpoint somewhere after the
|
|
loop, the program will cause you to exit. If you decide to
|
|
change the program so that it will let you pass regardless of
|
|
the checksum value, somewhere along the line, the program
|
|
will fuck up.
|
|
This goes back to the idea of INT 3. Right before debug
|
|
executes an instruction, it places an INT 3 at the next
|
|
instruction. In this program, when debug places this
|
|
interrupt and executes an instruction, the program is reading
|
|
in this INT 3 at the address and copies it to a different
|
|
address. INT 3 is obviously a different number than the
|
|
other instructions, so the checksum value will be different.
|
|
So, now that INT 3 is copied to another location in memory,
|
|
debug also cannot replace that with it's original byte value.
|
|
Therefore, if you try to force the checksum to match and
|
|
continue running the program, the program will crash because
|
|
the INT 3 is causing the instructions after itself to be
|
|
interpreted incorrectly by the CPU.
|
|
To bypass this, you have to make sure not to get your
|
|
INT 3 placed in the wrong place at the wrong time. Looking
|
|
|
|
|
|
Page 22
|
|
|
|
|
|
|
|
|
|
|
|
The Cracking Manual
|
|
|
|
|
|
|
|
at the program, you can keep tracing normally until the SI
|
|
register points to any byte past the CMP instruction at
|
|
address 519h. Then, you can do a "G 518" to finish off the
|
|
loop quicker. Debug will place a temporary INT 3 at address
|
|
518h, but it doesn't matter now since SI will be past 518h.
|
|
This is obviously a simple example, but it gets the point
|
|
across that you have to watch where you trace.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Page 23
|
|
|
|
|
|
|
|
|
|
|
|
The Cracking Manual
|
|
|
|
|
|
|
|
OVERLAYS/LOADERS
|
|
|
|
Overlays/Loaders
|
|
----------------
|
|
Sometimes, programs will have an initialization code and
|
|
upon its completion, call up another program or overlay.
|
|
These programs present unique situations in which it is
|
|
sometimes difficult, after finding the copy protection code,
|
|
to write the changes to disk. Let's see what these programs
|
|
do before we go on to the next topic of making changes
|
|
permanent.
|
|
Loaders are usually small programs that might first ask
|
|
you for the graphics mode or what sound card you have. When
|
|
finished, it will load up another program. Sometimes, this
|
|
is done with DOS' interrupt 21h, function 4B00h (load and
|
|
execute). This is the same interrupt DOS uses to load up
|
|
programs when you type them in at the DOS prompt. You can
|
|
tell what file is going to be executed by tracing up to the
|
|
INT 21 instruction and dumping the address pointed to by
|
|
DS:DX (type in "D DS:DX"). Also, internal procedures could
|
|
be used to call up the program. Use what you've learned to
|
|
trace through them.
|
|
Code decryptions or dynamic heap allocation where data
|
|
is to be loaded presents problems as well. Code that changes
|
|
as the program progresses makes code changes difficult in the
|
|
file itself. And when you want to alter sometime in the data
|
|
area, something called a heap is often used to store the
|
|
data. The thing with the heap is that it can be allocated at
|
|
anytime and depending on what is currently in memory, you
|
|
can't tell where the memory is going to be located. In these
|
|
cases, you might choose to go with run-time memory overlays
|
|
(discussed later).
|
|
|
|
Writing the Changes Out to the File
|
|
-----------------------------------
|
|
Okay, so you've found the copy protection. You also
|
|
know how to bypass it. Now, the next problem you will most
|
|
likely encounter is writing it out to a file. But first,
|
|
let's assume a simple case.
|
|
|
|
Using a Hex Dump Program
|
|
------------------------
|
|
Included is this package is one of the files from Norton
|
|
Utilities which does a decent job of finding and changing the
|
|
contents of files. Before we exit that debugger, we must
|
|
know what to look for.
|
|
|
|
1) At the location of the instruction, copy down the
|
|
machine language equivalent of the instruction. At
|
|
instructions after that, also take down their
|
|
machine level equivalents. This is what you will
|
|
use to search for the code in the file.
|
|
a) If there is a near call or a near jump or a near
|
|
memory access, you can just write down all the
|
|
|
|
|
|
Page 24
|
|
|
|
|
|
|
|
|
|
|
|
The Cracking Manual
|
|
|
|
|
|
|
|
hex numbers.
|
|
b) If there is a far call (CALL DS:[5C10+BX]) or a
|
|
far jump (JMP DWORD PTR ES:[5080+BX]) or a far
|
|
memory access (MOV AX,WORD PTR ES:[10+SI]), then
|
|
do not write these instructions down. In .EXE
|
|
files, anything that is located in different
|
|
segments will have different displacement
|
|
values. This is a value in the file. At the
|
|
beginning of the file is a table that tells DOS
|
|
where these instructions are located. When the
|
|
program is loaded into memory, the pointers are
|
|
changed appropriately to match the memory
|
|
location. So, write down other near
|
|
instructions like CLD, JZ 100, INC AX, etc.
|
|
2) After you know what to search for, you must now know
|
|
what you will have to be changing. Very often,
|
|
NOP's are used to "delete" code. For example, if
|
|
there is a CALL 3140 and we want to skip this call,
|
|
we can NOP it out. The near call takes up three
|
|
bytes. The NOP takes up one byte. So, type in "A"
|
|
at the address of the call and enter "NOP" three
|
|
times. Then unassemble the code to make sure that
|
|
the code still looks okay. Take down the machine
|
|
level equivalents of the NOP's (90h). Same thing
|
|
with conditional jumps. Suppose you have a JZ 90
|
|
and you want it to jump to address 90 everytime,
|
|
then type in "A" at the jump instruction and enter
|
|
"JMP 90". Then, just write down the machine code as
|
|
before. One thing, however. You cannot do what I
|
|
have just said above with far calls. Remember, the
|
|
numbers will be different in the file as compared to
|
|
memory. So what do you do? No problemo. At the
|
|
call instruction, trace into the call and place a
|
|
"RETF" instruction at the address of the callee.
|
|
This will be the location that you will search for
|
|
(write down the bytes here) and where you will be
|
|
writing to (RETF is CBh in machine language).
|
|
3) Finally, after all this is through, you can enter
|
|
your file editor and search for the numbers you
|
|
wrote down. Then, you can change the numbers. Now
|
|
run the program and it should be cracked. But
|
|
remember, always backup the file you are about to
|
|
change.
|
|
|
|
Using a Memory Overlay
|
|
----------------------
|
|
When do you use these things? You would use memory
|
|
overlays when step 3 (stated above) has failed in some way.
|
|
Maybe you couldn't find the code, or when you change it, the
|
|
program freezes up. Don't fret, the memory overlay is here.
|
|
What is a memory overlay? It is an external program (TSR)
|
|
that when it reaches a certain point during program
|
|
execution, it will change the location in memory you have
|
|
specified. It overlays the code during run time.
|
|
|
|
|
|
Page 25
|
|
|
|
|
|
|
|
|
|
|
|
The Cracking Manual
|
|
|
|
|
|
|
|
Here is what you will need to do to make the overlay
|
|
work. First, you must find some way for the program to call
|
|
up the overlay code. This can most easily be done by
|
|
reprogramming interrupts. So, the first thing you have to do
|
|
is look for an interrupt usage near the copy protection code
|
|
(usually an INT 21h or INT 10h). When you find this
|
|
interrupt (it must be fairly close to the code), write down
|
|
the address of the NEXT instruction. You must get down the
|
|
segment and the offset. Also, get down the current status of
|
|
the registers. For interrupts like INT 21h and INT 10h,
|
|
write down the functions numbers (eg. AX,AL,BX,DX,etc.).
|
|
Then, keep tracing until the copy protection code. Get the
|
|
address of the instruction that you want to change (the
|
|
segment and the offset). Also get down the machine language
|
|
equivalent of the changed code. This should be all you need
|
|
for the overlay program. Here is the overlay program:
|
|
|
|
INT_SEG equ 1DA5h ;SEG:OFF of instruction after the
|
|
INT_OFF equ 05D1h ; calling interrupt
|
|
CHANGE_SEG equ 2DA5h ;SEG:OFF of instruction to change
|
|
CHANGE_OFF equ 0432h
|
|
|
|
OVERLAY segment para 'code'
|
|
|
|
assume cs:OVERLAY,ds:OVERLAY
|
|
|
|
org 100h ;This will be a .COM program
|
|
|
|
START: jmp INITCODE ;Initialization code
|
|
|
|
;**************************************************************************
|
|
|
|
OLDINT dw 0,0 ;Storage for old interrupt address
|
|
|
|
ADDR_OFF equ <word ptr [bp+2]>
|
|
ADDR_SEG equ <word ptr [bp+4]>
|
|
|
|
CR equ 0Dh ;Carriage return
|
|
LF equ 0Ah ;Line feed
|
|
BEEP equ 07h ;Beep
|
|
EOS equ '$' ;End of DOS string
|
|
|
|
DISPLACEMENT equ CHANGE_SEG - INTSEG
|
|
|
|
;**************************************************************************
|
|
|
|
NEWINT proc far
|
|
|
|
push bp ;Establish stack frame
|
|
mov bp,sp
|
|
push ax ;Save necessary registers
|
|
push bx
|
|
push cx
|
|
push dx
|
|
|
|
|
|
Page 26
|
|
|
|
|
|
|
|
|
|
|
|
The Cracking Manual
|
|
|
|
|
|
|
|
push si
|
|
push di
|
|
push ds
|
|
push es
|
|
|
|
mov bx,ADDR_OFF ;Get offset
|
|
cmp bx,INT_OFF
|
|
jnz EXIT
|
|
|
|
cmp ax,0201h ;Check for AX=0201h <=(1)
|
|
jnz EXIT
|
|
cmp bx,0001h ;Check for BX=0001h <=(2)
|
|
jnz EXIT
|
|
|
|
mov bx,ADDR_SEG ;Get segment
|
|
add bx,DISPLACEMENT
|
|
mov ds,bx ;This will be the segment of change
|
|
|
|
;change the number at the next line to point to the offset of
|
|
; the address to be changed
|
|
mov bx,1C12h ;This is the offset of the change
|
|
mov al,0EBh ;This is the byte to be changed
|
|
mov [bx],al
|
|
|
|
;change the number at the next line to point to the offset of
|
|
; the address to be changed
|
|
mov bx,1C20h ;This is the new offset of the change
|
|
mov ax,0B8h ;This is the byte to be changed
|
|
mov [bx],ax
|
|
mov al,0 ;This is the next byte to be changed
|
|
mov [bx+2],al
|
|
|
|
pop es ;Restore necessary registers
|
|
pop ds
|
|
pop di
|
|
pop si
|
|
pop dx
|
|
pop cx
|
|
pop bx
|
|
pop ax
|
|
pop bp
|
|
iret ;Interrupt return
|
|
|
|
EXIT: pop es ;Restore necessary registers
|
|
pop ds
|
|
pop di
|
|
pop si
|
|
pop dx
|
|
pop cx
|
|
pop bx
|
|
pop ax
|
|
pop bp
|
|
jmp dword ptr cs:OLDINT ;Jump to old interrupt
|
|
|
|
|
|
|
|
Page 27
|
|
|
|
|
|
|
|
|
|
|
|
The Cracking Manual
|
|
|
|
|
|
|
|
NEWINT endp
|
|
|
|
;**************************************************************************
|
|
|
|
FINISH equ $
|
|
|
|
MESSAGE db "This is an overlay loader.",CR,LF
|
|
db "Written by The Cyborg.",CR,LF,BEEP,EOS
|
|
|
|
INITCODE:
|
|
mov ax,cs
|
|
mov ds,ax ;DS point to CS
|
|
|
|
mov ah,9 ;Print string
|
|
mov dx,offset MESSAGE ;The address of the message
|
|
int 21h
|
|
|
|
mov ax,3510h ;Get old interrupt address
|
|
int 21h
|
|
mov OLDINT[0],bx ;Save in memory for later use
|
|
mov OLDINT[2],es
|
|
|
|
mov ax,2510h ;Set new interrupt address
|
|
mov dx,offset NEWINT ;Point to new procedure
|
|
int 21h
|
|
|
|
lea dx,FINISH ;CS:DX of last byte of code to remain
|
|
int 27h ; in memory. Terminate and stay
|
|
; resident.
|
|
|
|
OVERLAY ends
|
|
|
|
end START
|
|
|
|
All you have to do is set the first four values in the first
|
|
four lines of the file. They are the segment:offset pairs of the
|
|
interrupt address and the address of the bytes to be changed.
|
|
Also, change the functions to check for at (1) and (2) to
|
|
appropriately check for proper code entry. Then, specify which
|
|
bytes you will be changing at the specified lines. Then compile
|
|
this crack ("ASM OVL {enter}").
|
|
The next program demonstrates a simple loader. It also
|
|
demonstrates what you can do if you have a program that utilizes
|
|
scripts or dynamically allocated data areas in heap spaces. This
|
|
program scans for a known segment in memory for a "keyword". When
|
|
it finds this, it can then begin writing new code to overlay the
|
|
old data. Note, KEYWORD specifies the keyword to look for. Then,
|
|
CRK (0's) is the list of bytes to replace the data areas pointed
|
|
to by addresses listed in LIST. The addresses in LIST are
|
|
displacement addresses. This means that at the address the
|
|
keyword was found in, the appropriate number listed in LIST is
|
|
added to that address. There are thirteen addresses whose data
|
|
are to be changed in this case.
|
|
Also interesting to note is that this program is using two
|
|
|
|
|
|
Page 28
|
|
|
|
|
|
|
|
|
|
|
|
The Cracking Manual
|
|
|
|
|
|
|
|
interrupt vectors, INT F1h and INT 21h. INT 21h is used in the
|
|
same way as the above overlay program uses it. It replaces two
|
|
bytes at offset 1FE5h with CDF1h. This is the machine language
|
|
equivalent of INT F1h. Now, let's examine what INT F1h actually
|
|
does. First, it changes the return address in the stack so that
|
|
instead of returning to the address right after the INT F1h
|
|
instruction, it will return to another instruction, located at
|
|
offset 1FE5. This is the location of the INT F1h instruction.
|
|
This interrupt, upon its completion, will replace the INT F1h
|
|
instruction with the original instruction and run the program
|
|
normally.
|
|
The loader itself is simple. It reallocates the memory
|
|
located to itself to accommodate a "daughter" program, the program
|
|
that it is going to load. If it can't find the program or if an
|
|
error has occurred trying to execute the program, the loader will
|
|
load itself up as a TSR. Then, you can run the program via DOS.
|
|
This loader also checks if INT F1h has been occupied and returns
|
|
an error if it is.
|
|
|
|
LOADER segment para 'code'
|
|
|
|
assume cs:LOADER,ss:LOADER
|
|
|
|
org 100h
|
|
|
|
BEGIN: jmp INIT
|
|
|
|
CR equ 0Dh
|
|
LF equ 0Ah
|
|
BEEP equ 07h
|
|
EOLN equ '$'
|
|
|
|
OPTION db 1 ;Options
|
|
CRC dw 0 ;Cyclic Redundency Checking data
|
|
|
|
START equ $
|
|
|
|
OLDINT1 dw 0,0
|
|
OLDINT2 dw 0,0
|
|
KEYWORD db "weat"
|
|
CRK db 0,0,0,0
|
|
LIST dw 0h,014h,019h,02Dh,041h,046h,05Ah,05Fh,073h,087h,08Ch,0A0h,0B4h
|
|
|
|
;********** New Interrupt 1 **********;
|
|
|
|
NEWINT1 proc far
|
|
|
|
push bp ;Establish stack frame
|
|
mov bp,sp
|
|
push ax ;Save registers
|
|
push bx
|
|
push cx
|
|
push dx
|
|
push di
|
|
|
|
|
|
Page 29
|
|
|
|
|
|
|
|
|
|
|
|
The Cracking Manual
|
|
|
|
|
|
|
|
push si
|
|
push ds
|
|
|
|
mov ax,cs
|
|
mov ds,ax
|
|
|
|
mov ax,word ptr [bp+2] ;Get offset
|
|
cmp ax,1FE7h
|
|
jnz EXIT1
|
|
|
|
NEXT1: mov ax,1FE5h ;Where to return next
|
|
mov word ptr [bp+2],ax
|
|
|
|
mov ax,word ptr [bp+4] ;Get segment
|
|
mov ds,ax ;Put in data segment
|
|
mov bx,1FE5h ;Offset to change
|
|
mov ax,0D803h ;The new code to put in
|
|
mov [bx],ax ;Store changes
|
|
|
|
mov ax,cs ;Get current data segment
|
|
mov ds,ax
|
|
|
|
mov di,0 ;Where to start search
|
|
mov dx,0FF00h ;Search the entire segment
|
|
mov bx,0
|
|
COMP: mov di,bx ;Where to begin
|
|
mov si,offset KEYWORD ;Get keyword
|
|
mov cx,4 ;Lenght of keyword
|
|
repe cmpsb ;Compare until done
|
|
jz MATCH
|
|
inc bx
|
|
dec dx ;Done?
|
|
jz EXIT1 ;If no match, exit
|
|
jmp COMP
|
|
|
|
MATCH: mov dx,bx
|
|
mov ax,0E07h
|
|
int 10h
|
|
mov bx,offset LIST ;Get list of codes to change
|
|
mov cx,13 ;Number of locations to change
|
|
NEXT2: push cx
|
|
mov cx,4 ;Lenght of string
|
|
mov di,[bx] ;Get destination
|
|
add di,dx
|
|
mov si,offset CRK ;Get string to copy from
|
|
rep movsb ;Copy String
|
|
inc bx ;Next location
|
|
inc bx
|
|
pop cx
|
|
loop NEXT2
|
|
|
|
EXIT1: pop ds ;Restore registers
|
|
pop si
|
|
pop di
|
|
|
|
|
|
Page 30
|
|
|
|
|
|
|
|
|
|
|
|
The Cracking Manual
|
|
|
|
|
|
|
|
pop dx
|
|
pop cx
|
|
pop bx
|
|
pop ax
|
|
pop bp
|
|
iret ;Interrupt return
|
|
|
|
NEWINT1 endp
|
|
|
|
;********** New Interrupt 2 **********;
|
|
|
|
NEWINT2 proc far
|
|
|
|
push bp ;Establish stack frame
|
|
mov bp,sp
|
|
push ax ;Save registers
|
|
push bx
|
|
push ds
|
|
|
|
mov bx,word ptr [bp+2] ;Get offset
|
|
cmp bx,0Ch ;See if called from the proper offset
|
|
jnz EXIT2 ;If not, exit
|
|
|
|
cmp ah,30h ;See if want this function call
|
|
jnz EXIT2 ;If not, exit
|
|
|
|
mov bx,word ptr [bp+4] ;Get segment
|
|
add bx,0F8Dh ;New segment
|
|
mov ds,bx
|
|
mov bx,1FE5h ;New offset
|
|
mov ax,0F1CDh ;The new instruction
|
|
mov [bx],ax ;Save changes in memory
|
|
|
|
EXIT2: pop ds ;Restore registers
|
|
pop bx
|
|
pop ax
|
|
mov sp,bp
|
|
pop bp
|
|
jmp dword ptr cs:OLDINT2 ;Call old interrupt
|
|
|
|
NEWINT2 endp
|
|
|
|
FINISH equ $
|
|
|
|
;********** Initialization Code **********;
|
|
|
|
PARAM dw 0
|
|
db 80h,0
|
|
PARAM1 dw 5 dup(0)
|
|
PROG db 8 dup('1234567890')
|
|
|
|
MESS db 'Savage Empire áeta Crack v1.0 July 15,1991',CR,LF
|
|
db 'Loader needed only after creating a character.',CR,LF
|
|
db "Press {ENTER} at the copy protection.",CR,LF,BEEP,EOLN
|
|
|
|
|
|
Page 31
|
|
|
|
|
|
|
|
|
|
|
|
The Cracking Manual
|
|
|
|
|
|
|
|
ERR1 db 'ERROR: Not enough memory. '
|
|
db 'Activating TSR sequence.',CR,LF,BEEP,EOLN
|
|
ERR2 db 'ERROR: Could not load program. '
|
|
db 'Activating TSR sequence.',CR,LF,BEEP,EOLN
|
|
ERR3 db 'ERROR: Interrupt vector (0xF1) already occupied.',CR,LF
|
|
db ' Release memory before restarting.',CR,LF,LF,BEEP,EOLN
|
|
|
|
INIT: mov ah,9 ;Print string
|
|
mov dx,offset MESS
|
|
int 21h
|
|
|
|
mov ax,35F1h ;Get interrupt vector
|
|
int 21h
|
|
mov OLDINT1[0],bx ;Save in memory
|
|
mov OLDINT1[2],es
|
|
|
|
cmp word ptr es:[bx],8B55h ;Check for vector occupation
|
|
jnz CONT1
|
|
|
|
mov ah,9 ;Write string
|
|
mov dx,offset ERR3
|
|
int 21h
|
|
mov ax,4C03h ;Exit with error 3
|
|
int 21h
|
|
|
|
CONT1: mov ax,25F1h ;Set interrupt vector
|
|
mov dx,offset NEWINT1
|
|
int 21h
|
|
|
|
mov ax,3521h ;Get interrupt vector
|
|
int 21h
|
|
mov OLDINT2[0],bx ;Save in memory
|
|
mov OLDINT2[2],es
|
|
|
|
mov ax,2521h ;Change interrupt vector
|
|
mov dx,offset NEWINT2
|
|
int 21h
|
|
|
|
cmp OPTION,0 ;See if wants to run program
|
|
jz EXIT3
|
|
|
|
mov ax,cs
|
|
mov ds,ax
|
|
mov es,ax
|
|
mov bx,offset ENDCODE ;Get end of memory
|
|
shr bx,1 ;Convert to paragraphs
|
|
shr bx,1
|
|
shr bx,1
|
|
shr bx,1
|
|
inc bx
|
|
mov ah,4Ah ;Reallocate memory
|
|
int 21h
|
|
jnc OKAY1 ;If no error, continue
|
|
|
|
|
|
|
|
Page 32
|
|
|
|
|
|
|
|
|
|
|
|
The Cracking Manual
|
|
|
|
|
|
|
|
mov ah,9h ;Write string
|
|
mov dx,offset ERR1
|
|
int 21h
|
|
jmp EXIT3
|
|
|
|
OKAY1: mov ax,cs
|
|
mov PARAM,ax
|
|
mov PARAM1,ax
|
|
mov bx,offset PARAM
|
|
mov dx,offset PROG
|
|
mov ax,4B00h ;Load and execute child
|
|
int 21h
|
|
jnc OKAY2 ;If no error, continue
|
|
|
|
mov ah,9h ;Write string
|
|
mov dx,offset ERR2
|
|
int 21h
|
|
jmp EXIT3
|
|
|
|
OKAY2: mov ax,25F1h ;Restore interrupt vector
|
|
lds dx,dword ptr OLDINT1
|
|
int 21h
|
|
|
|
mov ax,2521h ;Restore interrupt vector
|
|
lds dx,dword ptr OLDINT2
|
|
int 21h
|
|
|
|
mov ax,4C00h ;Exit with error code 0
|
|
int 21h
|
|
|
|
EXIT3: lea dx,FINISH ;Offset of booster
|
|
int 27h ;Exit with ejection of booster
|
|
|
|
LOADER ends
|
|
|
|
end BEGIN
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Page 33
|
|
|
|
|
|
|
|
|
|
|
|
The Cracking Manual
|
|
|
|
|
|
|
|
CONCLUSION
|
|
|
|
Conclusion
|
|
----------
|
|
Okay, so we've seen the processes of cracking. If you are
|
|
just a beginner and don't know much about programming, you
|
|
probably got lost somewhere right after the introduction. I would
|
|
suggest that you spend some time learning assembly before doing
|
|
anything else. Actually, you don't have to start out with
|
|
assembly. I started programming using BASIC. When I got really
|
|
good at it, I jumped into Assembly, regardless of how difficult
|
|
people said it was. Assembly is not at all difficult if you have
|
|
had some previous knowledge of another language. It is only
|
|
difficult if you make it hard. And after you've learned assembly,
|
|
you get a "feel" for the other languages and can learn them in a
|
|
matter of days. Pascal, Modula-2, C, C++, ..., they're are based
|
|
on assembly language programming.
|
|
Cracking is like the debugging process of programming. To
|
|
become experienced with debugging is to become adept at cracking.
|
|
You just need lots o' practice as practice makes perfect.
|
|
One final note. I got this manual out kinda quickly so there
|
|
are bound to be errors, inconsistencies in what I've said, unclear
|
|
passages, etc. Well, too bad. If you really want a good manual,
|
|
tell me or something and I'll consider it. I got really bored
|
|
towards the last parts of the manual so it went pretty fast,
|
|
skipping over some stuff. If a lot (and I mean A LOT) of people
|
|
want a better manual, tell me and give me suggestions. I'll find
|
|
the time to do it somehow.
|
|
Anyways, have fun!
|
|
- The Cyborg
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Page 34
|
|
|
|
|
|
|