exploit the possibilities
Home Files News &[SERVICES_TAB]About Contact Add New


Posted Dec 30, 2006

Beginning cracking of Window's software and software protection on x86 systems.

tags | paper, x86
SHA-256 | 8797103045b47d84aa72016aa7ac869d6c89827a1ae29cc23a29b9c65e12305d


Change Mirror Download
Beginning cracking of (x86) Window's software and software protection - without knowing assembly by Anonymous Author

Intro I learned how to crack simple programs quite a while before I learned any assembly language.
While it was crude and somewhat hit or miss, it was an aweful lot of fun. While I now know to some
small extent what I am doing, cracking software protection early on was practically a training
course in analysing things which I didn't understand. It is not neccessary to be able to write or
throughly understand assembly in order to crack software protection. In the following article, I
intend to teach you, the non cracking community, a little about cracking and analysing programs.
There are many very good crackers and reverse engineers out there, writing excelent cracking
tutorials, some of which will be referenced at the end of this article. The problem is that they all
focus specifically on one piece of software. While I will be doing this as well, this is intended to
be a more general guide, that will teach some basic techniques.

Tools _________

The first thing that pops to mind when told that one is going to be cracking software without
knowing assembly, is something along the line of "Wow! We must be using super 1337 analysing and
decompilation software!"

Dissassembler - Windasm 8.93 or later. You can no longer get this program from the original vendor,
so you'll have to look for it. Beware of backdoors and self exploiting versions of this software.
(Wait... why did DEP just catch something?) This is a disassembler. I will go into the background
theory on how it works later. There are much more advanced disassemblers, such as IDA Pro. I would
recomend against using these as they will become a crutch which will deprive you of the joy and
learning that use a cruder tool will allow you.

Hex Editor - There are a bunch of these, ranging from the simple (HexPert, HexEdit) to the seriously
cool (010 Editor). For our purposes, a simple hex editor such as hexpert (untimed shareware) is

Opcode reference - You are going to need a list of "opcodes" and what they do. See masm32. (Masm32
has a document called Opcodes.hlp, under help. You're going to need this.)

Debugger - We're not going to have use for this until much later in the article. I'd mainly like to
concintrate on using a disassembler, but I will explain some of the use of this tool.
Dissassemblers, especially extremely powerful ones (such as softice) quickly become crutches as
well. I would suggest OllyDbg as a good, simple debugger.

Pad of paper, notepad.exe, or something to take notes on - I always, always take notes.

masm32 - needed for assembling the crackme. Whatever you do, do NOT look at the examples that come
with this program. The examples are not in assembly!!! They are actually something called high level
assembly, a bastardization of assembly. Knowing this will not help you at all when looking at a

ZoneAlarm or other firewall - An lot of software calls out, and tries to tell the parent company if
you have a legit copy. Even if you don't care about being caught, you should block programs you are
cracking from the internet. Vendors will sometimes deactive cracked software when it calls out.

Information you will need to know _________________________________

- You will need to understand at least basic programming. You will need to be throughly familiar
with functions, loops, if/then/else, etc. While you need not be a programming guru, the more you
understand another programming language the more sense this will make.

- You will need to understand hexidecimal. Hexidecimal is base 16, basically you count going 0, 1,
2, 3, 4, 5, 6, 7, 8, 9, and then instead of 10, you go A, B, C, D, E, F. The next number after F is
10, then 11 etc. You're just adding more digits to the number system. Put the windows calculator in
scientific mode and play around with it, it's just like what you're used to. You can also use it to
convert between decimal (base 10, what your used to), and hexidecimal (base 16).

- You will need to know what assembly language is. You might laugh, but if you do not understand how
assembly relates to machine code, none of this will make sense.

- You must have the ablity to look up terms you don't understand. http://en.wikipedia.org is an
excelent resource for *anything* computer related. So if you don't know what an offset is, look it

Example programs ________________

I was initially going to use a piece of commercial software as an example, I ended up writing my own
crackmes as examples. This is so I could demonstrate, as directly as possible, whats going on.

- Crackme0 is the simplist copy protection I could come up with. It demonstrates basic cracking
techniques. It does not use a real software key, it only has a built in global variable to tell if
it's been registered or not. - Crackme1b is a more complex piece of copy protection, intended to
demonstrate removing a nag screen. It is also possible to crack the copy protection, as well as toy
with it in a number of different ways. This program uses a (very simple) software key.

Disclaimer & Warning ____________________

Disclaimer: I am not super leet. While I now understand assembly language, I am far from good at it.
I am also not a good cracker. There will most likely be a number of technical innaccuracies, but I
am teaching techniques, not a class. Everything I talk about in here I personally learned and done
at one time or another. I am not resonsible for you ripping off software; all software mentioned is
used as an educational example, and I do not condone or encourage anyone to do anything listed in
this paper. This is for educational purposes only.

In the beginning ________________

I tricked you, the reader. While you don't need to know assembly, I am going to teach you a tiny
tiny bit, just enough for you to be able to analyse the program. If you find this entertaining, I
highly recomend that you find a local college or course that will teach you assembly, so that you'll
actually be able to write it, rather than understand a little. You may want to fire up windasm, and
be looking at any random windows program while you read this part, so you can see examples of these
instructions in use.

I'd also like to add that this may look intimidating, but really is not.

One quick thing - Registers ___________________________

While this is not directly related to what we are doing, you will see these all the time, and need
to know at least what they are. A register is sort of like a variable, but it contains the
information on the processor it's self. There is a limited number of them, some of which have
special functions. They are called (in a 32 bit program) eax, ebx, ecx, and edx. There are more, for
special uses: ebp, esp, eip. These can moreover be broken up into other registers, for dealing with
smaller amounts of data, or a part of the value in the register; for example the second half of eax
(e stands for extended) is ax, and ax is made of ah and al. You don't really need to know any of
these, it's just useful for understanding whats going on.

Instructions that you need to know __________________________________ jmp (and friends) cmp call mov
nop Jmp is a very simple instruction. It moves to a new point in the program. It is unlike
programming in C, because you are not using a function. Say you see the following

label_a: jmp label_b blah blah blah blah label_b: dosomething

All you're doing here is moving the point at where the program is currently executing forward (or
backwards) to label_b. blah blah blah blah is therefore skipped. You should know that when you are
looking at a disassembled program, you will not have a informative label. It will rather be
something like "jmp 4Ch" 4C is a *relative* address. You take the current possition, add 4C bytes to
it and *poof* you have the new location.

<UnneccessaryInfo> For those interested in the details, or know a little assembly, you are changing
a register called eip (think of a register as sort of a perminant, changable variable, that stores
the information on the processor). eip always points to where the processor is currently at in any
piece of code. The jmp instruction tells the processor to add to eip. EIP stands for extended
instruction pointer. </UnneccessaryInfo>

cmp is another instruction you will need to know. Any time you see a cmp, the program is checking if
something. It's like an if(blah) statement in any other language. You cmp something, a register to a
register, a register to a piece of memory, something like that, and then decide what to do. Cmp will
NOT change where you are in memory, it just does the compairison, hence the next few instructions.

cmp, like everything else in "nasm" style assembly goes from right to left. The right instruction is
compaired to the left one. This isn't really important here, but it is when you are looking at a mov
statement (later).

<UnneccessaryInfo> The way cmp works is by simple subtraction. Think about the c statement if(3 ==
4). cmp subtracts 4 from 3, and sets some flags. if(3 == 3) then cmp comes up with 0 - they're
equal! It then sets some flags so that a conditional jump can be made. </UnneccessaryInfo>

Conditional Jumps a small (incomplete) table of the jump instructions:

jmp jump je == jump if equal jne != jump if not equal jg > jump if greater than jge >= jump if
greater than or equal jl < jump if less than jle <= jump if less than or equal jz == 0 jump if it's
equal to 0 jnz != 0 jump if it's not equal to 0

All these jump instructions work the same as jmp, except that they are used with a cmp to jump on a

Say you want to say if(haveValidKey != 0) run_the_program(); Thats what all these instructions are
for. First the information as to whether you have a valid key is evaluated (not shown), then the
information is moved to a register, then a compairison is made, then finally one of the above jump
statements is used to decide what to do.

So you should really think eax = haveValidKey; if(eax != 0) run_the_program();

This translates in assembly to mov eax, word ptr [haveValidKey] ;have valid key is a variable, it's
moved into eax (right to left) cmp eax, 0h ;0h is the same as 0. the h part means it's hex jne
run_the_program ;run_the_program is the location where the good stuff starts

As you can see, the data was moved to eax, a register, then compaired with 0, then lastly jne was
used. jne is Jump Not Equal, aka !=. See the UnneccessaryInformation for cmp if this confuses you.

Theres one last little thing I should point out, and thats when you're disassembling a program, you
get the exact same assembly code as above, but with one small difference: you don't get any labels,
comments, or variable names to make things clear.

In a disassembler this would look something like mov eax, word ptr [0x4d3db33f] cmp eax, 0x0 jne

0x4d3db33f would be the memory location of the variable that is being put into eax. 0x4d3db33f is
the same as saying 04d3db33fh - I use the h because that is what masm32 recognises. cmp checks 0,
and jne jumps to the rest of the program if it's != 0

You'll note if you look at the full list of jmp instructions, that there are a bunch of ones that do
pretty much similar things.

Full list of jmp instructions, stolen from an intel opcode reference (the one that comes with
masm32): JA Jump if Above JAE Jump if Above or Equal JB Jump if Below JBE Jump if Below or Equal JC
Jump if Carry

JCXZ Jump if CX Zero JE Jump if Equal JG Jump if Greater (signed) JGE Jump if Greater or Equal
(signed) JL Jump if Less (signed) JLE Jump if Less or Equal (signed) JMP Unconditional Jump (already
been covered)

JNA Jump if Not Above JNAE Jump if Not Above or Equal JNB Jump if Not Below JNBE Jump if Not Below
or Equal JNC Jump if Not Carry JNE Jump if Not Equal JNG Jump if Not Greater (signed)

JNGE Jump if Not Greater or Equal (signed) JNL Jump if Not Less (signed) JNLE Jump if Not Less or
Equal (signed) JNO Jump if Not Overflow (signed) JNP Jump if No Parity JNS Jump if Not Signed
(signed) JNZ Jump if Not Zero

JO Jump if Overflow (signed) JP Jump if Parity JPE Jump if Parity Even JPO Jump if Parity Odd JS
Jump if Signed (signed) JZ Jump if Zero

You can ignore all the ones (for what we're doing) that involve parity (a type of error checking),
and overflow (in assembly you can check for integer overflow and underflow, look it up if you're not
familiar with this).

call is an instruction that does the same thing as calling a function in any other language. It
moves to the new function, and when it is complete, keeps on going after the call.

An example would be call destroy_computer ;destroy_computer is a memory address in the program call

Say destroy_computer and reboot_computer are functions, this will call the function to destroy the
computer, and when that is done, will go to reboot computer, to really screw over whoever's computer
this is. Say, is that smoke coming out the back of the monitor?

<UnneccessaryInfo> You might be wondering about how data is passed to the functions. While I don't
want to go into detail, you need to read about the stack. It's really facinating - and with a little
assembly knowlage you'll start saying things like "but what if you did xyz, what would happen..."
xyz might be changing the return address, or some other fun way of messing with the computer. So
read about the stack, and the instructions that use it, push and pop. This is known as the stdcall -
the standard way of calling a function. Sometimes you'll see data stored in registers before a
calling a function. This is fastcall, because the computer does not need to mess around with the
stack (except to get where to return to). </UnneccessaryInfo>

mov just moves data from point a to b. You can move it from a register to a register, register to
memory, or vice versa. You just need to be able to recognise it. mov works from right to left

mov eax, 0h

puts 0 into eax. You should know that due to the physical constraints of the computer, you cannot
move memory to memory, without first storing it in a register. This is because if you were to copy
memory to memory, it would have no chance to go through the processor (basically).

nop does nothing. Literally. This instruction changes no data, processes nothing. It's really
useful. If you overwrite an annoying part of a program with nops, that annoying part has just ceased
to be. The nag screen on crackme1 can be removed with nops.

Now the tough part is over, and we can start to have some serious fun. For people interested in
learning more about assembly, I would recomend the book "Assembly Language, Programming for the IBM
PC Family" by William B Jones. Unfortunetly, the book is all MSDOS assembly, but all the techniques
are the same, and going from 16 bit dos to 32 bit windows is about as complicated as putting e in
front of ax.

First simple example ____________________

This is a small program that you are going to crack with your new, 1337 knowlage of assembly. All
this program does when run is pop up a window saying "This software is unregisterable!." All you are
going to do is make the other window pop up, the one that tells you that the program is registered.
There is no way to register this program other than cracking it. To get the most out of this
excersize, assemble the program in masm32's nice little editor, then disassemble it with windasm.
This is the way you are going to be looking at programs from now on. This will familiarize you with
windasm, with the original example to look at. Don't freak out if you don't understand all of this -
the point of this whole article is that you don't *need* to understand all of this to crack it. So
assemble this, run, disassemble in windasm, and prepair to crack it.

crackme0.asm ;-------------------------------------- ; Crackme0.asm by Anon ; Modify this program to
be registered. ;--------------------------------------

.486 .model flat, stdcall

option casemap:none ;don't worry about this crap

include c:\masm32\include\windows.inc ;masm32 includes for windows api calls and stuff include
c:\masm32\include\kernel32.inc ;this assumes that masm32 is installed to the include
c:\masm32\include\user32.inc ;default directory includelib c:\masm32\lib\kernel32.lib includelib

.STACK 256h .DATA ;This is the string table, pretty much. You can find it by going through a program
;With a hex editor - you'll find it near the end with all the strings used in the ;program
DLGCAP db "Crackme0",0 REG db "This program is registered",0 UNREG db "Damn - the program isn't
registered",0 ISREG dd 0 ;This is a global variable that tells us that the program isn't registered


;Main function - this can actually be called anything, but it's the same as main() Main PROC ; This
is the part of the program you need to be paying attention to

mov eax, ISREG cmp eax, 0 ;The comparison - is the program registered? jne prog_registered ;if(isreg
!= 0) goto prog_registered jmp prog_unregistered ;otherwise it's unregistered

prog_registered: ;Right here were are loading all the parameters for the dialog box ;then calling
it, then going to the end push MB_OK ;MB_OK is a value from one of the windows includes push offset
DLGCAP ;These are loading the strings push offset REG push 0 ;this is required by the windows
MessageBox function call MessageBoxA jmp theend

prog_unregistered: push MB_OK push offset DLGCAP push offset UNREG push 0 call MessageBoxA jmp

theend: push 0 ;end this program call ExitProcess

Main ENDP End Main ;------------------------------------------------------------------

Look at this program for a second. Think about what parts of this program could be changed, so that
the "This program is registered" box will appear. As with anything in life, there are multiple ways
to do it. Some people might have noticed the global variable ISREG. Well, what if this variable was
1, indicating that the program is registered? Because it is a global variable, you can actually find
and change this number. If it is a local or a temporary variable you cannot do this. So ok, you
could change ISREG. That would be the equivalent in a piece of serious copy protection to changing
the software key to something that works. So change ISREG, run the program, and it's registered. But
something like this isn't always practical. The variable will not always be part of memory, easy to
locate, or anything like that. Remember that we are going to be disassembling the program, so you
will not have a nice name of ISREG. In this case we should think about how we could tamper with the
actual compairison and jump. It's time for a little home made cracka theory.

Magic Spots ___________

This is my own name for it. I taught myself all this, so theres probibly a completely different name
for it. I call it a magic spot though. In any piece of copy protected software, the part that checks
the validity of the key on your computer (or even it's existance), is usually pretty complex. While
you could mess around with the ways in which it tries to evaluate the key, this is a pain in the ass
because it's complicated, and you don't understand everything thats going on. For each different
function that checks the validity of the key, no matter how complex, there is a point at which the
copy protection mechanism has made it's decision, and there is a cmp followed by some form of jmp.
This is a magic spot. No matter how many different ways the function is checking it's validity, it
will eventually narrow down to at least one comparison which is asking "After all that processing,
is this valid?" You want it to answer yes. Note that in 95% (or more) of copy protected software,
there is only one function checking the validity of the key. This means that in 95% (or more) of
software, there is at least one compairison, that when found and altered, cracks the software. The
problem is that there are a lot of cmp/jxx so finding the right one can be difficult. First you need
to find where the copy protection is, and where all the relevant parts of the program are. We'll go
into this later. For now, look at crackme0. This program is extrememly simple, so finding the exact
point in which the final comparison is made is quite easy. Remember this part? (The h after the 0
just means that it is a hexidecimal number.)

cmp eax, 0h ;The comparison - is the program registered? jne prog_registered

Well thats our magic spot. There is a compare and then if it is registered (eax != 0) you get the
dialog box saying it's registered. Crackme1 has a more complex example. There are a bunch of things
we could do to this, now that we've located it. You could change the comparison:

cmp eax, 0FFh ;masm32 likes having a 0 in front of hex numbers between A to F jne prog_registered

I think it's fairly safe to say that eax will not equal FFh (128 in decimal). In this case, the data
being compared to is different, and the the program will jump to registered. On the other hand, you
could change the logic of the jump. Instead of saying if(ISREG != 0) you could say if(ISREG == 0).

cmp eax, 0h je prog_registered

This can have some slightly weird behavior. In this case, if the program was originally registered,
it will now think it's not registered. However, if you're stealing this program, you'll get to use
it. Here is a list of some what operators are opposites:

Orig Opposite je jne jne je jg jle jge jl jl jge jle jg jz jnz jnz jz

Theres a better way to do it though. You want *everyone* to be able to use your crack, then why not
just change the conditional jump (jne) to an unconditional one?

cmp eax, 0h jmp prog_registered

Woot - it's cracked.

Before I leave this topic, I should note that finding a magic spot isn't the only way to crack a
program. More complicated cracking can be done - you can say, individually nop out a screen (and
it's parameters! Otherwise you'll mess up the stack) preventing you from using a program, rewrite
anything to get new behavior; many other things. Another thing you could do (not in this case, but
I'll make sure it's possible in some of the other crackmes) is to overwrite the beginning of the
copy protection with a jmp and have it land at a point directly after the copy protection. Remember
that there are different kinds of jumps depending on how far you want to go. There is a major
advantage to using a magic spot however, and that is that the program should work just as well as
had you bought it (copies of all crackmes available cheap!).

Patching your program _____________________

So you've found exactly what you want to change. You now need to patch the program. If you look at a
program thats disassembled in windasm, you'll notice that starting on the left, there is a column of
memory addresses, a column of hex, and a column of disassembled code. The memory addresses have
already been explained; it's where the program wants to be loaded into memory (***check).

<BackgroundInfo> While the way that windows loads a program is awfully complex, the basic idea is
that at least parts of it are read from the disk into memory before it's executed. I keep on talking
about what point a program is at in memory - I'm just talking about the computer going through this
piece of memory and executing the statements. Earlier I mentioned eip - this register contains the
address in memory that the code is currently at. </BackgroundInfo>

Basically what you have to do now is take your modification, and hand assemble the new instruction
and then patch the program with a hex editor. Fortunetly, this is simple. Assemblers are basically
tables of instructions and what their hex equivalent is. So with the documention, you can assemble
stuff by hand. In this case, we won't be changing the size of the program (which would require
updating some jmp instructions after the patch), we'll just be overwriting an instruction. You're
going to need something called an opcode table or "bare hex opcodes to mnemonics" table. I'll try to
include a link to one, but I don't know how long the sites I place it on will last for. There is one
in the help section of masm32. Because you might not want to find this now, I'll give a few hex
opcodes here (recognize this?). I have to explain one more thing first. These are not the only hex
opcodes for these instructions, they vary depending on the instruction, (sometimes) registers used,
amount of memory being used for arguements to the instruction, and other factors. All the hex
opcodes listed here are for SHORT jumps (this is what you will see 90% of the time). HEX jmp jump
EB je == jump if equal 74 jne != jump if not equal 75 jg > jump if greater than 7F jge >= jump if
greater than or equal 7D jl < jump if less than 7C jle <= jump if less than or equal 7E jz == 0 jump
if it's equal to 0 75 jnz != 0 jump if it's not equal to 0 74

cmp eax, anything 3D cmp anyregister, almostanything 81

nop 90 (recognize this from shellcode?)

The hex opcode given will be followed by the amount to jump (in hex). You'll note that jz = jne and
jnz = je. If you read the unneccessary information for cmp, you'll see that this is simple due to
the way cmp works. A short jmp will be followed by hex indicating how far to go. Likewise, a cmp
will be followed by the hex of what to compare it to.

I'm going to demonstrate patching crackme0.exe. In this case we're going to use the last crack for
crackme0, turning a conditional jump into an unconditional jump. First, disassemble the program in
windasm. You'll notice that while it's really the same, it'll look somewhat different. Get used to
seeing stuff like this. On the leftmost side there is the memory address, with the hex to the right
of that, and the instructions further right.

mov eax, ISREG cmp eax, 0 ;The comparison - is the program registered? jne prog_registered

now looks like:

:00401000 A148304000 mov eax, dword ptr [00403048] :00401005 83F800 cmp eax, 00000000 :00401008 7502
jne 0040100C

00403048 is the location of ISREG in memory, and 0040100C is the new location to jump to. Note that
the hex for that statement is 7502 - 75 is jne, 02 is how far forward to go (if you count the bytes,
start at the *end* of the instruction).

We want to make jne (75), unconditional (EB). All you have to do is find the right 75 in the hex
editor of your choice, and overwrite it with EB. Simple, huh? The only catch is in the hex editor
you will not have the same memory addresses. Instead you will have the offset from the beginning of
the file. The easiest thing to do is search for a long line of hex in the hexeditor. In this case
try A14830400083F8007502. The chances of there being another set of instructions that long with the
same hex is awefully small but possible. Change the last 75 to the EB.

<UnneccessaryInfo> Ok, you want to be able to calculate where the patch is supposed to go. In
windasm you will see:

Program Entry Point = 00401000 (crackme0.exe File Offset:00001600)

The entry point is where the program is entered NOT the beginning of the file. The file offset tells
you how far the entry point is from the beginning of the file. Lastly, the hex editor tells you how
far into the file you are. I'm just going to show you the algebra (make sure your calculator is in
hex mode):

a = instruction you want to change x = offset in the file

x = a - program_entry_point + file_offset_of_program_entry_point

The location of the jne is 401008. Go to x in crackme0.exe (in the hex editor). (***FIX wtf - is
windasm giving the wrong file offset?) </UnneccessaryInfo>

Memory and stuff ________________

I feel obligated to explain a little more background information before going into cracking genuine
software that you don't have the commented source for. When you disassemble a program, the numbers
represent where it's supposed to load in memory. Bizarrely enough, each program that is compiled has
a place in memory where it usually sits. (***check accuracy) If this location is taken, it can be
moved elsewhere. Buffer overflows use this a lot - ever notice that your exploit only works on one
particular distribution even though the vulnerablity is in a particular piece of software? This is
because bof (buffer overflows) frequently need to know where something - the program, a piece of
data or shellcode, or a library - is located. Because each distribution has different memory
locations, you need to find the correct locations to make the exploit work, and not do something
with the wrong piece of memory.

What part of the program do you want to target? _______________________________________________

Theres almost always more than one way to crack a program. For example, you could try to crack the
part of a program that detects if it's registered or not. You could also attack the part of the
program that registers the program - and let the register dialog do the hard part. Those are the
best two areas that I know of to attack by changing magic spots. If, for example, a program
restricts features until you pay for it, you can go around and try to crack that - either turning on
individual features, or find a magic spot where it tries to detect the copy protection. If it's a
time limit, you can do anything from changing the function that gets the time to always return a
time way in the future, or figure out where it's getting the original time. If you learn a bit more
of assembly more complex options are avaliable - you can toy around with adding functions, figuring
out weird pieces of code, modifying parameters of functions, stuff like that.

<ImportantNote> Whether you realize it or not, you're hacking a program - the same mind set applies.
While you can go through and do exactly what you were shown, you can also experement with playing
with the program in strange or unusual ways. The end goal is to get the program to do what you want,
and there are no holds barred in what you're allowed to try to get it to do that. Try to think of
clever, new, or unique ways of changing the program to alter it's behavior. </ImportantNote>

Finding the important stuff ___________________________

This is the single most important part of cracking using magic spots. You need to figure out where
it is. Strings, Dialogs, unique or recognisable API calls, and resources (which are not integrated
into windasm, and therefore are harder to track down) are going to be your way of tracking down the
important pieces of code. You can also find it with a debugger, which will be covered later, along
with it's advantages and disadvantages. String references are probibly the easiest way of finding
the parts of code that you want to first look at. Unfortunetly, as time goes on, you are
increasingly unlikely to find a string that leads you directly to the general area you want to be.
Basically, click on a string in windasm (like "This program has expired") and it'll take you to the
general region you want to be in. Dialog boxes - while a dialog will only be listed in windasm if
it's part of the resource table, this is still a useful way of finding things. API calls - There are
two ways which these are useful. First, they kind of comment parts of the code and tell you a little
about whats going on. Also, if there is an api that's probibly being used for copy protection, you
can narrow down the area that you're looking for. Windows resources - Unfortunetly, windasm hasn't
been added to in a long time, and does not have an easy way of telling you when a windows resource
is being referenced. This is still a problem for me; if anyone has a really good way of figuring out
what resources are being used when in a program, I'd appreciate knowing. When I deal with something
thats using a windows resource, I usually go through the program with a debugger and keep an eye out
for the resource. You can also figure out where a resource is in memory (inside the program), by
looking at the program's resource table (010 editor is great for this). You could also spend a lot
of time with a hex editor and the pecoff.doc document - it will tell you where to find this section
of the program. You could then go through and find references to memory locations that are on the
resource editor.

Windows APIs sometimes associated with copy protection

When there is a call to part of the windows API, windasm (and ollydbg) will tell you what api
(basically a microsoft supplied function) it is. In windasm, use the "imported functions" box to
find a list of api functions used. You should be aware that there exist ways of loading apis without
it being on the program's import table, but these (with luck) set off antivirus heuristics, and are
generally avoided by vendors. Disassembled programs have no programmer comments, but APIs give good
clues as to what a section of code is doing.

MessageBox / MessageBoxA / MessageBoxEx / MessageBoxExA: Everytime you see a little box pop up like
the one in crackme0, it's using a messagebox. These are frequently used for errors, telling you that
you're license has just expired, and other small bits of information. Sometimes, if there aren't a
whole lot of these, you can go through and find which messagebox is the one you want.

Anything with the word winsock in it: Winsock is windows sockets - network stuff. If you don't think
you're copy of Ableton Live should be talking to the internet, then it's probibly passing
information to the company about you.

GetFileSize: Some programs check to make sure that it's size has not changed (which would indicate
that it may have been cracked).

GetLocalTime: You'll see this frequently used to tell when a demo has expired.

GetFileTime: Sometimes programs will figure out if a trial has expired by reading the creation time
of it's self, or another file associated with the installation.

GetDriveTypeA: Sometimes used as a crude way of making sure that a program is being run from a
cdrom. Even more sophisticated anti duplication protection will ususally start by checking this.

Reg*: This indicates that the registry is being used at that point. Sometimes you'll see an
associated string or resource telling you what key is being messed with.

There are way too many to list here, I really just wanted to give the reader an idea of what to look

Using a debugger to find important stuff ________________________________________

I don't really want to go into how to use a debugger; I actually didn't start using one until a year
ago, but now I can't do without it. Basically, instead of hunting for clues to take you to an
important spot, you could let the program do it it's self, and tag along watching. This is one of
the many uses of a debugger. The basic idea is you let the program run until it reaches a point
which you want to find (something visable happens in the program that you know will be related to
copy protection). If you're using OllyDbg, "trace over" the program, then run it. Tracing
traditionally means going instruction by instruction to a program. As the program executes, note
that you can look at whats happening to registers and stuff. You can also see a list of calls that
were made. When you interrupt the program at an interesting area, you can use the call stack, and
see what functions led up to that point. Don't be supprised if you see the program jumping to weird
parts of memory, that are outside of the program. These are generally calls to the windows api. You
should be aware that you can set a breakpoint in a program with a debugger - if you'd like to
examine the program at a specific point that you've thought of, set a breakpoint. Then the program
will pause while you examine memory, registers, etc. I'd also like to note that it's an aweful lot
easier to program in assembly if you have a debugger there for when things misteriously don't work
the way you think they should. A debugger is an extremely powerful tool, and makes going through a
complex or simply large program a lot more efficient. It's also targeted by vendors, who will do
anything to fuck it up.

Analysing parameters to calls _____________________________

A really dense, hard to read book that contains a lot of excelent information is "Reversing Secret
of Reverse Engineering" by Eldad Eilam . I never managed to finish it, but the parts I read taught
me a lot. If you don't know assembly, you will get little out of it. Something that the author goes
into in length at the beginning of the book is how to figure out what the parameters are of a
function by looking at paramaters that are used right before a function call. I don't want to go
into anywhere near the detail that Eldad Eilam did, but you should look at this example:

;calling a function mov eax, word ptr[some_mem_location] push eax ;parameter 1 push offset blah
;parameter 2 push offset blah2 ;parameter 3 push 0 ;parameter 4 call some_function.

While I didn't go into it, push and pop are instructions for adding and removing data from the
stack, a piece of memory where you shove crap you don't want to deal with at that second. When you
see a bunch of pushes before a call, those are parameters that are being passed to the function. If
you go into the function it's self, you will generally not see a corresponding set of pops.
Generally the function will refer to these by their offset from ebp, the register that hold the base
pointer of the stack (memory location of the stack's bottom in memory). The stack's location will be
fixed back to the way it was originally when you ret (return) from the function. You'll notice one
other screwy thing, and thats when the parameters are used *in the function*, the first parameter
appears to be skipped in memory. That is because when you call the function, call puts one more
thing on the stack - the return address. The ret instruction uses this to get back to where it was,
after the call. See crackme1.asm for an example.

Tricks the software vendors will use against you ________________________________________________

I don't know all the tricks by a long shot. You'll start to see them as you go through programs. I
highly recomend perminantly saving any anticracking technique you see - this list will be invaluble.
I don't want to give away too many - you should be finding these your self.

- Having misleading strings leading to pieces of code. A great example is the old diabo II game. If
you disassemble the main program you'll see around 6 strings (don't really remember how many) with
similar messages, complaining about the cd not being legit. - Garbling strings. Look at the recent
norton antivirus updates. You'll see gibberish in the string table. If you whats happening you'll
see a string reference, followed by the code to decode it :). Note that there's another trick used
there, which is commonly used to screw up debuggers, disassemblers, and pretty much any kind of code
analysis. - Jumping to the middle of an instruction. Sometimes a section of a program will have an
instruction, and the instruction will be garbage or something (a really good coder could make both
do something useful, but I've never seen this). The jump instruction will place you in an arguement
to the instruction, which the computer will happily interprite as machine code. - Weird placement of
int. Int stands for interrupt, I won't go into what it's used for (complex), but you'll see it used
for setting hardware breakpoints. If a debugger somehow runs into one of these it will stop... -
Spurious exceptions. You'll find a lot of programs unneccessarily making exceptions and then
handling them. An exception is a way of checking if an error has occured. I can never tell if this
is the result of bad programming, or something deliberately made to annoy me. - Weird instructions.
Example: test esi,esi jl somewhere I finally wrote a short program to figure out how this one
worked. Basically it's a way of saying jmp. I'd imagine that programs that analyse program structure
and branches would get messed up by this. - Weird use of threads. A thread is a way of breaking the
execution of a program into several simultanious pieces of running program (think fork()). Sometimes
you'll see threads split off to confuse whoever's debugging the program.

Getting practice ________________

Theres no simple way of telling how good the copy protection is on a program, other than trying it.
Really expensive pieces of software are not a good place to start. Find some shareware programs
(without spyware) and try to crack them. Also, look for "crackme" online. A lot of people write copy
protection programs as tests or practice. Watch out for occasional malicious code with these. The
first program I cracked was the original norton standalone virus updates. If you can find one, it's
an excelent place to start. Screensavers are really just programs, and sometimes have simple copy
protection which isn't too hard to crack.

Other programs that will help you a lot _______________________________________

Filemon and Regmon - Sysinternals has a million useful programs. Find them at www.sysinternals.com.
Of particular interest to crackers are RegMon and FileMon. Filemon will tell you every file that is
being used. Use this to find if the programs trying to find a keyfile or something. Regmon will tell
you everything thats trying to use the registy, great for tracking down hard to find registry keys.
Play around, they're self explainitory.

Resedit/Reshack - This stands for resource editor, and allows you to view and modify anything in the
program's resource table. The name is actually kind of a joke, and is named after an old mac
program, with somewhat similar capablities.

Books _____

Opcodes.hlp by Intel - You'll find this in the help files for masm32. It is invaluble to a cracker,
and contains the most common instructions, how they work, and their hex equivalents. This is a must

Assembly Language - Programming for the IBM PC family by William B Jones - I really wish this book
wasn't 16 bit and intended for DOS. It also uses macros for a few common things (_Begin for
example). Other than that, it's an excelent book on programming in assembly.

Intel(R) Architecture Software Developer's Manuals (1-3) - I don't really recomend trying to read
this, but it is almost complete documentation for every damn thing a x86 processor can do.

Reversing Secrets of Reverse Engineering by Eldad Eilam - This book contains a lot of really really
good information. Unfortunetly, it's also extremely difficult to read. If you attempt to read it,
have a) whatever book you learned assembly from sitting next to you b) a lot of time to go through
examples c) headache medication and d) a very long attention span.

Hacker Disassembling Uncovered by Kris Kaspersky - This is much easier to read than Reversing
Secrets of Reverse Engineering. I haven't finished it yet, but so far it's pretty good.

PECOFF.DOC by Microsoft Corporation - This is the "Microsoft Portable Executable and Common Object
File Format Specification" In case you weren't aware, a windows program is in the PE executable
format. This great little document tells you the format for a windows program, and allows you to
decode and figure out certain things about the program. It's also fun when playing with a hex

Linux magic file - You can find this on any *nix machine. This useful file tells you how to figure
out what type of file something is by looking at what it begins with. This is useful when dealing
with anything that has a different type of file embedded in it - for example installers, self
extracting files, etc.

Other people's cracks - This is sort of like looking at the answers to a question. Find a program,
use the crack, and use a binary diff utility to find out what changed. Disassemble, and then figure
out how the program was modified.

Sites _____

http://www.woodmann.com/fravia/index.htm - While the original site is gone, this is a mirror. It has
many tutorials, guides, pretty much everything. Also has stuff about writing spiders.

http://www.crackstore.com/ - Has lots of tutorials. To download a tutorial, use the path given by
the error message and append it to www.crackstore.com. When they changed to a non vhost, they didn't
fix all the links.

http://uninformed.org/ - I'm not sure if these guys want to be linked to, but it's a really good
zine about hacking, exploitation, reverse engineering, and so forth. It basically fills the void
left by phrack.

http://win32assembly.online.fr/tutorials.html - Check out _Masta_'s assembly tutorials. Iczelion's
are kinda high level assembly (as in the language, not the difficulty), and while contain good
information, should be initially avoided.

; Crackme0.asm by Anon
; Modify this program to be registered.

.model flat, stdcall

option casemap:none ;don't worry about this crap

include c:\masm32\include\windows.inc ;masm32 includes for windows api calls and stuff
include c:\masm32\include\kernel32.inc
include c:\masm32\include\user32.inc
includelib c:\masm32\lib\kernel32.lib
includelib c:\masm32\lib\user32.lib

.STACK 256h
;This is the string table, pretty much. You can find it by going through a program
;With a hex editor - you'll find it near the end with all the strings used in the

DLGCAP db "Crackme0",0
REG db "This program is registered",0
UNREG db "Damn - the program isn't registered",0
ISREG dd 0 ;This is a global variable that tells us that the program isn't registered


;Main function - this can actually be called anything, but it's the same as main()
; This is the part of the program you need to be paying attention to

mov eax, ISREG
cmp eax, 0 ;The comparison - is the program registered?
jne prog_registered ;if(isreg != 0) goto prog_registered
jmp prog_unregistered ;otherwise it's unregistered

;Right here were are loading all the parameters for the dialog box, then calling it, then going to the end
push MB_OK ;MB_OK is a value from one of the windows includes
push offset DLGCAP ;These are loading the strings
push offset REG
push 0 ;this is required by the MessageBox function
call MessageBoxA
jmp theend

push MB_OK
push offset DLGCAP
push offset UNREG
push 0
call MessageBoxA
jmp theend

push 0 ;end this program
call ExitProcess

End Main

; Crackme1.asm by Anon, Simple Nag Screen
; Modify this program to be registered.
; This is an example of several things:
; -It has a nag screen which can be removed
; -It has a built in, incorrect key. You can
; crack the main program to accept the key,
; crack the function that checks the key (a
; little different) or crack the main function,
; so that it thinks a correct key has been
; given.
; -A keygen can be made for this program
; A correct key:

.model flat, stdcall

option casemap:none ;don't worry about this crap

include c:\masm32\include\windows.inc ;masm32 includes for windows api calls and stuff
include c:\masm32\include\kernel32.inc
include c:\masm32\include\user32.inc
includelib c:\masm32\lib\kernel32.lib
includelib c:\masm32\lib\user32.lib

.STACK 1024h
DLGCAP db "Crackme1",0
RUN db "You are now past the nag screen",0
UNREG db "Buy our damn software!",0
; WRONGKEY dd 1, 2, 3, 4, 5, 6, 7, 8 ;You'd usually see the key loaded from a file, registry key, or resource
WRONGKEY dd 7FDCh, 7FDCh, 7FDCh, 7FDCh, 7FDCh, 7FDCh, 7FDCh, 7FDCh

mov eax, offset WRONGKEY
push eax
call ChkRegistered ;returns in ebx
cmp ebx, 1
je mainprog

push MB_OK
push offset DLGCAP
push offset UNREG
push 0
call MessageBoxA

push MB_OK
push offset DLGCAP
push offset RUN
push 0
call MessageBoxA

push 0 ;end this program
call ExitProcess

ChkRegistered PROC
; params: ChkRegistered(int *key)
; returns whether its registered in ebx
; clobbers eax, ebx, ecx, and edx (damn you mul!)
; this is a very simple key check, see if you can
; write a keygen!
key equ [ebp + 8] ;read the end of "Analysing parameters to calls"
;kend equ [ebp + 12] ;this is now unneccessary, the keysize is fixed by KEYSIZE

push ebp
mov ebp, esp

mov ecx, 0 ;loop counter is ecx
cmp ecx, KEYSIZE
jge endchkregloop

push ecx ;this section comes up with the location of the current element
mov edx, 0 ;ecx * 4 + offset key
mov eax, ecx
push ecx
mov ecx, 4
mul ecx
pop ecx
mov ecx, eax
add ecx, key

mov eax, [ecx] ;ecx should contain the memory location of the current element
shl eax, 1 ;super secret reverse keygen algorythm!
xor eax, 0FFFFh ;check the size on the second arguement

mov edx, 0 ;when using div or idiv, quotient is in eax, remainder in edx
mov ecx, 7 ;eax is already set
idiv ecx ;divide by 7 - end of super secret reverse keygen algorythm
cmp edx, 0 ;remember, edx is the remainder. I'm basically doing % 7
jne notreg

pop ecx ;restore ecx to the counter
inc ecx
jmp chkregloop

mov ebx, 1
mov esp, ebp
pop ebp
ret 4

mov ebx, 0
mov esp, ebp
pop ebp
ret 4

ChkRegistered ENDP

End Main

Login or Register to add favorites

File Archive:

August 2022

  • Su
  • Mo
  • Tu
  • We
  • Th
  • Fr
  • Sa
  • 1
    Aug 1st
    20 Files
  • 2
    Aug 2nd
    4 Files
  • 3
    Aug 3rd
    6 Files
  • 4
    Aug 4th
    55 Files
  • 5
    Aug 5th
    16 Files
  • 6
    Aug 6th
    0 Files
  • 7
    Aug 7th
    0 Files
  • 8
    Aug 8th
    13 Files
  • 9
    Aug 9th
    13 Files
  • 10
    Aug 10th
    34 Files
  • 11
    Aug 11th
    16 Files
  • 12
    Aug 12th
    5 Files
  • 13
    Aug 13th
    0 Files
  • 14
    Aug 14th
    0 Files
  • 15
    Aug 15th
    25 Files
  • 16
    Aug 16th
    3 Files
  • 17
    Aug 17th
    0 Files
  • 18
    Aug 18th
    0 Files
  • 19
    Aug 19th
    0 Files
  • 20
    Aug 20th
    0 Files
  • 21
    Aug 21st
    0 Files
  • 22
    Aug 22nd
    0 Files
  • 23
    Aug 23rd
    0 Files
  • 24
    Aug 24th
    0 Files
  • 25
    Aug 25th
    0 Files
  • 26
    Aug 26th
    0 Files
  • 27
    Aug 27th
    0 Files
  • 28
    Aug 28th
    0 Files
  • 29
    Aug 29th
    0 Files
  • 30
    Aug 30th
    0 Files
  • 31
    Aug 31st
    0 Files

Top Authors In Last 30 Days

File Tags


packet storm

© 2022 Packet Storm. All rights reserved.

Hosting By