Reverse engineering

Unpacking, reversing, patching

Ninj@S3c
February 13, 2013 by
Ninj@S3c

This article is an introduction of packing, how to unpack, to reverse an exe and finally patching it. I have chosen to show reversing of a sample exe file and how to patch it.

Packing/ Unpacking

Packing is the process of compressing an exe,including the data and decompressing function with the compressed exe itself [Fig-1].

[caption id="" align="alignnone" width="626"] Fig-1[/caption]

Unpacking is the reverse of this; it's a process of identifying the decompressing function and extracts the original data out of exe.

Goals of packing:

  • To reduce the size of exe
  • To obfuscate the data, in case of malwares

There are lots of packers available such as UPX, NeoLite, PECompact, etc… to achieve the goals mentioned above.

Identifying the packer:

First, we need to identify the exe if it's a packed executable file. To confirm this we will use a tool called PEiD, which can really tell us if this is packed and if yes, using what packer. Launch the PEiD tool and locate the executable. You will see it displaying the information based on which tool it was packed with. [Fig-2].

[caption id="" align="alignnone" width="424"] Fig-2[/caption]

Unpacking the exe:

We'll use OllyDbg for unpacking the executable. Load the exe in OllyDbg; now there are two things in this exe, first- EP, which is the entry point where the OllyDbg lands; second is OEP, Original Entry Point, which is entry point for original code. So we have to detect the OEP in order to unpack the executable. As soon as the packed exe is loaded, it hit it's EP [Fig-3].

[caption id="" align="alignnone" width="424"] Fig-3[/caption]

Once the EP is found, we need to look for the OEP, which is original entry point for the exe. We need to just keep scrolling until we find an instruction called POPAD, which is used to pop words into general purpose registers. Soon after POPAD, we need to find a jump instruction, which takes us to the OEP. Make a breakpoint at this address (POPAD). Press F9 to load and execute the packed exe which comes and pause at the breakpoint. As shown in the Fig-4, the OEP address is in jump instruction.

[caption id="" align="alignnone" width="426"] Fig-4[/caption]

OllyDump plugin:

OllyDump is a plugin (.dll) which dumps the active process to an executable file (PE). Now, press F8 until it takes the jump and reaches to the address (00401000). Once there, we will use OllyDump to dump the original code. Go to Plugins->OllyDump->Dump debugged process. We will be presented with the screen shown below in Fig-5. As we can see, the Entry point was the address of the packed executable which is being modified to a new address and being assigned to the EIP register for executing the next instruction.

[caption id="" align="alignnone" width="459"] Fig-5[/caption]

Click the Dump button, save the new executable, which is now unpacked, to the location of your choice. Now the unpacked executable will be un-obfuscated, easy to read and analyze [Fig-6].

[caption id="" align="alignnone" width="563"] Fig-6[/caption]

Reverse engineering

Once the exe is unpacked, we will try to analyze it and patch it. As per Wikipedia, "Reverse engineering is the process of discovering the technological principles of a device, object, or system through analysis of its structure, function, and operation." A source code is compiled to the object file and finally it's linked to the executable. The executables are purely in binary mode and not in a human friendly form – it's not human readable. So when we try to reverse the same process and bring back the executables to its object phase, which is called disassembling, it's called reverse engineering. [Fig-7]

[caption id="" align="alignnone" width="368"] Fig-7[/caption]

Loading the exe to OllyDbg:

OllyDbg has four windows: Code Window-which shows assembly code of the application loaded, Register Window-shows values on each of the register, Stack Window-which shows different values loaded onto the stack at the time of execution and the Memory Dump Window. For executing instructions step by step, the F8 key is used; to run the application continuously F9 key is pressed. The F7 key is used to peek into any function and F2 is used to set a breakpoint where an application may be paused to check its behavior. There are several other options as well, but mainly only these four are used for the inspection of codes. [Fig-8]

[caption id="" align="alignnone" width="625"] Fig-8[/caption]

Reversing Exe

We shall start the reversing by using our unpacked exe (Crackme2.exe) [http://crackmes.de/ ]. Load the exe by going to the File menu of Olly and open the exe by locating it on your hard disk and the exe appears on the screen (Fig-9). As soon as the exe is loaded into Olly you can see a lot of assembly codes that is dissembled in the code section. To get a feel of the exe and what it does, press F9 to run it; the CrackMe.exe then appears on the screen:

[caption id="" align="alignnone" width="625"] Fig-9[/caption]

If you enter the wrong password and press OK, it will display a message "No luck there mate!" Since we don't know the correct password, we can't get through the application. So our goal will be to inspect the code and break this barrier to get the "Congrats…" message. This can be done in two ways:

  • We can understand the logic behind the password evaluation and supply a similar one
  • We can alter the flow of the execution without really caring about the password

The first option is a bit difficult as you really need to dive in each and every routine/subroutine and understand the logic. The second one is a bit easier as you only need to directly go and see how we can go to the logical end, and can then change the flow. We'll carefully go through the assembly, understand the logic behind this and try to overcome the password checking. Again, there may lots of ways to break this functionality and that depends on the software's behavior, but the ultimate goal is to bypass the password check. How and which routines/functions we need to inspect is entirely one's personal way of doing that based on intuition, but more or less it will be similar approach. This is my way of doing that and it may differ with the method of others.

Now let's understand the flow:

Now again, press CTRL+F2, this will reload the CrackMe2.exe into Olly (Fig-10). Once loaded, press F8 and step through the instructions to get an idea about the code. Olly lands at the following instructions:

[caption id="" align="alignnone" width="625"] Fig-10[/caption]

There are several APIs that are executed by them, such as, GetModuleHandleA, it returns the handle to the file of the current process. Similarly, few more APIs- FindWindowA, LoadIconA, LoadCursorA and CreateWindowExA which pretty much indicate that the exe being loaded and the icons and windows are being created. Similarly, ShowWindow and UpdateWindow are used to display a dialog box. But basically, what are we looking for is the API which actually takes the user input. Carefully going through the code window gives one API which seems to be a bit interesting: GetDlgItemTextA. We need to observe this very carefully because it's where we give the input and will capture the logic. We need to put a breakpoint, which pauses the execution there, for further inspection. So we press F2 to set the breakpoint where the function starts at 004012B3 (in Red) [Fig-11]:

[caption id="" align="alignnone" width="625"] Fig-11[/caption]

Now time to rerun the exe and catch at the breakpoint. Press CTRL+F2 to reload the app. Press F9 to run it, it will automatically come and halt at the set breakpoint. Now enter the password in the dialog box, I shall enter a two letter sample password 'ni' in the dialog box. As soon as we click 'OK', the execution halts at the breakpoint. Now it's is for the real observation of the code. Press F8 to step through each following instruction. Everything seems pretty normal as the code just accepts the input and traverse internally to some other address not directly related to main flow. I just keep pressing until it again return back to main execution flow. Where I can see the strings entered by me is being pushed (PUSH CRACKME2.0040217E) [Fig-12]. Just after pushing, two functions are being called. We will examine them one by one.

[caption id="" align="alignnone" width="626"] Fig-12[/caption]

Let's examine Function1 at (CRACKME2.00401365). I press F7 to enter into the function [Fig-13]. The value ('ni') copied and being pushed using ESI. Now the instruction MOV AL,BYTE PTR DS:[ESI], taking the first letter 'n' from the value and copying to AL. Now AL is 'n' (6E), so TEST AL,AL is not zero (equivalent to cmp AL, 0), the jump is not taken and goes to next instruction INC BYTE PTR DS:[402118], which is for incrementing the counter. The next instruction CMP AL,41 compares 'n' (6E) with 41 (A). The flow goes to CMP AL, 5A and compares 'n' (6E) with 5A (Z), which probably checks if the value supplied is between A and Z. Since yes, the flow goes to CALL CRACKME2.004013B2, which is another subroutine.

[caption id="" align="alignnone" width="625"] Fig-13[/caption]

Carefully inspecting the code, it shows that it just converting lower case letters to upper case (SUB AL, 20) [Fig-14].

[caption id="" align="alignnone" width="595"] Fig-14[/caption]

The same instructions are repeated until the next letter 'i' is converted to 'I'. Now the control goes to address 00401399 [Fig-15]. The instruction MOV CL,BYTE PTR DS:[EDI+4021A3] picks up one character, starting at 004021A3 from Hex dump and moving to CL ('M'). The instruction MOV BL,BYTE PTR DS:[ESI] transfers one byte to BL (our password's first letter 'N'). XOR BL,CL does an XOR operation with 'M' and 'N'. And it keeps doing that till our passwords last letter ('I') is finished. So, it has given us the hint that our password supplied is being XORed with the string at address 004021A3 (Messing_in_bytes), which is of 16 characters long. So that means our password length also should be 16. After XORing, the result is being pushed at address 0040217E [Fig-12]. In next call, CALL CRACKME2.004013B8, the result is being compared with the correct XOR result in 004013B8 [Function 2]. Now let's examine this function [Function 2]. Press F7 to step in [Fig-16]. So, the string being returned from 004013B8 is starting from the address 00402150 ie, 1F 2C 37 36 3B 3D 28 19 3D 26 1A 31 2D 3B 37 3E.

So, now to get the original password, we need to XOR the Hex of 'Messing_in_bytes' and 1F 2C 37 36 3B 3D 28 19 3D 26 1A 31 2D 3B 37 3E

So, 4D 65 73 73 69 6E 67 5F 69 6E 5F 62 79 74 65 73 XOR 1F 2C 37 36 3B 3D 28 19 3D 26 1A 31 2D 3B 37 3E = 52 49 44 45 52 53 4F 46 54 48 45 53 54 4F 52 4D (nice calculator here http://www.jdejong.net/tools/bitwisecalculator.php )

Now convert above Hex string (52 49 44 45 52 53 4F 46 54 48 45 53 54 4F 52 4D) to ASCII, which gives:

"RIDERSOFTHESTORM". So this is the correct password! So, if we feed this password in the Crackme2, we will get the message "Great work…"

[caption id="" align="alignnone" width="625"] Fig-15[/caption]

[caption id="" align="alignnone" width="624"] Fig-16[/caption]

Another approach:

This approach talks about changing the flow of the execution so that whatever password is supplied, it's successful. No need to detect the correct password. So, here we go. Supply any random password ('IamHere'), keep pressing F8 until it comes back to the code as shown in Fig-12. Now the instruction TEST CL, CL checks if value of CL=0 (equivalent to cmp CL=0) [Fig-17]. Since here CL=06, the next instruction JE SHORT CRACKME2.0040124A is not taken and instead CALL CRACKME2.00401349 is executed, which takes us to message saying " No luck mate..". In order to get messages "Good work…" , we need to change the flow of the code. So, if we change the address 00401349 with 00401334, we change the instruction as CALL CRACKME2.00401334. Now this takes us to our goal, where we are finally greeted with "Good Work…" message!

[caption id="" align="alignnone" width="576"] Fig-17[/caption]

Patching the code

Highlight the CALL Crackme2.00401349 instruction, hit the SPACE bar on the keyboard and change the address to 00401334 then click Assemble (Figure-18). Now the code CALL Crackme2.00401349 gets replaced by CALL Crackme2.00401334.

[caption id="" align="alignnone" width="626"] Figure-18[/caption]

To save this patched code, right click in code window, select copy to executables, all modifications, Copy All, Save File as PatchedCrackme.exe

Rerun the patched exe and supply any random password and be greeted with "Good work mate…

[caption id="" align="alignnone" width="626"] Fig-19[/caption]

Sources

Ninj@S3c
Ninj@S3c

Ninj@S3c is a Security Analyst with a leading MNC. He is predominantly focused on Application Security, Network Security and Wireless Security. Beyond this, he’s interested in Reverse Engineering and Forensics.