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 ideal. 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 debugger. 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 up. 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. 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. 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). 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. 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 condition. 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 0x000000BF 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 reboot_computer 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? 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). 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 c:\masm32\lib\user32.lib .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 .CODE ;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 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). 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. 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. 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?) 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. 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. 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 for. 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 have. 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 editor. 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. ;-------------------------------------- .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 include c:\masm32\include\user32.inc includelib c:\masm32\lib\kernel32.lib includelib c:\masm32\lib\user32.lib .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 .CODE ;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 MessageBox function call MessageBoxA jmp theend prog_unregistered: push MB_OK push offset DLGCAP push offset UNREG push 0 call MessageBoxA jmp theend theend: push 0 ;end this program call ExitProcess Main ENDP 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: ;---------------------------------------------- .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 include c:\masm32\include\user32.inc includelib c:\masm32\lib\kernel32.lib includelib c:\masm32\lib\user32.lib .STACK 1024h .DATA 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 KEYSIZE EQU 8 .CODE Main PROC 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 mainprog: push MB_OK push offset DLGCAP push offset RUN push 0 call MessageBoxA theend: push 0 ;end this program call ExitProcess Main ENDP 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 chkregloop: 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 endchkregloop: isreg: mov ebx, 1 mov esp, ebp pop ebp ret 4 notreg: mov ebx, 0 mov esp, ebp pop ebp ret 4 ChkRegistered ENDP End Main