3

I'm working on an automatic exploit-generation system for low level code, and I want to try it out on real world code.

I thought PCode might be a nice place to start, since it abstracts away over many of the details that for example x86 deals with.

I've installed Ghidra, and I am able to decompile binaries to C, but I am looking to get the PCode for a specific decompiled function from the binary.

There is a previous question on here that is related to this elsewhere, but the scripts that are linked no longer work with the latest version of Ghidra.

Could anyone provide some advice on how to get Ghidra to produce PCode after decompilation?

EDIT: For those interested, I've completed a script that dumps every decompiled function: https://github.com/niconaus/PCode-Dump/blob/main/PCodeDump.java

1 Answer 1

4

I assume that you want to get the PCode of an entire function at once and purely via a script. Getting the PCode for a specific line in the decompiler selected via the GUI is explained in my answer to the question you linked.

The easiest way to just dump the entire (decompiled) PCode of a function for human inspection is the Graph AST Control Flow Action hidden in the little menu at the top right of the decompiler window

enter image description here

This renders a CFG where the basic blocks consist of PCode. It nicely syncs with the GUI, i.e. clicking a node will select the corresponding lines in the decompiler and the listing, and vice versa. This will probably be extremely useful for debugging. If you click any token in the decompiler window you can also easily grab the actual corresponding PCodeAST object with currentLocation.token.pcodeOp

For getting the actual PCode objects from a plugin/script: The basic idea is that you need the HighFunction object of a function, which has the method HighFunction.getPcodeOps() that returns an iterator over the PcodeOpAST objects. The annoying part is getting the HighFunction. The following code is from the GraphAST.java GhidraScript file:

DecompileOptions options = new DecompileOptions();
DecompInterface ifc = new DecompInterface();
ifc.setOptions(options);

if (!ifc.openProgram(this.currentProgram)) {
    throw new DecompileException("Decompiler", "Unable to initialize: " + ifc.getLastMessage());
}
ifc.setSimplificationStyle("normalize");
DecompileResults res = ifc.decompileFunction(func, 30, null);
high = res.getHighFunction();
3
  • Thank you for the extensive answer. There seems to be a difference between the PCode that is shown in the AST that can be generated by clicking the CFG option, versus the AST generated by the script PCodeAST. I understand that A CFG is different from an AST, but I would expect the code to align. More specifically, I'm missing instructions in the AST that are present in the CFG. Any idea where this comes from?
    – Nico Naus
    Commented Dec 13, 2021 at 21:04
  • I have never really used the CFG, but there is an important difference in Ghidra between two kinds of PCode. There is the PCode that the instruction bytes are translated to (using sleigh) where each instruction is translated to multiple PCode Operations, e.g. setting specific flags, register, and memory values. There is also PCode that serves as the result of the decompiler, which has undergone various transformations and analysis operations. You might be running into that difference Commented Dec 14, 2021 at 11:29
  • If you are familiar with Binary Ninja, it's roughly similar to the Lifted IL vs Medium Level IL SSA Commented Dec 14, 2021 at 11:31

Your Answer

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

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