// Script to export decompiled C code from Ghidra // @category _Reman3 // @menupath Reman3.Decompile All import java.io.File; import java.io.PrintWriter; import java.io.StringWriter; import java.util.ArrayList; import java.util.HashSet; import java.util.Hashtable; import java.util.Iterator; import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern; import java.util.Arrays; import java.util.Dictionary; import ghidra.app.decompiler.ClangFieldToken; import ghidra.app.decompiler.ClangLine; import ghidra.app.decompiler.ClangSyntaxToken; import ghidra.app.decompiler.ClangToken; import ghidra.app.decompiler.DecompileResults; import ghidra.app.decompiler.PrettyPrinter; import ghidra.app.script.GhidraScript; import ghidra.program.model.address.Address; import ghidra.program.model.data.AbstractStringDataType; import ghidra.program.model.data.Array; import ghidra.program.model.data.ArrayDataType; import ghidra.program.model.data.BitFieldDataType; import ghidra.program.model.data.DataType; import ghidra.program.model.data.DataTypeComponent; import ghidra.program.model.data.DataTypeManager; import ghidra.program.model.data.EnumDataType; import ghidra.program.model.data.PointerDataType; import ghidra.program.model.data.ProgramBasedDataTypeManager; import ghidra.program.model.data.Structure; import ghidra.program.model.data.TypedefDataType; import ghidra.program.model.listing.Function; import ghidra.program.model.listing.VariableStorage; import ghidra.program.model.pcode.HighFunction; import ghidra.program.model.pcode.HighSymbol; import ghidra.program.model.pcode.PcodeOp; import ghidra.program.model.pcode.Varnode; import ghidra.program.model.symbol.Symbol; import ghidra.util.task.TaskMonitor; import re3lib.*; public class Decompile extends GhidraScript { // void headerGuardPre(PrintWriter writer, String tag) { // writer.println("#ifndef GH_GENERATED_" + tag + "_H"); // writer.println("#define GH_GENERATED_" + tag + "_H"); // writer.println(); // } // void headerGuardPost(PrintWriter writer, String tag) { // writer.println("#endif // GH_GENERATED_" + tag + "_H"); // } // void dumpGlobals(Hashtable globalSymbols) throws Exception { // File globalSymbolsListH = new File(RecompileConfig.INSTANCE.outputDir, "gh_global.h"); // PrintWriter hwriter = new PrintWriter(globalSymbolsListH, "UTF-8"); // hwriter.println("// AUTO-GENERATED FILE "); // headerGuardPre(hwriter, "GLOBALS"); // hwriter.println("#include "); // hwriter.println(); // File globalSymbolsListC = new File(RecompileConfig.INSTANCE.outputDir, "gh_global.cxx"); // PrintWriter cwriter = new PrintWriter(globalSymbolsListC, "UTF-8"); // cwriter.println("// AUTO-GENERATED FILE "); // cwriter.println("#include "); // hwriter.println(); // for (GlobalRec sym : globalSymbols.values()) { // HighSymbol highSym = sym.highSymbol; // DataType dt = highSym.getDataType(); // String dataType = dt.getDisplayName(); // String sanitizedName = sanitizeFunctionName(highSym.getName()); // String name = highSym.getName(); // if (!sanitizedName.equals(name)) { // println("Invalid global symbol name: " + name); // name = sanitizedName; // } // Address addr = sym.address; // // println("Symbol: " + symbol + " Addr: " + addr + " Size:" + symSize + " " + // // storage.getSerializationString()); // try { // String initBlk = " = "; // boolean fullyDefinedType = false; // if (dt instanceof AbstractStringDataType) { // AbstractStringDataType sdt = (AbstractStringDataType) dt; // dataType = "const char*"; // // String type // initBlk += "\"" + escapeCString(readCString(addr, 2048)) + "\""; // fullyDefinedType = true; // } else if (dt instanceof PointerDataType) { // PointerDataType pdt = (PointerDataType) dt; // DataType baseType = pdt.getDataType(); // dataType = baseType.getDisplayName() + "*"; // initBlk += "(" + dataType + ")&GH_MEM(0x" + addr + ")"; // fullyDefinedType = true; // } // if (fullyDefinedType) { // hwriter.println("extern " + dataType + " " + name + "; // " + addr); // cwriter.println(dataType + " " + name + initBlk + "; // " + addr); // } else { // if (dt instanceof Array) { // // println("Array: " + dt.getDisplayName() + " - " + addr + " - " + // // dt.getClass().getSimpleName()); // Array adt = (Array) dt; // DataType baseType = adt.getDataType(); // hwriter.println( // "extern " + baseType.getDisplayName() + "(&" + name + ")[" + adt.getNumElements() + "]; // " + addr); // cwriter.println( // baseType.getDisplayName() + "(&" + name + ")[" + adt.getNumElements() + "] = *reinterpret_cast<" // + baseType.getDisplayName() + "(*)[" + adt.getNumElements() + "]>(GH_MEM(0x" + addr + "));"); // } else { // String refTypeStr = dt.getDisplayName() + "&"; // hwriter.println("extern " + refTypeStr + " " + name + "; // " + addr); // cwriter.println(dataType + " " + name + "= (" + refTypeStr + ") GH_MEM(0x" + addr + ");"); // } // } // } catch (Exception e) { // println("Error processing global symbol: " + e); // println("Symbol: " + highSym.getName() + " - " + addr + " - " // + highSym.getHighFunction().getFunction().getName()); // } // } // headerGuardPost(hwriter, "GLOBALS"); // hwriter.close(); // cwriter.close(); // } void decompileAll(List functions) throws Exception { // Hashtable globalSymbols = new Hashtable<>(); // for (Function function : functions) { // decompileFunction(globalSymbols, function); // } // dumpStructureTypes(); // dumpGlobals(globalSymbols); } @Override public void run() throws Exception { if (currentProgram == null) { return; } RecompileConfig.INSTANCE = new RecompileConfig(this); if (!new File(RecompileConfig.INSTANCE.outputDir).exists()) { throw new Exception("Output directory does not exist: " + RecompileConfig.INSTANCE.outputDir); } // Make sure to create output folders RecompileConfig.INSTANCE.dirDecompFix.mkdirs(); RecompileConfig.INSTANCE.dirDecompAuto.mkdirs(); RecompileConfig.INSTANCE.dirDecompRef.mkdirs(); // buildFunctionBlacklist(); List functions = new ArrayList<>(); Iterator functionsIt = currentProgram.getFunctionManager().getFunctions(true).iterator(); while (functionsIt.hasNext()) { Function function = functionsIt.next(); // if (!shouldDecompileFunction(function)) { // continue; // } functions.add(function); } decompileAll(functions); } String sanitizeFunctionName(String name) { return name.replaceAll("[^a-zA-Z0-9_]", "_"); } }