How to Use Ghidra Headless Mode for Automated Batch Processing
Ghidra headless mode is a command-line interface that runs the full analysis engine without the GUI, enabling automated binary import, analysis, and scripting via the analyzeHeadless script located in Ghidra/RuntimeScripts/Common/support/.
The National Security Agency's Ghidra framework provides a powerful headless capability for reverse engineering automation. This mode allows security researchers and DevSecOps pipelines to process binaries at scale without launching the graphical interface. By leveraging the AnalyzeHeadless class and specific command-line flags, you can create projects, execute scripts, and generate reports entirely from the terminal.
Core Architecture Components
The headless implementation relies on three primary components that disable GUI functionality while preserving the full analysis engine.
analyzeHeadless Shell Script: Located at Ghidra/RuntimeScripts/Common/support/analyzeHeadless, this entry point builds the Java classpath, sets the SystemUtilities.isHeadless system property to true, and launches the ghidra.app.util.headless.AnalyzeHeadless class.
AnalyzeHeadless Java Class: Found in Ghidra/Features/Base/src/main/java/ghidra/app/util/headless/AnalyzeHeadless.java, this class parses command-line arguments, manages project creation, handles file imports via the -import flag, and orchestrates pre- and post-processing script execution.
System Utilities Flag: The SystemUtilities.isHeadless property, defined in Ghidra/Framework/Utility/src/main/java/ghidra/util/SystemUtilities.java, acts as a global boolean consulted throughout the codebase. When true, it prevents UI components and Swing utilities from loading, ensuring compatibility with servers, CI pipelines, and Docker containers.
Essential Command-Line Flags
The analyzeHeadless script accepts specific flags to control the batch processing pipeline:
-import <path>: Specifies a single file, directory, or wildcard pattern to import into the project.-recursive: Enables recursive directory traversal when importing multiple binaries.-preScript <script> [args...]: Executes a script before analysis begins, passing optional arguments.-postScript <script> [args...]: Executes a script after analysis completes.-noanalysis: Skips the built-in auto-analysis phase entirely.-log <file>: Writes Ghidra's console output to a specified file.-scriptlog <file>: Captures output specifically from script execution.-librarySearchPaths <paths>: Defines additional directories for resolving shared library dependencies.-max-cpu <n>: Limits CPU usage to n cores during the analysis phase.
Six-Step Batch Processing Workflow
A typical headless session follows this automated sequence:
- Project Initialization: Create or open a Ghidra project at the specified directory path.
- Binary Import: Load target files using
-importwith optional-recursivescanning for bulk operations. - Pre-Processing: Execute
-preScriptscripts to prepare binaries, rename sections, or configure loaders. - Analysis Phase: Run the default analyzer suite unless
-noanalysisis specified. - Post-Processing: Execute
-postScriptscripts to extract data, export symbols, or delete temporary files. - Logging: Capture all system and script output via
-logand-scriptlogfor audit trails and debugging.
Practical Automation Examples
Example 1: Simple Import with Automatic Analysis
<GHIDRA_INSTALL>/support/analyzeHeadless \
/tmp/ghidra_projects myProject \
-import /opt/binaries/*.exe \
-log /tmp/ghidra_log.txt
This command creates myProject under /tmp/ghidra_projects, imports all .exe files from /opt/binaries, runs the default analyzers, and writes operational logs to /tmp/ghidra_log.txt.
Example 2: Scripted Pipeline with Analysis Disabled
<GHIDRA_INSTALL>/support/analyzeHeadless \
/tmp/ghidra_projects myProject \
-import /opt/binaries/myapp.bin \
-preScript MyPrepScript.java arg1 \
-noanalysis \
-postScript ExportSymbols.py \
-scriptlog /tmp/post_script.log \
-log /tmp/run.log
Here, MyPrepScript.java prepares the binary before processing. Analysis is skipped via -noanalysis, and ExportSymbols.py extracts symbols afterward. Separate log files capture script output and runtime events according to the NSA Ghidra source code implementation.
Example 3: Recursive Batch Processing with Resource Limits
<GHIDRA_INSTALL>/support/analyzeHeadless \
/tmp/ghidra_projects myProject \
-import /opt/binaries -recursive \
-librarySearchPaths /opt/shared_libs \
-max-cpu 4 \
-log /tmp/recursive_import.log
This recursively processes all files under /opt/binaries, searches /opt/shared_libs for dependencies, constrains processing to four CPU cores, and logs the entire session to /tmp/recursive_import.log.
Scripting Considerations for Headless Execution
When writing scripts for headless mode, note that GhidraScript API methods requiring user interaction behave differently. According to the implementation in AnalyzeHeadless.java, methods like askString() or askFile() either become no-operations or throw ImproperUseException when SystemUtilities.isInHeadlessMode() returns true. Scripts must handle data programmatically rather than interactively.
Both Java and Jython (Python 2.7) scripts are supported. Place custom scripts in Ghidra's script directories or specify absolute paths when invoking via -preScript or -postScript.
Summary
- Ghidra headless mode enables full binary analysis without the GUI using the
analyzeHeadlessscript inGhidra/RuntimeScripts/Common/support/. - The entry point class
AnalyzeHeadless.javamanages project creation, import, and script execution while theSystemUtilities.isHeadlessflag prevents UI initialization. - Use
-importfor file ingestion,-preScriptand-postScriptfor automation, and-noanalysisto skip auto-analysis when needed. - Output control via
-logand-scriptlogensures capture of both Ghidra system messages and script-specific output. - Recursive processing, library resolution paths, and CPU throttling support enterprise-scale batch operations.
Frequently Asked Questions
Can I run Ghidra headless mode inside a Docker container?
Yes. The analyzeHeadless script automatically sets SystemUtilities.isHeadless=true, which disables all Swing and AWT dependencies. Since the mode never attempts to initialize a graphical display, it runs natively in containerized environments without requiring X11 forwarding or virtual displays.
What happens if my script calls a GUI dialog in headless mode?
According to the Ghidra source code, calling interactive methods like askString() or askFile() from the GhidraScript API during headless execution results in either a no-operation or an ImproperUseException. Scripts intended for batch processing must use non-interactive alternatives or pre-configure all parameters before execution.
How do I process thousands of binaries efficiently?
Use the -recursive flag combined with -max-cpu to limit resource consumption. For massive-scale operations, invoke multiple analyzeHeadless instances in parallel across different project directories, ensuring each instance writes to dedicated -log files to prevent I/O conflicts.
Where is the headless mode documentation located?
The authoritative documentation resides in Ghidra/RuntimeScripts/Common/support/analyzeHeadlessREADME.md within the NSA Ghidra repository. This file contains the complete flag reference, environment variable requirements, and advanced usage patterns for the AnalyzeHeadless class.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →