There are many reasons to reverse engineer a compiled binary for some type of patch. Maybe someone lost the source code to a program and it needs slight tweaking. It could be malware that is checking for a specific condition and we need to change that to get different behavior during analysis. Or maybe you just want to know how something works. No matter what the case, binary modification to most seems like dark magic not dare touched by mere mortals. Today I want to change that view for you as it isn’t as complicated as most think.
This demonstration is going to compile a simple program that doesn’t meet a certain condition and never will unless we recompile with the logic we want or by modifying the binary code inside the executable. For this we will use, Ghidra, an NSA open-source reverse engineering tool released for public use.
Building our test binary.
For our test binary, we will use a simple C program. All it does is compare the variable password with the string literal, “newpassword”. Since this is not what is stored in the password variable, the if else statement will always return else stating via the printf() statement that we have to modify the password.
# filename : crack.c
#include <stdio.h>
#include <string.h>
int
main(int argc, char *argv[])
{
char* password = "thepassword";
if(strcmp("newpassword", password) == 0)
{
printf("Nice work. The password is correct!\n");
}
else
{
printf("You have to modify the password, it's wrong!\n");
}
return 0;
}
For Windows, I use MingGW to have the GCC compiler available to build C programs. This is a simple test for our build options we just output the compiled program to an .exe file. Once it is build we can run it in the terminal and confirm the logic.
gcc crack.c -o crack.exe
Okay! Everything is working. We can now patch the binary to have the password variable set to “newpassword” so the program can congratulate us on having the right password without the need to recompile the program.
Modifying the binary with Ghidra
Start up Ghidra. When working with any binaries, we need to create a new project first. If you are not planning to work on the binary with a team, it is best to use a non-shared project. Name the project what ever you wish.
Importing the binary is simple. Just drag and drop the file into the “Active Project” window. We want to modify the raw binary so it is very important to change the settings so we can export correctly when we are done. We build the program with GCC so we need to confirm that in the “Language” dialog. My platform is x64 so make sure you have the correct bit for your compiled program here.
You can view and close the “Import Result Summary”. Then drag the imported file to the icon. Then confirm yes to analyzing the file. Once your program is done analyzing, go over to the “Program Trees” dialog on the top left corner of Ghidra. This breaks down all the sections of the executable. Our password string is a constant so it will be located in .rdata Data section. Click to highlight it.
With the .rdata section open in the “Listing” dialog you can see our string “thepassword” we want to change. If you highlight, right click and select “Patch Instructions” you will find a bug when you try to change the text. You get the the “Invalid instruction and/or prefix” when entering the ds instruction. We will have to find another way to modify the password.
Fortunately, there is another way to patch the string. Go to Window-> Bytes to open up a hex view of the data representation. If you click on “thepassword” you can now see the highlighted data in its hex format starting with 74 in the “Bytes” window.
First we need to convert our “newpassword” to hexidecimal to modify the binary with the right password to get our payload.
- “newpassword” = 6E657770617373776F7264
In the “Bytes” dialog, click on the icon so we can edit the hex. As you can see, when you change the hex values, the “Listing” dialog represents the change. For this demonstration we only need to change the first 3 values to get our new password.
We have patched our binary, we need to export it. Go to File->Export Program.
Make sure you change the format to “Binary”, change to a new name, then export.
With our patching complete and binary exported, we can go ahead and run it. Now that the strcmp() function returns 0 for a correct match, we get our congratulations for patching the program with the right password.
Wrap up
One can easily see the power of having the ability to actually change the bits around in an executable. You can change around lost of behavior of a program. This specifically come in handy when dealing with certain malicious code. Highly skilled malware writers are now checking for virtualized environments, certain types of languages, or anything else that will spook the writer into not having his/her code let go of it’s payload on a victim’s computer. Having control over a malicious code’s flow control could be the catalyst to learning exactly how the code works without having to be in the specific environment that will allow the code to infect.
If you want to learn more, stay tuned for new articles including how to modify jump calls in assembly change the programs conditions to trick malware into thinking its in the exact environment the writer wanted it to be in to learn its true behavior.
Comments are closed, but trackbacks and pingbacks are open.