This is a hands-on with Ghidra covering from setting up Ghidra to learning how to use it.
- Introduction
- Hands-On Ghidra
- Conclusion
- References
Introduction
On March 5, 2019, the NSA (National Security Agency) released the reverse engineering tool "Ghidra". The release day was like a festival, with many security streamers on YouTube and Twitch broadcasting live while using Ghidra.
So this time, I wanted to try using Ghidra myself.
The goal is to solve a simple challenge from crackmes.one1 using Ghidra.
Let's get started.
# Environment in this post Ubuntu 18.04.1 LTS Running on a virtual machine built with VMware on top of Windows 10.
Note: This article was translated from my original post.
Hands-On Ghidra
Setting Up
Installing Ghidra
First, download Ghidra from the official site.
At the time I downloaded it, the version was "ghidra_9.0". After downloading, I unzipped the file and checked how to install it.
In the docs folder, a file called InstallationGuide.html:
To install Ghidra, simply extract the Ghidra distribution file to the desired filesystem destination using any unzip program
It seems that simply unzipping the file is enough to install Ghidra. That's very simple.
While many software requires an installation process, it's rare to see one that works just by unzipping.
Ghidra acknowledges the pros and cons of this method. Pros include:
On the up side, administrative privilege is not required to install Ghidra for personal use. Also, because installing Ghidra does not update any OS configurations such as the registry on Windows, removing Ghidra is as simple as deleting the Ghidra installation directory.
On the other hand, the cons are:
On the down side, Ghidra will not automatically create a shortcut on the desktop or appear in application start menus.
Installing JDK (Java Development Kit)
Continuing through InstallationGuide.html, it says that installing the JDK (Java Development Kit) is required.
Ghidra requires a supported version of a Java Runtime and Development Kit on the PATH to run.
The guide provides detailed instructions on how to install the JDK and add it to PATH.
Linux and macOS (OS X): Extract the JDK distribution (.tar.gz file) to your desired location, and add the JDK's bin directory to your PATH:
1. Extract the JDK: tar xvf <JDK distribution .tar.gz> 2. Open ~/.bashrc with an editor of your choice. For example: vi ~/.bashrc 3. At the very end of the file, add the JDK bin directory to the PATH variable: export PATH=<path of extracted JDK dir>/bin:$PATH 4. Save file 5. Restart any open terminal windows for changes to take effect
I'll follow this guide.
First, download the JDK. The supported JDK version is:
Java 11 Runtime and Development Kit (JDK). OpenJDK distributed from jdk.java.net is suggested
JDK 11 is supported. Since OpenJDK 11 from jdk.java.net is recommended, I downloaded that.
Now, following step 1 of the guide, extract the JDK.
Using the tar xvf
command as shown:
$ tar xvf ./Downloads/openjdk-11.0.2_linux-x64_bin.tar.gz
This extracted jdk-11.0.2
into the home directory.
Next, follow steps 2 to 4 to add the JDK to the PATH.
Following the guide, add the JDK directory to the end of the ~/.bashrc
file.
# Open ~/.bashrc with vim $ vim ~/.bashrc # Add the following line at the end export PATH=~/jdk-11.0.2/bin:$PATH
Save the file, and that's it.
Finally, step 5: close all open terminals and the JDK installation is complete.
Launching Ghidra
Now, let's launch Ghidra. How to start it:
Run ghidraRun.bat (Windows) or ghidraRun (Linux or macOS)
Since I'm working on Linux, just need to execute the ghidraRun
file.
Let's go to the directory where Ghidra was extracted and run it.
$ cd ghidra_9.0_PUBLIC_20190228/ghidra_9.0/ $ ./ghidraRun
And Ghidra launched successfully.
Opening a File with Ghidra
Download and Extract a Challenge from Crackmes.one
Now, let's solve a simple challenge from Crackmes.one using Ghidra. Crackmes.one is a site where you can upload and download programs for reverse engineering. You can legally enjoy reverse engineering there.
I downloaded a simple challenge called "easy_reverse".
cbm-hackers's easy_reverse - Crackmes.one
When extracting the downloaded file, I was prompted for a password. Checking the official FAQ2:
The password for the files is "crackmes.one". If it does not work, this is probably because the crackme has been imported from crackmes.de, so use the password "crackmes.de" instead.
The password was "crackmes.one". I successfully extracted the file.
Opening the Binary File with Ghidra
Now, let's open this file with Ghidra.
When you first start Ghidra, three windows3 will pop up, but the most important one is the medium-sized window: Project Manager. From the Project Manager:
File -> New Project
Then create a new project.
Non-Shared Project -> Enter Directory and Name -> Finish
Now the new project is ready.
Next, import the binary file you downloaded and extracted into the project. This is easy—just drag and drop the binary file into the window. A settings window will appear, so configure it appropriately and click "OK" to complete the import. For this case, "Format" was set to "Executable and Linking Format (ELF)", and "Language" was "x86:LE:64:default:gcc".
Once imported, double-click the file to open the analysis window.
When the analysis window opens, you'll see the message <filename> has not been analyzed. Would you like to analyze it now?
. Choose "Yes".
The Analysis Options window will appear with many options, but for now, just proceed with the default settings by clicking "Analyze".
Now you can begin analysis (Fig. 1).
Practical Reverse Engineering
Checking the Behavior of the Binary File
Now, let's try to crack the simple challenge "rev50_linux64-bit" downloaded from Crackmes.one.
First, I ran the binary file in the terminal to observe its behavior.
$ ./rev50_linux64-bit USAGE: ./rev50_linux64-bit <password> try again!
It seems the goal is to find the correct password to unlock this file. Let's analyze it with Ghidra.
Decompiling the main Function with Ghidra
We'll decompile the main function in Ghidra to examine its contents. This is easy to do.
In Ghidra's left-hand "Symbol Tree" window, type "main" into the "Filter:" field to extract "main" from the Symbol Tree. Click the "main" under "Functions" to jump to the main function. At the same time, the "Decompile" window on the right will display the main function decompiled into C code.
undefined8 main(int iParm1,undefined8 *puParm2) { size_t sVar1; if (iParm1 == 2) { sVar1 = strlen((char *)puParm2[1]); if (sVar1 == 10) { if (*(char *)(puParm2[1] + 4) == '@') { puts("Nice Job!!"); printf("flag{%s}\n",puParm2[1]); } else { usage(*puParm2); } } else { usage(*puParm2); } } else { usage(*puParm2); } return 0; }
We can roughly understand the algorithm from this, but some parts are unfamiliar, so let's clean it up step by step.
Fixing the Code Notation
A typical C main function looks like this:
int main(int argc,char *argv[]) { ~ }
However, the decompiled code looks like this:
undefined8 main(int iParm1,undefined8 *puParm2) { ~ }
Let's fix this.
It's simple. Right-click the part you want to edit in Ghidra and select "Edit Function Signature" to modify it. After fixing the main function header, the entire main function became:
int main(int argc,char *argv[]) { size_t sVar1; if (argc == 2) { sVar1 = strlen(*(char **)(argv[] + 8)); if (sVar1 == 10) { if (*(char *)(*(long *)(argv[] + 8) + 4) == '@') { puts("Nice Job!!"); printf("flag{%s}\n",*(undefined8 *)(argv[] + 8)); } else { usage(*(undefined8 *)argv[]); } } else { usage(*(undefined8 *)argv[]); } } else { usage(*(undefined8 *)argv[]); } return 0; }
It's much easier to read, but there are still some odd parts.
It seems the notation around argv[]
is incorrect4.
To fix this, replace the array notation *argv[]
with the pointer notation **argv
.
Next, change the main function header from int main(int argc,char * argv[])
to int main(int argc,char** argv)
and review the entire main function.
int main(int argc,char **argv) { size_t sVar1; if (argc == 2) { sVar1 = strlen(argv[1]); if (sVar1 == 10) { if (argv[1][4] == '@') { puts("Nice Job!!"); printf("flag{%s}\n",argv[1]); } else { usage(*argv); } } else { usage(*argv); } } else { usage(*argv); } return 0; }
Now it's much more readable.
Let's analyze the algorithm from this code.
Analyzing the Algorithm
The first half of the main function seems important.
int main(int argc,char **argv) { size_t sVar1; if (argc == 2) { sVar1 = strlen(argv[1]); if (sVar1 == 10) { if (argv[1][4] == '@') { puts("Nice Job!!"); printf("flag{%s}\n",argv[1]); }
First, if (argc == 2)
checks if one argument has been passed.
If true, it proceeds. If false, it jumps to another branch and calls usage(*argv)
.
So the first condition is:
1. One argument is passed
Next, the validation:
sVar1 = strlen(argv[1]); if (sVar1 == 10) { ~ }
This gets the length of the argument with sVar1 = strlen(argv[1])
and checks if it's 10 with if (sVar1 == 10)
.
So the second condition is:
2. The argument is a 10-character string
Finally, the last validation is:
if (argv[1][4] == '@') { puts("Nice Job!!"); printf("flag{%s}\n",argv[1]);
Here, it checks if the 5th character5 of the argument is @
with if (argv[1][4] == '@')
.
If this condition is met, the flag is displayed.
To summarize the validation algorithm:
1. One argument is passed 2. The argument is a 10-character string 3. The 5th character of the argument is "@"
With these, we should be able to crack this program.
Cracking the Program with the Password
Let's try opening the file with the password 0123@56789
, which meets the conditions.
$ ./rev50_linux64-bit 0123@56789 Nice Job!! flag{0123@56789}
It worked perfectly, and I got the flag flag{0123@56789}
.
Nice Job!!
Conclusion
This time, I covered installing and using Ghidra, along with a simple reverse engineering practice.
The features of Ghidra I used were very basic, but Ghidra has many more powerful capabilities. For now, I've achieved my goal of reversing something with Ghidra.
The challenge from Crackmes.one was also at the easiest level. Many more challenges are posted there, so I'd like to try new ones.
[Related Posts]
References
- https://crackmes.one/ - A site where you can upload and download programs for reverse engineering. You can legally enjoy reverse engineering there.↩
- FAQ - Crackmes.one↩
- Small window: Tips, Medium window: Project Manager, Large window: Help↩
-
Ghidra seems to have trouble recognizing array notation
[]
initialization.↩ - Remember that arrays start at 0↩