TORN@DO presents: cRACKER's n0TES
Tips & Tricks for general cracking


Bogus Serial Choosing (MisterE) with addendum by Suby
When you crack programs that needed a Serial #, I recommend to use always the same one, so that you know, what your serial looks like in hexdecimal.


Suby:
I suggest using a serial with different chars like "1234567890" (the one I use) because if the program doesn't check the chars from the first to the last but it checks the third and the second then the last etc. you can easily know which one is checked.

If you use "1122334455" and it'll take the "1" you don't know if it takes the first or the second instead if you use "1234567890" and it takes "2" you're sure it'll check the second char of the serial.




CALLs (CrackZ)
Whenever you elect to step over a CALL in a protection, check the contents of any registers which have changed, you may find the Serial # there, alternativly when you have exhausted all posibilities, re-trace your steps and examine functions.




How a Cracker/Programmer thinks (rudeboy)
Programmers are taught that whenever you have a task that is going to be done more that once, you should create a function to do that task, and just call the function when you need to perform the task. Now, most programs that use a name/serial # combination check the code at least twice, once when you enter the code, and once when the program starts up. Because of this the programmer will usually call a function to test your reg code. And usually, this function will be called every time the code is checked. At this point you should probably see where I am going with this. If you patch the function that is called to test the reg code, it will show up as valid whenever the program does it's check.

The techniques employed here do not only apply to cracking programs with name/reg code routines. Do not limit yourself by thinking "Inside the Box", these techniques can be used with many other types of protections as well (for example, many times a date check and a nag screen are done by one function).




INT 3 Using (josephCo)
In case you haven't heard already, INT 3 was set for debugging purposes. So if you want to break at a specified routine, you can use this instruction. You can just "patch" (the op code for INT 3 is just CC) a COPY of the file. Try to replace a single byte op code with CC. If you can't find one, you've to put it inside a full instruction: don't forget to "NOP" (the op code for NOP is just 90) out the remaining bytes. Then you can use SoftICE to break on INT 3. Don't forget to note down the original data, because you need it when SoftICE breaks at this location. When you're there (before the INT 3 is executed), type A and then enter the commands you note down - if you don't do this, you'll cause a General Protection Fault. Just continue like you want to ...




Return Values
When a function returns a value to see if a check has been successful mostly 1 (or sometimes 0) will indicate success. -1 is normally used to indicate NO SUCCESS!




SoftICE conditional breakpoints (Rhayader)
In my early cracking experience, I usually set a BPX for GetDlgItemTextA and GetWindowTextA inside SoftICE, whenever I found a program that ask for serial. Entering dummy code, and 'hoping' that SoftICE would pop up. Most of the time it works. Problem is, after I hit F12 (P RET), I usually get lost inside the code. Wondering where's that bloody text buffer that I can set a BPR with.

After digging into SoftICE docs, I finally found a better way to do it (it's in Chapter 7 of the User Guide). IMHO, you should read it too. Some of the terms there might be hard to understand if you were just started. But, hey, that's what The Forum is for, isn't it?
:)

My aim here is to get SoftICE show us the text buffer for the two Win32 APIs mentioned above. I'll use breakpoint "action" to do that.

Let's take a look at GetWindowTextA first. It's declared as:

int GetWindowText(HWND hWnd, LPTSTR lpString, int nMaxCount);

GetWindowText use stdcall calling convention. That means that argument will be pushed right to left. Since SoftIce pop up before the prologue code is executed, the EBP stack frame isn't set up yet. So we had to use ESP to adressed the argument. Here's how the stack will look like when SoftIce pop up:

...
[ESP+0Ch] - nMaxCount
[ESP+08h] - lpString
[ESP+04h] - hwnd
[ESP+00h] - return EIP

When the function return, GetWindowTextA will put the text it retrieved to the location pointed to by lpString (LPTSTR is a long pointer to a null terminated string). Thus, we had to use SoftICE's indirection operator (it's the * character, same as C language, see Chapter 8 ;). For example, the command:

D *(esp+8)

means, "show in data window, the location pointed to by the content of esp+8". Since, this is a very common operation, SoftICE had a shorthand for it: esp->8. Allright then, now we can set the breakpoint such as this:

BPX GetWindowTextA DO "D esp->8;"

And when we hit F12, we return to the caller and the text we entered will sit nicely at the top of the data window, waiting for us to set up a BPR with it :) Why don't we do a return to the caller automatically? Well, in my case, the screen flashes, and I hate it.
But, if you want to try, you can set the breakpoint as:

BPX GetWindowTextA DO "D esp->8;P RET;"

Now, let's take a look at GetDlgItemTextA. It is declared as:

UINT GetDlgItemText(HWND hDlg, int nIDDlgItem, LPTSTR lpString, int nMaxCount);

The only difference is nIDDlgItem, which is the ID of the control to get the text from. The stack will look like this:

...
[ESP+10h] - nMaxCount
[ESP+0Ch] - lpString << here it is
[ESP+08h] - nIDDlgItem
[ESP+04h] - hwnd
[ESP+00h] - return EIP

And the breakpoint to set (I had a feeling that you already find out ;)

BPX GetDlgItemTextA DO "D esp->C;"

Well, that's all my friends. If you didn't want to type it everytime you want to use it, then you had to set up a macro for it. Read chapter 11 :D I'd like to tell you, but this became a looong post already. See ya...




Tip for NEW Reverse Engineerers (CrackZ)
When starting to reverse engineer a target it can be very tempting to immediately use a variety of intrusive techniques, I for one am all to keen to fire SoftICE and start tracing. In most cases this approach will work, but in order to reverse at a higher level you should perhaps undertake an analysis of the code prior to using SoftICE - you would do well to feel the code before entering SoftICE and attempting to study the protection in detail. Using WDasm32 you'll easily locate some interesting String References. By simple back tracing you could easily locate a deciding check.




Unregistred? (CbD)
If you crack a program and it says unregistred, you did most change a jmp here and there and make the program take you an invalid code as a real one but the program wrote your code to the registry or an ini file when you restarted it, the read the number or key and it was an invalid one, so you must find where the program looks for a registration entry (RegQueryValueEx[A] or a GetPrivateProfile[A]) and force the program to validate any key that it sees. This can be a very difficult process so be prepared for a lot of hell for this one. But the best idea is to use W32DASM to disassemble the target then look in the import functions to find the functions above, then trace each one of them (will be many) then after you trace the code and find the right one it will most likely be a matter of changing a jnz to jz or something simple like that. If you still can't do it seek help from a wise cracker.




Watches (Mammon)
Watches allow you track a variable while you are debugging a program; needless to say, this is a very important function for cracking and reverse engineering. To open the watch window, type ww at the Soft-Ice command line; typing watch followed by an variable name (eg watch user_id) adds that variable (and its value) to the watch window. Registers and stack offsets (not to mention memory values) can be watched by using them in place of the variable name, such as watch es:di and watch [ebp 18]. In addition, since many registers and stack offsets merely point to address where the real variables are stored, you can watch the value referenced by the register or stack offset by typing a * before the name of the register/offset (eg, watch *es:di). Good variables to watch are es:di, *es:di, eax, and any [esp ?] or [ebp ?] that references input by a user.





The cRACKER's n0tES are divided into 10 main parts:
 00. INDEX
 01. Assembly for Crackers (CoRN2)
 02. SoftICE (Boot Menu, Setup, Commands)
 03. Breakpoints & Win API Details
 04. Jump Instructions
 05. SET Instructions
 06. Tips & Tricks for Cracking
        1 Crippled Programs
        2 Dongles
        3 General
        4 InstallSHIELD Setups
        5 Key File Protections
        6 NAG Screens
        7 Runtime Limits
        8 Serials
        9 Time Limits
       10 Visual Basic 'Programs'
 07. Window Messages For Crackers
 08. Identifying Functions, Arguments, and Variables (Rhayader)
 09. Commerical Protection Systems
 10. Bitmanipulation (Cruehead)
 11. General Cracking Theory
 12. FAQ

 +A. How to contact me
 +B. What's New?



The cRACKER's n0TES are Copyright © 1998-2000 by TORN@DO of ID. All Rights Reserved. Archived and Re-hosted by Werdstaff