Hacking — Best OF Reverse Engineering — Part 5
How to Analyze Applications With Olly Debugger?
The process of analyzing a computer program’s structure, functions and operations without having source code available is called reverse engineering.
In this article, I would like to introduce you the one of the most important tools for reverse engineers — Olly debugger. While reading this article, I will introduce Olly debugger, explain the basic features and functions and ways of using them, and later we will analyze two programs (crackmes). “Crackme” is a program that is used for practicing your reverse engineering skills. As reverse engineering of commercial applications may violate some laws, we will stay with crackmes during this article. In the first program, we will use program patching to change its functionality, in the second program we will try to reverse the algorithm behind its password checking routine.
After reading the article, you should be able to open a program in Olly debugger and start analyzing it. If necessary, you should be able to make your own patch or reverse simple algorithms.
Before you continue reading this article, make sure you have Olly debugger downloaded and installed. When you search (on the Internet) ollydbg, you quickly discover the project’s main webpage ollydbg. de. From this page, download version 2 of the debugger, unpack archive and execute ollydbg.exe. You also need two target programs (crackmes) — crackme1.zip and crackme2.zip. See attachment for more information. Now you are ready to follow the rest of this tutorial.
What is Olly Debugger?
Olly Debugger (we will call it OllyDbg) is a 32-bit debugger for analyzing portable executable (PE) files for Microsoft Windows. (There are many different types of computer files. PE files are standard executable .EXE files, DLL libraries, SCR screensavers, etc… When you open the file in any editor, you notice two signatures — MZ in the beginning and PE a bit further. At address 0x3C you will see the offset of PE signature. In our example value on address 0x3c is 0xB0, therefore on address 0xB0 you will see PE signature).
See Figure 1 for screenshot.
When you execute ollydbg.exe and drag and drop any executable file on it (in my case I used crackme_01. exe), you will notice four sub-windows — disassembly (upper left), registers (upper right), dump (bottom left) and stack (bottom right) (see Figure 2). We will say a little bit about each of these sub-windows.
The Disassembly sub-window shows the disassembly of the program. Each line contains several columns — memory address, opcodes, opcodes translated into assembly language, additional information added by debugger (in case of API calls you can see parameter values and their types). If you look at the first line of Figure 2, you will see 00401000 (memory address), 6A 00 (opcode), PUSH 0 (disassembly of opcode 6A 00, i.e. instruction which stores number 0 on the stack), Type = MB_OK|MB_DEFBUTTON1|MB_ APPLMODAL (additional information added by debugger — it says that this value in Type parameter of MessageBox Windows function). If you want to know more about MessageBox or any other API function, search the internet for “msdn messagebox.” MSDN means Microsoft Developer Network.
The Register sub-window contains processor registers. When a register changes, its color becomes red. Below registers (in middle part of sub-window), you can see processor flags — 1 bit values which signalize results of previously performed operations (results of comparison of two numbers, etc…). In bottom part of sub-window, you can see Floating Point Unit registers, which are used for arithmetic operations involving decimal point numbers. If you want to know more about registers, processor instructions, etc., search in internet for “IA-32 architecture.”
The dump sub-window shows you raw binary data from addresses you specify. When you right click into dump sub-window, select Go To -> Expression (Ctrl+G), you can choose the address which you want to display binary data from. You can choose from various forms of data representation — just right click ondump window and select one of the options (Hex, Text, Integer, Float or Disassemble).
The stack sub-window shows a block of memory generally used for storing parameters of functions, return addresses of function calls, local variables within functions. Stack is a data structure based on “Last In First Out” principle. When you push a value (instruction PUSH) onto the stack, it appears on the top, when you pop value (instruction POP) from the stack, the value from the top of the stack is removed. In Figure 2, first line in stack sub-window is 0012FFC4 (address), 7C816D4F (value stored on address), RETURN to kernel32.7C816D4F (additional information added by debugger).
That’s all for the description of the four basic sub-windows. However, if you need to display more information, you can click on View menu and select any of those options to display optional sub-windows — see Figure 3.
Executable modules shows list of all modules loaded in the memory space of the analyzed program. It gives basic information as 00400000 (base address), 0004000 (size of image in memory), 00401000 (address of entry point, where execution of module starts), Crackme_01 (name), file version and path to file. The Threads window enumerates all thread in active program. It shows basic information like identifier, windows title, last error, entry point, status, priority, etc.
To explain the purpose of following optional windows, we should understand what a breakpoint is.
A Breakpoint is a condition set in debugger. When this condition is met, program stops running and waits for user action. Three main types of breakpoint are: software breakpoint, memory breakpoint and hardware breakpoint. In order to have the same output as in this tutorial, do the following: Set software breakpoint at address 401021 (click on line with address 401021 and press F2), set memory breakpoint at address 40102D (right click on line 40102D, select Breakpoint-> Memory and press OK — see Figure 4), and finally set hardware breakpoint at address 401046 (right click on line 401046, select Breakpoint->Hardware and press OK — see Figure 5).
After all theses steps, the disassembly window will look like Figure 6 — lines on which breakpoints are set, become red.
INT3 breakpoints window shows all addresses where software breakpoints were set. In our example,
it shows 00401021 (address), Crackme_01 (module name), Active(status, not disabled now), disassembly of address the breakpoint was set on, comment added by debugger.
The Memory breakpoints window enumerates all memory breakpoints. In our example, it shows 0040102D (address), 0000005 (size of region in bytes), Crackme_01 (module name), E (type Execution), Active (Status, it is not disabled now).
The Hardware breakpoints window enumerates all hardware breakpoints. In our example, 1 (one of four slots), Write:1 (type of hardware breakpoint and number of bytes it is applied for), 00401046 (address where breakpoint was set), Crackme_01 (module name), Active (status, not disabled now).
The Memory map shows all memory regions loaded to user mode. It displays address, size of region,
owning process, section name, description of contents, memory type and access rights. In the case
for our Crackme_01 program, it gives us following information: It has 4 memory blocks.
00400000, which is PE header of Crackme_01.exe
(as shown in Figure 1)
00401000, which is .text section of Crackme_01.exe
00402000, which is .rdata section of Crackme_01.exe
00403000, which is .data section of Crackme_01.exe
The first example
If you followed tutorial in the previous sections, you have Crackme_01.exe loaded in your OllyDbg, you set three different breakpoints and now you are ready for your first analysis.
When you press key F9 or Run icon from toolbar application Crackme_01.exe starts running. It continues running until breakpoint is hit or until user action is expected. In this case, message box is display and application waits for user to click on OK button (Figure 7).
After clicking OK, no more messages are being displayed, however, the debugger stops at address 401021, where we set software breakpoint. It is just before the second message box will be displayed. Now, we will press F8 Step Over, toolbar icon and another message is displayed (Figure 8).
After pressing OK, we stop at 401026. If we press F9 (Run) again, we stop at 40102D, because we set Memory Breakpoint on Execute at this address. We can continue either by pressing F9 once or by pressing F8 for each line of code until we reach another message box at 401034. This message box says “NAG NAG Remove Me!” (Figure 9). As strings displayed in message box show, our goal is to remove this message box so that when we run the crackme again, it is not displayed anymore.
After pressing OK and F9 (Run) again, the debugger does not stop at 401046, because we set hardware breakpoint on write, not hardware breakpoint on execute. Meanwhile, the application called ExitProcess and exited (you can see red text “Terminated” in right bottom corner).
Now restart the application by pressing CTRL+F2 delete all breakpoints because we do not need them anymore (go to all windows with breakpoints, select breakpoint, right click and Remove) and continue
stepping through the application using F8 (Step Over). When you reach line 401026, you are at the place where the first parameter of the message box is pushed on the stack. As long as we want to remove the message box, we should remove not only “call MessageBoxA” instruction, but also all its parameter. Removal will be done by replacing the instructions by other instructions which do nothing. For such a purpose, No OPeration instruction (NOP) with opcode 0x90 is the best candidate. It has only one byte, herefore it allows us to replace any other instruction with it, removing the effect of original function and doing nothing instead.
OllyDbg allows to edit instructions in disassembly by pressing Space key. Dialog as in Figure 10
displays. You only need to overwrite original instruction address with “nop” and press “Assemble”
button. After pressing “Assemble” button, original instruction with size 2 bytes is replaced with two
NOP instructions (red colored lines in Figure 11).
Repeating the same for all PUSH instructions (belonging to call) and the call instruction itself will result in following code (Figure 12).
Now, we should save all modifications into a new file and we are done with this task. Therefore, select all modified lines with mouse, right click, select Edit->Copy to Executable. A New window with the modified exe file will open (Figure 13). Right click into this newly created window, right click and select Save File… Enter new file name (something like crackme_01_patched.exe), click on Save and patched file is saved. Later, when you try to run the patched file, only two message boxes are displayed and instead of the third message box, several nop instructions are executed, therefore nothing happens and no message box is displayed.
The second example
Our second example will be a slightly more complicated crackme — sf_cme04.exe. First of all, we run the crackme to see how the application looks like. Figure 15 shows that we have two text fields, About link, Exit link. When we try to insert random text into both fields, nothing happens.
Let’s open the application with OllyDbg and try to find some information to help us start reversing.
The first step will be to look at string references. Right click on disassembly window, select “Search for” -> “All referenced text strings” (Figure 16).
We scroll down the list of text strings and try to find anything interesting or suspicious. We are quite lucky,because we can see a lot of strings in this crackme. The strings are not encrypted or obfuscated so we can see them in their plain forms. After lengthy scrolling down we notice the following interesting message: “You were successful! Now send me your serial or write a tutorial” (Figure 17).
Double click on this line and we will land at address 4475E0 in the disassembly window. Scroll slightly above, procedure which has something to do with our suspicious string starts at 00447540 with PUSH EBP instruction. Remember this address — later we will set a breakpoint here. Run crackme by pressing F9, enter arbitrary strings in both text fields (in our case we enter “crackme” and “123456” — Figure 19), set breakpoint at 4475E0 (Figure 18). Now we can try to click on various places of crackme’s window, but nothing happens. Only when we try to modify the text in the second text field (for example from “123456” to “1234567”), debugger breaks at 4475E0.
Then we keep pressing F8 (Step Over) and observe stack window, register window if we notice any changes,which are interesting for us. Typically we are looking for situations where we can see the data which we inserted into program’s text boxes. When we reach address 447563 (the address right after call XXXX), we can see that register EDX contains address of the string “emkcarc”, which is reverse string of “crackme” — contents of the first text field we entered (Figure 20).
Stepping out further, another interesting address is 447573. In register EAX, we can see reference to string “754–09.” We don’t know what these numbers means, but we can guess that they come out from procedure 447565 (Figure 21).
A few lines below — at address 447597, register EAX contains our magic value “754–09”, register EDX contains string “1234567” (which we entered to the second text box). Then at 00447597 a procedure is called and if a zero flag is set during the call of the procedure, then SETZ BL sets BL register to 1 (Figure 22). However, in our case, zero flag is not set during calling procedure 00447597, therefore SETZ BL sets register BL to 0.
Further in the code, at address 4475D1, you can see instruction TEST BL, BL followed by JZ 4475EA (you can see it in Figure 22 too). If BL equals 0, TEST BL, BL (which corresponds to logical function BL & BL) sets zero flag to 1 (0 & 0 = 0, result is zero, therefore zero flag = TRUE = 1) and JZ jumps to 4475EA, therefore no message is displayed.
The opposite situation occurs when a zero flag is not set during function call at 447597. In such case, SETZ BL sets BL register to 1. Later in the code, TEST BL, BL results in zero flag = 0, JZ does not jump and message box is displayed.
From the aforementioned description, we can expect that instruction CALL at address 447597 is comparison of two strings, which pointers are passed in registers EAX and EDX. You can simply verify it by keeping the first text box with text “crackme” and modifying the second text box to value “754–09”. When you do this, you can expect to see something like in Figure 23.
Now our work is over. We found the correct name/serial combination, but unfortunately we do not yet know what the exact relation between name and serial number. Is the serial number computed from the name? Is the serial number computed from something else? Is the serial number constant and hardcoded somewhere in program? In the text above, we mentioned that “magic text” “754–09” appeared in the program soon after calling procedure at address 447565. Let’s examine this procedure a little bit. First of all, we need to press F9 to continue running the application (leave from debugger), we edit text in the second text box, and we hit breakpoint at 447540 again. We keep pressing F8 to Step over until we reach 447565, where we press F7 to Step into the procedure. Now we land at 447470.
Keep pressing F8 Step over again and observe what happens. In the middle of the procedure, you will find a loop (Figure 24), which
* measures length of text of the first text box (004474B1: CALL 0041B798)
* gets pointer to the text of the first text box (004474B6: MOV EAX,DWORD PTR SS:[EBP-4])
* reads (ESI-1)-th character from the beginning of the string to EAX (004474B9: MOVZX EAX,BYTE PTR DS:[ESI+EAX-1])
* reads (ESI-1)-th character from the end of the string to EDX (004474C4: MOVZX EDX,BYTE PTR DS:[ESI+EDX-1])
* multiplies EAX by EDX (004474C9: IMUL EDX)
* adds result to temporary variable (004474CB: ADD DWORD PTR DS:[EBX+1F8],EAX)
* repeats length-1 times
In our example, the following is being computed for string “crackme”. ASCII code for character ‘c’ is 0x63, for character ‘e’ is 0x65, etc…
( c * e ) + ( r * m ) + ( a * k ) + ( c * c ) +
( k * a ) + ( m * r ) + ( e * c ) =
= ( 0x63 * 0x65 ) + ( 0x72 * 0x6D ) + ( 0x61 *
0x6B ) + ( 0x63 * 0x63 ) + ( 0x6B * 0x61 ) +
( 0x6D * 0x72 ) + ( 0x65 * 0x63 ) =
= 0x270F + 0x308A + 0x288B + 0x2649 + 0x288B +
0x308A + 0x270F = 0x12691 = 75409 (in decimal)
This is the method of computing serial number from string supplied by user.
Originally published at https://learncybersec.blogspot.com.