Craig Young
4 min readApr 2, 2023

A Guide to Reversing Shared Objects with Ghidra

I’m excited to announce that I will be returning this year to the Black Hat USA 2023 conference in Las Vegas. As with previous years’ classes, A Guide to Reversing with Ghidra aims to bootstrap students with a working knowledge of how to use Ghidra for a range of real-world applications. In this post, I will give a sample of one of the new exercises being introduced for 2023.

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.

Students are challenged in this exercise to identify obfuscated functionality in a compiled library within a hypothetical scenario. The binary has a lot of complexity to it and the suggested solution is to use Ghidra’s debugger support to perform dynamic analysis as a time saver. This exercise develops skills for debugging within a shared module (can be trickier than it sounds) as well as comprehension of obfuscated functionality.

For the sake of this article, let’s consider the hypothetical scenario of a product engineer working on the next generation ACME Instant Tunnel AR unit. Customers have reported less than adequate field results with some users experiencing inconsistent results. Management has promised them support for Globex’s new AI-powered avian detector. Globex will happily license this technology, but they want to maintain control of their intellectual property and will only deliver it as a pre-compiled library. During sandboxed testing however, the module is making a DNS lookup for the domain ‘secur3.us’ which does not show in a dump of the binary.

The challenge from here is to identify the reference to this domain and how it is being used. It was already determined that the DNS lookup is triggered when calling `void initialize_bdu(char *devname)` where devname is set to /dev/null rather than the expected TTY device.

Opening this function in Ghidra shows the following:

Loading libglobex.so:initialize_bdu() in Ghidra

Although we could certainly untangle this mess through static analysis, the debugger presents an opportunity to save a lot of time by allowing the program to perform the obfuscated functions while under inspection.

The general process for this is as follows:

  1. Create a wrapper application to invoke `initialize_bdu()`.
  2. Load the wrapper into Ghidra and perform auto-analysis.
  3. Launch the wrapper application in the debugger
    Be sure to specify an environment where the shared library can be located.
  4. Run the program until it is about to call into libglobex.so
  5. Map the module (libglobex.so) to the dynamic process.
    This allows Ghidra to compute proper addresses within libglobex.so
  6. Set a breakpoint within analyzed function `initialize_bdu()`.
  7. Step through program while watching memory for ‘secur3.us’

The most troublesome step in this process for me has been getting the mapping correct between libglobex.so and running instance of the wrapper application. Ghidra seems to sometimes get into a state where the dynamic range doesn’t get updated after a module is loaded if you attempt to interact with the module too soon in the process lifecycle. Before attempting to map, make sure the module shows a nonzero base address as shown in the screenshot below. Once the mapping is set, it should remain for future debugging sessions.

Ghidra Module Listing from libglobex.so

A sample file to try this is here in case anyone wants to try this out at home: https://secur3.us/libglobex.so

A simple wrapper can be constructed by compiling:

// Compile with: gcc -o wrapper_app main.c -L. -lglobex -lcurl -ldl -lcrypto
#include <stdio.h>

extern void initialize_bdu(char *devname);

int main() {
printf("Calling suspect function...\n");
initialize_bdu("/dev/null");
return 0;
}

And for an example of what to look for when searching the memory:

After spotting the data, you can time travel through the recorded trace to work out how it got there. You can also dump the memory at this point and inspect it for other interesting strings. If there is interest in a follow-up to this post, please comment below or reach out to me on Twitter (@CraigTweets) with questions about how to get this far or where to go from here!

I hope you enjoyed reading, and if you have, I hope you will consider joining me this summer in Vegas for A Guide to Reversing with Ghidra at Black Hat USA 2023 (or Monday/Tuesday). In the classroom, you’ll learn everything you need to know to get started using Ghidra to reverse engineer programs and go through hands-on activities illustrating various professional use cases for this powerful software reversing suite.

Craig Young

I’m a 15-year veteran of the infosec industry with 200+ CVEs, two USENIX papers, a Pwnie award, and a bunch of bounties to my name. Currently teaching Ghidra.