Ghidra is an open source tool developed by the U.S. National Security Agency (NSA) for reverse engineering binaries when you don't have access to the source code. It can be used to assist in capture the flag cyber security challenges. Among its many features is that it can convert binaries into C code. Ghidra can run headless or through a Java GUI. This post will focus on using the GUI to decompile and debug a C program given just the binary.
Installation
This installation guide assumes you are installing to a Debian based Linux distribution.
Install JDK
Ghidra requires the Java Development Kit (currently uses JDK 21) to run. Eclipse Termurin is a free, open-source JDK provided by the Eclipse Adoptium project. It is a build of OpenJDK that is widely used as an alternative to Oracle JDK. Depending on the Linux distribution, you may be able to install the JDK using the following command:
$ sudo apt install temurin-21-jdk
If your distribution doesn't distribute a Temurin JDK, then you can download the version for your hardware architecture from Adoptium. Follow the installation instructions for archives.
Install GBD
Run the following command to install GDB (the GNU debugger) if you want to be able to use Ghidra's debugging features:
$ sudo apt install gdb
You will need gdb compiled with Python version of at least 3.7. Verify the version of Python supported by GDB by running the following:
$ gdb
(gdb) python import sys
(gdb) python print(sys.version)
(gdb) quit
Make sure the version is 3.7 or higher.
Install psutil and protobuf Python Modules
To use the GDB debugger in Ghidra, you need the psutil and protobuf Python modules to be installed:
$ sudo apt install python3-psutil python3-protobuf
Install Ghidra
Download the appropriate zip file from the GitHub repo. Unzip it to a directory then find the "ghidraRun" script and run it.
Create a Sample C Program
You can skip this step if you already have a binary you want to decompile but when learning I think it is best to start with something where you already know the code being decompiled. This code comes from the leetcode solution for the simple two sum problem. Create a main.c file:
#include <stdlib.h>
#include <stdio.h>
int* twoSum(int* nums, int numsSize, int target, int* returnSize)
{
for (int i = 0; i < numsSize; i++) {
for (int j = i + 1; j < numsSize; j++) {
if (nums[j] == target - nums[i]) {
int* result = malloc(sizeof(int) * 2);
result[0] = i;
result[1] = j;
*returnSize = 2;
return result;
}
}
}
*returnSize = 0;
return malloc(sizeof(int) * 0);
}
int main() {
int nums[5] = { 7, 3, 5, 10, 22 };
int returnSize = 0;
int* twoSumResult = twoSum(nums, sizeof(nums) / sizeof(nums[0]), 32, &returnSize);
if (returnSize > 0){
for (int i = 0; i < returnSize; ++i){
printf("twoSumResult[%d]: %d\n", i, twoSumResult[i]);
}
free(twoSumResult);
}
else{
printf("No result\n");
}
}
Compile an executable by running:
$ gcc -o main main.c
Note you may have to install the gcc compiler if you haven't already done so.
Creating a Project in Ghidra
- Go to "File" then "New Project" and select "Non-shared Project".
- Select the directory and give the project a name (in our case TwoSum).
- Drag and drop the main executable from a file explorer window to the newly created project pane.
- A pop-up should appear. Have a look around at the options and languages then click "OK" and then "OK" again when the next popup appears.
Browsing the Code
- Select "main" in the Active Project pane and drag it to the dragon button (i.e. Code browser) in the Tool Chest set of buttons.
- Click "Yes" on the analyze popup then click "Analyze" on the next popup keeping all options set to the defaults.
Finding the TwoSum Function
- Select "Search" then "Program Text" from the menu.
- Select the "All Fields" button then click "Search All".
A popup should appear. Select "twoSum" and the listing window should auto navigate to the disassembly listing.
Next select "Window" then "Decompiler" from the menu. A pane should appear with the decompiled code.
You can see that the decompiled code differs from the original code we wrote. This is because Ghidra reverse engineers C code from the compiler generated instructions in the binary file.
Debugging the Code
- Close the Code Browser window and return to the Ghidra project window.
- Select "main" and drag it to the button with a bug on it (the debugger tool).
- Click "Yes" to analyze then click "Analyze".
- From the "Debugger" menu item click "Configure and Launch main using...".
- Then select "gdb" then click "Launch" on the popup keeping the defaults selected.
- The launch of GDB should be successful and you should see a message in the GDB pane:
Connected to Ghidra 11.2.1 at 127.0.0.1:36921
- Next click on "Window" then "Decompile: main" from the menu. You should see a pane that now shows the decompiled main code.
Setting a Breakpoint
- In the decompiled code pane, right click on the line you want to break at and select "Toggle Breakpoint".
- Leave the defaults as selected (specifically ensure "SW_EXECUTE" is selected) and click "OK".
- Click on the the green arrow button on the main debugger window to start debugging.
- You should see the debugger stop at the breakpoint.
- You can then step using the arrow buttons on the debugger menu:
Note you can see the values of various variables as you step by hovering over them.
Conclusion
This was a brief introduction to installing and using Ghidra. It has many more features to explore so take your time. Or you could join a capture the flag challenge and see how you go using it on unfamiliar code. There are also lots of YouTube videos showing how it can be used in capture the flag challenges too.
Top comments (0)