0% found this document useful (0 votes)
256 views

The Cracking Manual

Cracking is the art of removing copy protected coding from programs. Unlike software development, you are given no source code, only the machine level code. Cracking requires patience. No patience, no cracking.

Uploaded by

rajulhakim
Copyright
© Attribution Non-Commercial (BY-NC)
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
256 views

The Cracking Manual

Cracking is the art of removing copy protected coding from programs. Unlike software development, you are given no source code, only the machine level code. Cracking requires patience. No patience, no cracking.

Uploaded by

rajulhakim
Copyright
© Attribution Non-Commercial (BY-NC)
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
You are on page 1/ 27

The Cracking Manual

-------------------------------------------------------------
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 ------------ 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.

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. 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 neat 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

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 kindergarten 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 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 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.
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] 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 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.
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 handy. Also, when the data within the
file changes due to overlays, loaders are also good to use.
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.
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.
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.
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
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 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
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 an

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. 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
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. 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.
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 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.
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

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.
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 theINT_OFF equ 05D1h ;
calling interruptCHANGE_SEG equ 2DA5h ;SEG:OFF of
instruction to changeCHANGE_OFF equ 0432hOVERLAY segment para
'code' assume cs:OVERLAY,ds:OVERLAY org 100h
;This will be a .COM programSTART: jmp INITCODE
;Initialization
code;*****************************************************************
*********OLDINT dw 0,0 ;Storage for old
interrupt addressADDR_OFF equ <word ptr [bp+2]>ADDR_SEG
equ <word ptr [bp+4]>CR equ 0Dh
;Carriage returnLF equ 0Ah ;Line feedBEEP
equ 07h ;BeepEOS equ
'$' ;End of DOS stringDISPLACEMENT 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 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 returnEXIT: 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 interruptNEWINT
endp;*****************************************************************
*********FINISH equ $MESSAGE db "This is an overlay
loader.",CR,LF db "Written by The
Cyborg.",CR,LF,BEEP,EOSINITCODE: 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 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 100hBEGIN: jmp INITCR
equ 0DhLF equ 0AhBEEP equ 07hEOLN equ
'$'OPTION db 1 ;OptionsCRC dw 0
;Cyclic Redundency Checking dataSTART equ $OLDINT1 dw
0,0OLDINT2 dw 0,0KEYWORD db "weat"CRK db
0,0,0,0LIST 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 push si
push ds mov ax,cs mov ds,ax mov
ax,word ptr [bp+2] ;Get offset cmp ax,1FE7h jnz
EXIT1NEXT1: 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,0COMP: 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 COMPMATCH:
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 changeNEXT2: 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
NEXT2EXIT1: pop ds ;Restore registers
pop si pop di pop dx pop cx
pop bx pop ax pop bp iret
;Interrupt returnNEWINT1 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
memoryEXIT2: pop ds ;Restore registers
pop bx pop ax mov sp,bp pop bp
jmp dword ptr cs:OLDINT2 ;Call old interruptNEWINT2 endpFINISH
equ $ ;********** Initialization Code **********;PARAM dw
0 db 80h,0PARAM1 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,EOLNERR1 db 'ERROR: Not enough memory.
' db 'Activating TSR sequence.',CR,LF,BEEP,EOLNERR2 db
'ERROR: Could not load program. ' db 'Activating TSR
sequence.',CR,LF,BEEP,EOLNERR3 db 'ERROR: Interrupt vector
(0xF1) already occupied.',CR,LF db ' Release memory before
restarting.',CR,LF,LF,BEEP,EOLNINIT: 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
21hCONT1: 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 mov
ah,9h ;Write string mov dx,offset ERR1
int 21h jmp EXIT3OKAY1: 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
EXIT3OKAY2: 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 21hEXIT3: lea dx,FINISH
;Offset of booster int 27h ;Exit with
ejection of boosterLOADER ends end BEGIN
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!

You might also like