How the crackers crack code?
Posted by davitb on October 11th, 2009
There are several reasons why a software company would decide to implement heavy protection schemes in their applications by spending lot of development resources, time and money. These reasons are mainly related to the business models of the applications. License based applications (IDE, compilers, etc), applications with valuable IP inside (EDA applications, etc) and applications which have access to confidential information (DRM, authentication software, etc), in addition to their main logic, also require difficult protection schemes implemented inside which will ensure that the integrity, confidentiality and availability of the assets, inside these applications, will not be damaged.
It has always been a mystery for me how crackers try to break software. What techniques they are starting with when they have the executable in hand, or what tools they are using for doing the crack.
In general the motivation of crackers is obvious and is the same as what the abovementioned applications want to prevent from:
- They are trying to use software without paying money (break)
- They are trying to steal intellectual property of applications to create a copy of it
- They are trying to steal confidential information (such as cryptographic keys) from applications to have access to other valuable information, such as user credentials, high-definition video content, etc, which is accessible in this application
In this article we will try to outline the techniques and tools that crackers are using while trying to break protections that exist in applications.
Typical “cracking lifecycle” consists of the following steps:
- Static and dynamic analysis of binary executable file
- Preparation for an attack
- Automation (optional)
Usually the first two steps are mandatory but the third is optional and depends on the crackers motivation. If the goal is reverse engineering of IP based algorithms – there is no need to automate the attack. However, for removing license checks – the automation phase is essential.

The diagram above shows details of these steps and how they actually interact with each other. The adversary usually starts with conducting static and dynamic analyze of the executable. After some protection mechanisms are discovered, the next step will be to remove it, rebuild the executable and test. This process will continue until all protections primitives are removed.
During analysis the adversary can use very different techniques and of course there is no way to cover all possible approaches in one article as they are being improved over time and new, smarter, more complex approaches are being invented. It’s important to note that the cracker has full control over the environment where he runs the target executable. He can run debuggers, run the executable under virtual machine, hook system DLLs, write a kernel rootkit, etc.
Let’s go over each technique mentioned in the diagram above and see how they are performed.
Learning the Executable structure (Static analysis)
The first thing that the cracker would do (though it highly depends on his/her taste) is probably learning the structure of executable. Though this step is not very difficult (comparing to others) the information she can gather from it is essential for the next steps.
The following information can be comparably easily obtained from an executable:
- What libraries is it dynamically linked to? (if any)
- Symbol Table (if any)
- The starting address of executable
- The starting and ending addresses of text and data segments
Tools which can help you to dump this information are usually available by default in the operating system or are included in the package of integrated development environments. For Linux type systems it will be GNU Binutils (http://en.wikipedia.org/wiki/GNU_Binary_Utilities), for Windows – set of Dumpbin tools. In addition of course IDA Tool, PE explorer can also be used for this purpose.
The following link provides comprehensive listing of available tools:
http://en.wikibooks.org/wiki/X86_Disassembly/Analysis_Tools
Searching for known strings (Static analysis)
The next obvious thing the adversary will try to do is searching for string characters which the program outputs as an indication for error. For example, a license checking or registration based program must have a way to inform the user that registration code is wrong or that the license has been expired. Obviously the adversary can search for these strings in the binary file and try to locate the place of license check.
Constant data is usually embedded in data segment so the basic algorithm for disabling the license check or registration code check would be:
- Search for the error indication string (smth like “incorrect registration code”) in data segment
- Retrieve the address of this string in data segment
- Search for the reference of this address in code segment. The code will be something like this:
- cmp readRegCode, realRegCode
- je regCodeValid
- …
- Replace the “je” command with ‘always’ jump command (“jmp”)
Note that for some architectures the address gathered from data segment will not be referred directly in code but will be constructed as a “base + offset”. It may make harder finding the appropriate code in code segment.
De-compilation (Static analysis)
Another helpful technique is to try to decompile the binary code into higher level language, such as C. After decompilation is done obviously the code will still be hard to analyze but it may give a better understanding of high-level structure of modules and functions in binary file.
The following resource discusses more about decompilation process and what can be achieved with it:
http://en.wikipedia.org/wiki/Decompiler
Searching for algorithm patterns (Static analysis)
If the target program has cryptographic features implemented inside, such as encryption/decryption functions, it may be an interesting option to try to search the binary file for patterns of “encryption instructions”.
Usually encryption functions have lot of XOR and SHIFT commands inside and that makes them different from usual code. Every standard encryption algorithm (AES, DES, TEA, etc) has its pattern of implementation (a sequence of assembly instructions similar to mov, shl, shl, shl, xor, shr, etc) and if the adversary searches with this pattern, he may be lucky by finding the encryption/decryption functions. After these functions are found if can be easy to locate where exactly the data is being encrypted or decrypted.
Listening for library calls (Dynamic analysis)
The first dynamic analysis technique we will discuss here is the “listening for library calls”. The idea behind this technique is to set a breakpoint on a library function call which is definitely going to be called while checking the license expiration or registration code.
Let’s see an example. Suppose the target program checks for registration code and prints “incorrect code” on command prompt if the input code is wrong. Most probably the program will call printf function to do the print. If the adversary sets a breakpoint in printf function and gives a wrong registration code to the program, the breakpoint will be hit. The cracker can navigate up by the call stack and find the appropriate code fragment which is comparing the real registration code with wrong one.
It’s possible that the target program, instead of dynamic linking, used static linking with C libraries. So it won’t be possible to set a break point on printf function as it won’t be called. For these cases there are two options:
- Search for the pattern of printf function in target binary and set a breakpoint there.
- Set a breakpoint on an underlying system call which will be called when printf is called and navigate back by call stack. For printf it will probably be the “write” system call.
Monitoring memory (Dynamic analysis)
Sometimes replacing the “je” command with “jmp” won’t be enough for cracking the software. The software developers could implement complicated protections schemes against cracking which assume crashing of software at random places if the registration code was incorrect – e.g. instead of having just an “if” statement for checking the validness of input registration code the software may also have a logic which overwrites some important data in RAM and after the software executes – it crashes at different points. So even if the adversary was able to crack the checking of “reg code” she won’t be able to use the program properly.
In order to understand where exactly the program crashes the following technique could be used:
- The program is usually crashing when an inaccessible memory is read or write
- The cracker will run the program until it’s crashed
- The cracker will review the crash dump information and locate the memory address which was being read
- The cracker will set a breakpoint on this memory address and wait until it’s hit
- In simplest scenario this memory will be is just set to zero
- After identifying the code fragment the cracker replaces the “mov” command with appropriate number of “nops” so that the size of binary file is not modified.
Dumping the internal data (Dynamic analysis)
Sometime the adversary’s goal is to obtain data which is being available in the program at some point of execution. This data could be user credentials, high definition video content, etc.
Let’s assume that after playing with binary file for some period the attacker found the place where the data is getting available. Now he needs to output it to an external disc. The first option that will come to mind is to add a code to the executable that dumps this data. However, this is not trivial. Adding a new code to a binary executable is not easy as it will break the offsets of different data in the binary file and its integrity will be broken.
So a better approach will be to use the debugger for this purpose. The adversary will run the debugger and set a breakpoint on the place where the data is available. Then he may use the features of debugger to output the content of a variable to external disc (the debuggers usually have a feature of executing set of commands when a breakpoint is hit).
Hooking the library calls (Dynamic analysis)
I’m sure everyone reading this article has heard about DLL hooking. This technique provides a way to intercept the program data that is being passed to different functions that are called from DLLs.
“Hooking library calls” technique can be used for two purposes:
- The one that we mentioned above – intercept the program data
- Replace standard functions with yours and make the program to use them
We will focus on the second technique.
Sometimes it’s much easier for the adversary to change the environment settings that surround the target program to turn off protection schemes implemented in the program. For example if a program is calling time() function to get the current time, the adversary might provide his own implementation of this function, which will always return a previous time and the license checking code will always succeed.


November 12th, 2009 at 11:07 am
I have been reading your posts lately, just want to say thanks for all informative stuff i have found here, helped me learn alot lately.
Much Regards, Mark