# How to Create Custom Analyzers in Ghidra: A Complete Developer Guide

> Learn how to create custom analyzers in Ghidra with this developer guide. Extend AbstractAnalyzer and register your analyzer for the Auto-Analysis pipeline.

- Repository: [National Security Agency/ghidra](https://github.com/NationalSecurityAgency/ghidra)
- Tags: how-to-guide
- Published: 2026-03-04

---

**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`](https://github.com/NationalSecurityAgency/ghidra/blob/main/ghidra/app/services/Analyzer.java), which extends `ExtensionPoint` to enable plugin discovery. The **`ClassSearcher`** utility in [`ghidra/util/classfinder/ClassSearcher.java`](https://github.com/NationalSecurityAgency/ghidra/blob/main/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`](https://github.com/NationalSecurityAgency/ghidra/blob/main/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`](https://github.com/NationalSecurityAgency/ghidra/blob/main/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`](https://github.com/NationalSecurityAgency/ghidra/blob/main/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`.

```java
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`](https://github.com/NationalSecurityAgency/ghidra/blob/main/ghidra/app/analyzers/FunctionStartAnalyzer.java).

## Summary

- Create a class ending with "Analyzer" that extends `AbstractAnalyzer` from [`ghidra/app/services/AbstractAnalyzer.java`](https://github.com/NationalSecurityAgency/ghidra/blob/main/ghidra/app/services/AbstractAnalyzer.java)
- Implement the `added()` method defined in [`ghidra/app/services/Analyzer.java`](https://github.com/NationalSecurityAgency/ghidra/blob/main/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`](https://github.com/NationalSecurityAgency/ghidra/blob/main/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`](https://github.com/NationalSecurityAgency/ghidra/blob/main/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`](https://github.com/NationalSecurityAgency/ghidra/blob/main/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`](https://github.com/NationalSecurityAgency/ghidra/blob/main/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.