ghidriff: function level binary diffing on top of Ghidra
Python Command-Line Ghidra Binary Diffing Engine
At a glance
- What is it?
- ghidriff drives Ghidra from the command line to compare two binaries at function level, then writes the result as JSON, markdown and optional side by side HTML. It is built for patch diffing, where a single command has to produce something you can paste into a writeup, and it ships three differ implementations that range from symbol matching to Ghidra's own version tracking.
- Who is it for?
- Adopt ghidriff when you need reproducible, publishable diffs between two builds of a binary, especially in a patch analysis workflow where the output has to survive into a report or a gist. Do not adopt it expecting a general purpose binary comparison tool, since the function matching depends on Ghidra analysis and the fastest differ relies on Ghidra's own version tracking data.
- Can I use it commercially?
- Yes, with conditions. GPL-3.0 is a copyleft licence: if you distribute software that includes it, you must release that software's source code under the same licence. Running it internally without distributing it does not trigger that obligation.
- Is it still maintained?
- Yes. The repository last received commits 165 days ago.
- What is it written in?
- Mainly Python, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.
Editorial analysis
One command, two binaries, a diff you can publish
ghidriff provides a command-line binary diffing capability, and the design goal is stated plainly in the feature list as a patch diffing workflow reduced to a single step. The heavy analysis belongs to Ghidra; ghidriff supplies the workflow, the function matching, and the rendered output.
The mechanism is documented at a high level in the project diagram. An old binary and a new binary both feed into a GhidraDiffEngine, which produces Ghidra project files on one side and a diffs output directory on the other. That output directory holds three artefacts with predictable names, a markdown file, a JSON file and a side-by-side HTML file, each suffixed with the two binary names.
The output formats are a deliberate design choice rather than an afterthought. Results are stored in JSON for machine consumption and rendered in markdown, optionally as side-by-side HTML, and the documentation describes the markdown output as promoting social diffing because results are easy to publish in a gist or include in a writeup or a blog post.
For security research that means a diff can travel: the JSON is the record, the markdown is the argument, and the HTML is the review artefact. That is a different output philosophy from a tool that prints to a terminal and leaves you to screenshot it.
Three differ implementations, from symbol names to version tracking
There are currently three diffing implementations, and the documentation frames them as also displaying the evolution of diffing within the project. Each one extends the same base class and implements find_matches.
SimpleDiff is the simple one, and the name is explained: it relies mostly on known symbol names for matching. That is fast and predictable when both binaries carry symbols, and it degrades quickly when they do not, since a stripped binary offers nothing to match on. StructualGraphDiff is described as a slightly more advanced differ that begins to perform some more advanced hashing, such as Halvar's Structural Graph Comparison, which matches on the shape of a function's control flow rather than its name.
VersionTrackingDiff is the latest differ, and it uses several correlators for function matching. A correlator is described in the documentation as an algorithm used to score specific associations based on code, program flow, or any observable aspect of comparison. This one is fast, and it is the one to reach for when you want the same answer the Ghidra analyst would reach.
The choice is a real trade-off rather than a single recommended mode. Symbol matching is cheap and brittle, structural hashing survives stripped binaries but can be fooled by recompilation, and version tracking is the most informed and the least portable because it leans on Ghidra's own analysis.
The engine is a base class you can subclass, and the abstract method is find_matches
ghidriff is built as an engine in the sense the documentation defines: a self-contained but externally-controllable piece of code that encapsulates powerful logic designed to perform a specific type of work. The core is a GhidraDiffEngine base class that can be extended to create your own binary diffing implementations.
The base class covers the first three steps of the headless Ghidra workflow. Those steps are creating a Ghidra project, which is a directory and collection of Ghidra project files and data, importing one or more binaries into that project for analysis, and analyzing the binary, where Ghidra performs its default binary analysis on each one. What the base class leaves open is the matching itself, through the abstract find_matches method, and that is where the actual diffing takes place.
Writing a differ means implementing that one method. The documented skeleton shows the shape:
class NewDiffTool(GhidraDiffEngine):
def __init__(self,verbose=False) -> None:
super().__init__(verbose)The method takes the old and new binary paths and returns a dict of matches and unmatched functions. This is a clean seam. Ghidra setup, analysis, project management and output rendering are already handled, and the part that is genuinely yours is the function correspondence, which is exactly the part that differs between tools and between use cases.
The command line exposes engine choice, project reuse and forced analysis
The usage line for the tool shows how much control sits behind the single command:
usage: ghidriff [-h] [--engine {SimpleDiff,StructualGraphDiff,VersionTrackingDiff}] [-o OUTPUT_PATH] [--summary] [-p PROJECT_LOCATION]The engine flag selects between the three differ implementations, which means you can change the matching strategy without changing anything else about the run. The output path and a summary option control what gets written, and the project location and project name options let you point the tool at an existing Ghidra project rather than creating a fresh one.
Two further options matter in practice. A symbols path and a GZFS path point at extra symbol sources, and a base address option handles binaries whose load address you need to state. Then there is the threaded toggle with its explicit opposite, so you can turn concurrency off when a Ghidra run behaves badly in parallel, and a force analysis flag for when the cached project state cannot be trusted.
The performance claim in the feature list is worth reading precisely rather than approximately: the tool can diff the full Windows kernel in less than a minute, after Ghidra analysis is complete. The qualification is the whole story. Ghidra analysis of the kernel is the expensive part, and the diffing step is cheap by comparison.
Meta diffs catch what a function-level diff misses
Beyond the added, deleted and modified function list, ghidriff produces what the documentation calls unique meta diffs, in four categories: binary strings, called, calling, and binary metadata.
Binary strings matter because a patch often changes data rather than logic. A new URL, a changed command line, a shifted error message, and none of that shows up as a modified function. Called and calling are call-graph edges, so the diff also tells you that function A no longer calls function B, or that a new caller appeared, which is a different kind of signal from a changed body.
Binary metadata covers the header-level facts, and comparing them is a quick way to spot a rebuild, a retarget, or a change in the file structure itself before you read a single function diff.
The design goals behind these additions are stated as finding all added, deleted and modified functions, providing a foundation for automation, being simple, fast and accurate, being resilient and extendable, and making results easy to share. The automation goal is the one that matters most for a pipeline. A tool that writes JSON is a tool you can put in CI, and the project backs that with a separate test suite and a Docker setup.
Docker, a Makefile and a Ghidra image that needs no licence
The batteries-included claim in the feature list names three things: Docker support, automated testing, and Ghidra with no license required. That last point is the one that matters for adoption in a commercial setting, since Ghidra is what carries out the binary analysis and the tool does not ask you to buy anything to use it.
The Dockerfile is a thin wrapper. It builds on a prebuilt image, ghcr.io/clearbluejar/ghidra-python:11.3.1ghidra3.12python-bookworm, sets GHIDRA_INSTALL_DIR to /ghidra, and installs the tool from pip:
FROM ghcr.io/clearbluejar/ghidra-python:11.3.1ghidra3.12python-bookworm
ENV GHIDRA_INSTALL_DIR=/ghidraand the install step is a single pip call:
RUN pip install ghidriffNote the base image name, which pins Ghidra 11.3.1. The image also creates a symlink from the ghidriffs directory into the user home, which is what supports the documented invocation pattern of mounting a host directory and passing two binaries straight to the entry point.
For local work the Makefile covers the same ground: an install target that installs the package in editable mode, a dev-setup target that also runs the PyGhidra initialisation script, separate fast and integration test targets selected by pytest markers, and lint and format targets driven by ruff. The check target runs lint and the fast tests together, which is the loop you want in a pre-commit hook.
The licence is GPL-3.0 and the newest release is from July 2025
The project is distributed under the GNU General Public License 3. For a research tool that is usually the least interesting fact, but for anyone who wants to fold ghidriff into a commercial scanning service it is the first one, since the copyleft obligations attach to distributing the tool rather than merely running it.
On versions, the release list is short. v1.0.0 was tagged on 2025-07-04 and carries the note Ghidra 11.4 Support. Before that, v0.9.0 on 2025-04-23 added Program Options Support, and v0.8.0 on 2025-02-12 brought Ghidra 11.3 support and the update to PyGhidra. The last push to the repository was on 2026-05-11, and the repository is not archived.
So the source has been touched more recently than the last tag, and the tagged releases track Ghidra version bumps closely. That correlation is the practical thing to check before you install: a Ghidra version newer than the one your ghidriff release names may or may not work, and the release notes for a Ghidra support bump are the place to look.
The repository also carries a docs/ directory that is published as the official documentation site, a www/ directory, a .devcontainer/ configuration and a .vscode/ directory, which tells you the intended development setup is a container with an editor attached to the same Ghidra image.
Editorial conclusion
Adopt ghidriff when you need reproducible, publishable diffs between two builds of a binary, especially in a patch analysis workflow where the output has to survive into a report or a gist. Do not adopt it expecting a general purpose binary comparison tool, since the function matching depends on Ghidra analysis and the fastest differ relies on Ghidra's own version tracking data. Before you run it, check that your Ghidra version is covered by the release you install, since v1.0.0 was cut for Ghidra 11.4, and confirm your headless Ghidra analysis has already completed for both binaries, because that analysis dominates the wall clock time.
Frequently asked questions
What does ghidriff compare between two binaries?
It finds the added, deleted and modified functions of two arbitrary binaries using Ghidra's Program API, and it also produces meta diffs covering binary strings, called and calling relationships, and binary metadata.
Which differ implementation should I use in ghidriff?
Three are available. SimpleDiff relies mostly on known symbol names for matching, StructualGraphDiff begins to do more advanced hashing such as Halvar's Structural Graph Comparison, and VersionTrackingDiff uses several correlators and is described as the fast one.
How do I write my own differ for ghidriff?
Subclass GhidraDiffEngine and implement the abstract find_matches method, taking the old and new binary paths and returning the matched and unmatched functions. The base class handles the Ghidra project creation, binary import and analysis steps.
Does ghidriff need a Ghidra license?
No. The feature list names Ghidra with no license required among the included items, and the Docker setup builds on a public Ghidra Python image that installs the tool from pip.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/clearbluejar-ghidriff)Was this useful?