Today, I was doing a pwning challenge (maybe more on this on a future blog post) and for some stupid reason, I wanted to load the glibc of my system on Ghidra. 99% of the times there is no real good reason to load glibc on Ghidra.
That being said, loading other symbols for other binaries can be useful in other scenarios, hence the post.
This guide will cover symbols in DWARF (.debug
) format. Other
symbol formats exist (E.G. map files), some scripts enable partial support of those but they are deemed
out-of-scope for the purpose of this post.
Step 1: retrieve the symbols
Skip this step if you already got your hands on the .debug
file of your binary.
As an old grumpy debian user, the first thing I did was looking for the symbols in apt:
$ apt-cache search libc debug | rg ^libc
libc6-dbg - GNU C Library: detached debugging symbols
Thus, I ensured that the symbols were installed, and listed the content of the package:
$ sudo apt install libc6-dbg
libc6-dbg is already the newest version (2.40-2).
$ dpkg -L libc6-dbg
/.
/usr
/usr/lib
/usr/lib/debug
/usr/lib/debug/.build-id
/usr/lib/debug/.build-id/00
/usr/lib/debug/.build-id/00/816b247f0a7b16e16a4f5d3923c2db381a88b1.debug
/usr/lib/debug/.build-id/00/ec9617d2109516ef19a58c67e51c6ddbc52884.debug
/usr/lib/debug/.build-id/03
/usr/lib/debug/.build-id/03/168341ee3ad1b6a0f12236f485ad52adde5dcc.debug
/usr/lib/debug/.build-id/03/db02abdea2b823013af088df1f2cd3fc688ac3.debug
...
Okay, great.. but what is the one corresponding to my currently installed libc? readelf
comes to the rescue:
$ readelf -n /usr/lib/x86_64-linux-gnu/libc.so.6 | grep Build
Build ID: d66c2f639cbba67fc6461d75acbd0087169bc2f1
Then, it was possible to copy the debug file from the /usr/lib/debug
folder:
$ cp /usr/lib/debug/.build-id/d6/6c2f639cbba67fc6461d75acbd0087169bc2f1.debug ~/ctf/libc.6.so.debug
Step 2A: embedding symbols to the binary
While reading pwntools’ documentation on libcdb a really interesting unstrip_libc function caught my eye:
pwnlib.libcdb.unstrip_libc(filename)
Given a path to a libc binary, attempt to download matching debug info and add them back to the given binary.
This modifies the given file.
Trying the example code on my pwn vm resulted in the following error:
Thereafter, I installed elfutils
and used eu-unstrip
to merge the .debug
symbols with the binary:
$ eu-unstrip libc.so.6 libc.so.6.debug -o libc.so.6.WITHSYMBOLS
$ ls -lah libc.so*
-rwxr-xr-x 1 user user 1.9M Oct 11 15:32 libc.so.6
-rwxrwxr-x 1 user user 5.6M Oct 11 16:17 libc.so.6.WITHSYMBOLS
-rw-r--r-- 1 user user 3.8M Oct 11 16:17 libc.so.6.debug
Loading the binary with embedded symbols (libc.so.6.WITHSYMBOLS
) in Ghidra and running the Auto-Analysis
(WITH THE DWARF STEP ENABLED), correctly loaded the symbols contained in the .debug
file.
Step 2B: define a search directory for DWARF symbols
Before coming up with the solution described in step 2A, I searched on the web (without success) how to load DWARF files in Ghidra. Many posts and github issues referenced how it was now built-in in Ghidra and some settings non-more-existing to limit the number of symbols loaded by Ghidra’s DWARF plugin.
After searching for DWARF
in Ghidra’s script, the following script caught my eye:
It was possible to load the .debug
files present in /usr/lib/debug
by adding the following to my .bashrc
:
export DWARF_EXTERNAL_DEBUG_FILES="/usr/lib/debug"
Thereafter:
- Closed Ghidra (all windows not only the code browser)
- Reloaded the terminal (
. ~/.bashrc
) - Loaded the file without symbols (
libc.so.6
) - Run the
Auto-Analysis
(WITH THE DWARF STEP ENABLED)
The above steps resulted in the .debug
file symbols being loaded from the specified DWARF_EXTERNAL_DEBUG_FILES
directory.
Conclusion
Loading glibc symbols on Ghidra will be rarely useful to anybody. Hopefully, loading .debug
files will be for someone!