├── Module.manifest ├── lib ├── .gitignore └── README.txt ├── src ├── reva_cli │ ├── .gitignore │ ├── __init__.py │ ├── launcher.py │ └── stdio_bridge.py ├── main │ ├── resources │ │ └── images │ │ │ └── README.txt │ ├── help │ │ └── help │ │ │ ├── topics │ │ │ └── skeleton │ │ │ │ └── help.html │ │ │ └── TOC_Source.xml │ └── java │ │ └── reva │ │ ├── tools │ │ ├── ProgramValidationException.java │ │ └── ToolProvider.java │ │ ├── plugin │ │ ├── config │ │ │ ├── ConfigurationBackendListener.java │ │ │ ├── ConfigurationBackend.java │ │ │ ├── InMemoryBackend.java │ │ │ └── ToolOptionsBackend.java │ │ ├── ConfigChangeListener.java │ │ ├── RevaPlugin.java │ │ └── RevaApplicationPlugin.java │ │ ├── util │ │ ├── SymbolUtil.java │ │ ├── RevaInternalServiceRegistry.java │ │ ├── SimilarityComparator.java │ │ ├── DebugLogger.java │ │ └── MemoryUtil.java │ │ ├── resources │ │ ├── ResourceProvider.java │ │ ├── AbstractResourceProvider.java │ │ └── impl │ │ │ └── ProgramListResource.java │ │ ├── revaAnalyzer.java │ │ ├── revaExporter.java │ │ ├── services │ │ └── RevaMcpService.java │ │ ├── ui │ │ └── RevaProvider.java │ │ ├── revaFileSystem.java │ │ └── server │ │ └── ApiKeyAuthFilter.java ├── test.slow │ ├── java │ │ └── reva │ │ │ ├── CLAUDE.md │ │ │ ├── plugin │ │ │ ├── RevaPluginIntegrationTest.java │ │ │ └── ConfigManagerSecurityTest.java │ │ │ └── tools │ │ │ ├── memory │ │ │ └── MemoryToolProviderIntegrationTest.java │ │ │ ├── comments │ │ │ └── CommentToolProviderIntegrationTest.java │ │ │ ├── bookmarks │ │ │ └── BookmarkToolProviderIntegrationTest.java │ │ │ └── data │ │ │ └── DataToolProviderIntegrationTest.java │ ├── resources │ │ └── logback.xml │ └── CLAUDE.md ├── test │ └── java │ │ └── reva │ │ ├── util │ │ └── RevaPluginTest.java │ │ ├── RevaHeadlessIntegrationTestBase.java │ │ ├── plugin │ │ └── RevaPluginUnitTest.java │ │ └── tools │ │ └── strings │ │ └── StringToolProviderTest.java └── CLAUDE.md ├── ghidra_scripts ├── README.txt ├── sample_script.py └── SampleScript.java ├── extension.properties ├── .continue └── docs │ ├── new-doc-1.yaml │ └── new-doc.yaml ├── ReVa ├── .mcp.json └── .claude-plugin │ └── plugin.json ├── .claude ├── hooks │ ├── setup-gradle.sh │ ├── clone-ghidra-source.sh │ └── install-ghidra-binary.sh ├── settings.json ├── README.md └── agents │ └── reva-setup-installer.md ├── .gitignore ├── data ├── sleighArgs.txt ├── languages │ ├── skel.opinion │ ├── skel.ldefs │ ├── skel.pspec │ ├── skel.slaspec │ ├── skel.cspec │ └── skel.sinc ├── README.txt └── buildLanguage.xml ├── .vscode ├── extensions.json └── launch.json ├── os ├── linux_x86_64 │ └── README.txt ├── mac_x86_64 │ └── README.txt └── win_x86_64 │ └── README.txt ├── tests ├── requirements.txt ├── __init__.py ├── test_pyghidra.py ├── test_config.py ├── test_launcher.py └── test_mcp_tools.py ├── .claude-plugin └── marketplace.json ├── .github ├── dependabot.yml ├── workflows │ ├── claude.yml │ ├── test-headless.yml │ ├── publish-ghidra.yml │ ├── publish-pypi.yml │ └── test-ghidra.yml └── copilot-instructions.md ├── config └── reva-headless-example.properties └── pyproject.toml /Module.manifest: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /lib/.gitignore: -------------------------------------------------------------------------------- 1 | *.jar -------------------------------------------------------------------------------- /src/reva_cli/.gitignore: -------------------------------------------------------------------------------- 1 | _version.py 2 | -------------------------------------------------------------------------------- /ghidra_scripts/README.txt: -------------------------------------------------------------------------------- 1 | Java source directory to hold module-specific Ghidra scripts. 2 | -------------------------------------------------------------------------------- /extension.properties: -------------------------------------------------------------------------------- 1 | name=ReVa 2 | description=Reverse Engineering Assistant 3 | author=CyberKaida 4 | createdOn= 5 | version=@extversion@ 6 | -------------------------------------------------------------------------------- /src/main/resources/images/README.txt: -------------------------------------------------------------------------------- 1 | The "src/resources/images" directory is intended to hold all image/icon files used by 2 | this module. 3 | -------------------------------------------------------------------------------- /.continue/docs/new-doc-1.yaml: -------------------------------------------------------------------------------- 1 | name: New doc 2 | version: 0.0.1 3 | schema: v1 4 | docs: 5 | - name: New docs 6 | startUrl: https://docs.continue.dev 7 | -------------------------------------------------------------------------------- /.continue/docs/new-doc.yaml: -------------------------------------------------------------------------------- 1 | name: Model Context Protocol Java 2 | version: 0.0.1 3 | schema: v1 4 | docs: 5 | - name: MCP 6 | startUrl: https://modelcontextprotocol.io/sdk/java/mcp-overview 7 | -------------------------------------------------------------------------------- /ghidra_scripts/sample_script.py: -------------------------------------------------------------------------------- 1 | # Sample PyGhidra GhidraScript 2 | # @category Examples 3 | # @runtime PyGhidra 4 | 5 | from java.util import LinkedList 6 | java_list = LinkedList([1,2,3]) 7 | 8 | block = currentProgram.memory.getBlock('.text') 9 | -------------------------------------------------------------------------------- /lib/README.txt: -------------------------------------------------------------------------------- 1 | The "lib" directory is intended to hold Jar files which this module is dependent upon. Jar files 2 | may be placed in this directory manually, or automatically by maven via the dependencies block 3 | of this module's build.gradle file. -------------------------------------------------------------------------------- /ReVa/.mcp.json: -------------------------------------------------------------------------------- 1 | { 2 | "mcpServers": { 3 | "ReVa": { 4 | "command": "uv", 5 | "args": ["run", "mcp-reva"], 6 | "env": { 7 | "UV_WORKING_DIRECTORY": "${CLAUDE_PLUGIN_ROOT}/../" 8 | } 9 | } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /.claude/hooks/setup-gradle.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -ex 3 | 4 | # Log to both stderr and log file 5 | LOG_FILE="/tmp/reva-setup-gradle.log" 6 | exec > >(tee -a "${LOG_FILE}") 2>&1 7 | 8 | # Verify Java and Gradle 9 | java -version 10 | gradle --version -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .gradle 2 | build/ 3 | dist/ 4 | bin/ 5 | *.egg-info 6 | *.pyc 7 | *.class 8 | .venv 9 | .vim/ 10 | .DS_Store 11 | .mypy_cache/ 12 | __pycache__ 13 | 14 | # Java heap dump files 15 | *.hprof 16 | 17 | # ReVa local project directories 18 | .reva/ -------------------------------------------------------------------------------- /data/sleighArgs.txt: -------------------------------------------------------------------------------- 1 | # Add sleigh compiler options to this file (one per line) which will 2 | # be used when compiling each language within this module. 3 | # All options should start with a '-' character. 4 | # 5 | # IMPORTANT: The -a option should NOT be specified 6 | # -------------------------------------------------------------------------------- /.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | "recommendations": [ 3 | "ms-python.mypy-type-checker", 4 | "vscjava.vscode-gradle", 5 | "ms-python.vscode-pylance", 6 | "ms-python.python", 7 | "vscjava.vscode-java-pack" 8 | ] 9 | } 10 | -------------------------------------------------------------------------------- /os/linux_x86_64/README.txt: -------------------------------------------------------------------------------- 1 | The "os/linux_x86_64" directory is intended to hold Linux native binaries 2 | which this module is dependent upon. This directory may be eliminated for a specific 3 | module if native binaries are not provided for the corresponding platform. 4 | -------------------------------------------------------------------------------- /os/mac_x86_64/README.txt: -------------------------------------------------------------------------------- 1 | The "os/mac_x86_64" directory is intended to hold macOS (OS X) native binaries 2 | which this module is dependent upon. This directory may be eliminated for a specific 3 | module if native binaries are not provided for the corresponding platform. 4 | -------------------------------------------------------------------------------- /os/win_x86_64/README.txt: -------------------------------------------------------------------------------- 1 | The "os/win_x86_64" directory is intended to hold MS Windows native binaries (.exe) 2 | which this module is dependent upon. This directory may be eliminated for a specific 3 | module if native binaries are not provided for the corresponding platform. 4 | -------------------------------------------------------------------------------- /ReVa/.claude-plugin/plugin.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ReVa", 3 | "description": "ReVa (Reverse Engineering Assistant) - AI-assisted binary analysis and reverse engineering with Ghidra integration", 4 | "version": "0.1.0", 5 | "author": { 6 | "name": "CyberKaida" 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /ghidra_scripts/SampleScript.java: -------------------------------------------------------------------------------- 1 | // Sample Java GhidraScript 2 | // @category Examples 3 | import ghidra.app.script.GhidraScript; 4 | 5 | public class SampleScript extends GhidraScript { 6 | 7 | @Override 8 | protected void run() throws Exception { 9 | println("Sample script!"); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/test.slow/java/reva/CLAUDE.md: -------------------------------------------------------------------------------- 1 | - When writing integration tests, make sure to set up the program, call the tool and then validate the output. If the tool modifies the program, validate the modification. 2 | - Don't write useless tests, make sure they have a purpose. 3 | - **CRITICAL**: Integration tests should validate actual Ghidra program state changes, not just MCP tool responses 4 | -------------------------------------------------------------------------------- /tests/requirements.txt: -------------------------------------------------------------------------------- 1 | # ReVa Headless Integration Test Dependencies 2 | 3 | # PyGhidra for headless Ghidra integration 4 | pyghidra>=1.0.0 5 | 6 | # MCP SDK for proper client communication 7 | mcp>=1.0.0 8 | httpx>=0.27.0 9 | httpx-sse>=0.4.0 10 | 11 | # Pytest framework 12 | pytest>=7.0.0 13 | pytest-timeout>=2.0.0 14 | 15 | # Optional: Better test output 16 | pytest-sugar>=0.9.0 17 | -------------------------------------------------------------------------------- /.claude-plugin/marketplace.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "reva", 3 | "description": "ReVa - AI-assisted binary analysis and reverse engineering with Ghidra integration", 4 | "owner": { 5 | "name": "CyberKaida" 6 | }, 7 | "plugins": [ 8 | { 9 | "name": "ReVa", 10 | "source": "./ReVa", 11 | "description": "AI-assisted binary analysis and reverse engineering with Ghidra integration" 12 | } 13 | ] 14 | } 15 | -------------------------------------------------------------------------------- /src/reva_cli/__init__.py: -------------------------------------------------------------------------------- 1 | """ 2 | ReVa CLI - stdio MCP bridge for ReVa Ghidra extension. 3 | 4 | This package provides a command-line interface that bridges stdio MCP transport 5 | to ReVa's StreamableHTTP server, enabling seamless integration with Claude CLI. 6 | """ 7 | 8 | try: 9 | from ._version import version as __version__ 10 | except ImportError: 11 | # Fallback version if not installed or in development without git tags 12 | __version__ = "0.0.0.dev0" 13 | -------------------------------------------------------------------------------- /.claude/hooks/clone-ghidra-source.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -ex 3 | 4 | # Log to both stderr and log file 5 | LOG_FILE="/tmp/reva-clone-ghidra.log" 6 | exec > >(tee -a "${LOG_FILE}") 2>&1 7 | 8 | GHIDRA_GIT=$(readlink -f "${CLAUDE_PROJECT_DIR}/../ghidra") 9 | 10 | if [ ! -d "${GHIDRA_GIT}" ]; then 11 | echo "The ghidra code is not at ${GHIDRA_GIT} use the @reva-setup-installer to fix this" 12 | else 13 | echo "Ghidra source already exists at ${GHIDRA_GIT}" 14 | fi 15 | -------------------------------------------------------------------------------- /.claude/hooks/install-ghidra-binary.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -ex 3 | 4 | # Log to both stderr and log file 5 | LOG_FILE="/tmp/reva-install-ghidra.log" 6 | exec > >(tee -a "${LOG_FILE}") 2>&1 7 | 8 | # Only run in remote (web) environments 9 | if [ -n "${GHIDRA_INSTALL_DIR}" ]; then 10 | echo "GHIDRA_INSTALL_DIR is not set, use @reva-setup-installer to install the Ghidra binary distribution" 11 | fi 12 | 13 | # Persist environment variables for all subsequent bash commands 14 | if [ -n "$CLAUDE_ENV_FILE" ]; then 15 | echo "Make sure to add an export command for GHIDRA_INSTALL_DIR to ${CLAUDE_ENV_FILE}" 16 | fi 17 | -------------------------------------------------------------------------------- /data/languages/skel.opinion: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 12 | 13 | -------------------------------------------------------------------------------- /data/languages/skel.ldefs: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 20 | 21 | -------------------------------------------------------------------------------- /data/README.txt: -------------------------------------------------------------------------------- 1 | The "data" directory is intended to hold data files that will be used by this module and will 2 | not end up in the .jar file, but will be present in the zip or tar file. Typically, data 3 | files are placed here rather than in the resources directory if the user may need to edit them. 4 | 5 | An optional data/languages directory can exist for the purpose of containing various Sleigh language 6 | specification files and importer opinion files. 7 | 8 | The data/buildLanguage.xml is used for building the contents of the data/languages directory. 9 | 10 | The skel language definition has been commented-out within the skel.ldefs file so that the 11 | skeleton language does not show-up within Ghidra. 12 | 13 | See the Sleigh language documentation (docs/languages/index.html) for details Sleigh language 14 | specification syntax. 15 | -------------------------------------------------------------------------------- /src/test/java/reva/util/RevaPluginTest.java: -------------------------------------------------------------------------------- 1 | package reva.util; 2 | 3 | import static org.junit.Assert.*; 4 | 5 | import org.junit.Test; 6 | 7 | import reva.plugin.RevaPlugin; 8 | 9 | public class RevaPluginTest { 10 | 11 | @Test 12 | public void testPluginClassExists() { 13 | // Basic test to ensure the RevaPlugin class exists and can be instantiated 14 | assertNotNull("RevaPlugin class should exist", RevaPlugin.class); 15 | assertEquals("Package should be correct", "reva.plugin", RevaPlugin.class.getPackage().getName()); 16 | } 17 | 18 | @Test 19 | public void testPluginConstructorSignature() throws NoSuchMethodException { 20 | // Verify the plugin has the correct constructor signature for Ghidra plugins 21 | assertNotNull("RevaPlugin should have a constructor that takes PluginTool", 22 | RevaPlugin.class.getConstructor(ghidra.framework.plugintool.PluginTool.class)); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /data/languages/skel.pspec: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /src/main/help/help/topics/skeleton/help.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 7 | 8 | 9 | 10 | 11 | 12 | Skeleton Help File for a Module 13 | 14 | 15 | 16 | 17 |

Skeleton Help File for a Module

18 | 19 |

This is a simple skeleton help topic. For a better description of what should and should not 20 | go in here, see the "sample" Ghidra extension in the Extensions/Ghidra directory, or see your 21 | favorite help topic. In general, language modules do not have their own help topics.

22 | 23 | 24 | -------------------------------------------------------------------------------- /.claude/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "permissions": { 3 | "additionalDirectories": ["../ghidra"], 4 | "allow": [ 5 | "Search(path:../ghidra)", 6 | "Read(../ghidra/**)" 7 | ], 8 | "deny": [] 9 | }, 10 | "hooks": { 11 | "SessionStart": [ 12 | { 13 | "matcher": "startup", 14 | "hooks": [ 15 | { 16 | "type": "command", 17 | "command": "${CLAUDE_PROJECT_DIR}/.claude/hooks/clone-ghidra-source.sh" 18 | }, 19 | { 20 | "type": "command", 21 | "command": "${CLAUDE_PROJECT_DIR}/.claude/hooks/install-ghidra-binary.sh" 22 | }, 23 | { 24 | "type": "command", 25 | "command": "${CLAUDE_PROJECT_DIR}/.claude/hooks/setup-gradle.sh" 26 | } 27 | ] 28 | } 29 | ], 30 | "PostToolUse": [ 31 | { 32 | "matcher": "Edit|MultiEdit|Write", 33 | "hooks": [ 34 | { 35 | "type": "command", 36 | "command": "gradle compileJava" 37 | } 38 | ] 39 | } 40 | ] 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | # Dependabot configuration for reverse-engineering-assistant 2 | # For more information see: https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates 3 | 4 | version: 2 5 | updates: 6 | # Enable version updates for Gradle dependencies 7 | - package-ecosystem: "gradle" 8 | directory: "/" # Location of build.gradle 9 | schedule: 10 | interval: "weekly" 11 | day: "monday" 12 | time: "09:00" 13 | open-pull-requests-limit: 10 14 | labels: 15 | - "dependencies" 16 | - "gradle" 17 | commit-message: 18 | prefix: "chore" 19 | include: "scope" 20 | 21 | # Enable version updates for GitHub Actions 22 | - package-ecosystem: "github-actions" 23 | directory: "/" # GitHub Actions workflows are in .github/workflows/ 24 | schedule: 25 | interval: "weekly" 26 | day: "monday" 27 | time: "09:00" 28 | open-pull-requests-limit: 5 29 | labels: 30 | - "dependencies" 31 | - "github-actions" 32 | commit-message: 33 | prefix: "chore" 34 | include: "scope" -------------------------------------------------------------------------------- /tests/__init__.py: -------------------------------------------------------------------------------- 1 | """ 2 | ReVa Headless Integration Tests 3 | 4 | This package contains integration tests for ReVa's headless mode using PyGhidra. 5 | 6 | These tests verify that ReVa components work together in headless mode: 7 | - PyGhidra can initialize Ghidra 8 | - RevaHeadlessLauncher can start/stop servers 9 | - MCP tools are accessible and functional 10 | - Configuration files are loaded correctly 11 | 12 | Test Structure: 13 | - test_pyghidra.py - PyGhidra integration verification 14 | - test_launcher.py - RevaHeadlessLauncher lifecycle tests 15 | - test_mcp_tools.py - MCP tool connectivity and functionality 16 | - test_config.py - Configuration file loading tests 17 | 18 | Fixtures (conftest.py): 19 | - ghidra_initialized - One-time PyGhidra initialization (session scope) 20 | - test_program - Shared test program with memory and strings (session scope) 21 | - server - Start/stop server for each test (function scope) 22 | - mcp_client - MCP request helper (function scope) 23 | 24 | Usage: 25 | pytest tests/ -v 26 | pytest tests/test_launcher.py -v 27 | pytest tests/ -k "config" -v 28 | pytest tests/ --timeout=60 29 | """ 30 | -------------------------------------------------------------------------------- /src/test.slow/resources/logback.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | %d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /.github/workflows/claude.yml: -------------------------------------------------------------------------------- 1 | name: Claude Code 2 | 3 | on: 4 | issue_comment: 5 | types: [created] 6 | pull_request_review_comment: 7 | types: [created] 8 | issues: 9 | types: [opened, assigned] 10 | pull_request_review: 11 | types: [submitted] 12 | 13 | jobs: 14 | claude: 15 | if: | 16 | (github.event_name == 'issue_comment' && contains(github.event.comment.body, '@claude')) || 17 | (github.event_name == 'pull_request_review_comment' && contains(github.event.comment.body, '@claude')) || 18 | (github.event_name == 'pull_request_review' && contains(github.event.review.body, '@claude')) || 19 | (github.event_name == 'issues' && (contains(github.event.issue.body, '@claude') || contains(github.event.issue.title, '@claude'))) 20 | runs-on: ubuntu-latest 21 | permissions: 22 | contents: write 23 | pull-requests: write 24 | issues: write 25 | id-token: write 26 | steps: 27 | - name: Checkout repository 28 | uses: actions/checkout@v5 29 | with: 30 | fetch-depth: 1 31 | 32 | - name: Run Claude Code 33 | id: claude 34 | uses: anthropics/claude-code-action@beta 35 | with: 36 | anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }} 37 | 38 | -------------------------------------------------------------------------------- /src/main/java/reva/tools/ProgramValidationException.java: -------------------------------------------------------------------------------- 1 | /* ### 2 | * IP: GHIDRA 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package reva.tools; 17 | 18 | /** 19 | * Exception thrown when program validation fails. 20 | * This exception is used to indicate various program-related errors such as: 21 | * - Program not found 22 | * - Program is in an invalid state (e.g., closed) 23 | * - Invalid program path provided 24 | */ 25 | public class ProgramValidationException extends RuntimeException { 26 | 27 | public ProgramValidationException(String message) { 28 | super(message); 29 | } 30 | 31 | public ProgramValidationException(String message, Throwable cause) { 32 | super(message, cause); 33 | } 34 | } -------------------------------------------------------------------------------- /.github/copilot-instructions.md: -------------------------------------------------------------------------------- 1 | - This is a Ghidra extensions for Ghidra 12.0 and later called "ReVa", the Reverse Engineering Assistant. 2 | - The extension provides a Model Context Protocol (MCP) server for Ghidra. The server is implemented in Java and uses the MCP Java SDK. 3 | - Remember that MCP is in development, so make sure to check the MCP documentation for the latest information. 4 | 5 | Some good resources include: 6 | - [The MCP Java SDK](https://modelcontextprotocol.io/sdk/java/mcp-server) 7 | - [Ghidra on GitHub](https://github.com/NationalSecurityAgency/ghidra) 8 | 9 | - If you want to find a Ghidra API, start from the FlatProgramAPI or the ProgramPlugin API in the Ghidra repo. Use the GitHub tools to search for Ghidra documentation. 10 | - We don't use a gradle wrapper, so just run `gradle` in the root directory to build the project. We do have the Java tools installed in VSCode so you can just check for errors with VSCode instead. 11 | - When writing tests, use the Ghidra test framework. The tests are in the `src/test` directory. It is easy to run them with `gradle test --info` and the integration tests with `gradle integrationTest --info`. 12 | - You can use standard gradle test filtering to run specific tests with both of the test targets. 13 | - We target Ghidra 12.0 and later. Note we should use Java 21. -------------------------------------------------------------------------------- /src/main/java/reva/plugin/config/ConfigurationBackendListener.java: -------------------------------------------------------------------------------- 1 | /* ### 2 | * IP: GHIDRA 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package reva.plugin.config; 17 | 18 | /** 19 | * Listener interface for configuration backend changes. 20 | * Backends that support change notifications will call this when values change. 21 | */ 22 | public interface ConfigurationBackendListener { 23 | 24 | /** 25 | * Called when a configuration value changes 26 | * @param category The configuration category 27 | * @param name The configuration name 28 | * @param oldValue The previous value 29 | * @param newValue The new value 30 | */ 31 | void onConfigurationChanged(String category, String name, Object oldValue, Object newValue); 32 | } 33 | -------------------------------------------------------------------------------- /src/main/java/reva/plugin/ConfigChangeListener.java: -------------------------------------------------------------------------------- 1 | /* ### 2 | * IP: GHIDRA 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package reva.plugin; 17 | 18 | /** 19 | * Interface for listening to configuration changes in the ReVa plugin. 20 | * Implementations can register with ConfigManager to receive notifications 21 | * when configuration values change. 22 | */ 23 | public interface ConfigChangeListener { 24 | 25 | /** 26 | * Called when a configuration option has changed. 27 | * 28 | * @param category The category of the option that changed 29 | * @param name The name of the option that changed 30 | * @param oldValue The previous value of the option 31 | * @param newValue The new value of the option 32 | */ 33 | void onConfigChanged(String category, String name, Object oldValue, Object newValue); 34 | } -------------------------------------------------------------------------------- /src/main/java/reva/util/SymbolUtil.java: -------------------------------------------------------------------------------- 1 | /* ### 2 | * IP: GHIDRA 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package reva.util; 17 | 18 | import java.util.regex.Pattern; 19 | 20 | /** 21 | * Utility methods for working with Ghidra symbols. 22 | */ 23 | public class SymbolUtil { 24 | // Regular expressions for Ghidra's default naming patterns 25 | private static final Pattern DEFAULT_NAME_PATTERN = Pattern.compile( 26 | "^(FUN|LAB|SUB|DAT|EXT|PTR|ARRAY)_[0-9a-fA-F]+$" 27 | ); 28 | 29 | /** 30 | * Check if a symbol name appears to be a default Ghidra-generated name 31 | * @param name The symbol name to check 32 | * @return True if the name follows Ghidra's default naming patterns 33 | */ 34 | public static boolean isDefaultSymbolName(String name) { 35 | if (name == null) { 36 | return false; 37 | } 38 | 39 | return DEFAULT_NAME_PATTERN.matcher(name).matches(); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /data/languages/skel.slaspec: -------------------------------------------------------------------------------- 1 | # sleigh specification file for Skeleton Processor 2 | # >> see docs/languages/sleigh.htm or sleigh.pdf for Sleigh syntax 3 | # Other language modules (see Ghidra/Processors) may provide better examples 4 | # when creating a new language module. 5 | 6 | define endian=little; 7 | define alignment=1; 8 | 9 | define space ram type=ram_space size=2 default; 10 | 11 | define space io type=ram_space size=2; 12 | define space register type=register_space size=1; 13 | 14 | define register offset=0x00 size=1 [ F A C B E D L H I R ]; 15 | define register offset=0x00 size=2 [ AF BC DE HL ]; 16 | define register offset=0x20 size=1 [ A_ F_ B_ C_ D_ E_ H_ L_ ]; # Alternate registers 17 | define register offset=0x20 size=2 [ AF_ BC_ DE_ HL_ ]; # Alternate registers 18 | 19 | define register offset=0x40 size=2 [ _ PC SP IX IY ]; 20 | 21 | define register offset=0x50 size=1 [ rCBAR rCBR rBBR ]; 22 | 23 | # Define context bits (if defined, size must be multiple of 4-bytes) 24 | define register offset=0xf0 size=4 contextreg; 25 | 26 | define context contextreg 27 | assume8bitIOSpace = (0,0) 28 | ; 29 | 30 | # Flag bits (?? manual is very confusing - could be typos!) 31 | @define C_flag "F[0,1]" # C: Carry 32 | @define N_flag "F[1,1]" # N: Add/Subtract 33 | @define PV_flag "F[2,1]" # PV: Parity/Overflow 34 | @define H_flag "F[4,1]" # H: Half Carry 35 | @define Z_flag "F[6,1]" # Z: Zero 36 | @define S_flag "F[7,1]" # S: Sign 37 | 38 | # Include contents of skel.sinc file 39 | @include "skel.sinc" 40 | -------------------------------------------------------------------------------- /src/main/java/reva/tools/ToolProvider.java: -------------------------------------------------------------------------------- 1 | /* ### 2 | * IP: GHIDRA 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package reva.tools; 17 | 18 | import ghidra.program.model.listing.Program; 19 | 20 | /** 21 | * Interface for MCP tool providers. 22 | * Tool providers are responsible for registering and managing 23 | * MCP tools that allow interactive operations with Ghidra data. 24 | */ 25 | public interface ToolProvider { 26 | /** 27 | * Register all tools with the MCP server 28 | */ 29 | void registerTools(); 30 | 31 | /** 32 | * Notify the provider that a program has been opened 33 | * @param program The program that was opened 34 | */ 35 | void programOpened(Program program); 36 | 37 | /** 38 | * Notify the provider that a program has been closed 39 | * @param program The program that was closed 40 | */ 41 | void programClosed(Program program); 42 | 43 | /** 44 | * Clean up any resources or state 45 | */ 46 | void cleanup(); 47 | } 48 | -------------------------------------------------------------------------------- /src/main/java/reva/resources/ResourceProvider.java: -------------------------------------------------------------------------------- 1 | /* ### 2 | * IP: GHIDRA 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package reva.resources; 17 | 18 | import ghidra.program.model.listing.Program; 19 | 20 | /** 21 | * Interface for MCP resource providers. 22 | * Resource providers are responsible for registering and managing 23 | * MCP resources that provide read-only access to Ghidra data. 24 | */ 25 | public interface ResourceProvider { 26 | /** 27 | * Register all resources with the MCP server 28 | */ 29 | void register(); 30 | 31 | /** 32 | * Notify the provider that a program has been opened 33 | * @param program The program that was opened 34 | */ 35 | void programOpened(Program program); 36 | 37 | /** 38 | * Notify the provider that a program has been closed 39 | * @param program The program that was closed 40 | */ 41 | void programClosed(Program program); 42 | 43 | /** 44 | * Clean up any resources or state 45 | */ 46 | void cleanup(); 47 | } 48 | -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "0.2.0", 3 | "configurations": [ 4 | { 5 | "type": "java", 6 | "name": "Ghidra", 7 | "request": "launch", 8 | "mainClass": "ghidra.Ghidra", 9 | "args": "ghidra.GhidraRun", 10 | "classPaths": [ 11 | "${env:GHIDRA_INSTALL_DIR}/Ghidra/Framework/Utility/lib/Utility.jar" 12 | ], 13 | "vmArgs": [ 14 | "-Dghidra.external.modules=${workspaceFolder}", 15 | "-Djava.system.class.loader=ghidra.GhidraClassLoader", 16 | "-Dfile.encoding=UTF8", 17 | "-Duser.country=US", 18 | "-Duser.language=en", 19 | "-Duser.variant=", 20 | "-Dsun.java2d.opengl=false", 21 | "-Djdk.tls.client.protocols=TLSv1.2,TLSv1.3", 22 | "-Dcpu.core.limit=", 23 | "-Dcpu.core.override=", 24 | "-Dfont.size.override=", 25 | "-Dpython.console.encoding=UTF-8", 26 | "-Xshare:off", 27 | "-Declipse.filelock.disable=true", 28 | "-Dapple.laf.useScreenMenuBar=false", 29 | "-Dapple.awt.application.appearance=system" 30 | ] 31 | }, 32 | { 33 | "type": "debugpy", 34 | "name": "PyGhidra", 35 | "request": "launch", 36 | "module": "pyghidra.ghidra_launch", 37 | "args": [ 38 | "--install-dir", 39 | "${env:GHIDRA_INSTALL_DIR}", 40 | "-g", 41 | "ghidra.GhidraRun" 42 | ], 43 | "env": { 44 | "PYGHIDRA_DEBUG": "1" 45 | } 46 | }, 47 | { 48 | "type": "java", 49 | "name": "Ghidra Attach", 50 | "request": "attach", 51 | "hostName": "localhost", 52 | "port": 18001 53 | } 54 | ] 55 | } -------------------------------------------------------------------------------- /.claude/README.md: -------------------------------------------------------------------------------- 1 | # Claude Code Web Environment Setup 2 | 3 | This directory contains configuration and scripts for Claude Code Web environment. 4 | 5 | ## Files 6 | 7 | - **settings.json** - Claude Code configuration including hooks and permissions 8 | - **setup-environment.sh** - SessionStart hook script that configures the web environment 9 | 10 | ## SessionStart Hook 11 | 12 | The `setup-environment.sh` script automatically runs when a Claude Code Web session starts and: 13 | 14 | 1. **Only runs in web environments** - Skips execution on local installations 15 | 2. **Installs required dependencies**: 16 | - OpenJDK 21 (Java Development Kit) 17 | - Gradle 8.14 (Build tool) 18 | - Ghidra latest release (Reverse engineering framework) 19 | 3. **Sets up environment variables**: 20 | - `GHIDRA_INSTALL_DIR=/opt/ghidra` 21 | - `PATH` includes `/opt/gradle/bin` 22 | 4. **Persists configuration** - Saves environment variables to `CLAUDE_ENV_FILE` for subsequent bash commands 23 | 5. **Caches setup** - Uses `/tmp/.reva-env-setup-complete` marker to skip reinstallation on session resume 24 | 25 | ## Installation Locations 26 | 27 | - **Gradle**: `/opt/gradle` 28 | - **Ghidra**: `/opt/ghidra` 29 | 30 | ## Environment Detection 31 | 32 | The script uses `CLAUDE_CODE_REMOTE` environment variable to detect web environments and only runs there, ensuring it doesn't interfere with local development setups. 33 | 34 | ## Building 35 | 36 | After environment setup completes, you can build the project with: 37 | 38 | ```bash 39 | gradle buildExtension 40 | ``` 41 | 42 | The environment is configured to match the CI/CD pipeline defined in `.github/workflows/test-ghidra.yml`. 43 | -------------------------------------------------------------------------------- /data/buildLanguage.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | -------------------------------------------------------------------------------- /tests/test_pyghidra.py: -------------------------------------------------------------------------------- 1 | """ 2 | Test PyGhidra integration for headless Ghidra operation. 3 | 4 | Verifies that: 5 | - PyGhidra can be imported 6 | - Ghidra can be initialized in headless mode 7 | - Basic Ghidra functionality works (program creation, etc.) 8 | """ 9 | 10 | import pytest 11 | 12 | 13 | class TestPyGhidraIntegration: 14 | """Test that PyGhidra integration works correctly""" 15 | 16 | def test_pyghidra_imports(self): 17 | """PyGhidra module can be imported""" 18 | import pyghidra 19 | assert pyghidra is not None 20 | 21 | def test_ghidra_initialized(self, ghidra_initialized): 22 | """Ghidra can be initialized in headless mode""" 23 | # The fixture handles initialization 24 | # Just verify we can import Ghidra classes 25 | from ghidra.program.database import ProgramDB 26 | from ghidra.program.model.lang import LanguageID 27 | assert ProgramDB is not None 28 | assert LanguageID is not None 29 | 30 | def test_test_program_created(self, test_program): 31 | """Test program fixture creates valid program""" 32 | assert test_program is not None, "Failed to create test program" 33 | 34 | # Verify program properties 35 | assert test_program.getName() == "TestHeadlessProgram" 36 | 37 | # Verify memory was created 38 | memory = test_program.getMemory() 39 | assert memory is not None 40 | 41 | # Verify .text section exists 42 | text_block = memory.getBlock(".text") 43 | assert text_block is not None 44 | assert text_block.getStart().getOffset() == 0x00401000 45 | assert text_block.getSize() == 0x1000 46 | 47 | def test_reva_classes_importable(self, ghidra_initialized): 48 | """ReVa classes can be imported after Ghidra initialization""" 49 | from reva.headless import RevaHeadlessLauncher 50 | assert RevaHeadlessLauncher is not None 51 | -------------------------------------------------------------------------------- /src/test.slow/java/reva/plugin/RevaPluginIntegrationTest.java: -------------------------------------------------------------------------------- 1 | /* ### 2 | * IP: GHIDRA 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package reva.plugin; 17 | 18 | import static org.junit.Assert.*; 19 | 20 | import org.junit.Test; 21 | 22 | import reva.RevaIntegrationTestBase; 23 | import reva.util.RevaInternalServiceRegistry; 24 | 25 | /** 26 | * Integration tests for the RevaPlugin 27 | */ 28 | public class RevaPluginIntegrationTest extends RevaIntegrationTestBase { 29 | 30 | @Test 31 | public void testPluginLoadsSuccessfully() { 32 | assertNotNull("Plugin should be loaded", plugin); 33 | assertEquals("Plugin should have correct name", "RevaPlugin", plugin.getName()); 34 | } 35 | 36 | @Test 37 | public void testPluginRegistersInServiceRegistry() { 38 | RevaPlugin registeredPlugin = RevaInternalServiceRegistry.getService(RevaPlugin.class); 39 | assertNotNull("Plugin should be registered in service registry", registeredPlugin); 40 | assertEquals("Registered plugin should be the same instance", plugin, registeredPlugin); 41 | } 42 | 43 | @Test 44 | public void testProgramCreation() { 45 | assertNotNull("Test program should be created", program); 46 | assertNotNull("Program memory should exist", program.getMemory()); 47 | assertTrue("Program should have memory blocks", program.getMemory().getBlocks().length > 0); 48 | } 49 | } -------------------------------------------------------------------------------- /config/reva-headless-example.properties: -------------------------------------------------------------------------------- 1 | # ReVa Headless Configuration Example 2 | # 3 | # This file shows all available configuration options for ReVa in headless mode. 4 | # Copy this file and customize it for your needs. 5 | # 6 | # Usage: 7 | # python scripts/reva_headless_server.py --config config/reva-headless.properties 8 | 9 | # Server Configuration 10 | # Port number for the MCP server (default: 8080) 11 | reva.server.options.server.port=8080 12 | 13 | # Host interface to bind to (default: 127.0.0.1) 14 | # Use 127.0.0.1 for localhost only (recommended for security) 15 | # Use 0.0.0.0 to accept connections from any interface (use with caution!) 16 | reva.server.options.server.host=127.0.0.1 17 | 18 | # Whether the server is enabled (default: true) 19 | reva.server.options.server.enabled=true 20 | 21 | # API Key Authentication 22 | # Enable API key authentication for MCP server access (default: false) 23 | reva.server.options.api.key.authentication.enabled=false 24 | 25 | # API key required for access when authentication is enabled 26 | # Generate a secure random key for production use 27 | reva.server.options.api.key=ReVa-change-this-to-a-secure-random-key 28 | 29 | # Debug Configuration 30 | # Enable debug mode for additional logging (default: false) 31 | reva.server.options.debug.mode=false 32 | 33 | # Decompiler Configuration 34 | # Maximum number of functions before warning about decompiler search (default: 1000) 35 | reva.server.options.max.decompiler.search.functions=1000 36 | 37 | # Timeout in seconds for decompiler operations (default: 10) 38 | reva.server.options.decompiler.timeout.seconds=10 39 | 40 | # Security Notes: 41 | # 1. Keep API keys secure - never commit them to version control 42 | # 2. Use API key authentication in production environments 43 | # 3. Bind to 127.0.0.1 unless you need remote access 44 | # 4. When using 0.0.0.0, always enable API key authentication 45 | # 5. Use HTTPS reverse proxy for production deployments 46 | 47 | # Performance Notes: 48 | # 1. Higher decompiler timeout allows more complex analysis but slower responses 49 | # 2. Lower max functions limit prevents accidental full-program decompilation 50 | # 3. Debug mode adds overhead - disable in production 51 | -------------------------------------------------------------------------------- /src/main/java/reva/util/RevaInternalServiceRegistry.java: -------------------------------------------------------------------------------- 1 | /* ### 2 | * IP: GHIDRA 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package reva.util; 17 | 18 | import java.util.HashMap; 19 | import java.util.Map; 20 | 21 | /** 22 | * A simple service registry to allow components to locate each other at runtime. 23 | * This is a static registry that provides global access to core services. 24 | */ 25 | public class RevaInternalServiceRegistry { 26 | private static final Map, Object> services = new HashMap<>(); 27 | 28 | /** 29 | * Register a service implementation 30 | * @param The service type 31 | * @param serviceClass The service interface class 32 | * @param implementation The service implementation 33 | */ 34 | public static void registerService(Class serviceClass, T implementation) { 35 | services.put(serviceClass, implementation); 36 | } 37 | 38 | /** 39 | * Get a registered service 40 | * @param The service type 41 | * @param serviceClass The service interface class 42 | * @return The service implementation or null if not found 43 | */ 44 | @SuppressWarnings("unchecked") 45 | public static T getService(Class serviceClass) { 46 | return (T) services.get(serviceClass); 47 | } 48 | 49 | /** 50 | * Remove a service from the registry 51 | * @param The service type 52 | * @param serviceClass The service interface class 53 | */ 54 | public static void unregisterService(Class serviceClass) { 55 | services.remove(serviceClass); 56 | } 57 | 58 | /** 59 | * Clear all registered services 60 | */ 61 | public static void clearAllServices() { 62 | services.clear(); 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /src/main/java/reva/revaAnalyzer.java: -------------------------------------------------------------------------------- 1 | /* ### 2 | * IP: GHIDRA 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package reva; 17 | 18 | import ghidra.app.services.AbstractAnalyzer; 19 | import ghidra.app.services.AnalyzerType; 20 | import ghidra.app.util.importer.MessageLog; 21 | import ghidra.framework.options.Options; 22 | import ghidra.program.model.address.AddressSetView; 23 | import ghidra.program.model.listing.Program; 24 | import ghidra.util.exception.CancelledException; 25 | import ghidra.util.task.TaskMonitor; 26 | 27 | /** 28 | * Provide class-level documentation that describes what this analyzer does. 29 | */ 30 | public class revaAnalyzer extends AbstractAnalyzer { 31 | 32 | public revaAnalyzer() { 33 | 34 | // Name the analyzer and give it a description. 35 | 36 | super("My Analyzer", "Analyzer description goes here", AnalyzerType.BYTE_ANALYZER); 37 | } 38 | 39 | @Override 40 | public boolean getDefaultEnablement(Program program) { 41 | 42 | // Return true if analyzer should be enabled by default 43 | 44 | return true; 45 | } 46 | 47 | @Override 48 | public boolean canAnalyze(Program program) { 49 | 50 | // Examine 'program' to determine of this analyzer should analyze it. Return true 51 | // if it can. 52 | 53 | return true; 54 | } 55 | 56 | @Override 57 | public void registerOptions(Options options, Program program) { 58 | 59 | // If this analyzer has custom options, register them here 60 | 61 | options.registerOption("Option name goes here", false, null, 62 | "Option description goes here"); 63 | } 64 | 65 | @Override 66 | public boolean added(Program program, AddressSetView set, TaskMonitor monitor, MessageLog log) 67 | throws CancelledException { 68 | 69 | // Perform analysis when things get added to the 'program'. Return true if the 70 | // analysis succeeded. 71 | 72 | return false; 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /src/main/java/reva/revaExporter.java: -------------------------------------------------------------------------------- 1 | /* ### 2 | * IP: GHIDRA 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package reva; 17 | 18 | import java.io.File; 19 | import java.io.IOException; 20 | import java.util.ArrayList; 21 | import java.util.List; 22 | 23 | import ghidra.app.util.*; 24 | import ghidra.app.util.exporter.Exporter; 25 | import ghidra.app.util.exporter.ExporterException; 26 | import ghidra.framework.model.DomainObject; 27 | import ghidra.program.model.address.AddressSetView; 28 | import ghidra.util.task.TaskMonitor; 29 | 30 | /** 31 | * Provide class-level documentation that describes what this exporter does. 32 | */ 33 | public class revaExporter extends Exporter { 34 | 35 | /** 36 | * Exporter constructor. 37 | */ 38 | public revaExporter() { 39 | 40 | // Name the exporter and associate a file extension with it 41 | 42 | super("My Exporter", "exp", null); 43 | } 44 | 45 | @Override 46 | public boolean supportsAddressRestrictedExport() { 47 | 48 | // Return true if addrSet export parameter can be used to restrict export 49 | 50 | return false; 51 | } 52 | 53 | @Override 54 | public boolean export(File file, DomainObject domainObj, AddressSetView addrSet, 55 | TaskMonitor monitor) throws ExporterException, IOException { 56 | 57 | // Perform the export, and return true if it succeeded 58 | 59 | return false; 60 | } 61 | 62 | @Override 63 | public List