From 9574223421d6ad8740a8a9959de3a9a0af6e680e Mon Sep 17 00:00:00 2001 From: ian-mad <177447559+ian-mad@users.noreply.github.com> Date: Sun, 30 Mar 2025 23:54:46 +0200 Subject: [PATCH 01/12] Improved build instructions --- README.md | 10 +++++++++- lib/.gitignore | 2 ++ 2 files changed, 11 insertions(+), 1 deletion(-) create mode 100644 lib/.gitignore diff --git a/README.md b/README.md index 27a729fc..0129cc98 100644 --- a/README.md +++ b/README.md @@ -78,7 +78,15 @@ Another MCP client that supports multiple models on the backend is [5ire](https: 3. Command: `python /ABSOLUTE_PATH_TO/bridge_mcp_ghidra.py` # Building from Source -Build with Maven by running: +1. Copy the following files from your Ghidra directory to this project's `lib/` directory: +- `Ghidra/Features/Base/lib/Base.jar` +- `Ghidra/Features/Decompiler/lib/Decompiler.jar` +- `Ghidra/Framework/Docking/lib/Docking.jar` +- `Ghidra/Framework/Generic/lib/Generic.jar` +- `Ghidra/Framework/Project/lib/Project.jar` +- `Ghidra/Framework/SoftwareModeling/lib/SoftwareModeling.jar` +- `Ghidra/Framework/Utility/lib/Utility.jar` +2. Build with Maven by running: `mvn clean package assembly:single` diff --git a/lib/.gitignore b/lib/.gitignore new file mode 100644 index 00000000..c96a04f0 --- /dev/null +++ b/lib/.gitignore @@ -0,0 +1,2 @@ +* +!.gitignore \ No newline at end of file From e106cc4d782a6cd8e55ccd633870dd6864d5ecd0 Mon Sep 17 00:00:00 2001 From: tuxuser <462620+tuxuser@users.noreply.github.com> Date: Mon, 31 Mar 2025 19:49:41 +0200 Subject: [PATCH 02/12] ci: Create build workflow --- .github/workflows/build.yml | 60 +++++++++++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) create mode 100644 .github/workflows/build.yml diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml new file mode 100644 index 00000000..40deee43 --- /dev/null +++ b/.github/workflows/build.yml @@ -0,0 +1,60 @@ +name: Build with Maven + +on: + push: + branches: [ "main" ] + pull_request: + branches: [ "main" ] + +jobs: + build: + runs-on: ubuntu-latest + env: + GHIDRA_VERSION: 11.3.1 + GHIDRA_DATE: 20250219 + GHIDRA_LIBS: >- + Features/Base/lib/Base.jar + Features/Decompiler/lib/Decompiler.jar + Framework/Docking/lib/Docking.jar + Framework/Generic/lib/Generic.jar + Framework/Project/lib/Project.jar + Framework/SoftwareModeling/lib/SoftwareModeling.jar + Framework/Utility/lib/Utility.jar + + steps: + - uses: actions/checkout@v4 + - name: Set up JDK 21 + uses: actions/setup-java@v4 + with: + java-version: '21' + distribution: 'temurin' + cache: maven + + - name: Download Ghidra + run: | + wget --no-verbose -O ghidra.zip https://github.com/NationalSecurityAgency/ghidra/releases/download/Ghidra_${{ env.GHIDRA_VERSION }}_build/ghidra_${{ env.GHIDRA_VERSION }}_PUBLIC_${{ env.GHIDRA_DATE }}.zip + 7z x -bd ghidra.zip + + - name: Copy Ghidra libs + run: | + mkdir ./lib + for libfile in ${{ env.GHIDRA_LIBS }} + do echo "Copying ${libfile} to lib/" + cp ghidra_${{ env.GHIDRA_VERSION }}_PUBLIC/Ghidra/${libfile} ./lib/ + done + + - name: Build with Maven + run: mvn clean package assembly:single + + - name: Assemble release directory + run: | + mkdir release + cp target/GhidraMCP-*-SNAPSHOT.zip release/ + cp bridge_mcp_ghidra.py release/ + + - name: Upload artifact + uses: actions/upload-artifact@v4 + with: + name: GhidraMCP-artifact + path: | + release/* From 94ab9bcfddd14fc05dc3a35c253cedd8ed74ccd6 Mon Sep 17 00:00:00 2001 From: jeFF0Falltrades <8444166+jeFF0Falltrades@users.noreply.github.com> Date: Sun, 13 Apr 2025 01:45:37 -0400 Subject: [PATCH 03/12] Utilize urljoin to gracefully handle variations of server name strings --- bridge_mcp_ghidra.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/bridge_mcp_ghidra.py b/bridge_mcp_ghidra.py index 0b238bb7..5b43fd15 100644 --- a/bridge_mcp_ghidra.py +++ b/bridge_mcp_ghidra.py @@ -8,6 +8,7 @@ import sys import requests +from urllib.parse import urljoin from mcp.server.fastmcp import FastMCP @@ -23,7 +24,7 @@ def safe_get(endpoint: str, params: dict = None) -> list: if params is None: params = {} - url = f"{ghidra_server_url}/{endpoint}" + url = urljoin(ghidra_server_url, endpoint) try: response = requests.get(url, params=params, timeout=5) @@ -38,9 +39,9 @@ def safe_get(endpoint: str, params: dict = None) -> list: def safe_post(endpoint: str, data: dict | str) -> str: try: if isinstance(data, dict): - response = requests.post(f"{ghidra_server_url}/{endpoint}", data=data, timeout=5) + response = requests.post( urljoin(ghidra_server_url, endpoint), data=data, timeout=5) else: - response = requests.post(f"{ghidra_server_url}/{endpoint}", data=data.encode("utf-8"), timeout=5) + response = requests.post( urljoin(ghidra_server_url, endpoint), data=data.encode("utf-8"), timeout=5) response.encoding = 'utf-8' if response.ok: return response.text.strip() From b3d435ab1169c4e9a3cdc0465ea84ceb865a9b75 Mon Sep 17 00:00:00 2001 From: pinksawtooth Date: Wed, 16 Apr 2025 09:43:37 +0900 Subject: [PATCH 04/12] add Add cross-reference (xref) functionality --- bridge_mcp_ghidra.py | 45 ++++++ .../java/com/lauriewired/GhidraMCPPlugin.java | 138 ++++++++++++++++++ 2 files changed, 183 insertions(+) diff --git a/bridge_mcp_ghidra.py b/bridge_mcp_ghidra.py index e171a7ad..a2fd7bc3 100644 --- a/bridge_mcp_ghidra.py +++ b/bridge_mcp_ghidra.py @@ -222,6 +222,51 @@ def set_local_variable_type(function_address: str, variable_name: str, new_type: """ return safe_post("set_local_variable_type", {"function_address": function_address, "variable_name": variable_name, "new_type": new_type}) +@mcp.tool() +def get_xrefs_to(address: str, offset: int = 0, limit: int = 100) -> list: + """ + Get all references to the specified address (xref to). + + Args: + address: Target address in hex format (e.g. "0x1400010a0") + offset: Pagination offset (default: 0) + limit: Maximum number of references to return (default: 100) + + Returns: + List of references to the specified address + """ + return safe_get("xrefs_to", {"address": address, "offset": offset, "limit": limit}) + +@mcp.tool() +def get_xrefs_from(address: str, offset: int = 0, limit: int = 100) -> list: + """ + Get all references from the specified address (xref from). + + Args: + address: Source address in hex format (e.g. "0x1400010a0") + offset: Pagination offset (default: 0) + limit: Maximum number of references to return (default: 100) + + Returns: + List of references from the specified address + """ + return safe_get("xrefs_from", {"address": address, "offset": offset, "limit": limit}) + +@mcp.tool() +def get_function_xrefs(name: str, offset: int = 0, limit: int = 100) -> list: + """ + Get all references to the specified function by name. + + Args: + name: Function name to search for + offset: Pagination offset (default: 0) + limit: Maximum number of references to return (default: 100) + + Returns: + List of references to the specified function + """ + return safe_get("function_xrefs", {"name": name, "offset": offset, "limit": limit}) + def main(): parser = argparse.ArgumentParser(description="MCP server for Ghidra") parser.add_argument("--ghidra-server", type=str, default=DEFAULT_GHIDRA_SERVER, diff --git a/src/main/java/com/lauriewired/GhidraMCPPlugin.java b/src/main/java/com/lauriewired/GhidraMCPPlugin.java index 0716c2e8..c83b9d76 100644 --- a/src/main/java/com/lauriewired/GhidraMCPPlugin.java +++ b/src/main/java/com/lauriewired/GhidraMCPPlugin.java @@ -7,6 +7,10 @@ import ghidra.program.model.listing.*; import ghidra.program.model.mem.MemoryBlock; import ghidra.program.model.symbol.*; +import ghidra.program.model.symbol.ReferenceManager; +import ghidra.program.model.symbol.Reference; +import ghidra.program.model.symbol.ReferenceIterator; +import ghidra.program.model.symbol.RefType; import ghidra.program.model.pcode.HighFunction; import ghidra.program.model.pcode.HighSymbol; import ghidra.program.model.pcode.LocalSymbolMap; @@ -305,6 +309,30 @@ private void startServer() throws IOException { sendResponse(exchange, responseMsg.toString()); }); + server.createContext("/xrefs_to", exchange -> { + Map qparams = parseQueryParams(exchange); + String address = qparams.get("address"); + int offset = parseIntOrDefault(qparams.get("offset"), 0); + int limit = parseIntOrDefault(qparams.get("limit"), 100); + sendResponse(exchange, getXrefsTo(address, offset, limit)); + }); + + server.createContext("/xrefs_from", exchange -> { + Map qparams = parseQueryParams(exchange); + String address = qparams.get("address"); + int offset = parseIntOrDefault(qparams.get("offset"), 0); + int limit = parseIntOrDefault(qparams.get("limit"), 100); + sendResponse(exchange, getXrefsFrom(address, offset, limit)); + }); + + server.createContext("/function_xrefs", exchange -> { + Map qparams = parseQueryParams(exchange); + String name = qparams.get("name"); + int offset = parseIntOrDefault(qparams.get("offset"), 0); + int limit = parseIntOrDefault(qparams.get("limit"), 100); + sendResponse(exchange, getFunctionXrefs(name, offset, limit)); + }); + server.setExecutor(null); new Thread(() -> { try { @@ -1206,6 +1234,116 @@ private void updateVariableType(Program program, HighSymbol symbol, DataType dat } } + /** + * Get all references to a specific address (xref to) + */ + private String getXrefsTo(String addressStr, int offset, int limit) { + Program program = getCurrentProgram(); + if (program == null) return "No program loaded"; + if (addressStr == null || addressStr.isEmpty()) return "Address is required"; + + try { + Address addr = program.getAddressFactory().getAddress(addressStr); + ReferenceManager refManager = program.getReferenceManager(); + + ReferenceIterator refIter = refManager.getReferencesTo(addr); + + List refs = new ArrayList<>(); + while (refIter.hasNext()) { + Reference ref = refIter.next(); + Address fromAddr = ref.getFromAddress(); + RefType refType = ref.getReferenceType(); + + Function fromFunc = program.getFunctionManager().getFunctionContaining(fromAddr); + String funcInfo = (fromFunc != null) ? " in " + fromFunc.getName() : ""; + + refs.add(String.format("From %s%s [%s]", fromAddr, funcInfo, refType.getName())); + } + + return paginateList(refs, offset, limit); + } catch (Exception e) { + return "Error getting references to address: " + e.getMessage(); + } + } + + /** + * Get all references from a specific address (xref from) + */ + private String getXrefsFrom(String addressStr, int offset, int limit) { + Program program = getCurrentProgram(); + if (program == null) return "No program loaded"; + if (addressStr == null || addressStr.isEmpty()) return "Address is required"; + + try { + Address addr = program.getAddressFactory().getAddress(addressStr); + ReferenceManager refManager = program.getReferenceManager(); + + Reference[] references = refManager.getReferencesFrom(addr); + + List refs = new ArrayList<>(); + for (Reference ref : references) { + Address toAddr = ref.getToAddress(); + RefType refType = ref.getReferenceType(); + + String targetInfo = ""; + Function toFunc = program.getFunctionManager().getFunctionAt(toAddr); + if (toFunc != null) { + targetInfo = " to function " + toFunc.getName(); + } else { + Data data = program.getListing().getDataAt(toAddr); + if (data != null) { + targetInfo = " to data " + (data.getLabel() != null ? data.getLabel() : data.getPathName()); + } + } + + refs.add(String.format("To %s%s [%s]", toAddr, targetInfo, refType.getName())); + } + + return paginateList(refs, offset, limit); + } catch (Exception e) { + return "Error getting references from address: " + e.getMessage(); + } + } + + /** + * Get all references to a specific function by name + */ + private String getFunctionXrefs(String functionName, int offset, int limit) { + Program program = getCurrentProgram(); + if (program == null) return "No program loaded"; + if (functionName == null || functionName.isEmpty()) return "Function name is required"; + + try { + List refs = new ArrayList<>(); + FunctionManager funcManager = program.getFunctionManager(); + for (Function function : funcManager.getFunctions(true)) { + if (function.getName().equals(functionName)) { + Address entryPoint = function.getEntryPoint(); + ReferenceIterator refIter = program.getReferenceManager().getReferencesTo(entryPoint); + + while (refIter.hasNext()) { + Reference ref = refIter.next(); + Address fromAddr = ref.getFromAddress(); + RefType refType = ref.getReferenceType(); + + Function fromFunc = funcManager.getFunctionContaining(fromAddr); + String funcInfo = (fromFunc != null) ? " in " + fromFunc.getName() : ""; + + refs.add(String.format("From %s%s [%s]", fromAddr, funcInfo, refType.getName())); + } + } + } + + if (refs.isEmpty()) { + return "No references found to function: " + functionName; + } + + return paginateList(refs, offset, limit); + } catch (Exception e) { + return "Error getting function references: " + e.getMessage(); + } + } + /** * Resolves a data type by name, handling common types and pointer types * @param dtm The data type manager From d770d44e8ae2cf5f485a984d4a7c46737d5e058c Mon Sep 17 00:00:00 2001 From: pinksawtooth Date: Wed, 16 Apr 2025 12:32:36 +0900 Subject: [PATCH 05/12] Add functionality to list all defined strings in binaries --- bridge_mcp_ghidra.py | 18 +++++ .../java/com/lauriewired/GhidraMCPPlugin.java | 72 +++++++++++++++++++ 2 files changed, 90 insertions(+) diff --git a/bridge_mcp_ghidra.py b/bridge_mcp_ghidra.py index a2fd7bc3..cbb2040e 100644 --- a/bridge_mcp_ghidra.py +++ b/bridge_mcp_ghidra.py @@ -267,6 +267,24 @@ def get_function_xrefs(name: str, offset: int = 0, limit: int = 100) -> list: """ return safe_get("function_xrefs", {"name": name, "offset": offset, "limit": limit}) +@mcp.tool() +def list_strings(offset: int = 0, limit: int = 2000, filter: str = None) -> list: + """ + List all defined strings in the program with their addresses. + + Args: + offset: Pagination offset (default: 0) + limit: Maximum number of strings to return (default: 2000) + filter: Optional filter to match within string content + + Returns: + List of strings with their addresses + """ + params = {"offset": offset, "limit": limit} + if filter: + params["filter"] = filter + return safe_get("strings", params) + def main(): parser = argparse.ArgumentParser(description="MCP server for Ghidra") parser.add_argument("--ghidra-server", type=str, default=DEFAULT_GHIDRA_SERVER, diff --git a/src/main/java/com/lauriewired/GhidraMCPPlugin.java b/src/main/java/com/lauriewired/GhidraMCPPlugin.java index c83b9d76..b417a286 100644 --- a/src/main/java/com/lauriewired/GhidraMCPPlugin.java +++ b/src/main/java/com/lauriewired/GhidraMCPPlugin.java @@ -333,6 +333,14 @@ private void startServer() throws IOException { sendResponse(exchange, getFunctionXrefs(name, offset, limit)); }); + server.createContext("/strings", exchange -> { + Map qparams = parseQueryParams(exchange); + int offset = parseIntOrDefault(qparams.get("offset"), 0); + int limit = parseIntOrDefault(qparams.get("limit"), 100); + String filter = qparams.get("filter"); + sendResponse(exchange, listDefinedStrings(offset, limit, filter)); + }); + server.setExecutor(null); new Thread(() -> { try { @@ -1344,6 +1352,70 @@ private String getFunctionXrefs(String functionName, int offset, int limit) { } } +/** + * List all defined strings in the program with their addresses + */ + private String listDefinedStrings(int offset, int limit, String filter) { + Program program = getCurrentProgram(); + if (program == null) return "No program loaded"; + + List lines = new ArrayList<>(); + DataIterator dataIt = program.getListing().getDefinedData(true); + + while (dataIt.hasNext()) { + Data data = dataIt.next(); + + // Check if this is a string data type + if (data != null && isStringData(data)) { + String value = data.getValue() != null ? data.getValue().toString() : ""; + + // Apply filter if provided + if (filter == null || value.toLowerCase().contains(filter.toLowerCase())) { + // Escape string for better display + String escapedValue = escapeString(value); + lines.add(String.format("%s: \"%s\"", data.getAddress(), escapedValue)); + } + } + } + + return paginateList(lines, offset, limit); + } + + /** + * Check if the given data is a string type + */ + private boolean isStringData(Data data) { + if (data == null) return false; + + DataType dt = data.getDataType(); + String typeName = dt.getName().toLowerCase(); + return typeName.contains("string") || typeName.contains("char") || typeName.equals("unicode"); + } + + /** + * Escape special characters in a string for display + */ + private String escapeString(String input) { + if (input == null) return ""; + + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < input.length(); i++) { + char c = input.charAt(i); + if (c >= 32 && c < 127) { + sb.append(c); + } else if (c == '\n') { + sb.append("\\n"); + } else if (c == '\r') { + sb.append("\\r"); + } else if (c == '\t') { + sb.append("\\t"); + } else { + sb.append(String.format("\\x%02x", (int)c & 0xFF)); + } + } + return sb.toString(); + } + /** * Resolves a data type by name, handling common types and pointer types * @param dtm The data type manager From 4c7d275f5834cc37683215472237dffa21b65559 Mon Sep 17 00:00:00 2001 From: pinksawtooth Date: Wed, 16 Apr 2025 15:52:11 +0900 Subject: [PATCH 06/12] Delete comments --- src/main/java/com/lauriewired/GhidraMCPPlugin.java | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/main/java/com/lauriewired/GhidraMCPPlugin.java b/src/main/java/com/lauriewired/GhidraMCPPlugin.java index b417a286..a04c910b 100644 --- a/src/main/java/com/lauriewired/GhidraMCPPlugin.java +++ b/src/main/java/com/lauriewired/GhidraMCPPlugin.java @@ -1365,13 +1365,10 @@ private String listDefinedStrings(int offset, int limit, String filter) { while (dataIt.hasNext()) { Data data = dataIt.next(); - // Check if this is a string data type if (data != null && isStringData(data)) { String value = data.getValue() != null ? data.getValue().toString() : ""; - // Apply filter if provided if (filter == null || value.toLowerCase().contains(filter.toLowerCase())) { - // Escape string for better display String escapedValue = escapeString(value); lines.add(String.format("%s: \"%s\"", data.getAddress(), escapedValue)); } From 83e46806af2212a1404d3d8311e598fb913c87cf Mon Sep 17 00:00:00 2001 From: LaurieWired Date: Sun, 20 Apr 2025 18:01:13 -0700 Subject: [PATCH 07/12] Fix ghidra server configuration on mcp side --- bridge_mcp_ghidra.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/bridge_mcp_ghidra.py b/bridge_mcp_ghidra.py index e171a7ad..d4fd53a7 100644 --- a/bridge_mcp_ghidra.py +++ b/bridge_mcp_ghidra.py @@ -234,6 +234,8 @@ def main(): help="Transport protocol for MCP, default: stdio") args = parser.parse_args() + # Use the global variable to ensure it's properly updated + global ghidra_server_url if args.ghidra_server: ghidra_server_url = args.ghidra_server From d8528220019e02fd1a29034f2fe0db86f999f8f8 Mon Sep 17 00:00:00 2001 From: LaurieWired <123765654+LaurieWired@users.noreply.github.com> Date: Sun, 20 Apr 2025 18:32:20 -0700 Subject: [PATCH 08/12] Update README.md --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index d140d648..b5b92bc0 100644 --- a/README.md +++ b/README.md @@ -48,7 +48,7 @@ https://github.com/user-attachments/assets/75f0c176-6da1-48dc-ad96-c182eb4648c3 ## MCP Clients -Theoretically, any MCP client should work with ghidraMCP. Two examples are given below. +Theoretically, any MCP client should work with ghidraMCP. Three examples are given below. ## Example 1: Claude Desktop To set up Claude Desktop as a Ghidra MCP client, go to `Claude` -> `Settings` -> `Developer` -> `Edit Config` -> `claude_desktop_config.json` and add the following: @@ -107,6 +107,7 @@ Another MCP client that supports multiple models on the backend is [5ire](https: - `Ghidra/Framework/Project/lib/Project.jar` - `Ghidra/Framework/SoftwareModeling/lib/SoftwareModeling.jar` - `Ghidra/Framework/Utility/lib/Utility.jar` +- `Ghidra/Framework/Gui/lib/Gui.jar` 2. Build with Maven by running: `mvn clean package assembly:single` From 02631d7b3464a4e07dc12a0ce4e45ec172af84b0 Mon Sep 17 00:00:00 2001 From: LaurieWired <123765654+LaurieWired@users.noreply.github.com> Date: Mon, 21 Apr 2025 21:10:22 -0700 Subject: [PATCH 09/12] Update build.yml --- .github/workflows/build.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 40deee43..c5943eba 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -20,6 +20,7 @@ jobs: Framework/Project/lib/Project.jar Framework/SoftwareModeling/lib/SoftwareModeling.jar Framework/Utility/lib/Utility.jar + Framework/Gui/lib/Gui.jar steps: - uses: actions/checkout@v4 From 3b876ddbf761a9b41c6c4c42697e8fb5a3cedcdb Mon Sep 17 00:00:00 2001 From: LaurieWired <123765654+LaurieWired@users.noreply.github.com> Date: Mon, 21 Apr 2025 21:13:52 -0700 Subject: [PATCH 10/12] Update build.yml --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index c5943eba..4bc01771 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -38,7 +38,7 @@ jobs: - name: Copy Ghidra libs run: | - mkdir ./lib + mkdir -p ./lib for libfile in ${{ env.GHIDRA_LIBS }} do echo "Copying ${libfile} to lib/" cp ghidra_${{ env.GHIDRA_VERSION }}_PUBLIC/Ghidra/${libfile} ./lib/ From 865bf483077bc146498ead809c14aede0de8c681 Mon Sep 17 00:00:00 2001 From: DaCodeChick Date: Fri, 20 Jun 2025 14:47:40 -0700 Subject: [PATCH 11/12] Fixed for Ghidra 11.3.2 --- .gitignore | 3 +++ pom.xml | 16 ++++++++-------- .../java/com/lauriewired/GhidraMCPPlugin.java | 6 +++--- src/main/resources/extension.properties | 4 ++-- 4 files changed, 16 insertions(+), 13 deletions(-) diff --git a/.gitignore b/.gitignore index 0701e633..2bdf632f 100644 --- a/.gitignore +++ b/.gitignore @@ -49,3 +49,6 @@ mvnw.cmd hs_err_pid* replay_pid* +# Third party JAR files from Ghidra +lib/*.jar + diff --git a/pom.xml b/pom.xml index aa7c31dc..6452d96e 100644 --- a/pom.xml +++ b/pom.xml @@ -15,56 +15,56 @@ ghidra Generic - 11.3.1 + 11.3.2 system ${project.basedir}/lib/Generic.jar ghidra SoftwareModeling - 11.3.1 + 11.3.2 system ${project.basedir}/lib/SoftwareModeling.jar ghidra Project - 11.3.1 + 11.3.2 system ${project.basedir}/lib/Project.jar ghidra Docking - 11.3.1 + 11.3.2 system ${project.basedir}/lib/Docking.jar ghidra Decompiler - 11.3.1 + 11.3.2 system ${project.basedir}/lib/Decompiler.jar ghidra Utility - 11.3.1 + 11.3.2 system ${project.basedir}/lib/Utility.jar ghidra Base - 11.3.1 + 11.3.2 system ${project.basedir}/lib/Base.jar ghidra Gui - 11.3.1 + 11.3.2 system ${project.basedir}/lib/Gui.jar diff --git a/src/main/java/com/lauriewired/GhidraMCPPlugin.java b/src/main/java/com/lauriewired/GhidraMCPPlugin.java index a04c910b..88583bab 100644 --- a/src/main/java/com/lauriewired/GhidraMCPPlugin.java +++ b/src/main/java/com/lauriewired/GhidraMCPPlugin.java @@ -530,7 +530,7 @@ private boolean renameFunction(String oldName, String newName) { Msg.error(this, "Error renaming function", e); } finally { - program.endTransaction(tx, successFlag.get()); + successFlag.set(program.endTransaction(tx, successFlag.get())); } }); } @@ -652,7 +652,7 @@ private String renameVariableInFunction(String functionName, String oldVarName, Msg.error(this, "Failed to rename variable", e); } finally { - program.endTransaction(tx, true); + successFlag.set(program.endTransaction(tx, true)); } }); } catch (InterruptedException | InvocationTargetException e) { @@ -875,7 +875,7 @@ private boolean setCommentAtAddress(String addressStr, String comment, int comme } catch (Exception e) { Msg.error(this, "Error setting " + transactionName.toLowerCase(), e); } finally { - program.endTransaction(tx, success.get()); + success.set(program.endTransaction(tx, success.get())); } }); } catch (InterruptedException | InvocationTargetException e) { diff --git a/src/main/resources/extension.properties b/src/main/resources/extension.properties index b0c5ea9b..3ca8018c 100644 --- a/src/main/resources/extension.properties +++ b/src/main/resources/extension.properties @@ -2,5 +2,5 @@ name=GhidraMCP description=A plugin that runs an embedded HTTP server to expose program data. author=LaurieWired createdOn=2025-03-22 -version=11.3.1 -ghidraVersion=11.3.1 \ No newline at end of file +version=11.3.2 +ghidraVersion=11.3.2 \ No newline at end of file From 7e8e50fa56577f6654e00316dc976f7d02844678 Mon Sep 17 00:00:00 2001 From: DaCodeChick Date: Fri, 20 Jun 2025 15:48:12 -0700 Subject: [PATCH 12/12] Update build.yml --- .github/workflows/build.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 4bc01771..868268ac 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -10,8 +10,8 @@ jobs: build: runs-on: ubuntu-latest env: - GHIDRA_VERSION: 11.3.1 - GHIDRA_DATE: 20250219 + GHIDRA_VERSION: 11.3.2 + GHIDRA_DATE: 20250415 GHIDRA_LIBS: >- Features/Base/lib/Base.jar Features/Decompiler/lib/Decompiler.jar