First Look: Ghidra 10.3 Emulator
Ghidra 10.3 dropped this week with a dedicated Emulator tool! I’ve been eagerly anticipating such a feature and so I am very excited that it is available in time for Black Hat USA this year. I’ve spent the morning tinkering and I’m pleasantly surprised with how performant and intuitive it is to use. In this post, I’ll share a little of what I have learned by walking you through analysis of a reversing challenge.
UPDATE 3/2/24: Registration is currently open for “A Basic Guide to Bug Hunting with Ghidra” at Black Hat USA 2024. The two day class will be offered August 3–4 and again August 5–6.
The example this week is called sneaker and you can download the binary from https://secur3.us/GhidraFiles/sneaker to follow along.
After importing and analyzing the binary, you should end up with a Ghidra main()
decompilation that looks like:
undefined8 FUN_00101352(void)
{
char *__s;
int iVar1;
ulong uVar2;
undefined8 uStack_a0;
undefined4 local_98 [4];
undefined4 local_88;
undefined4 local_84;
undefined4 local_80;
undefined4 local_7c;
undefined4 local_78;
undefined4 local_74;
undefined4 local_70;
undefined4 local_6c;
undefined4 local_68;
undefined4 local_64;
undefined4 local_60;
undefined4 *local_50;
long local_48;
int local_3c;
local_98[0] = 5;
local_98[1] = 6;
local_98[2] = 0xffffffff;
local_98[3] = 4;
local_88 = 6;
local_84 = 9;
local_80 = 0xfffffffc;
local_7c = 0xffffffff;
local_78 = 10;
local_74 = 0xfffffffc;
local_70 = 0xfffffffa;
local_6c = 9;
local_68 = 0xfffffffc;
local_64 = 0xb;
local_60 = 10;
local_3c = 0xf;
uStack_a0 = 0x1013fe;
FUN_0010122e(local_98,0xf,8);
iVar1 = local_3c;
local_48 = (long)(local_3c + 1) + -1;
uVar2 = ((long)(local_3c + 1) + 0xfU) / 0x10;
local_50 = local_98 + uVar2 * -4;
(&uStack_a0)[uVar2 * -2] = 0x10146d;
FUN_001012b8(local_98,local_98 + uVar2 * -4,iVar1);
__s = (char *)local_50;
(&uStack_a0)[uVar2 * -2] = 0x101479;
puts(__s);
return 0;
}
Reading over this, we see various stack variables initialized and then passed to two functions before some result is printed with puts
. Looking over the Function Call Graph, we can see that the program is structured with a few layers of functions:
Similar to the Debugger lesson, we could work through the code to decipher what is being printed, but it will be tedious. Instead, we will let Ghidra do the heavy lifting by running this in an emulated trace and then inspecting the memory before the puts
call.
Ghidra 10.3 or newer is required to use this feature. In this version, you can open Emulator tool by clicking the new tool icon shown below between the Debugger and Version Tracker tools:
Open sneaker in the Emulator by dragging it to this icon:
Proceed to find main
by scrolling down in entry
and locating the call to __libc_start_main
:
FUN_004007af
is the main
function. Double-click that symbol to jump the cursor to the start of main
:
At this point, we can start emulating the program from here in a new trace by clicking the Emulator icon on the toolbar or using the menu option at Debugger->Emulate Program in New Trace.
The Dynamic view will now come alive as Ghidra starts emulating the program:
From here, things work similar to being in the Debugger with a trace being recorded. We can scroll to the end of the function and set a breakpoint immediately at the puts
to make short work of deciphering this mess:
Press ‘k’ to load the ‘Toggle Breakpoint’ window and accept the defaults:
After setting the Breakpoint, the Breakpoints plugin should show that it is set in the program (top) and assigned within the emulator (bottom).
With the breakpoint in place, you can click the ‘Resume’ button (or F5 on Windows) to run the emulation. The Emulator tool should look similar to the following when it hits the breakpoint:
Switching to the ‘Registers’ plugin from the Debugger views, we can see the address in RDI and jump to it in the emulated RAM by right-clicking as shown below:
Doing so brings us to the Dynamic view where the output of the secret functions can be viewed with ease:
Using the keyboard shortcut (‘) you can retype this to a char and then to a defined string to make it more readable:
And there you have it, Ghidra’s emulator has run the program and computed it’s output!
Join Me At Black Hat To Learn More
As always, I hope you have enjoyed reading this post. If you found this interesting and want to learn more, please consider joining me in Vegas this summer for ‘A Guide to Reversing with Ghidra’. The class is offered twice, Saturday/Sunday and Monday/Tuesday. Early-bird pricing is still available but spaces are limited so please reserve your space today!