In this article, I will tell about the main tools that a modern software reverser uses in his work.
This article is for readers, who are familiar with the Assembler language, network interaction principles, and have experience of programming for Windows using API functions.
Researcher of Driver R&D Team
1. Applications for software reverse engineering
1.1. IDA-Pro, Hex Rays
1.2. CFF Explorer
1.3. API Monitor
1.8. Relocation Section Editor
2. Practical software reverse engineering examples to show tools
2.1. Opening of the researched executable in IDA-Pro
2.2. Getting the information about the packer in PEiD
2.3. Unpacking with CFF Explorer
2.4. Modification of the executed statements in Hiew
2.5. Deleting a value from the Relocation table by means of Relocation Section Editor
2.6. Modification of a value in the Relocation table by means of CFF Explorer
2.7. API Monitor
There are so many different software applications in the modern world, and the source code of the most of them is hidden from our sight. But there are a number of situations, when we do need to understand the logic of functioning of platforms and applications, their algorithms and specifics. That is when the legal software reversing is called up – a service provided by Apriorit software research department.
There are a lot of products to make this task easier. We are going to discuss some of the software reverse engineering tools; mainly it will be tools for Windows application reversing and research. Notice that you can learn more details about the process and nuances of Windows software reversing in this post (great example included). If you are more interested in iOS/OS X code reverse engineering tools and approaches - take a look at this post prepared by our researches.
It’s hard to name the best software reverse engineering tool – there quite a few of them, and each one resolves some specific task of the multistep reversing process. Let’s make a brief overview of the those applications, Apriorit researchers frequently use in their projects.
IDA Pro can be definitely mentioned among the best reverse engineering tools. It is an interactive disassembler, which is widely used for software reversing. It has the in-built command language (IDC), supports a number of executables formats for variety of processors and operating systems.
This tool allows you to build diagrams, change marker names, look through the local procedures in the stack, and much more.
Hex Rays Decompiler is a plug-in for IDA Pro to decompile Assembler code.
You can find more details here.
CFF Explorer includes:
- PE and HEX editors
- Resource editor
- Import editor
- Signature scanner
- Address converter
- Dependency analyzer
- and more.
Find more details here.
API Monitor is an application, which intercepts API function calls. It can display input and output data. By default, there are 10,000 API functions and more than 600 COM-interfaces enabled.
You can learn more details here.
It is a HEX-editor that provides rich set of features and tools.
WinHex can display checksums or codes of software files, which simple text editor is not able to do.
You can learn more details here.
Hiew is a binary files editor, focused on work with code. It has built-in disassembler for x86, x86-64, and ARM, assembler for x86, x86-64.
- Viewing and editing logical and physical drives.
- Searching for assembler commands by template.
- Keyboard macros.
- Built-in 64-bit calculator.
- Tools to create custom plugins.
Learn more details here.
Fiddler is a proxy that operates with traffic between computer and remote server, and allows viewing or changing it (MITM). It can work with both HTTP and HTTPS.
You can use Fiddler to intercept traffic that goes between the application and the server.
It allows to intercept HTTP/HTTPS. It is possible to add plugins (e.g. wbxml view, which can decode wbxml), display requests/responses in different views. It contains built-in hex editor. Fiddler is also able to generate requests based on the selected one, or create a custom request.
In addition, there is the “Request to Code” plugin for Fiddler, which allows to get ready code that executes requests on C#, VB, or Python. You can download it here.
It is an application that allows to dump a running application process and restore the import table. After that, you can run the application. You can download the application here.
Application that removes values from the Relocation table. You can download it here.
PEiD is the best tool to use to detect the packer. By analyzing the entropy, PEiD can detect whether the application is packed or not.
There is also the KANAL (Krypto Analyzer for PEiD) plugin, which analyses PE file for the presence of known encryption algorithms.
There are various useful plugins that help to analyze PE files.
Learn more details here.
Now let’s consider how to use mentioned software reverse engineering tools in practice, to research the applications. We will research a test application, you can download it here.
Let’s download a test application to IDA Pro. We receive the following message:
It means that something goes wrong with application: import table cannot be found. After that, we press the OK button and get the following:
The import table is almost empty. Its upper part shows that it was possible to detect a small piece of code (the blue part), and the left part shows which functions were detected (in our case, only two functions were detected). As we can see, there is a set of undetected bytes above the start function. We suppose that the application is packed by means of some packer. PeiD will help us to detect which packer was used.
Load our application.
The fact that Entry Point is located in the UPX1 section is not really saying much. It is necessary to run a scan. Just go to Options and choose "Hardcode scan":
Then, select the folder where our application is. After scan, we will see the result:
We can see that the application is packed using UPX.
The tool contains various plugins:
We are not going to consider them all, just mentioning that one of them is able to unpack the application. We will better do this via CFF Explorer.
CFF Explorer helps to unpack the application. To do that, we go to the UPX Utility page and press the Unpack button:
After that, we can upload the application to IDA Pro, and assembler code will be restored.
We download it again to IDA Pro, which will ask whether to upload symbols from server, and we agree. Here is the result:
We see that there are code, some functions in the application, and import table. Now we run the application and debug it in IDA Pro. Select Debugger->Select Debuger->Local Win32 debugger, and then F9. As a result, we get:
The tested application detected that it was debugged, and even displayed a message that it was not registered:
We need to get rid of the fact that the application has detected a debugger.
See the import table:
At once, we can notice the NtQueryInformationProcess function. After clicking on it, we get the following list of xref functions:
Clicking on it, we can see where it is called. The third parameter is an output one, if it equals to 1, then debugger is attached to application, if it equals to 0, then debugger is not attached. Let’s see where the result of this function is written to:
We see that the third parameter contains the address of local variable (var_8). After function call, the result of the function is checked (test eax, eax). Then the value of var_8 is checked. If it is not 0, then the value is written to byte_131443C. Let’s check if this variable is used somewhere else in this function:
We’ll start from the end. This value contains the result from al (lower bytes). Before that, the esi result is written to eax, and 1 is written to esi. Above, we see the condition for writing 1 to esi: if ecx + 2 is not equal to 0. The value in ecx is large fs:30h (and then + 2), it is a verification of debugger presence bypassing the IsDebuggerPresent function (a field of undocumented PEB structure). Let’s rename this variable. Press “N” or Right click->Rename. Let’s see where it is used:
There is “…” in the end, so it is used in more places. Place the cursor over it and click «X» or Right click->Jump to xref to operand:
We already know the first places, where it is used, but not the last one. Let’s check it:
We see that it is checked whether it equals to 0. If it doesn’t, then we receive the message that there is a debugger.
We’ll consider the way to remove this verification in the “Hiew” section. It is worth noticing that IDA also allows to patch memory/code. In order to quickly find this piece of code, we’ll run the Rebase program to get the same offset as in Hiew. Select Edit->Segments->Rebase program, enter 0x400000:
Let’s get the address of the code that performs the comparison. It is 0х401329:
This value will be used in Hiew.
Let’s upload our application. First, it looks as follows:
Switch to the Decode mode. Press F4->Decode. Now we have to find the address, which we received in IDA Pro earlier. It is 0х401329. Press F5 and set the address this way:
We get code that compares our variable (g_isDebbugerPresent):
Now we can replace it with, for example, jmp to specific address, so that this condition would never be satisfied (in real applications, it can be an exception to immediately close the application).
Press F3 and then F2 to switch to the Edit mode. Enter the address of the next command after if. Add “.” in the beginning of the address, so that it would be relative:
After editing, our modified command is highlighted in yellow. Press F9 (Update), our application is saved.
If we try to run it, it is crashed.
Considering the Assembler code, we see that the new jmp will result in call esi, and esi will contain garbage instead of the MessageBox function address. We’ve missed the first mov esi, ds: MessageBox:
Therefore, let's swap saving address to esi and our jmp. Now, we should set relative address in jmp to 14, but no longer to 1E, because the command became closer to the command we are going to.
Now, to make jmp, we should save the MessageBox address to esi.
After working with Hiew, let’s run it in IDA Pro, we go to our address:
We see that there is an unconditional jump. If we run application using debugger, we’ll receive crash, because previous command contained absolute address, and after application start, loader passes the Relocation table and adds delta to and each value to make all addresses valid. We just have to remove this value from the Relocation table. Let’s upload the original file to IDA Pro, find deleted earlier cmp, and enable option of showing commands in byte representation in IDA. Select Option->General:
This is what we get:
Cmp is a double-byte command starting with 1329, and the address starts with 132B. We can see that jmp is a one-byte command and its address is relative (it means that it shouldn’t be in the Relocation table):
Thus, we have to remove the 132A value from the Relocation table.
Open the application, changed by us, via Relocation Section Editor.
We have loaded the application and found the target value - 0x0040132A.
Remove it and save. After running, we get crash again. Go back to IDA Pro.
After removing 132A from the Relocation table and swapping jmp/mov, we also get crash. That’s because we haven’t edited the value, which previously pointed to mov, and now should point to jmp.
Open it in CFF Explorer. We have found the value, on which delta for MessageBox used to be added before. It is 1332.
Now, we’ll replace it with 132B, new value, bt which MessageBox can be found.
We run the application and see that it is not crashed any more and doesn’t show message about debugger detecting:
You can remove this message yourself :).
This program contains a number functions it can monitor. There is also a possibility to add your own functions.
Let’s monitor our application – we’ll try to find the MessageBox function calling:
I have pointed only a few functions.
Select File->Monitor New Process and set the path to our file.
After running our process, we see the list of the called functions. Let’s try to find MessageBox – here it is:
API Monitor shows which parameters were passed to it.
It is possible to set different breakpoints:
Run the monitoring of our file and here is what we get:
We can see the parameters, passed to this function.
By means of API Monitor, it is easy to monitor the network function calls and research the passed parameters (of course, if the traffic is not encrypted).
We should detect the type of binary file before exploring it. To do that, you can use any hex editor. As an example, I will use WinHex. Open file:
MZ signature at zero offset corresponds to the PE-format files (executables or shared libraries), so it is an exe file or dll.
For example, dump will look as follows:
Most file formats have its unique signatures.
In this section, we’ll consider the packed app. We are not going to unpack it, we will make its memory dump and try to run it.
To do that, open the packed executable file in IDA Pro. We do it to find the original entry point into the application (OEP), rather than the entry point of the packer.
The pusha command saves general-purpose registers to the stack. In the end, there should be popa, which pushes the stored register values. After this command, there is jmp to the original point of entry. You can use the "Search for text" option by pressing Alt + T and looking for popa.
Below the popa, there is jmp 40A191, which will eventually move to the original entry point.
Put a breakpoint in jmp and run the debugger.
Now let's follow jmp, but IDA Pro shows:
It means that there is no code at the point, we're going to. Therefore, IDA will create instructions in disassembled listing on the basis of bytes pointed by EIP.
0x00971A91 is the address of the original entry point after unpacking the application into memory.
Now, without closing the IDA Pro, open the Scylla in order to make the application dump and restore the import table.
In the process list, we choose our application and put OEP into the field:
Press IAT Autosearch, and then press Get imports. As a result, it shows that the import table is found.
Let’s make an application dump: press Dump, save it, then Fix Dump, and select the previously saved application.
If we run our application, it will still crash. So, we need to remove the Relocation table.
Open modified dump (it has the _SCY prefix) in CFF Explorer.
Set 0 to the «Relocation Directory RVA» field.
Check whether the ImageBase is the same as the application loaded into memory. This value can be found in IDA Pro, Edit-> Segments-> Rebase program.
Save and run your application. We receive the expected message:
In this example, I tried to show you the work with every software reverse engineering tool we briefly considered in the first section. Anyway, the best way to master all these products is just start experimenting and researching yourself :)