Skip to main content
Glama
CreateStruct.java4.93 kB
package com.lauriewired.handlers.act; import com.lauriewired.handlers.Handler; import com.sun.net.httpserver.HttpExchange; import ghidra.framework.plugintool.PluginTool; import ghidra.program.model.data.DataType; import ghidra.program.model.data.DataTypeConflictHandler; import ghidra.program.model.data.DataTypeManager; import ghidra.program.model.data.StructureDataType; import ghidra.program.model.listing.Program; import com.google.gson.Gson; import javax.swing.SwingUtilities; import java.io.IOException; import java.lang.reflect.InvocationTargetException; import java.util.*; import java.util.concurrent.atomic.AtomicReference; import static com.lauriewired.util.GhidraUtils.*; import static com.lauriewired.util.ParseUtils.*; import static com.lauriewired.util.StructUtils.StructMember; import ghidra.program.model.data.CategoryPath; import static ghidra.program.util.GhidraProgramUtilities.getCurrentProgram; /** * Handler for creating a new struct in Ghidra. * Expects parameters: name, size (optional), members (optional JSON array). * Members should be in the format: [{"name": "member1", "type": "int", "offset": 0, "comment": "Member 1"}, ...] */ public final class CreateStruct extends Handler { /** * Constructs a new CreateStruct handler. * * @param tool The PluginTool instance to interact with Ghidra. */ public CreateStruct(PluginTool tool) { super(tool, "/create_struct"); } /** * Handles the HTTP request to create a new struct. * Parses parameters from the POST request and creates the struct in Ghidra. * * @param exchange The HTTP exchange containing the request and response. * @throws IOException If an I/O error occurs during handling. */ public void handle(HttpExchange exchange) throws IOException { Map<String, String> params = parsePostParams(exchange); String name = params.get("name"); long size = parseIntOrDefault(params.get("size"), 0); String membersJson = params.get("members"); // Optional if (name == null || name.isEmpty()) { sendResponse(exchange, "Struct name is required"); return; } sendResponse(exchange, createStruct(name, (int) size, membersJson)); } /** * Creates a new struct in Ghidra with the specified parameters. * This method runs on the Swing thread to ensure thread safety when interacting with Ghidra's data types. * * @param name The name of the struct to create. * @param category The category path where the struct will be created (optional). * @param size The size of the struct (optional, defaults to 0). * @param membersJson JSON array of struct members (optional). * @return A message indicating success or failure of the operation. */ private String createStruct(String name, int size, String membersJson) { Program program = getCurrentProgram(tool); if (program == null) return "No program loaded"; final AtomicReference<String> result = new AtomicReference<>(); try { SwingUtilities.invokeAndWait(() -> { int txId = program.startTransaction("Create Struct"); boolean success = false; try { DataTypeManager dtm = program.getDataTypeManager(); CategoryPath path = new CategoryPath("/"); if (dtm.getDataType(path, name) != null) { result.set("Error: Struct " + name + " already exists"); return; } StructureDataType newStruct = new StructureDataType(path, name, size, dtm); StringBuilder responseBuilder = new StringBuilder( "Struct " + name + " created successfully"); if (membersJson != null && !membersJson.isEmpty()) { Gson gson = new Gson(); StructMember[] members = gson.fromJson(membersJson, StructMember[].class); int membersAdded = 0; for (StructMember member : members) { DataType memberDt = resolveDataType(tool, dtm, member.type); if (memberDt == null) { responseBuilder.append("\nError: Could not resolve data type '").append(member.type) .append("' for member '").append(member.name) .append("'. Aborting further member creation."); break; } if (member.offset != -1) { newStruct.replaceAtOffset((int) member.offset, memberDt, -1, member.name, member.comment); } else { newStruct.add(memberDt, member.name, member.comment); } membersAdded++; } responseBuilder.append("\nDefined ").append(membersAdded).append(" members."); } dtm.addDataType(newStruct, DataTypeConflictHandler.DEFAULT_HANDLER); result.set(responseBuilder.toString()); success = true; } catch (Exception e) { result.set("Error: Failed to create struct: " + e.getMessage()); } finally { program.endTransaction(txId, success); } }); } catch (InterruptedException | InvocationTargetException e) { return "Error: Failed to execute create struct on Swing thread: " + e.getMessage(); } return result.get(); } }

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/harry-cysic/GhidraMCP'

If you have feedback or need assistance with the MCP directory API, please join our Discord server