It’s been two weeks since the National Security Agency publicly released GHIDRA, a powerful software reverse engineering framework. Despite that GHIDRA comes with Motorola 68000 and 6502 processor support, the NSA didn’t release any of their retro game hacking scripts leaving the community to wonder how they have been spending our tax dollars. Today, I’d like to share a couple GHIDRA scripts that I wrote along with this blog post to serve as an introduction to GHIDRA for the ROM hacking community.
Introduction to GHIDRA
GHIDRA is a powerful static software analysis tool similar to IDA Pro or Binary Ninja, tools used primarily for analyzing compiled code. It supports multiple architectures to include Motorola 68000, the processor used by the SEGA Genesis console. GHIDRA takes a IL approach by transforming native code into P-code, the tools intermediate representation. Much of the analysis is done on the IL, allowing the majority of its core features (to include the decompiler and integrated assembler) to work across the 20+ supported architectures. There are way to many great features to cover in a blog post, and I’m still learning myself. If you haven’t already, I encourage you to start with ghidra.re to learn the basics.
Loading a SEGA Genesis ROM
To get started, create a project and import a SEGA Genesis ROM binary. You will be prompted to provide the language. Select 68000 (the default variant). This is all that is required to load the binary. You should be ready to use the Code Browser. To do so, drag the binary over top of the dragon in the tool chest. The ROM will open in the Code Browser, and you will be asked if you want to run initial analysis on the binary. Click no. Because you are loading a flat file, initial analysis will not work correctly without telling GHIDRA more information on the file format. You have two options, do everything manually or download my loader script into your
ghidra_scripts folder and run it with the script manager. The loader script will setup the vector table and ROM header before kicking off initial disassembly starting at the functions with entries in the vector table.
Patching the ROM
Now that the ROM has been loaded and initial analysis has been ran, we can analyze our ROM and modify instructions. In this blog post I’ll demonstrate a simple patch in Sonic The Hedgehog to jump to the end of the game. For clarity, I’ve labeled the
MainGameLoop and the call targets for each game mode in the jump table. To branch to the end of the game let’s modify the branch instruction to the normal level game mode (
GM_Level) to branch to
GM_Ending, instead. To edit a instruction, simply click on the instruction and type
Ctrl+Shift+G. Type a new M68K instruction and hit
Enter. GHIDRA even has tab completion!
Sonic, like most SEGA games, calculates the ROM checksum at runtime. Therefore, if you export the patched binary and try to run it in an emulator without fixing the checksum, it won’t run. Instead, you get a red screen. This leads me to my second GHIDRA script. A script that calculates and fixes the ROM checksum. Simply download the script into your
ghidra_scripts directory and run it with the Script Manager. After calculating the new checksum, export the binary by hitting
O and save it to a file. Then, load the patched ROM into your favorite emulator to be underwhelmed.