Really enable Ghidra's Developer plugins in both tools
A bare <PACKAGE NAME="Developer" /> only adds the package's RELEASED plugins, so half of them (the STABLE ones) were missing and Configure showed Developer unticked. The project window wasn't configured at all. - CodeBrowser: insert ghidra/codebrowser-developer.xml, which lists the STABLE plugins explicitly, into the default CodeBrowser.tool in Public_Release.jar. - Project window: it has no default config to patch, so ship ghidra/FrontEndTool.xml in the user settings with its three Developer plugins. - Pre-creating the settings dir makes Ghidra show its user agreement; ghidra/preferences sets USER_AGREEMENT=ACCEPT, the value Ghidra writes by itself on a fresh start. Verified by closing Ghidra cleanly: it rewrites FrontEndTool.xml from the loaded plugins and kept all three Developer plugins. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -37,7 +37,7 @@ Early stage. What exists: a single image (`Dockerfile`, `launch-apps.sh`) with C
|
||||
|
||||
## Architecture
|
||||
|
||||
- **Claude Desktop and Ghidra share one container** (the root `Dockerfile`, started by `run.sh`), at the user's request. Ghidra is the official GitHub release (version, build date and SHA-256 are build args), runs on Ubuntu's `openjdk-25-jdk`, lives in `/opt/ghidra` and starts together with Claude Desktop. The CodeBrowser has the **Developer** plugin package enabled: the build patches `defaultTools/CodeBrowser.tool` inside `Public_Release.jar` (user settings reset every start, so patching user config wouldn't stick). Further services such as the RE MCP server may still get their own containers.
|
||||
- **Claude Desktop and Ghidra share one container** (the root `Dockerfile`, started by `run.sh`), at the user's request. Ghidra is the official GitHub release (version, build date and SHA-256 are build args), runs on Ubuntu's `openjdk-25-jdk`, lives in `/opt/ghidra` and starts together with Claude Desktop. The **Developer** plugin package is enabled in both the project window and the CodeBrowser. A bare `<PACKAGE NAME="Developer" />` only adds the package's RELEASED plugins, so the STABLE ones are listed with `<INCLUDE CLASS=...>`. CodeBrowser: the build inserts `ghidra/codebrowser-developer.xml` into `defaultTools/CodeBrowser.tool` inside `Public_Release.jar`. Project window: it has no default to patch, so `ghidra/FrontEndTool.xml` is copied into the user settings, along with `ghidra/preferences` (`USER_AGREEMENT=ACCEPT`, because a pre-created settings dir otherwise makes Ghidra ask for its user agreement). To check a config really loaded, close Ghidra cleanly and see whether the plugins survive in the file it rewrites; Ghidra drops what it didn't load.
|
||||
- **Shared workspace volume.** Every container mounts the workspace at `/workspace`, so a file path means the same thing to Claude, Ghidra and the RE MCP. `run.sh` asks for the host folder on each start in the desktop's folder picker (`zenity`, or `kdialog` on KDE; terminal prompt if neither exists), opening at the last folder used, else `./workspace`. Skip it with `--workspace DIR` or `WORKSPACE=DIR`. It refuses `/` and `$HOME`. The image symlinks `~/workspace` to `/workspace` for Claude Desktop's file picker.
|
||||
- **GUI forwarding.** Claude Desktop and Ghidra are GUI apps. Default to X11 forwarding (`/tmp/.X11-unix` + `DISPLAY`). Support Wayland through XWayland. Keep a noVNC/VNC fallback in mind for headless hosts. Never solve display access with a blanket `xhost +`. Scope it (`xhost +local:docker` or `+SI:localuser:...`).
|
||||
- **GhidraMCP wiring.** GhidraMCP has two parts:
|
||||
|
||||
+22
-5
@@ -56,21 +56,38 @@ ENV GHIDRA_INSTALL_DIR=/opt/ghidra
|
||||
# CodeBrowser. Ghidra copies its default tools into the user's settings on
|
||||
# first start, and settings are reset on every container start, so the
|
||||
# default CodeBrowser.tool inside the jar is patched instead of user config.
|
||||
# The build fails if the line could not be inserted.
|
||||
# A bare <PACKAGE NAME="Developer" /> only adds the package's RELEASED
|
||||
# plugins; the snippet also lists the STABLE ones. The build fails if the
|
||||
# snippet could not be inserted.
|
||||
COPY ghidra/codebrowser-developer.xml /tmp/codebrowser-developer.xml
|
||||
RUN set -e; cd /tmp \
|
||||
&& jar_file=/opt/ghidra/Ghidra/Configurations/Public_Release/lib/Public_Release.jar \
|
||||
&& unzip -q "$jar_file" defaultTools/CodeBrowser.tool \
|
||||
&& sed -i '0,/<ROOT_NODE/s//<PACKAGE NAME="Developer" \/>\n <ROOT_NODE/' defaultTools/CodeBrowser.tool \
|
||||
&& grep -q '<PACKAGE NAME="Developer" />' defaultTools/CodeBrowser.tool \
|
||||
&& awk 'FNR==NR { snip = snip $0 "\n"; next } !done && /<ROOT_NODE/ { printf "%s", snip; done = 1 } { print }' \
|
||||
/tmp/codebrowser-developer.xml defaultTools/CodeBrowser.tool > /tmp/CodeBrowser.tool \
|
||||
&& mv /tmp/CodeBrowser.tool defaultTools/CodeBrowser.tool \
|
||||
&& grep -q 'FidDebugPlugin' defaultTools/CodeBrowser.tool \
|
||||
&& jar uf "$jar_file" defaultTools/CodeBrowser.tool \
|
||||
&& rm -r /tmp/defaultTools
|
||||
&& rm -r /tmp/defaultTools /tmp/codebrowser-developer.xml
|
||||
|
||||
# Ubuntu 24.04 ships a default "ubuntu" user on UID 1000; replace it.
|
||||
RUN if id ubuntu >/dev/null 2>&1; then userdel -r ubuntu; fi \
|
||||
&& groupadd -g "${USER_GID}" "${USER_NAME}" \
|
||||
&& useradd -m -u "${USER_UID}" -g "${USER_GID}" -s /bin/bash "${USER_NAME}" \
|
||||
&& install -d -o "${USER_UID}" -g "${USER_GID}" /workspace \
|
||||
&& ln -s /workspace "/home/${USER_NAME}/workspace"
|
||||
&& ln -s /workspace "/home/${USER_NAME}/workspace" \
|
||||
&& install -d -o "${USER_UID}" -g "${USER_GID}" \
|
||||
"/home/${USER_NAME}/.config" \
|
||||
"/home/${USER_NAME}/.config/ghidra" \
|
||||
"/home/${USER_NAME}/.config/ghidra/ghidra_${GHIDRA_VERSION}_PUBLIC"
|
||||
|
||||
# Ghidra's project window has no default config to patch; it builds one in
|
||||
# code and saves it on exit. So a starting FrontEndTool.xml with the Developer
|
||||
# plugins is put in the user settings. Pre-creating the settings dir makes
|
||||
# Ghidra ask for its user agreement, which it otherwise accepts by itself on
|
||||
# a fresh start, so preferences carries the same USER_AGREEMENT=ACCEPT.
|
||||
COPY --chown=${USER_UID}:${USER_GID} ghidra/FrontEndTool.xml ghidra/preferences \
|
||||
/home/${USER_NAME}/.config/ghidra/ghidra_${GHIDRA_VERSION}_PUBLIC/
|
||||
|
||||
COPY --chmod=755 launch-apps.sh /usr/local/bin/launch-apps
|
||||
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!-- Initial config for Ghidra's project window (front end). Ghidra overwrites
|
||||
it on exit; it is copied into the image so that every container start
|
||||
opens with the "Developer" plugin package enabled (File > Configure). -->
|
||||
<!-- VERSION must match GHIDRA_VERSION in the Dockerfile. -->
|
||||
<FRONTEND VERSION="12.2">
|
||||
<TOOL_CONFIG CONFIG_NAME="NO_LONGER_USED">
|
||||
<ICON LOCATION="view_detailed.png" />
|
||||
<TOOL TOOL_NAME="Ghidra: NO ACTIVE PROJECT" INSTANCE_NAME="">
|
||||
<OPTIONS />
|
||||
<PACKAGE NAME="Utility" />
|
||||
<PACKAGE NAME="Ghidra Core" />
|
||||
<!-- Developer plugins that may run in the project window. All are
|
||||
STABLE, not RELEASED, so each must be listed explicitly. -->
|
||||
<PACKAGE NAME="Developer">
|
||||
<INCLUDE CLASS="ghidra.app.plugin.debug.DomainFolderChangesDisplayPlugin" />
|
||||
<INCLUDE CLASS="ghidra.app.plugin.debug.GenerateOldLanguagePlugin" />
|
||||
<INCLUDE CLASS="ghidra.app.plugin.debug.JavaHelpPlugin" />
|
||||
</PACKAGE>
|
||||
<ROOT_NODE X_POS="560" Y_POS="240" WIDTH="800" HEIGHT="600" EX_STATE="0" FOCUSED_OWNER="FrontEnd Tool" FOCUSED_NAME="FrontEnd" FOCUSED_TITLE="Project Window">
|
||||
<COMPONENT_NODE TOP_INFO="0">
|
||||
<COMPONENT_INFO NAME="FrontEnd" OWNER="FrontEnd Tool" TITLE="Project Window" ACTIVE="true" GROUP="Default" />
|
||||
</COMPONENT_NODE>
|
||||
</ROOT_NODE>
|
||||
</TOOL>
|
||||
</TOOL_CONFIG>
|
||||
</FRONTEND>
|
||||
@@ -0,0 +1,8 @@
|
||||
<!-- Inserted at build time (see Dockerfile). The bare package adds its
|
||||
RELEASED plugins; the STABLE ones must be listed explicitly. -->
|
||||
<PACKAGE NAME="Developer">
|
||||
<INCLUDE CLASS="ghidra.app.plugin.debug.GenerateOldLanguagePlugin" />
|
||||
<INCLUDE CLASS="ghidra.app.plugin.debug.JavaHelpPlugin" />
|
||||
<INCLUDE CLASS="ghidra.app.plugin.gui.WindowLocationPlugin" />
|
||||
<INCLUDE CLASS="ghidra.feature.fid.plugin.FidDebugPlugin" />
|
||||
</PACKAGE>
|
||||
@@ -0,0 +1,4 @@
|
||||
# Same value Ghidra writes on its own on a fresh start (no settings dir).
|
||||
# Needed because the image pre-creates the settings dir for FrontEndTool.xml,
|
||||
# which otherwise makes Ghidra show its user agreement dialog every start.
|
||||
USER_AGREEMENT=ACCEPT
|
||||
Reference in New Issue
Block a user