Is there a way to run ghidra from command line ?
GUI interface is very heavy.
What i want is just to get functions list and decompile them in c.
Thanks
The Ghidra decompiler was integrated into radare2, which is a command line disassembler (among other things).
You need to install the r2ghidra-dec package. You can then use the afl command to print the function list and the pdg command to show Ghidra's decompiled output for a given function.
For example:
[0x080484d0]> afl 0x080484d0 1 50 entry0 0x08048503 1 4 fcn.08048503 0x08048480 1 6 sym.imp.__libc_start_main 0x08048530 4 50 -> 41 sym.deregister_tm_clones 0x08048570 4 58 -> 54 sym.register_tm_clones 0x080485b0 3 34 -> 31 entry.fini0 0x080485e0 1 6 entry.init0 0x08048780 1 2 sym.__libc_csu_fini 0x08048520 1 4 sym.__x86.get_pc_thunk.bx 0x0804865f 1 63 sym.vuln 0x08048430 1 6 sym.imp.gets 0x08048714 1 4 loc.get_return_address 0x08048420 1 6 sym.imp.printf 0x08048784 1 20 sym._fini 0x08048720 4 93 sym.__libc_csu_init 0x08048510 1 2 sym._dl_relocate_static_pie 0x0804869e 1 118 main 0x08048490 1 6 sym.imp.setvbuf 0x08048450 1 6 sym.imp.getegid 0x080484b0 1 6 sym.imp.setresgid 0x08048460 1 6 sym.imp.puts 0x080485e6 3 121 sym.flag 0x080484a0 1 6 sym.imp.fopen 0x08048470 1 6 sym.imp.exit 0x08048440 1 6 sym.imp.fgets 0x080483e8 3 35 sym._init [0x080484d0]> pdg @ sym.vuln // WARNING: Variable defined which should be unmapped: var_4h // WARNING: [r2ghidra] Removing arg arg_4h because it doesn't fit into ProtoModel void sym.vuln(void) { undefined4 uVar1; int32_t unaff_EBX; char *s; int32_t var_4h; sym.__x86.get_pc_thunk.bx(); sym.imp.gets(&s); uVar1 = loc.get_return_address(); sym.imp.printf(unaff_EBX + 0x19c, uVar1); return; } Check my answer here.
All you have to do is to use ./analyzeHeadless script, which comes with ghidra:
./analyzeHeadless ghidra-project-directory -import binary-file -postscript yourpythonscript You can either use java or python 2.7. You can check the ghidra api here.
You can write the script (in python) in the following way:
from ghidra.app.decompiler import DecompInterface from ghidra.util.task import ConsoleTaskMonitor # get the current program # here currentProgram is predefined program = currentProgram decompinterface = DecompInterface() decompinterface.openProgram(program); functions = program.getFunctionManager().getFunctions(True) for function in list(functions): print(function) # decompile each function tokengrp = decompinterface.decompileFunction(function, 0, ConsoleTaskMonitor()) print(tokengrp.getDecompiledFunction().getC()) One way is using Ghidra's CppExporter class within a Java class that extends GhidraScript class. Ghidra's source code contains some sample codes that could be found at the following link : Decompiler samples. I took one of them and improved a bit the code.
The code below has to be copied in a file called Decompile.java Then, you have to run Ghidra's analyzeHeadless binary tool.
<ghidra_root>/support/analyzeHeadless <ghidra_project_dir> <project_name> \ -import <path_to_binary> -postscript <your_path>/Decompile.java <out_C_file_path> Command example :
./analyzeHeadless MyProjDir MyProj -import libX.so -postscript Decompile.java libX_dec.c Note : You might have to create project dir if it does not already exist.
Decompile.java example :
import java.io.File; import java.io.IOException; import java.util.ArrayList; import java.util.List; import java.util.Arrays; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import ghidra.app.plugin.core.script.Ingredient; import ghidra.app.plugin.core.script.IngredientDescription; import ghidra.app.script.GatherParamPanel; import ghidra.app.script.GhidraScript; import ghidra.app.util.Option; import ghidra.app.util.OptionException; import ghidra.app.util.exporter.CppExporter; import ghidra.app.util.exporter.ExporterException; public class Decompile extends GhidraScript implements Ingredient { private static Logger log; public Decompile() { log = LogManager.getLogger(Decompile.class); } public void export(String filename) { File outputFile = new File(filename); CppExporter cppExporter = new CppExporter(); cppExporter.setExporterServiceProvider(state.getTool()); List<Option> options = new ArrayList<Option>(); Option cppExportHeaderOption = new Option(CppExporter.CREATE_HEADER_FILE, new Boolean(false)); options.add(cppExportOption); try { cppExporter.setOptions(options); } catch (OptionException e) { log.error("Unable to set cppExporter options", e); return; } try { cppExporter.export(outputFile, currentProgram, null, monitor); } catch (IOException e) { log.error("Failed writing decompiled code as output", e); } catch (ExporterException e) { log.error("Failed to export with cppExporter", e); } } @Override public void run() throws Exception { IngredientDescription[] ingredients = getIngredientDescriptions(); for (IngredientDescription ingredient : ingredients) { state.addParameter(ingredient.getID(), ingredient.getLabel(), ingredient.getType(), ingredient.getDefaultValue()); } String[] args = getScriptArgs(); export(args[0]); } @Override public IngredientDescription[] getIngredientDescriptions() { IngredientDescription[] retVal = new IngredientDescription[] { new IngredientDescription( "COutputFile", "Output C File", GatherParamPanel.FILE, "")}; return retVal; } } I wrote this script that takes in a binary and spews out the C source to a file. Just had to slightly modify ghidra's Ghidra/Features/Decompiler/ghidra_scripts/Decompile.java script.