Practicing with Ghidra
What is ghidra?
From the ghidra page
A software reverse engineering (SRE) suite of tools developed by NSA’s Research Directorate in support of the Cybersecurity mission.
According to Ghidra devs it is pronunced gee-druh
Gee-druh. The G sounds like the G in goto, great, good, graph, and GitHub. The emphasis goes on the first syllable.
Ghidra is written in Java and needs JDK11 to run. From the source code it seems to be developed from 1999. It supports scripts in java and python with Jython (sigh.)
A Ghidra tour
To explore Ghidra we will play with a real malware sample.
In January 2019, Kasperky LAB discovered a supply chain attack involving the ASUS Live Update Utility.
The image below shows the first window that appears when ghidraRun is executed.
The project can be Shared and Non-Shared. Shared project is for multi-users, it needs a running Ghidra server. Non-Shared is for single local user.
Created the project, we need to import a file, in this case I used the Setup.exe 9a72f971944fcb7a143017bc5c6c2db913bbb59f923110198ebd5a78809ea5fc
User Interface overview
When a file is imported, ghidra asks for the analysis, below there is an example of default analysis options. We are not changing them at moment, so just Analyze it and take a break, it takes some time :).
Ghidra also shows a summary of imported file informations.
Once the analysis is terminated, we want to actually start reverse engineering the binary. There are several important parts of the user interface. The program tree highlights the sections of the file, as well as the executable you are currently looking at. The symbol tree contains all the variables and information that Ghidra found during its analysis. The Data Type manager is extremely helpful for full source code reversing.
The Listing is where we see the common disassembly view. Since we are looking at a 32-bit Windows PE, relevant information is highlighted in the center view. What I really like is that all of the data structures are outlined in the code view. This makes understanding some internal Windows APIs very simple.
As you can see I modified a little bit the windows and the colors, Ghidra is very customizable, check the Tool Options in Edit menu.
After some time digging around the assembly, I didn’t find any interesting piece of code to triage, then I took a look in the PE resources section. A large resource with the name “EXE” captured my attention.
A smarter way to get useful infos about the behaviour is to perform a dynamic analysis, but for this tutorial I will use static analysis with Ghidra only.
The size of this section is around 1.6MB bytes (0x195e00).
Next step is to see if there is a reference to this EXE resource. CTRL+SHIFT+F shows the list of References to the selected address.
The function at address 0x004032a0 seems interesting, it calls ShellExecuteW with selfupdt.exe as input file to run.
DAT_0051dbc4 is a pointer to the string “EXE” which is the resource name.
In the Image below we can see what the function at 0x00401810 does: Read the resource passed as input and write the content to thefile selfupdt.exe
but the resource content is not a PE (no track of ‘MZ’), so the ShellExecuteW should fail to run this file.
At this point, there is no reference to an absolute address to the resource, then we can check for a relative address reference.
To get this address we just have to substract the EXE resource address to the start image address 0x400000.
Now we search this address in memory. Below we can see that the only reference to this address is the resource section.
I was pretty stuck when I analyzed this binary (because of a ghidra bug, but we will see it later :)), but someone on twitter said that there is a code injection in __crtExitProcess. So I quickly checked there and spotted the injected call.
Here we go! the call to SUB_0051b908 is the code injected. But if we try to follow it, we get an error, “Address not found in programm memory: 0051b908”, visible in the bottom status bar.
This happens because Ghidra maps the binary using the VirtualSize and not the SizeOfRawData. For this particular sample it is important because the malicious code is appended at the end of the text segment, so SizeOfRawData is increased but not the VirtualSize.
From Mich blog post:
In the ShadowHammer’s
Setup.exea small shellcode, which then unpacked more shellcode from a resource, was appended to the end of the
.textsection. However, embedded this shellcode, however, only adjusted the
SizeOfRawDataand not the
There is an open issue on ghidra about this bug. https://github.com/NationalSecurityAgency/ghidra/issues/327
An easy workaround for this issue is patching the VirtualSize in the binary header for the text segment.
Once the binary in patched, we need to re-import the binary in Ghidra and run the analysis again. Jump to the __crtExitProcess and this time the call to the code is correctly followed.
In the next post I will show how to reverse the shellcode and get the code used to connect to the C2 with the MAC addresses checking list.