82 lines
3.7 KiB
Java
82 lines
3.7 KiB
Java
// Export every function in the current Ghidra program as one traceable C-like file.
|
|
// @category TDKPIN
|
|
|
|
import java.io.BufferedWriter;
|
|
import java.io.FileWriter;
|
|
import java.io.PrintWriter;
|
|
|
|
import ghidra.app.decompiler.DecompInterface;
|
|
import ghidra.app.decompiler.DecompileResults;
|
|
import ghidra.app.script.GhidraScript;
|
|
import ghidra.program.model.listing.Function;
|
|
import ghidra.program.model.listing.FunctionIterator;
|
|
import ghidra.program.model.mem.MemoryBlock;
|
|
|
|
public class ExportDecompilation extends GhidraScript {
|
|
@Override
|
|
public void run() throws Exception {
|
|
String[] args = getScriptArgs();
|
|
if (args.length != 2) {
|
|
throw new IllegalArgumentException("usage: ExportDecompilation.java OUTPUT_C OUTPUT_TSV");
|
|
}
|
|
|
|
DecompInterface decompiler = new DecompInterface();
|
|
decompiler.toggleCCode(true);
|
|
decompiler.toggleSyntaxTree(true);
|
|
if (!decompiler.openProgram(currentProgram)) {
|
|
throw new IllegalStateException("cannot open program in decompiler");
|
|
}
|
|
|
|
int total = 0;
|
|
int internal = 0;
|
|
int external = 0;
|
|
int succeeded = 0;
|
|
int failed = 0;
|
|
try (PrintWriter c = new PrintWriter(new BufferedWriter(new FileWriter(args[0])));
|
|
PrintWriter ledger = new PrintWriter(new BufferedWriter(new FileWriter(args[1])))) {
|
|
c.println("/*");
|
|
c.println(" * Raw Ghidra decompilation of TDKPIN.EXE.");
|
|
c.println(" * Function boundaries and names are analysis artifacts, not original source symbols.");
|
|
c.println(" */");
|
|
c.println();
|
|
ledger.println("address\tname\tkind\tstatus\tmessage");
|
|
|
|
FunctionIterator functions = currentProgram.getFunctionManager().getFunctions(true);
|
|
while (functions.hasNext() && !monitor.isCancelled()) {
|
|
Function function = functions.next();
|
|
total++;
|
|
String address = function.getEntryPoint().toString();
|
|
String name = function.getName();
|
|
MemoryBlock block = currentProgram.getMemory().getBlock(function.getEntryPoint());
|
|
boolean imported = function.isExternal() || block == null ||
|
|
!block.isInitialized() || "EXTERNAL".equals(block.getName());
|
|
if (imported) {
|
|
external++;
|
|
ledger.printf("%s\t%s\texternal\tn/a\timported function%n", address, name);
|
|
continue;
|
|
}
|
|
internal++;
|
|
DecompileResults result = decompiler.decompileFunction(function, 120, monitor);
|
|
c.printf("/* ===== %s %s ===== */%n", address, name);
|
|
if (result.decompileCompleted() && result.getDecompiledFunction() != null) {
|
|
c.println(result.getDecompiledFunction().getC());
|
|
succeeded++;
|
|
ledger.printf("%s\t%s\tinternal\tok\t%n", address, name);
|
|
} else {
|
|
String message = result.getErrorMessage();
|
|
c.printf("/* DECOMPILATION FAILED: %s */%n%n", message);
|
|
failed++;
|
|
ledger.printf("%s\t%s\tinternal\tfailed\t%s%n", address, name,
|
|
message == null ? "" : message.replace('\t', ' ').replace('\n', ' '));
|
|
}
|
|
}
|
|
c.printf("/* SUMMARY: total=%d internal=%d external=%d succeeded=%d failed=%d */%n",
|
|
total, internal, external, succeeded, failed);
|
|
println(String.format("Exported total=%d internal=%d external=%d succeeded=%d failed=%d",
|
|
total, internal, external, succeeded, failed));
|
|
} finally {
|
|
decompiler.dispose();
|
|
}
|
|
}
|
|
}
|