Hello!
I’ve been playing recently a bit with Ghidra, which is a reverse engineering tool that was recently open sourced by the NSA. The official website describes the tool as:
A software reverse engineering (SRE) suite of tools developed by NSA’s Research Directorate in support of the Cybersecurity mission
I’m at the beginning of my reverse engineering career, I didn’t do anything advanced and I don’t know what features to expect from a professional tool like this, if you’re looking to read about advanced Ghidra features them I’m sorry. :/
In this article I will try to solve a simple crackme challenge that I’ve found on the website root-me. The challenge I’m solving is called ELF – CrackPass , if you want to give it try by yourself then you should consider not reading this article because I will spoil the challenge from you.
Let’s get started! I open up Ghidra and create a new Project which I call RootMe.
In Ghidra we must create a Project, we don’t work with individual files like in other disassemblers. Then I import the challenge file by dragging it to the project folder, I will go with the defaults.
After being presented with some if about the binary file, I press OK, select the file and double click it. This opens up Ghidra’s code browser utility and asks if I want to analyse the file, then I press Yes and go on with the defaults.
After we import the file we get some information about the binary file. Pressing OK, dismissing this window and then double clicking the file we imported opens up Ghidra’s code browser utility. I select Yes when prompted to analyze the binary and go on with the defaults.
The Code Browser is quite convenient. In the left panel we get to see the disassembly view and in the right panel the decompile view.
Ghidra shows us directly the ELF header info and the entry point of the binary, after double clicking the entry point, the dissembler view jumps to the entry function.Now we can successfully identify the main function, which I rename to main, it would be nice if the tool would attempt to automatically detect the main function and rename it accordingly.
Before analyzing the main function I wanted to change it’s signature. I changed the return type to int and corrected the parameters’ type and name. This change has taken effect in the decompile view. Which is cool!
Highlighting a line in the decompile view also highlights it in the assembly view.
Let’s explore the FUN_080485a5 function, which I’ll rename to CheckPassword.
The contents of the CheckPassword function can be found below. I’ve copied the code directly from Ghidra’s decompile view, which is a neat feature that many tools of this type lack! Being able to copy assembly and code is a nice to have feature!
|
|
After taking a look at the code I’ve came to the following conclusions. The block with the if checks if the user has provided a password and inspects the provided password to check if it’s a valid character or something. I’m not exactly sure what it’s checking for, but here’s what __ctype_b_loc()’s docummentation says:
|
|
Anyways, that block of code is not really worth the time, because it doesn’t modify our the password in any way, it just verifies it, and we can skip this kind of verification.
The next function called is FUN_080484f4. Looking at it’s code, we can tell that it’s just a custom memcopy implementation. Instead of copying the C code from the decompiler view I copied the assembly code, yes, this is fun.
|
|
************************************************************* * FUNCTION ************************************************************* undefined FUN_080484f4 (undefined4 param_1 , undefined4 p undefined AL:1 <RETURN> undefined4 Stack[0x4]:4 param_1 XREF[1]: 080484f8 (R) undefined4 Stack[0x8]:4 param_2 XREF[1]: 080484fb (R) FUN_080484f4 XREF[1]: CheckPassword:080485f5 (c)
|
|
And the other function FUN_0804851c generates the password from the “THEPASSWORDISEASYTOCRACK” string. Looking at the decompiled view we can roughly see how this function works, if we didn’t have that we would need to manually analyze every assembly instruction from the function to understand what it does.
Then, we compare the previously generated password with the password that we got from the user (the first argument, argv[1]). If it matches, the program says good job and prints it, else it prints an error message.
From this basic analysis, we can conclude, that if, we patch the program in various places, we can get it to spit the password without us needing to reverse any C function and write code. Patching the program means changing some of it’s instructions.
Let’s see what we have to patch:
At address 0x0804868c – We patch the JNS instruction into a JMP. And voila, the change is reflected in the decompiler view. The ptrace result check is bypassed.
|
|
At address 0x080485b8 – We patch the JZ instruction into a JMP. We bypass that password verification block we saw earlier.
|
|
At address 0x0804861e – We patch JNZ to JZ. This inverts the if/else condition and since we don’t know the password, we’re going to submit a random passwords that is not equal to the generated one thus executing the printf on the else block.
|
|
That’s all!
Now, we run the program, in other tools we just save the file and it just works, but in Ghidra it seems that we need to export it.
To export the program, we go to File -> Export Program (O). We change the format binary and click OK.
I get the exported program on my desktop but, that didn’t work, I couldn’t manage to run the exported program. After trying to read it’s header with the readelf -h program I get the following output:
|
|
Shame. It looks like Ghidra has messed up the file header… and, right now I don’t want to manually fix headers, so I’ve fired up Binary Ninja and applied the same patches to the file, saved it, ran it with a random argument and validated the flag.
Conclusions
Ghidra is a nice tool with a lot of potential, in it’s current state it’s not that great but it works, I’ve also encountered a weird scrolling bug while running it on my laptop.
The alternatives would be to pay $$ for other tools of this kind, make your own tools or work with free but not so user friendly tools.
Let’s hope that once the code is released the community will start doing fixes and improve Ghidra.
Thanks for reading!