Tool Release: Cartographer
There’s no doubt that reverse engineering can be a very complex and confusing matter, even for those that love doing it. Jumping into a program and being greeted with tons of assembly and weirdly-named functions and variables is hardly what most would call a fun time. Not to mention that identifying specific functionality in a program can be an exercise in sanity at times.
That’s why today we’re releasing Cartographer: A Ghidra plugin for mapping out code coverage data.
Cartographer simplifies the complexities of reverse engineering by allowing researchers to visually observe which parts of a program were executed, obtain details about each function’s execution, compare different runs of the same program, and much more.
GitHub link: https://github.com/nccgroup/Cartographer
Back in 2017, there was a new and incredibly useful plugin for IDA Pro called Lighthouse, which not only colorized code coverage data, but it also provided many useful tools for researchers, such as displaying function heat maps and the ability to perform logical operations on multiple loaded coverages.
When Ghidra was released back in 2019, many researchers (myself included) eagerly awaited a version of Lighthouse for Ghidra. When 2022 rolled around and there was still no sign of a Ghidra version of Lighthouse, I decided to make my own.
Cartographer implements much of the same functionality as Lighthouse while also providing its own enhancements and offering additional Ghidra-specific functionality, such as the ability to load coverage data for binary overlays (i.e. segments that occupy the same memory addresses, but are located in different address spaces).
Below are two case studies showing the practical uses of Cartographer and how it can complement the reverse engineering workflow.
Case Study: AES Crypt
AES Crypt is a utility that encrypts and decrypts files utilizing AES. In August 2022, a critical vulnerability was discovered in the code for the Linux version of AES Crypt, specifically the code that prompts for user input.
Originally, this section was going to recreate that vulnerability and demonstrate how this sort of issue would be found using Cartographer. In fact, the entire setup and workflow for the demonstration had been entirely completed.
After drafting the demonstration, out of sheer curiosity, I decided to analyze the compiled Windows executable for AES Crypt just so I could see the differences between the two. However, instead of simply observing differences in their execution, I ended up discovering a previously-unreported buffer overflow vulnerability in the Windows version of AES Crypt.
First, code coverage from two different runs of the program were collected using DynamoRIO: One where an incorrect password was entered at the prompt, and one where an incorrect password was specified via the
Once code coverage data was collected, the data from both of these code coverage files was loaded into Ghidra via Cartographer, with the prompt coverage being loaded first and the
-p flag coverage loaded after.
Next, in Cartographer’s Code Coverage window, the expression
B - A was used to isolate the functionality that only occurs in the coverage for the
-p flag. The resulting coverage showed that only 2 functions had different executions from those in the prompt coverage.
Clicking on the 1st highlighted function (
FUN_004053b0) and scrolling down to around line 96 shows the following decompiled code blocks (variables renamed for readability).
As shown above, the input string passed to the
-p flag is added to the
buf variable (defined as
char buf ) character-by-character, effectively creating a form of
strcpy, and as such is vulnerable to a buffer overflow due to the unchecked length of the input buffer.
By passing a specially-crafted input string to the application, it is possible to overwrite the address of the SEH handler and redirect execution to an arbitrary address in memory.
Case Study: Animal Crossing
Many gamers have fond memories of playing Animal Crossing for the Nintendo GameCube growing up, but what they may not realize that the developers left significant amounts of debug functionality within the final game.
First, code coverage data was collected starting from system boot to the point where “Press START!” appears on the screen.
Next, the main
main.dol file for the game was loaded into Ghidra using the Ghidra GameCube Loader plugin. Once the executable completed auto-analysis, the code coverage data was loaded via Cartographer.
boot::main function, the game version (offset
0x7 of the disk header) is checked to see if the version is
0x99, then checked twice more to see if the version is greater than
0x8F. When the 3rd condition is true, something called “ZURUMODE2” is enabled.
According to the code above, setting the 8th byte of the disk header to
0x99 should enable this “zuru mode”. When this value is set and the game is booted up, the regular Nintendo trademark screen will have significantly more information displayed, indicative of some form of debug mode being enabled.
Additionally, the game will now have debug information displayed on the screen, with various screens and displays able to be toggled by using an additional controller plugged in to the 2nd controller port.
Note: As I was typing up this part of this blog post, I came across an old PDF that I had originally stumbled upon years ago that first introduced me to this debug functionality, titled Secrets of Animal Crossing. What I didn’t know was that the author was James Chambers, a fellow colleague here at NCC Group.
I’d highly recommend checking out James’ full write-up of the inner workings of Animal Crossing’s developer mode on his blog: Reverse engineering Animal Crossing’s developer mode
As shown in the case studies above, Cartographer can significantly reduce the complexities of reverse engineering and help with isolating target functionality, whether it’s analyzing code being executed or code not being executed.
If you have any suggestions for improvements or ideas for features, feel free to open an issue or create a pull request on GitHub!