This shows you the differences between two versions of the page.
Both sides previous revisionPrevious revisionNext revision | Previous revisionLast revisionBoth sides next revision | ||
cracks [2015/11/24 07:28] – [Applying Binary Patches] office | cracks [2022/04/19 08:28] – external edit 127.0.0.1 | ||
---|---|---|---|
Line 1: | Line 1: | ||
+ | ====== Disclaimer and Purpose of the Documents ====== | ||
+ | <WRAP important> | ||
+ | The content on the following pages describes how various software protections can be defeated by using very simple techniques - we try to the stick to the simplest ones. In no way should you use these cracks for any illegal purposes and we definitely do not support or condone any illicit behaviour from our readers. All the cracking procedures describe a way of attacking various software packages and we encourage the creators to improve the quality of their software by eliminating the flaws that we point out in the pages that follow from this name-space. Similarly, we would also like to point out to the public how the software is protected, as a risk management, in many cases where the software being attacked is able to transmit or hide data from the intended audience with or without their consent. | ||
+ | </ | ||
+ | |||
+ | ====== About ====== | ||
+ | |||
+ | The following programs have been reverse-engineered using: | ||
+ | |||
+ | * [[http:// | ||
+ | * [[http:// | ||
+ | * [[http:// | ||
+ | |||
+ | Wizardry and Steamworks does not distribute any pirated software. We are not a warez site. By following the instructions you will be able to break this software yourself and gain your own experience in the process. | ||
+ | |||
+ | For exercise' | ||
+ | |||
+ | ====== Theory ====== | ||
+ | |||
+ | We use a brute-approach to cracking programs, based on intuition and manipulation of flow control. Disassembling any piece of software yields a series of data movements between memory addresses, calls to functions that do more of that and a bunch of jumps (or '' | ||
+ | |||
+ | Every program consists of a series of a top-down flow of sequentially executed commands. If the program is event-driven, | ||
+ | |||
+ | ===== if ===== | ||
+ | |||
+ | On a high-level, '' | ||
+ | |||
+ | <WRAP centeralign> | ||
+ | <WRAP column 40% round box> | ||
+ | ===== Flow ===== | ||
+ | < | ||
+ | \begin{tikzpicture}[scale=2, | ||
+ | % Place nodes | ||
+ | \node [block] (read) {\texttt{read}}; | ||
+ | \node [decision, below of=read] (compare) {\texttt{compare}}; | ||
+ | \node [block, right of=compare, node distance=2.5cm] (jump) {\texttt{jump}}; | ||
+ | \node [block, below of=compare, node distance=2.5cm] (continue) {\texttt{continue}}; | ||
+ | % Draw edges | ||
+ | \path [line] (read) -- (compare); | ||
+ | \path [line] (compare) -- (jump); | ||
+ | \path [line] (compare) -- (continue); | ||
+ | \end{tikzpicture} | ||
+ | </ | ||
+ | </ | ||
+ | <WRAP column 40% leftalign> | ||
+ | ===== C ===== | ||
+ | <code c> | ||
+ | int reg = isRegistered(); | ||
+ | if(reg != 1) { // compare | ||
+ | return; // jump | ||
+ | } | ||
+ | start(); // continue | ||
+ | ... | ||
+ | </ | ||
+ | </ | ||
+ | <WRAP column 40% leftalign> | ||
+ | ===== ASM ===== | ||
+ | <code asm> | ||
+ | xor cl, cl ; read (exchange) | ||
+ | cmp rax, rbx ; compare | ||
+ | jle 0x10001FF07 ; jump | ||
+ | mov cl, 0x1 ; continue | ||
+ | ... | ||
+ | </ | ||
+ | </ | ||
+ | <WRAP clear> | ||
+ | </ | ||
+ | </ | ||
+ | |||
+ | Manipulating '' | ||
+ | |||
+ | <code c> | ||
+ | int reg = isRegistered(); | ||
+ | if(reg != 1) { // compare | ||
+ | return; // jump | ||
+ | } | ||
+ | start(); // continue | ||
+ | ... | ||
+ | </ | ||
+ | |||
+ | If '' | ||
+ | |||
+ | In order to do that, we manipulate the outcome of the '' | ||
+ | |||
+ | <code c> | ||
+ | int reg = isRegistered(); | ||
+ | if(reg != 1) { // compare | ||
+ | |||
+ | } | ||
+ | start(); // continue | ||
+ | ... | ||
+ | </ | ||
+ | |||
+ | Now the '' | ||
+ | |||
+ | <code c> | ||
+ | if(reg != 1) { // compare | ||
+ | |||
+ | } | ||
+ | </ | ||
+ | |||
+ | There are many ways to eliminate the jump in assembler. The most obvious, given the top-down flow of execution, is to get rid of the jump ('' | ||
+ | |||
+ | <code asm> | ||
+ | xor cl, cl ; read (exchange) | ||
+ | cmp rax, rbx ; compare | ||
+ | jle 0x10001FF07 ; jump | ||
+ | mov cl, 0x1 ; continue | ||
+ | ... | ||
+ | </ | ||
+ | |||
+ | by substituting the jump using some '' | ||
+ | |||
+ | <code asm> | ||
+ | xor cl, cl ; read (exchange) | ||
+ | cmp rax, rbx ; compare | ||
+ | nop ; no more jumping | ||
+ | nop ; | ||
+ | mov cl, 0x1 ; continue | ||
+ | ... | ||
+ | </ | ||
+ | |||
+ | Thus the comparison: | ||
+ | <code asm> | ||
+ | cmp rax, rbx ; compare | ||
+ | </ | ||
+ | is not even checked. We can '' | ||
+ | |||
+ | ===== () ===== | ||
+ | |||
+ | Very often we want to short-circuit functions, namely functions that are labeled '' | ||
+ | |||
+ | <WRAP centeralign> | ||
+ | <WRAP column 40% round box> | ||
+ | ===== Flow ===== | ||
+ | < | ||
+ | \begin{tikzpicture}[scale=2, | ||
+ | % Place nodes | ||
+ | \node [block] (enter) {\texttt{enter}}; | ||
+ | \node [block, below of=enter, node distance=2.5cm] (execute) {\texttt{execute}}; | ||
+ | \node [block, below of=execute, node distance=2.5cm] (return) {\texttt{return}}; | ||
+ | % Draw edges | ||
+ | \path [line] (enter) -- (execute); | ||
+ | \path [line] (execute) -- (return); | ||
+ | \end{tikzpicture} | ||
+ | </ | ||
+ | </ | ||
+ | <WRAP column 40% leftalign> | ||
+ | ===== C ===== | ||
+ | <code c> | ||
+ | needsLicenseReminder() { // enter | ||
+ | ... // execute | ||
+ | return; // return | ||
+ | } | ||
+ | </ | ||
+ | </ | ||
+ | <WRAP column 40% leftalign> | ||
+ | ===== ASM ===== | ||
+ | <code asm> | ||
+ | _needsLicenseReminder: | ||
+ | push rbp | ||
+ | rbp, rsp | ||
+ | r15 | ||
+ | r14 | ||
+ | rbx | ||
+ | ... ; execute | ||
+ | pop rbx | ||
+ | pop r14 | ||
+ | pop r15 | ||
+ | pop rbp | ||
+ | ret ; return | ||
+ | </ | ||
+ | </ | ||
+ | <WRAP clear> | ||
+ | </ | ||
+ | </ | ||
+ | |||
+ | Since we are very important people and do not need a license, we can short-circuit this function such that it does not do anything. We could even '' | ||
+ | |||
+ | <code asm> | ||
+ | _needsLicenseReminder: | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | ... | ||
+ | 0x2129 pop rbx | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | </ | ||
+ | |||
+ | The result of adding a '' | ||
+ | |||
+ | ===== Stuff You Will Need To Know ===== | ||
+ | |||
+ | The number of operations and rules you will need to learn is very small, in fact, there are only '' | ||
+ | |||
+ | * Jumps are prefixed by '' | ||
+ | |||
+ | * Return from functions as you enter them, symmetrically. This is due to the way that functions are called and how they return (stack based). We can make a simple rule out of this: "what function pushes on entry, that it shall pop on return" | ||
+ | |||
+ | * The opcode for return is '' | ||
+ | |||
+ | * '' | ||
+ | |||
+ | ===== Flow Equivalence ===== | ||
+ | |||
+ | As you may have noticed, '' | ||
+ | |||
+ | <WRAP centeralign> | ||
+ | <WRAP column 45% leftalign> | ||
+ | <code asm> | ||
+ | 0x0001 nop ; do nothing | ||
+ | 0x0002 mov rdi, r14 ; move | ||
+ | </ | ||
+ | </ | ||
+ | <WRAP column 45% leftalign> | ||
+ | <code asm> | ||
+ | 0x0001 jmp 0x0002 | ||
+ | 0x0002 mov rdi, r14 ; move | ||
+ | </ | ||
+ | </ | ||
+ | <WRAP clear> | ||
+ | </ | ||
+ | </ | ||
+ | |||
+ | More precisely, we can say that a '' | ||
+ | |||
+ | ===== NOP Sledges ===== | ||
+ | |||
+ | The illustriously wise frequently take some post-condition and slide it via '' | ||
+ | |||
+ | <WRAP centeralign> | ||
+ | <WRAP column 45% leftalign> | ||
+ | <code c> | ||
+ | int reg = getRegistered(); | ||
+ | if(reg == 1) { | ||
+ | reg = 1; // very clever! | ||
+ | printf(" | ||
+ | return; | ||
+ | } | ||
+ | |||
+ | printf(" | ||
+ | setTimer(); | ||
+ | |||
+ | return; | ||
+ | </ | ||
+ | </ | ||
+ | <WRAP column 45% leftalign> | ||
+ | <code asm> | ||
+ | mov rbx, 0x1 ; reg = 1 | ||
+ | nop ; fuuuuuuuuuu.. | ||
+ | nop ; ...uuuuuuuuuuu... | ||
+ | nop ; ...uuuuuuuuuuu... | ||
+ | ... | ||
+ | ... | ||
+ | ... | ||
+ | ... | ||
+ | ... | ||
+ | nop ; uuuuuuuuuuuuuuuu! | ||
+ | ret | ||
+ | </ | ||
+ | </ | ||
+ | <WRAP clear> | ||
+ | </ | ||
+ | </ | ||
+ | |||
+ | which essentially moves the assignment, by setting '' | ||
+ | |||
+ | |||
+ | ====== Applying Binary Patches ====== | ||
+ | |||
+ | '' | ||
+ | <code bash> | ||
+ | brew install bsdiff | ||
+ | </ | ||
+ | in case you have MacPorts, issue: | ||
+ | <code bash> | ||
+ | port install bsdiff | ||
+ | </ | ||
+ | |||
+ | in order to install '' | ||
+ | |||
+ | Patches are named in this namespace conventionally and you will need to copy & paste the gibberish text in files before applying them. For example, the patch for '' | ||
+ | < | ||
+ | filename.bsdiff.uue | ||
+ | </ | ||
+ | the '' | ||
+ | < | ||
+ | filename.bsdiff | ||
+ | </ | ||
+ | to indicate a patch file. | ||
+ | |||
+ | In order to patch '' | ||
+ | <code bash> | ||
+ | uudecode -o filename.bsdiff < filename.bsdiff.uue | ||
+ | </ | ||
+ | at which point you will have obtained the '' | ||
+ | |||
+ | The next step is to apply the patch. This can be done by moving '' | ||
+ | <code bash> | ||
+ | bspatch filename filename filename.bsdiff | ||
+ | </ | ||
+ | which will apply the patch '' | ||
+ | |||
+ | Remember that if you patched a binary with '' | ||
+ | <code bash> | ||
+ | chmod +x filename | ||
+ | </ | ||
+ | in case the executable will not load. | ||
+ | |||
+ | ====== Index ====== | ||
+ | |||
+ | {{indexmenu> |