A collection of scripts for automating Ghidra's headless analyser — batch-decompile binaries, export filtered C code and Markdown reports, and extract constants from memory, all without touching the GUI.
- Automatic Ghidra discovery —
run_ghidra_headless.shsearches common macOS and Linux install paths so you rarely need to setGHIDRA_HOMEmanually. - Regex-filtered decompilation —
ExportDecompFiltered.javamatches functions by name pattern and exports clean C source alongside Markdown metadata (call trees, entry points, signatures). - Constant extraction —
ExtractConstants.javareads hardcoded doubles or floats from specific memory addresses and prints them to the console or a file. - Extensible script base — the included Java examples are intentionally minimal; drop in new
GhidraScriptsubclasses and pass them straight to--post-script.
- Ghidra 10.x or 11.x installed locally
- JDK 17 or later (JDK 21 recommended for Ghidra 11.x)
- Bash 4+ (macOS ships Bash 3 — install a newer version via Homebrew if needed)
git clone https://github.com/olivercase/ghidra_headless.git
cd ghidra_headless
chmod +x run_ghidra_headless.shNo build step is required. Ghidra compiles the .java scripts at runtime.
If your Ghidra installation is in a non-standard location, export the environment variable before running:
export GHIDRA_HOME=/path/to/ghidra_11.x_PUBLIC./run_ghidra_headless.sh \
--import /path/to/target_binary \
--post-script ExportDecompFiltered.java /path/to/output_dir "^FUN_.*"./run_ghidra_headless.sh \
--ghidra-home /Applications/ghidra_11.0.1_PUBLIC \
--project-dir ~/ghidra_projects \
--project-name my_analysis \
--import /path/to/target_binary \
--post-script ExportDecompFiltered.java ./out "^sub_"./run_ghidra_headless.sh \
--import /path/to/target_binary \
--post-script ExtractConstants.javaUse -- to forward arguments directly to Ghidra:
./run_ghidra_headless.sh \
--import /path/to/target_binary \
-- -noanalysis -readOnlyRun ./run_ghidra_headless.sh --help for the full option reference.
Thin Bash wrapper around Ghidra's analyzeHeadless launcher.
| Flag | Default | Description |
|---|---|---|
--ghidra-home PATH |
auto-detected | Path to Ghidra installation root |
--project-dir PATH |
./ghidra_projects |
Directory for Ghidra project files |
--project-name NAME |
tfm_analysis |
Ghidra project name |
--import FILE |
— | Binary to import and analyse |
--post-script SCRIPT [args…] |
— | Script to run after analysis, with optional arguments |
-- |
— | Forward remaining arguments to analyzeHeadless |
Ghidra home is resolved in this order: --ghidra-home → $GHIDRA_HOME → automatic path search.
Decompiles every function whose name matches a regex and writes two files per function into the output directory.
Arguments (passed after the script name):
ExportDecompFiltered.java <output_dir> <regex>
Output per matched function:
| File | Content |
|---|---|
<name>-<address>.c |
Decompiled C source |
<name>-<address>.md |
Metadata: entry point, signature, call tree, callers |
A decomp_summary.txt is also written summarising exported, failed, and skipped counts.
Reads double values from three hardcoded memory addresses and prints them via println. Edit the address literals in the script to target your binary.
Reads a single float from a hardcoded address and writes it to sampling_freq.txt in the working directory. A minimal example for adapting to other data types.
Running ExportDecompFiltered.java against a binary with the pattern ^FUN_ produces:
FUN_007baf30-007baf30.md
# FUN_007baf30
- Entry: 007baf30
- Signature: `undefined FUN_007baf30(void)`
## Calls
- FUN_007c9850 @ 007c9850
- FUN_006ea100 @ 006ea100
- FUN_006e9ec0 @ 006e9ec0
## Called By
- FUN_00801240 @ 00801240FUN_007baf30-007baf30.c
void FUN_007baf30(int param_1)
{
uint uVar1;
uVar1 = (uint)*(ushort *)(param_1 + 0x802);
if (uVar1 < 0x1202) {
/* ... */
}
}decomp_summary.txt
Program: target_binary
Regex: ^FUN_.*
OK: FUN_007baf30 @ 007baf30
OK: FUN_007c9850 @ 007c9850
...
Exported: 142
Failed: 3
Skipped (regex mismatch): 891
Contributions are welcome. To propose a change:
- Fork the repository and create a feature branch.
- Follow the style of existing scripts — keep Java scripts self-contained
GhidraScriptsubclasses. - Open a pull request with a clear description of what the script does and why it is useful.
Please open an issue before starting significant new work so the direction can be agreed on first.
Distributed under the MIT Licence. See LICENSE for details.
Maintained by Oliver Case.