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 ClassSearcher will ignore it during startup.
  • Interface implementation: The class must implement the Analyzer interface, typically by extending AbstractAnalyzer from ghidra/app/services/AbstractAnalyzer.java to inherit default method implementations for name handling and priority management.
  • Analysis type declaration: You must return an AnalyzerType (such as AnalyzerType.FUNCTION_ANALYZER or AnalyzerType.BYTE_ANALYZER from ghidra/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 analyzers
  • setDefaultEnablement(boolean) determines whether the analyzer is checked by default in the Auto-Analysis dialog
  • setSupportsOneTimeAnalysis() 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 Analyzer to satisfy the ClassSearcher discovery requirement
  • The constructor calls setPriority(), setDefaultEnablement(), and setSupportsOneTimeAnalysis() to control UI behavior
  • The added method contains the actual analysis logic, iterating over addresses while checking monitor.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 AbstractAnalyzer from ghidra/app/services/AbstractAnalyzer.java
  • Implement the added() method defined in ghidra/app/services/Analyzer.java to execute your analysis logic
  • Configure priority, default enablement, and one-time analysis support using the constructor helper methods
  • Declare the appropriate AnalyzerType from ghidra/app/services/AnalyzerType.java to 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:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →