Ghidrathon: Snaking Ghidra with Python 3 Scripting
Ghidrathon is a Ghidra extension that adds Python 3 scripting capabilities that tightly integrate with the user interface. Today, Ghidra ships with a Python 2 extension system based on Jython; however, there’s not an easy way to run Python 3. With Ghidrathon, you can use modern Python, like version 3.10, with the existing extension system! In this post you will learn what Ghidrathon offers, how it works, and why you should start using Python 3 scripting in Ghidra today.
Ghidra is a popular, open-source software reverse engineering framework developed and maintained by the National Security Agency Research Directorate. Ghidra supports a powerful scripting API that helps users programmatically dissect programs using Ghidra scripts written in Java or Python 2.7 (via Jython).
Unfortunately, Python 2.7 reached end of life in 2020 and many tools developed by the security community are now written in Python 3. This makes it difficult, and in some cases impossible, to integrate these third-party tools with Ghidra. More so, reverse engineering tools, including IDA Pro and Binary Ninja natively support Python 3 scripting, posing additional problems for researchers wishing to port existing analysis scripts to Ghidra. Ideally, a solution should integrate tightly with the framework’s user interface, support all maintained Python 3 versions, and install as a Ghidra extension to allow a seamless user experience.
Ghidrathon embeds your local Python 3 interpreter in Ghidra, giving it access to your database and the framework’s scripting API. You can then use modern Python, including any third-party packages you have installed, to programmatically access your Ghidra database. Ghidrathon also supports Python virtual environments, helping you isolate and manage packages you may only want installed for use with Ghidra. You can install Ghidrathon like any other extension and run Ghidra without modification.
Ghidrathon replaces the existing Python 2 extension implemented via Jython. This includes the interactive interpreter window, integration with the Ghidra Script Manager, and script execution in Ghidra headless mode. You can build and install Ghidrathon using the steps outlined in our README to start using the features described below.
The Ghidrathon interpreter window shown in Figure 1 provides interactive access to your local Python 3 interpreter. You can import and use your local Python packages alongside the Ghidra scripting API. Click "Window" and select "Ghidrathon" to open the Ghidrathon interpreter window.
Ghidra Script Manager Integration
Ghidrathon integrates with the Ghidra Script Manager enabling you to create, edit, and execute Python 3 scripts inside Ghidra as shown in Figure 2. Click "Create New Script" and select "Python 3" to create a new Python 3 script. Click "Run Script" or "Run Editor's Script" to execute your Python 3 script and check the Ghidra Console window for your script output.
Ghidra Headless Mode
Ghidra headless mode helps you automate analysis across many files without the overhead of Ghidra’s user interface. You can also specify Ghidra scripts to run before and/or after analysis has finished. Ghidrathon enables Python 3 scripts to be executed in headless mode as shown in Figure 3. Execute the "anlayzeHeadless" script located in your Ghidra installation folder specifying your Python 3 script and check your terminal window for script output.
Third-Party Python Packages
One of our biggest motivations behind Ghidrathon was enabling the use of third-party Python 3 packages alongside the Ghidra scripting API. The open-source community has released great analysis tools, many of which are written in Python 3, and we want to be able to take advantage of these tools in Ghidra. For example, we can emulate code using the popular open-source emulator framework Unicorn without leaving Ghidra. Let’s say we want to emulate ARM code shown in Figure 4 that builds a stack string.
We can start using Unicorn in Ghidra by installing the Unicorn module for the same local Python installation that we used to build Ghidrathon. Once installed, we can import and use the Unicorn module just as we would in any standard Python setup. In our example here we want to read the stack string code from our Ghidra database, emulate it using Unicorn, and print the resulting stack string to our Ghidrathon interpreter Window.
We import Unicorn and configure an ARM emulator using the code shown in Figure 5.
We read the stack string code from our Ghidra database using the Ghidra scripting variable
currentSelection and Ghidra scripting function
getBytes using the code shown in Figure 6.
We write the stack string code to our emulator, start emulation, and read the stack string from the
r0 register using the code shown in Figure 7.
How Does Ghidrathon Work?
This project stemmed from the question “can we execute modern Python 3 inside the Java Virtual Machine (JVM) alongside Ghidra”. Our initial considerations for a solution were multifold – it should be:
- Executed by the JVM
- Able to interact with a Ghidra database using the Ghidra scripting API
- Tightly integrated with the Ghidra UI
We wanted our solution to be executed by the JVM primarily so it could be initiated and controlled by a Ghidra extension. This would make it easy for users to install because Ghidra has a great extension system. The requirement forced us to develop Ghidrathon with the support of Ghidra’s extensive Java APIs. We believe it opens the door to develop future Ghidra extensions where Java is used to implement frontends for data processed by Python. Ultimately, we got the extension working using the open-source project Jep.
Jep can embed multiple, mostly sandboxed CPython interpreters in the JVM using the Java Native Interface (JNI). Using Jep, we can create a CPython interpreter in the JVM alongside Ghidra and marshal data between Java and Python. How do we do this? Jep provides a Java API that we use to configure, start, interact with, and stop each interpreter. For example, when you open the Ghidrathon interpreter window we use Jep’s APIs to create a new CPython interpreter to back it. As you enter Python code to execute, we use Jep’s APIs to pass that code to the interpreter for execution. When we no longer need a CPython interpreter we use Jep’s APIs to close it. For more information about how Jep works see their documentation here.
Ghidrathon is the glue that binds Ghidra and Jep, tightly integrating Jep’s abilities with the Ghidra UI. Ghidrathon configures each CPython interpreter with access to your Ghidra database and the Ghidra scripting API. Jep can then automatically translate member access across the Python and Java boundary. We also configure the interpreter to redirect output back to the appropriate Window in Ghidra. For example, when configuring a CPython interpreter for the Ghidrathon interpreter window we redirect stdout and stderr to the interpreter window displayed in Ghidra. Ghidrathon also maintains a state between Ghidra and the CPython interpreter. For example, we ensure Ghidra script variables like currentAddress are accessible in your interpreter and contain the correct data.
From our research, adding native support for Python 3 to Ghidra requires use of the JNI which the Ghidra developers advise against for reasons discussed here. We believe the benefits of using modern Python 3 in Ghidra outweigh the downsides of using JNI and leave the choice up to each Ghidrathon user.
Ghidrathon is one of multiple solutions, including Ghidraal, Ghidra Bridge, and pyhidra, that enables Python 3 scripting in Ghidra. Each solution is implemented differently with accompanying benefits and limitations. We encourage you to explore all solutions and choose which best fits your needs.
In this post we introduced Ghidrathon, a Ghidra extension that adds Python 3 scripting capabilities to Ghidra that tightly integrates with Ghidra's UI. We are excited to release Ghidrathon to the community and hope it encourages you to start extending Ghidra using modern Python 3. Check out our README for information on building and installing Ghidrathon for your environment. Please contact us via the tool’s GitHub page if you have any comments, questions, or run into any issues.
We would like to thank William Ballenthin for helping formulate the initial idea of using the Java Native Interface to embed Python in the JVM and for providing creative input throughout development. Additional thanks to Moritz Raabe and Ana Maria Martinez Gomez for their testing and feedback.