How to Create Custom Analyzers in Ghidra: A Complete Developer Guide
Extend AbstractAnalyzer, ensure the class name ends with "Analyzer", and implement the added() method to register your analyzer with Ghidra's Auto-Analysis pipeline.
Creating custom analyzers in Ghidra allows you to automate reverse engineering tasks by extending the NationalSecurityAgency/ghidra analysis framework. This guide explains the architecture, implementation requirements, and deployment process based on the actual source code in the Ghidra repository.
Understanding Ghidra's Analyzer Architecture
Ghidra's analysis engine relies on the Analyzer interface defined in ghidra/app/services/Analyzer.java, which extends ExtensionPoint to enable plugin discovery. The ClassSearcher utility in ghidra/util/classfinder/ClassSearcher.java automatically discovers analyzer classes at runtime by scanning the classpath for implementations whose names end with the suffix "Analyzer".
Discovered analyzers are managed by AnalyzerEnablementState objects in ghidra/app/plugin/core/analysis/AnalyzerEnablementState.java, which control their visibility, default enablement status, and prototype flags in the Auto-Analysis dialog.
Requirements for Custom Ghidra Analyzers
Every custom analyzer must satisfy three core requirements to be recognized by the framework:
- Class naming convention: The class name must end with "Analyzer"—otherwise
ClassSearcherwill ignore it during startup. - Interface implementation: The class must implement the
Analyzerinterface, typically by extendingAbstractAnalyzerfromghidra/app/services/AbstractAnalyzer.javato inherit default method implementations for name handling and priority management. - Analysis type declaration: You must return an
AnalyzerType(such asAnalyzerType.FUNCTION_ANALYZERorAnalyzerType.BYTE_ANALYZERfromghidra/app/services/AnalyzerType.java) to specify when the analyzer runs during the analysis pipeline.
Step-by-Step Implementation Guide
Extend AbstractAnalyzer and Configure the Constructor
Subclass AbstractAnalyzer and call the superclass constructor with your analyzer's name, description, and type. Use the following helper methods to configure runtime behavior:
setPriority(AnalysisPriority)controls execution order relative to other analyzerssetDefaultEnablement(boolean)determines whether the analyzer is checked by default in the Auto-Analysis dialogsetSupportsOneTimeAnalysis()enables the "Analyze Once" right-click menu action
Implement the Core Analysis Logic
Override the added(Program program, AddressSetView set, TaskMonitor monitor, MessageLog log) method to perform your analysis. This method receives the target program, address range, progress monitor for cancellation checking, and message log for reporting. Return true to indicate success or false to signal that the analyzer should be disabled for subsequent runs.
Optionally implement removed(Program program, AddressSetView set, TaskMonitor monitor, MessageLog log) to clean up when analysis is cancelled or addresses are removed from the program.
Add Optional Configuration Settings
For analyzers requiring user-configurable parameters, override registerOptions(Options options, Program program) to define UI-visible settings and optionsChanged(Options options, Program program) to read current values. The Options class integrates with Ghidra's preferences system to persist settings between sessions.
Complete Custom Analyzer Example
The following Java class demonstrates a functional analyzer that adds end-of-line comments to every byte address. This example shows proper constructor configuration, the required added() implementation, and cancellation handling via TaskMonitor.
package my.ghidra.analyzers;
import ghidra.app.services.*;
import ghidra.app.util.importer.MessageLog;
import ghidra.framework.options.Options;
import ghidra.program.model.address.*;
import ghidra.program.model.listing.Program;
import ghidra.util.exception.CancelledException;
import ghidra.util.task.TaskMonitor;
/**
* Example custom analyzer that adds a comment to every byte address.
* It runs as a one-time analysis.
*/
public class ByteCommenterAnalyzer extends AbstractAnalyzer {
public ByteCommenterAnalyzer() {
super("Byte Commenter", "Adds a generic comment to every address", AnalyzerType.BYTE_ANALYZER);
setPriority(AnalysisPriority.MEDIUM_PRIORITY);
setDefaultEnablement(true);
setSupportsOneTimeAnalysis(); // enables the "Analyze Once" action
}
@Override
public boolean added(Program program, AddressSetView set,
TaskMonitor monitor, MessageLog log) throws CancelledException {
monitor.initialize(program.getMemory().getNumAddresses());
Address start = program.getAddressFactory().getDefaultAddressSpace().getMinAddress();
for (Address addr = start; !monitor.isCancelled() && addr != null; addr = addr.next()) {
program.getListing().setComment(addr, CodeUnit.EOL_COMMENT, "generated by ByteCommenter");
monitor.incrementProgress(1);
}
return true;
}
// No special options → no need to override registerOptions/optionsChanged
}
Key implementation details:
- The class name ends with
Analyzerto satisfy theClassSearcherdiscovery requirement - The constructor calls
setPriority(),setDefaultEnablement(), andsetSupportsOneTimeAnalysis()to control UI behavior - The
addedmethod contains the actual analysis logic, iterating over addresses while checkingmonitor.isCancelled()to support user interruption
Building and Deploying Your Analyzer
Compile your analyzer against the Ghidra SDK and package it as a JAR file. Place the JAR in <GHIDRA_INSTALL>/Extensions or bundle it within a Ghidra module structure using the provided Gradle build scripts in GHIDRA/Build.
Upon restarting Ghidra, open Tools → Auto Analysis… to locate your analyzer in the enablement list. If you called setDefaultEnablement(true) in the constructor, the analyzer will already be enabled for new programs. For a production-ready reference implementing complex analysis logic, examine FunctionStartAnalyzer in ghidra/app/analyzers/FunctionStartAnalyzer.java.
Summary
- Create a class ending with "Analyzer" that extends
AbstractAnalyzerfromghidra/app/services/AbstractAnalyzer.java - Implement the
added()method defined inghidra/app/services/Analyzer.javato execute your analysis logic - Configure priority, default enablement, and one-time analysis support using the constructor helper methods
- Declare the appropriate
AnalyzerTypefromghidra/app/services/AnalyzerType.javato control execution phase - Package as a JAR in the Extensions directory and enable via the Auto-Analysis dialog managed by
AnalyzerEnablementState
Frequently Asked Questions
Why must my analyzer class name end with "Analyzer"?
The ClassSearcher discovery mechanism in ghidra/util/classfinder/ClassSearcher.java specifically filters for classes implementing ExtensionPoint whose names end with "Analyzer". This naming convention allows Ghidra to efficiently identify analyzer plugins during startup without loading every class in the classpath, as implemented in the NationalSecurityAgency/ghidra source tree.
What is the difference between Analyzer and AbstractAnalyzer?
Analyzer in ghidra/app/services/Analyzer.java is the interface defining the contract all analyzers must fulfill, while AbstractAnalyzer in the same package provides concrete implementations of common methods like getName(), getDescription(), and priority handling. Always extend AbstractAnalyzer unless you need complete control over every interface method, since it correctly implements the ExtensionPoint contract required by ClassSearcher.
How do I make my analyzer run only when manually invoked?
Call setSupportsOneTimeAnalysis() in your constructor and avoid calling setDefaultEnablement(true). This configuration adds your analyzer to the right-click "Analyze" menu while keeping it disabled during automatic background analysis, as tracked by AnalyzerEnablementState in ghidra/app/plugin/core/analysis/AnalyzerEnablementState.java.
Can I access program memory and symbols from within the added() method?
Yes. The added() method receives a Program object providing access to the listing, memory (program.getMemory()), symbol table (program.getSymbolTable()), and reference manager. Use the AddressSetView parameter to limit processing to specific address ranges, and check TaskMonitor.isCancelled() regularly to support responsive user cancellation.
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 →