pyghidra-scripting

Write and run PyGhidra Python scripts inside a ReVa-hosted Ghidra session via MCP tools.

823|73|Updated Aug 18, 2023
One-click install
npx skills add https://github.com/cyberkaida/reverse-engineering-assistant --skill pyghidra-scripting
Or copy as Structured Prompt for Agent
Please help me install this Agent Skill.
Skill: pyghidra-scripting
Source: https://github.com/cyberkaida/reverse-engineering-assistant/tree/main/ReVa/skills/pyghidra-scripting
Command: npx skills add https://github.com/cyberkaida/reverse-engineering-assistant --skill pyghidra-scripting

SYSTEM DOCUMENTATION & REQUIREMENTS

💡 This Skill includes references (resource) components.

What problem does it solve?

Reverse engineering tasks often outgrow the fixed set of structured MCP tools that ReVa exposes, forcing analysts to either make many slow round-trips or give up on custom analysis. This Skill lets an assistant write, run, save, and edit Python (PyGhidra) scripts directly inside the live Ghidra session, unlocking the full Ghidra Java API for custom analysis passes.

Core Features & Use Cases

  • Inline script execution: Send one-shot Python code to the run-script tool with pre-bound Ghidra globals like currentProgram, toAddr, and getFunctionAt, with captured stdout/stderr and cooperative timeout handling.
  • Script lifecycle management: Use list-scripts, read-script, write-script, and edit-script to discover, persist, and iterate on reusable .py scripts in Ghidra's registered script directories.
  • Deep API references: Bundled cheat-sheets cover the Flat API, decompiler internals (HighFunction, Varnode, PcodeOp), JPype interop pitfalls, and copy-pasteable recipes for xrefs, batch renames, struct definition, emulation, and data-flow tracing.
  • Use Case: Ask the assistant to find every callsite of WinExec and trace which constant is passed as its first argument; it writes an inline PyGhidra script that decompiles callers, walks PCode def-use chains, and returns structured JSON results.

Quick Start

Ask the assistant to run a PyGhidra script against the current program, for example to list all functions larger than 4096 bytes with their entry points.

Frequently Asked Questions about pyghidra-scripting

High-intent search queries and answers about installing and using this skill.

FAQPage Schema
How do I run a Python script inside Ghidra using ReVa?

Use the run-script MCP tool with inline code or a saved scriptName. Your code runs under PyGhidra with pre-bound globals like currentProgram, toAddr, and getFunctionAt, and print() output is captured in the result's stdout field.

When should I use run-script instead of ReVa's dedicated MCP tools?

Use run-script only when the structured tools (decompiler, functions, strings, xrefs) cannot express the query, such as custom predicates over all functions or PCode-level data-flow tracing. Dedicated tools have stable schemas and are easier to reason about.

Why does run-script fail with PyGhidraNotAvailableException?

run-script only works when Ghidra was launched under PyGhidra, such as via mcp-reva, pyghidra-gui, or reva_headless_server.py. A plain ghidraRun launch has no PyGhidra runtime, so relaunch using one of the supported modes.

Why do my Ghidra script changes throw IllegalStateException not in transaction?

ReVa's run-script does not open an automatic transaction, so any mutation like renaming, commenting, or creating data must be wrapped manually in currentProgram.startTransaction and endTransaction. Read-only scripts need no transaction.

How do I trace which constant is passed to a function argument in Ghidra?

Decompile the caller functions, walk the HighFunction's PcodeOps to find CALL ops, then follow the argument Varnode's getDef() chain backwards through COPY, CAST, and INT_AND ops until you reach a constant. The bundled recipes include a complete implementation.

What are the limitations of run-script output and timeouts?

stdout and stderr are each capped at 64K characters by default, with truncation flags in the result. The timeout only fires if your code checks monitor.isCancelled() inside loops, so long iterations must poll the monitor cooperatively.