Exploring Ghidra with Baby ELF

RIXED LABS
RIXED_LABS
Published in
7 min readMay 20, 2021

--

0x0: A boring introduction

In our last articles, we discussed tools regarding static binary analysis like the IDA and dynamic binary analysis like the WinDbg, but we did miss a handy tool for binary analysis known as Ghidra, so this blog will be based on exploring Ghidra, it’s utilities and will end with reversing a small ELF crackme for the clarity of the concepts.

0x1: Downloading and setting it up Ghidra

Head over to the official website and download it, once you download the zip file, if you are on Linux, you are less likely to encounter this problem, but if you are on Windows you will be encountering this issue which pops up “Java Runtime Not Found”

For a quick fix, head over to this website, select your specific OpenJDK version, and your desired architecture, once you download the installer, run it and then click on the ghidraRun.bat file, and finally you will be greeted with the Welcome message!!

0x2: Setting up a workspace & importing files

In Ghidra, setting up a workspace is quite easy, click on File tab > Click on New Project > After that you will be prompted for entering the name of your project, once you finally create your project, it’s time for importing the files whose static analysis is to be done. Here I have names my workspace as “session1”. And I have imported quite a number of files, after importing the files, all it needs to be done is select on the executable and double-click on it, after the double click you will be prompted with the Code Browser where you will be able to view disassembly, decompiled view, function call graphs and a lot more. Let's look at what features code browser has to offer to make the analysis process a little easy for us.

0x3 : Getting hands on a few features

Now, after we have finally reached to the code browser, it’s time we should learn to rename variable, edit function signature, commenting and looking for interesting addresses!

A random function signature
Program Tree
Function signature before editing
Function signature after editing

The very first thing when you load a binary is a window which pops up and asks for analysis of the binary, once the analysis is complete you are present with interesting functions to look around, and many others like exports, imports, labels, classes etc. Here our main focus would be on the functions, 💭 so, what’s next ? Let us find the entry main function of the program. If you look out for the existing function signature above, it looks weird, isn’t it ? And what are param_1 & param_2 even? As, we know can executable needs to be passed with some command line argument, we can move ahead and edit the function signature which makes it easy for us to identify things. To change the function signature right-click on the function, and you will be popped up with an option to edit function signature, then we can change the function signature as per desired, which makes us easy for us to identify things 😃.

Snap before commenting
Snap after adding a comment

Now, after we learned to change the function signature, the next step is to add a comment to the decompiled code, which makes things easy for us to keep a track of things or even the changes we have made. After changing the function signature we can see that there are two arguments which needs to be passed, so let’s set a comment that there are two arguments to be passed, let’s comment it out. In the above screenshot the steps before adding a comment are right click and select on comments, and you can add your desired comment.

Snapshot before renaming the variable
Snapshot after renaming the local variable

After adding comments, let’s see on renaming variables, the existing variables with nomenclature Var1, Var2 are pretty confusing let’s understand how and why do we need to rename the variable. As we can see the variable sVar = strlen(argv[1]), which means the length of the first second argument, as we have 2 arguments which needs to be passed, the first argument or argv[0] is the name of the program, and the second argument or argv[1] is the input which the program needs to print the desired password, so with this we can conclude that the input which the program needs should be 5 characters in length, now let’s rename sVar2 to length.

0x4 : Function graphs & Strings

Similar to other disassemblers, we can also have a look around the Function call graphs & function graphs for a better visualization of the functions, to look for function call graph & function graph click on the Window tab, and then you can look for both the function call graph & normal function graph.

Function Call Graph
Function Graph

The right-hand side, is the function call graph for a better understanding of this let’s have a look at the decompiled code, the _start function can be said as the parent function of the main function which we are currently viewing at our de-compilation tab, next the puts & strlen can be said as the child functions of the main function, so if there are two arguments argv[0][1] are passed the main calls the strlen function and if only one argument argv[0] is passed the puts function is called, now coming back to the left-hand side which is the function graph. If we see both two nodes which are light green, which shows the main function calls the puts function which prints “Please enter the password” if argc == 1, whereas if argc == 2, the flow of program moves to the blue node and checks if the argv[1] == 5, if it is less than 5 it moves to the red node where it says “We would never use that small password”. Now at the end let’s look on the three yellow nodes and the white node, what it actually does it if the first character of the argv[1][0] is h, and the fourth character of argv or argv[1][4] is u, we will finally have the correct password 😺!

We can search for interesting strings inside Ghidra by using defined strings!

0x5 : Searching for interesting address

Using Ghidra, we can also look for some interesting address, let’s assume we open our program using a debugger and select some random address and try to look at it. Let’s select the address 0x0000000000400495 and look into it, click on the G key which is a shortcut for looking into addresses, now after looking into the address we conclude the fact that it landed up at _libc_start_main , this way we can look for interesting address or non-interesting from the debugger and into the Ghidra. 😄

0x6: Solving Baby_ELF 😆

Finally we learned to look for strings, addresses, use graphs, rename variables, function signatures and a bit of other things which are helpful for getting started with Ghidra, now let’s complete our formality by solving the small ELF crackme , from the disassembly and decompiled code we know that:

argv[1][0] = h
argv[1][1] = ?
argv[1][2] = ?
argv[1][3] = ?
argv[1][4] = u

Now, let us try random alphabets between argv[1][0]….argv[1][4] and it works!!

0x7: Conclusion

So, here ends our small tour of Ghidra with Baby_ELF, I might try to reverse some other architecture using Ghidra and will document every part of it 😄. Till then goodbye ! Happy analyzing.

Blog by Nerd of AX1AL. Join our small discord server.

--

--