pyghidra-mcp Meets Ghidra GUI: Drive Project-Wide RE with Local AI Contents pyghidra-mcp Meets Ghidra GUI: Drive Project-Wide RE with Local AI TL;DR pyghidra-mcp v0.2.0 introduces a --gui mode. The same headless pyghidra-mcp server that ships an entire Ghidra project to an LLM can now drive a live Ghidra CodeBrowser window. In this post, I drive an LLM session with OpenWebUI (local Gemma4) against D-Link DNS-320L firmware, watching the agent rename functions, write plate comments, and pivot across two binaries to fully annotate the CVE-2024-3273 RCE chain end to end. Every edit appears in the Ghidra GUI as it happens and is recorded in the undo history. OpenWebUI on the left, real Ghidra CodeBrowser on the right. Same project, same program, live edits. When the first pyghidra-mcp post shipped back in August, the advantage was project wide analysis with the convenience of a headless server. That part is still the core of the tool. What was missing was a way for the human reverse engineer to see what the agent was doing without paging through a wall of tool-call JSON. This post is about filling that gap, and about what multi-binary reverse engineering looks like when the agent and the human share one window. The Problem with Headless-Only Headless works great for CI, Docker, and one-shot “analyze this whole firmware dump” scripts. It is less ideal when I am actively reversing something and I want to read the listing, follow an xref, set a bookmark, or sanity-check that the agent renamed the thing I thought it did. Before GUI mode, the project file was a black box until I closed the server and reopened it manually. By then the session context was gone, including any chance to catch the agent in the act when it sounded confident and was wrong. The fix is straightforward in retrospect. I had filed GUI mode away as impossible because Ghidra’s project lock means two separate JVMs cannot open the same .gpr at the same time. Walking through the Ghidra source turned that into the obvious answer: do not run them as separate processes. Run pyghidra-mcp and ghidra.GhidraRun inside the same JVM, share one project, share one set of Program objects, and every MCP write lands in the GUI. What I Wanted from a Ghidra MCP I wanted GUI mode because I had already seen what it felt like from the other side. LaurieWired ’s GhidraMCP was the first project I saw that put an LLM inside Ghidra’s CodeBrowser as a plugin, and watching the listing update under tool calls stuck with me. pyghidra-mcp came at the same problem from the other end, headless-first for project-wide visibility across many binaries, scriptable batch analysis, and Docker-friendly CI. What Shipped in v0.2.0 pyghidra-mcp --gui starts the server and launches Ghidra’s Project Manager against the same project the MCP tools are operating on. A CodeBrowser window opens for each binary the agent works on, sharing the same Program objects, so any write performed through an MCP tool lands in the GUI instantly. 1 2 $ uvx pyghidra-mcp --gui --transport http --port 8337 \ --project-path /path/to/dns320l_research.gpr pyghidra-mcp --gui starting up: the server logs GUI-backed server initialized and the CodeBrowser launches against the project. On the tool side, GUI mode adds a handful of new MCP tools that only make sense once you have a window to drive: open_program_in_gui opens a binary in CodeBrowser set_current_program switches the active program when more than one is loaded goto scrolls the listing to a function name or hex address rename_function , set_comment , rename_variable , set_function_prototype , set_variable_type perform writes that land live in the GUI import_binary adds a binary to the project from a file path GUI mode requires --transport http . Ghidra captures stdout and stderr for its own logging the moment the CodeBrowser comes up, so the MCP server has to speak over a socket rather than fighting Ghidra for stdio. The Setup: Local Agent, Local GUI Three processes, three ports: 1 2 3 4 5 6 7 8 9 # pyghidra-mcp with GUI $ uvx pyghidra-mcp --gui --transport http --port 8337 \ --project-path /path/to/dns320l_research.gpr # MCPO fronts the streamable-http MCP as OpenAPI $ uvx mcpo --port 8200 --server-type streamable-http -- http://localhost:8337/mcp # OpenWebUI (already running) at http://localhost:9099/, configured with the # OpenAPI tools panel pointed at http://localhost:8200 Model: google/gemma-4-31b-it , running locally. No API keys, no cloud calls, the agent and the GUI both sit on my laptop. OpenWebUI’s Tools panel sees pyghidra-mcp as an OpenAPI tool server at http://localhost:8200 . The Target: CVE-2024-3273 in the DNS-320L Firmware D-Link’s own product page for the DNS-320L, marked End of Life. D-Link’s DNS-320L is end of life. The vendor classified the affected NAS line as EOL/EOS and declined to patch CVE-2024-3273 , recommending users “retire and replace” instead. Censys clocked 92,000+ exposed devices at the time of disclosure. Two years on the coun...
The article demonstrates a new GUI mode for pyghidra-mcp that allows a local LLM agent to perform live, project-wide reverse engineering within the Ghidra CodeBrowser, using the CVE-2024-3273 RCE chain in D-Link DNS-320L firmware as a case study. According to the NVD, CVE-2024-3273 has a CVSS 3.1 score of 7.3 (HIGH) and affects D-Link DNS-320L firmware versions 1.01.0702.2013, 1.03.0904.2013, and 1.11. The article focuses on the tool's capabilities and does not provide a fixed version or workaround for the vulnerability.