A brief intro to my tutorials
Have you ever wanted to crack a program? Have you ever pirated an application that contained a crack with it? Ever wondered what happens when an application is run? If you're reading this, the answer to one of those is probably yes. I'm hoping to start slow with some intro tutorials, then work my way up to showing you how to crack current applications (or at least mimic the protections used).
First, let's answer some questions about assembly, cracking, and reversing. Afterwards some brief descriptions of things we're going to see within the debugger.
I saw a tutorial online that said "crack any software." How come you're not showing that?
Those videos only implement string checks (which is my first tutorial). They're using click bait titles to get you to watch. Any video without dialog but with loud, annoying trance music shouldn't be worth your time.
What program(s) do you use?
A combo of x32dbg/x64dbg, Ollydbg, Immunity Debugger, IDA for Windows; dnSpy, dotPeek, .net Reflector for .Net applications; GDB for Linux; CFF Explorer, Lord PE, PEBrowse32/64 for PE Editors; ResHacker, Hex Workshop, 010 Editor for hex and text editing.. It all depends on the application I'm reversing and type of binary it is. I don't do much kernel debugging, so I don't really use Windbg although it's a powerful tool. You can find most of these for free online. I'll be hosting the files around the next tutorial or so.
I heard that X cracking group uses a specific program. Shouldn't I be using that too?
This is similar to most anything in life. There's never a single tool to do the job. The best crackers will use multiple tools depending on what they're trying to achieve.
You didn't explain X in one of your tutorials OR you explained X wrong.
Please feel free to reach out to me on my contact form if you feel that I need more detail for a specific tutorial or stated something incorrectly. Most tutorials will be in Windows, but I'll try to throw some Linux GDB for good measure.
Do I need to learn assembly?
This all depends how deep you would like your understanding of reversing to go. You might be able to follow most tutorials, but without a deeper understanding of what's going on, you're only going to be cracking simple applications.
For a deeper understanding of assembly and reversing I highly recommend:
-Reversing: Secrets of Reverse Engineering
-Reverse Engineering for Beginners
-Introductory Intel x86: Architecture, Assembly, Applications, & Alliteration
-Lena's tutorials - Assumes a basic understanding of assembly
What exactly is the difference between cracking, reversing, patching, and keygenning?
Cracking is the art of modifying or altering software usually in a way that benefits the person using the application. Some cases may be to register something illegally (pirating), disable DRM, or modification of software. Reversing does not necessarily need to include cracking and is more of a way to figure out what is going on with software or hardware. Reversing can include figuring out what an out-of-date piece of hardware does and how to change it so that it works with newer technology. Patching is the actual alteration of software. Where a program may say to jump to a specific location in the program or memory, you can force the application to jump to a different location or not take a jump (usually goes hand-in-hand with cracking). Keygenning is similar to cracking with the addition of an external or in-line way to generate a key or serial the same way that the application does.
Can you crack X for me or put up a tutorial for it?
I don't take requests. The reversing portion of my site is geared toward user-generated code, crackmes, reversemes, and keygenmes. I may through in an actual application but only if it's defunct and/or I have approval from the vendor. Although what is taught or my site and other reverse engineering sites may be applied to current applications.
Inside the debuggers
Inside the code we're going to see a few things which I'll touch on quickly. The first being PUSH and POP. These are instructions which tell the processor how to add or remove a parameter to the stack (region in memory). The stack is referred to by the register ESP (extended stack pointer). When we see a PUSH command, we'll see that the stack adds that instruction into memory. The opposite is the POP instruction which removes the saved memory instruction off the stack. Another assembly instruction is JMP or jump which is non-conditional, meaning that no matter what happens before the instruction, a jump will always take place. A NOP stands for "no operation" and is used to negate or overwrite an instruction, essentially skipping over it. In the background a NOP command is actually using the instruction MOV EAX, EAX (moving EAX into itself and basically doing nothing). MOV is the move command. In intel syntax which I'll be using 99% percent of the time instructions are read from right to left. So MOV EBP, ESP says "move the address of ESP (what the stack points to) to EBP. Lastly the CALL. This branches off to another area of code, typically a function or subroutine.
Inside of the debuggers there are some shortcuts that we'll be using and terms and sections that you should know:
Spacebar = open the assembly option so that you can change the instruction
F2 = put a breakpoint on a line of code within the program - stops the program from moving forward once it's hit
F7 = step into - runs the next line of code including a call to another function
F8 = step over - skips over calls to functions
"Goodboy" and "badboy" = Short names for the correct and incorrect password, dialog box, function, or password prompt
The top-left section holds the virtual addresses (memory locations), OPcodes, our human-readable code, and comments put in by the debugger. Our registers are found in the top-right section. The stack at the bottom-right (where our PUSH and POP values come into play). The dump window is displayed at the bottom-left and may look familiar if you've ever used a hex edit before.
Easy1.zip - Zip of both files analyzed in this tutorial (password: blackwinter)
This tutorial will address the most basic version of reversing available and that's through a string or text search. This is what makes up a lot of the tutorials you find on Youtube with titles such as "crack any program." The truth is, you'll be hard-pressed to find this in the wild anymore. For this tutorial, the programs Easy1Cplus.exe and Easy1noOP.exe were created using C++ 2008 Express but with C and C++ code optimizations (source at the end). I'll show 2 different versions from Immunity so that you can see how the debugger is affected by compiler optimizations and programming languages.
Using Easy1Cplus.exe, the first thing I like to do is check to see if the program is obfuscated or packed. I use both PEiD and Die (Detect-It-Easy). In PEiD we can see that the application detects C++ 2008. In Die, the entropy line correlates to a default application without obfuscation. We can also see that Die displays "not packed" for this application.
(I originally made a single program Easy1.exe which is what the screenshot displays before adding a second with different optimizations)
Next we'll load Easy1noOP.exe into Immunity and run it. Immediately we see that we're thrown into the mainCRTStartup section of the program but just a little varied. We can either follow and step through the program or, because it's such a small program, we can scroll. Scrolling up we find our goodboy and badboy strings, and again our password string.
We can also pull the password another way. While in our program (check the title bar to make sure you've hit play and aren't in ntdll), right-click inside our code section, select Search For, then All referenced text strings. In the strings window the ASCII text is displayed and once again we find our password. There is also a new string: '%s'. We'll see this often when reversing and especially throughout IDA. The debugger was able to figure out that the application is looking for a string value as an answer.
What else can we do with this application? In some cases we can patch the program to always register as correct no matter what we toss into it. We'll do this 2 ways using Easy1noOP.exe. Restart the application, play the application, and scroll up to the entry point of our code and set a breakpoint at PUSH EBP. Pressing play again will break at this point.
The first method is to adjust the jump so that it always hits the correct password string. At 012A1037 (your virtual address will be different) we see the TEST instruction after the _strcmp (string compare) function. This tells us that we're testing to see if what we put into the string matches what the program is looking for. If it is, we jump to the goodboy, if not the badboy is hit. We put a breakpoint at the TEST address and play. Don't worry that we enter the kernel dll instead of our application. This is due to giving the operating system flow control. Click the application icon on the taskbar to open the command prompt and enter a password of "123" then enter. We hit our TEST EAX, EAX breakpoint. What this instruction is doing behind the scenes is saying "does the value at EAX+4 match the value at EAX+8" OR "does your value match the value stored in memory"? I arbitrarily picked +4 and +8. Stepping into the next instruction we can see our preview window is stating that the jump is being taken. But this will jump right over the good boy instruction and we don't want that. We can change the Z Flag (I'll talk about this in another tutorial), but that will only temporarily adjust what happens within the application. To fix our issue and always hit the good boy we're going to NOP the non-conditional jump.
You'll notice that our 74 15 instruction is now set to 90 90, although on separate lines (which really doesn't matter). Now that we've done this we hit play again and are thrown into back into ntdll.dll. We can check our application and see what happened.
The good boy is hit! Great work. But we're not quite done. If you were to restart the application it still shows the badboy with a code of "123." Why? Because we need to save our changes and rewrite the executable. Restart the application, play, enter your code, and NOP the jump. Right-click inside the now-highlighted NOP code, select 'Copy to Executable' the 'Selection.' Right-click on the new window that popped up, select 'Save File,' and give it a name. I'll call mine Easy1-cracked.exe. Now run the application and give it any password.
Yes! We finally did it! We serial phished the password that was inside of the application AND we successfully patched it.
Code used for Easy1Cplus.exe:
using namespace std;
cout << "Please enter your product key: ";
cin >> password;
if (password == "klj80fdjo4")
cout << "Correct password";
cout << "Wrong password";
Code used for Easy1noOP.exe
printf ("Please enter your product key: ");
scanf ("%s", &password);
if (password == "klj80fdjo4")
printf ("Correct password");
printf ("Wrong password");