9

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

4 Answers 4

4

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;
}
1
  • r2pm install r2ghidra
    – elig
    Dec 20, 2021 at 5:42
10

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())
2

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;
    }
}
1

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.

https://github.com/h4sh5/ghidra-headless-decompile

1
  • Please provide the core details of the solution in your answer and not only link to code that accomplishes that. It will make it far more useful as a reference in the future.
    – tmr232
    Aug 5, 2019 at 12:40

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.