IDA program patching
It's not a rare occurrence when we want to load a binary executable in a debugger, change some bytes and then save the changed binary to a hard drive, making a new, patched executable. Actually, this is fairly frequent if we're trying to make a patch for a simple game or some other program for the fun of it. It can also be a useful skill to have if the code of some program is obfuscated and we would like to clear it up and save it.
Become a certified reverse engineer!
Program Patching in Ida
Ida's primary purpose is not binary patching, because when you first load the binary, it takes a snapshot of the binary and builds an internal representation, which is saved in the .idb database. Because of this, the binary executable is no longer needed to debug and execute the program; everything is saved in the .idb archive database and can be used by reverse engineers.
Let's first take a look at the Edit – Patch program options, which can be shown on the picture below:
On the picture above we can see three options: Change byte, Change word and Assemble, which can be used to change the database that Ida uses for representing the binary executable. With these options, we won't actually change the binary executable itself, but only the database representation of the executable that Ida uses for reversing. We can use the options presented above to change the Ida database, which we can later use to create a new patched binary executable.
If the Patch program submenu in the Edit menu is not present, we need to change the idagui.cfg configuration file and change the DISPLAY_PATCH_SUBMENU configuration option to YES as we can see on the picture below:
After that, we need to restart Ida for the Patch program submenu to become available.
The Edit – Patch program – Change byte option can be used to change one or more bytes in the Ida database. Let's first switch to the hexadecimal view, which can be seen on the picture below:
We're currently located at the first byte 0x91 at address 0x004011E5. If we now press on the Edit – Patch program – Patch bytes, a new pop-up window will be displayed presenting the first 16 bytes from the beginning of our cursor, which is located at the address 0x004011E5. In the picture above, we can see that the first 16 bytes are indeed the exact same ones as on the picture below.
The "Address" here presents the virtual address where our cursor is currently located. The "File offset" presents the number of offset bytes at which the presented bytes lie in original binary executable. And the "Original value" presents the original 16 bytes located at the current virtual address. These bytes never change even if we modify the same 16 bytes located at the same virtual address multiple times; they always reflect the bytes from the original binary executable.
If we close the dialog box without changing any bytes and open another with the Edit – Patch program – Patch word menu option, we'll be presented with a dialog that we can see below:
We can see that this dialog only enables us to change two bytes at a time, while the previous allowed changing 16 bytes. This clearly makes the previous dialog more useful, because we can change more bytes at a time.
But there's also a third option to patch Ida's database file which is accessible through the Edit – Patch program – Assemble menu option. The dialog is shown below:
With the Assemble dialog, we can input the actual assembly instructions into the input box and the instructions will automatically be converted into the corresponding hexadecimal bytes, which are saved at the virtual address location. We can only input one instruction at a time though. If we open the assemble dialog and enter a "mov eax, 10" instruction in there twice, we'll get the following hexadecimal instructions:
We can see that the "mov eax, 10" instruction is automatically converted to bytes: B8 0A 00 00 00, which we can see displayed at the beginning of the previous picture (with the brown background). If we switch to assembly view, we can see the instruction as presented on the picture below:
We can see that the first two instructions are "mov eax, 10" as we've inputted them in the assembly dialog box. So far, we've seen three possible ways to change Ida's database file, and at most, we've been able to change 16 bytes at once.
Let's also take a look at the options that can be accessed through the File – Product file menu option in Ida. All the options are presented on the picture below:
We can see that Ida is capable of creating various file formats, like ASM, EXE, HTML, C, etc. Let's describe what each of the options in the Produce file can be used for. Ida can be used to produce the following file formats:
- MAP: files that contain information about symbol names from the executable. When creating the MAP file, we'll be able to choose which symbol names to include in it. A dialog box like the one presented on the picture below will be shown, asking us what we would like to include in the MAP file:
- ASM: files that contain all the information needed to create the binary file with the assembler. The assembler must understand the syntax that Ida uses for this to be possible. Ida uses the assembly that is chosen under the Options – General – Analysis menu option, which can be seen on the picture below; in our case, the "Generic Intel 80x86" target assembler is being used.
When the ASM file is created, the following is printed to the output window: "Assembler file has been created, total 30178 lines."
- INC: files that contain the information about structures and enum data structures. LST: files that contain the disassembled assembly instructions from the IDA View-A window. On the picture below, a sample of the disassembly instructions are shown:
- EXE: this option should basically create the new executable file, but most of the time, it doesn't work because Ida doesn't know how to restore the imports, exports and resources back into the executable. Usually, we will receive a warning message box presented on the picture below:
- DIF: this option generates the DIFF file that presents all the changed bytes in the Ida database. If we would like to patch the original binary executable, we can use this option to get all the changed bytes which we can later apply to the original executable. The picture below presents a basic sample of changes. In this example, 10 changes have been made, where the first number in a line is the offset in a binary executable, the second byte is the previous value of the changed byte and the third byte is the currently used byte that we've replaced the old one with.
- HTML: this option is basically the same as the LST option, where Ida generates the disassembly instructions in an HTML format. We can see an example on the picture below:
If we want to patch a program in Ida easily, we can download pe_scripts.zip from http://www.openrce.org/downloads/details/57/PE_Scripts and extract it. The zip archive contains the files presented on the picture below:
For this example, let's create a new console project in Visual Studio and create the following main source file:
[cpp]
#include "stdafx.h"
#include <stdio.h>
int _tmain(int argc, _TCHAR* argv[])
{
printf("Hello Dear Windows!n");
/* wait */
getchar();
}
[/cpp]
We can see that the program is really simple; all it does is print the "Hello Dear Windows!" string on the screen and then wait for the user to input a key. This is done for the sole reason that we won't have to set breakpoints at the end of the program, because the program execution is stopped while waiting for an input from the user. Once we compile and run the program, we'll be presented with a new window that can be seen on the picture below:
Let's now load the new program hello.exe into Ida. When loading the program into Ida, we must uncheck the "Make imports section" because this option will convert .idata section definitions to "extrn" directives and truncate it. If there is some data in the .idata section, then this data will be lost, which is why we must disable this option when loading the executable. The dialog where we have disabled the "Make imports section" can be seen on the picture below:
After the executable has been loaded, we need to run the pe_sections.idc script to translate all sections from the executable file into Ida's database. We can run the file by selecting it in the File – Script file dialog. Before the script is run, we'll have the segments presented on the picture below loaded into the Ida database:
After running the pe_sections.idc script, we'll have the following segments:
We can see that a few segments have been loaded into Ida's database. Now it's time to change the bytes in Ida's database. In our case, we'll change the string "Hello Dear Windows!" into "Hello Dear Linux!" We can quickly locate the string by opening the Strings window, which is presented on the picture below:
The string "Hello Dear Windows!" is located at the address 0x0041573C, which is in the .rdata segment. To patch the string, we much double-click on the entry in the Strings window, which will take us to the disassembly. We then must change to the Hex view. After that, we must click on the 'W' letter that is part of the 'Windows' word and click on the Edit – Patch program – Change byte. A new pop-up window will be shown and is presented on the picture below:
We can see that the string that we're changing corresponds exactly to the "Windows!n" string. We need to change the above bytes to the "Linux!n" string bytes. To get the exact bytes, we can use Python programming language to convert the string into its hexadecimal representation. We can do that with the command presented below:
[plain]
>>> "Linux!n".encode("hex")
'4c696e7578210a
[/plain]
The bytes 4c696e7578210a are the hexadecimal representation of the string "Linux!n" which we need to input into the Patch Bytes dialog box as shown below:
After saving the new bytes, the memory at that location will look like this:
We can see that the bytes have been properly changed. To save the executable, we can run the pe_write.idc script with the use of File – Script file and save the executable as hello.exe. After that, we can run the program from console and it should print "Hello Dear Linux!" instead of "Hello Dear Windows!"
Conclusion
We've looked at the capabilities that Ida has for patching binaries. Most of the functionalities save the changes into Ida's database, but we can later export the changes to various formats. The most useful format is DIF, which outputs only the differences made to the executable. We can't really export the file as EXE, because the functionality will most likely fail. This is why we should use pe_scripts, which are good for exporting the current Ida's database into the EXE binary executable. We've also created an example to show how to change a string in the executable using Ida.
Become a certified reverse engineer!
Sources
[1] Chris Eagle, The IDA Pro Book: The unofficial guide to the world's most popular disassembler.