当前位置: 首页 > 工具软件 > Ghidra > 使用案例 >

通过Ghidra Java API同时获取一个function的low level和high level IR

朱昊乾
2023-12-01

接上一篇博客。这也是个很基础的需求,只不过我想简单记录一下:

下面以一个简单的C函数为例,假设我们想获得这个函数的low level和high level IR:

#include <stdio.h>
#include <stdlib.h>

int a=0;
char *p1;

void main(void)
{
    int b;
    char s[]="abc";
    char *p2;
    static int c=0;
    
    p1=(char *)malloc(10);
    p2=(char *)malloc(20);

    printf("Global test!\n");   
}

那应该怎么做呢,下面直接给出代码:

import java.util.Iterator;

import ghidra.app.decompiler.DecompInterface;
import ghidra.app.decompiler.DecompileOptions;
import ghidra.app.decompiler.DecompileResults;
import ghidra.app.script.GhidraScript;
import ghidra.framework.options.ToolOptions;
import ghidra.framework.plugintool.PluginTool;
import ghidra.framework.plugintool.util.OptionsService;
import ghidra.program.model.listing.Function;
import ghidra.program.model.listing.FunctionIterator;
import ghidra.program.model.listing.Instruction;
import ghidra.program.model.listing.InstructionIterator;
import ghidra.program.model.listing.Program;
import ghidra.program.model.pcode.HighFunction;
import ghidra.program.model.pcode.PcodeOp;
import ghidra.program.model.pcode.PcodeOpAST;

public class PrintFuncIns extends GhidraScript {
	
	private DecompInterface decomplib;
	
	public void run() throws Exception {
		
		decomplib = setUpDecompiler(currentProgram);
		if (!decomplib.openProgram(currentProgram)) {
			printf("Decompiler error: %s\n", decomplib.getLastMessage());
			return;
		}
		
		FunctionIterator functionManager = this.currentProgram.getFunctionManager().getFunctions(true);
		for (Function function : functionManager) {
			if(function.getName().equals("main")) {
				System.out.println("##########################################################");
				InstructionIterator iter = currentProgram.getListing().getInstructions(function.getBody(), true);
				for(Instruction ins : iter) {
					System.out.println(ins.getMnemonicString());
					int numOperands=ins.getNumOperands();
					PcodeOp[] rawPcode = ins.getPcode();
					for (PcodeOp pcodeOp : rawPcode) {
						System.out.println(pcodeOp.toString());
					}
				}
				System.out.println("##########################################################");
				
				HighFunction hfunction = decompileFunction(function);
				Iterator<PcodeOpAST> opIter=hfunction.getPcodeOps();
				
        		while (opIter.hasNext()) {
        			PcodeOpAST pcodeOp = opIter.next();
        			System.out.println(pcodeOp.toString());
        		}
        		System.out.println("##########################################################");
			}
		}		
	}
	
	public HighFunction decompileFunction(Function f) {
		HighFunction hfunction = null;
		try {
			DecompileResults dRes = decomplib.decompileFunction(f, decomplib.getOptions().getDefaultTimeout(),
					getMonitor());
			hfunction = dRes.getHighFunction();
		} catch (Exception exc) {
			printf("EXCEPTION IN DECOMPILATION!\n");
			exc.printStackTrace();
		}
		return hfunction;
	}
    /*
	 * set up the decompiler
	 */
	private DecompInterface setUpDecompiler(Program program) {
		DecompInterface decompInterface = new DecompInterface();
		DecompileOptions options;
		options = new DecompileOptions();
		PluginTool tool = state.getTool();
		if (tool != null) {
			OptionsService service = tool.getService(OptionsService.class);
			if (service != null) {
				ToolOptions opt = service.getOptions("Decompiler");
				options.grabFromToolAndProgram(null, opt, program);
			}
		}
		decompInterface.setOptions(options);
		decompInterface.toggleCCode(true);
		decompInterface.toggleSyntaxTree(true);
		decompInterface.setSimplificationStyle("decompile");
		return decompInterface;
	}
}

其实流程是很简单的,简单来说,low level IR就是汇编指令的直接翻译,而high level IR是decompiler处理之后的结果,具体可以参考这里:

Possible to access higher-level IR in decompilation process? · Issue #978 · NationalSecurityAgency/ghidra · GitHub

得到的结果我这里也贴一下,相信大家一看就明白:

##########################################################
PUSH
(unique, 0xe780, 8) COPY (register, 0x28, 8)
(register, 0x20, 8) INT_SUB (register, 0x20, 8) , (const, 0x8, 8)
 ---  STORE (const, 0x1b1, 8) , (register, 0x20, 8) , (unique, 0xe780, 8)
MOV
(register, 0x28, 8) COPY (register, 0x20, 8)
SUB
(register, 0x200, 1) INT_LESS (register, 0x20, 8) , (const, 0x20, 8)
(register, 0x20b, 1) INT_SBORROW (register, 0x20, 8) , (const, 0x20, 8)
(register, 0x20, 8) INT_SUB (register, 0x20, 8) , (const, 0x20, 8)
(register, 0x207, 1) INT_SLESS (register, 0x20, 8) , (const, 0x0, 8)
(register, 0x206, 1) INT_EQUAL (register, 0x20, 8) , (const, 0x0, 8)
(unique, 0x12c00, 8) INT_AND (register, 0x20, 8) , (const, 0xff, 8)
(unique, 0x12c80, 1) POPCOUNT (unique, 0x12c00, 8)
(unique, 0x12d00, 1) INT_AND (unique, 0x12c80, 1) , (const, 0x1, 1)
(register, 0x202, 1) INT_EQUAL (unique, 0x12d00, 1) , (const, 0x0, 1)
MOV
(unique, 0x4f00, 8) INT_ADD (register, 0x110, 8) , (const, 0x28, 8)
(unique, 0xbd80, 8) LOAD (const, 0x1b1, 4) , (unique, 0x4f00, 8)
(register, 0x0, 8) COPY (unique, 0xbd80, 8)
MOV
(unique, 0x3100, 8) INT_ADD (register, 0x28, 8) , (const, 0xfffffffffffffff8, 8)
(unique, 0xbd80, 8) COPY (register, 0x0, 8)
 ---  STORE (const, 0x1b1, 4) , (unique, 0x3100, 8) , (unique, 0xbd80, 8)
XOR
(register, 0x200, 1) COPY (const, 0x0, 1)
(register, 0x20b, 1) COPY (const, 0x0, 1)
(register, 0x0, 4) INT_XOR (register, 0x0, 4) , (register, 0x0, 4)
(register, 0x0, 8) INT_ZEXT (register, 0x0, 4)
(register, 0x207, 1) INT_SLESS (register, 0x0, 4) , (const, 0x0, 4)
(register, 0x206, 1) INT_EQUAL (register, 0x0, 4) , (const, 0x0, 4)
(unique, 0x12c00, 4) INT_AND (register, 0x0, 4) , (const, 0xff, 4)
(unique, 0x12c80, 1) POPCOUNT (unique, 0x12c00, 4)
(unique, 0x12d00, 1) INT_AND (unique, 0x12c80, 1) , (const, 0x1, 1)
(register, 0x202, 1) INT_EQUAL (unique, 0x12d00, 1) , (const, 0x0, 1)
MOV
(unique, 0x3100, 8) INT_ADD (register, 0x28, 8) , (const, 0xfffffffffffffff4, 8)
(unique, 0xbd00, 4) COPY (const, 0x636261, 4)
 ---  STORE (const, 0x1b1, 4) , (unique, 0x3100, 8) , (unique, 0xbd00, 4)
MOV
(register, 0x38, 8) COPY (const, 0xa, 8)
CALL
(register, 0x20, 8) INT_SUB (register, 0x20, 8) , (const, 0x8, 8)
 ---  STORE (const, 0x1b1, 8) , (register, 0x20, 8) , (const, 0x1011a2, 8)
 ---  CALL (ram, 0x101050, 8)
MOV
(ram, 0x104020, 8) COPY (register, 0x0, 8)
MOV
(register, 0x38, 8) COPY (const, 0x14, 8)
CALL
(register, 0x20, 8) INT_SUB (register, 0x20, 8) , (const, 0x8, 8)
 ---  STORE (const, 0x1b1, 8) , (register, 0x20, 8) , (const, 0x1011b3, 8)
 ---  CALL (ram, 0x101050, 8)
MOV
(unique, 0x3100, 8) INT_ADD (register, 0x28, 8) , (const, 0xffffffffffffffe8, 8)
(unique, 0xbd80, 8) COPY (register, 0x0, 8)
 ---  STORE (const, 0x1b1, 4) , (unique, 0x3100, 8) , (unique, 0xbd80, 8)
LEA
(register, 0x38, 8) COPY (const, 0x102004, 8)
CALL
(register, 0x20, 8) INT_SUB (register, 0x20, 8) , (const, 0x8, 8)
 ---  STORE (const, 0x1b1, 8) , (register, 0x20, 8) , (const, 0x1011c3, 8)
 ---  CALL (ram, 0x101030, 8)
NOP
MOV
(unique, 0x3100, 8) INT_ADD (register, 0x28, 8) , (const, 0xfffffffffffffff8, 8)
(unique, 0xbd80, 8) LOAD (const, 0x1b1, 4) , (unique, 0x3100, 8)
(register, 0x0, 8) COPY (unique, 0xbd80, 8)
XOR
(unique, 0x4f00, 8) INT_ADD (register, 0x110, 8) , (const, 0x28, 8)
(register, 0x200, 1) COPY (const, 0x0, 1)
(register, 0x20b, 1) COPY (const, 0x0, 1)
(unique, 0xbd80, 8) LOAD (const, 0x1b1, 4) , (unique, 0x4f00, 8)
(register, 0x0, 8) INT_XOR (register, 0x0, 8) , (unique, 0xbd80, 8)
(register, 0x207, 1) INT_SLESS (register, 0x0, 8) , (const, 0x0, 8)
(register, 0x206, 1) INT_EQUAL (register, 0x0, 8) , (const, 0x0, 8)
(unique, 0x12c00, 8) INT_AND (register, 0x0, 8) , (const, 0xff, 8)
(unique, 0x12c80, 1) POPCOUNT (unique, 0x12c00, 8)
(unique, 0x12d00, 1) INT_AND (unique, 0x12c80, 1) , (const, 0x1, 1)
(register, 0x202, 1) INT_EQUAL (unique, 0x12d00, 1) , (const, 0x0, 1)
JZ
 ---  CBRANCH (ram, 0x1011d8, 8) , (register, 0x206, 1)
CALL
(register, 0x20, 8) INT_SUB (register, 0x20, 8) , (const, 0x8, 8)
 ---  STORE (const, 0x1b1, 8) , (register, 0x20, 8) , (const, 0x1011d8, 8)
 ---  CALL (ram, 0x101040, 8)
LEAVE
(register, 0x20, 8) COPY (register, 0x28, 8)
(register, 0x28, 8) LOAD (const, 0x1b1, 8) , (register, 0x20, 8)
(register, 0x20, 8) INT_ADD (register, 0x20, 8) , (const, 0x8, 8)
RET
(register, 0x288, 8) LOAD (const, 0x1b1, 8) , (register, 0x20, 8)
(register, 0x20, 8) INT_ADD (register, 0x20, 8) , (const, 0x8, 8)
 ---  RETURN (register, 0x288, 8)
##########################################################
(unique, 0x1000005d, 8) INT_ADD (register, 0x110, 8) , (const, 0x28, 8)
(unique, 0xbd80, 8) LOAD (const, 0x1b1, 4) , (unique, 0x4f00, 8)
(unique, 0x4f00, 8) CAST (unique, 0x1000005d, 8)
(unique, 0x10000065, 8) CALL (ram, 0x101050, 8) , (const, 0xa, 8)
(register, 0x110, 8) INDIRECT (register, 0x110, 8) , (const, 0x23, 4)
(ram, 0x104020, 8) INDIRECT (ram, 0x104020, 8) , (const, 0x23, 4)
(register, 0x0, 8) CAST (unique, 0x10000065, 8)
 ---  CALL (ram, 0x101050, 8) , (const, 0x14, 8)
(register, 0x110, 8) INDIRECT (register, 0x110, 8) , (const, 0x28, 4)
(ram, 0x104020, 8) INDIRECT (register, 0x0, 8) , (const, 0x28, 4)
 ---  CALL (ram, 0x101030, 8) , (unique, 0x10000055, 8)
(register, 0x110, 8) INDIRECT (register, 0x110, 8) , (const, 0x2f, 4)
(ram, 0x104020, 8) INDIRECT (ram, 0x104020, 8) , (const, 0x2f, 4)
(unique, 0x10000055, 8) COPY (const, 0x102004, 8)
(unique, 0x1000006d, 8) INT_ADD (register, 0x110, 8) , (const, 0x28, 8)
(unique, 0xbd80, 8) LOAD (const, 0x1b1, 4) , (unique, 0x4f00, 8)
(register, 0x206, 1) INT_NOTEQUAL (unique, 0xbd80, 8) , (unique, 0xbd80, 8)
(unique, 0x4f00, 8) CAST (unique, 0x1000006d, 8)
 ---  CBRANCH (ram, 0x1011d8, 1) , (register, 0x206, 1)
 ---  CALL (ram, 0x101040, 8)
 ---  RETURN (const, 0x1, 4)
(ram, 0x104020, 8) INDIRECT (ram, 0x104020, 8) , (const, 0x41, 4)
(ram, 0x104020, 8) COPY (ram, 0x104020, 8)
 ---  RETURN (const, 0x0, 8)
(ram, 0x104020, 8) COPY (ram, 0x104020, 8)
##########################################################

 类似资料: