def decompile(func): global decompiler if decompiler is None: decompiler = DecompInterface() decompiler.openProgram(currentProgram) results = decompiler.decompileFunction(func, 10, TaskMonitor.DUMMY) return results
def renameFunctionsBasedOnstringRefrencesUsingTheDecompiler(): monitor.setMessage("Rename Functions Based on string refrences ") function = getFirstFunction() decompinterface = DecompInterface() decompinterface.openProgram(currentProgram) uniqueList = [] while function is not None and not monitor.isCancelled(): try: tokengrp = decompinterface.decompileFunction(function, 0, ConsoleTaskMonitor()) code = tokengrp.getDecompiledFunction().getC() pattern1 = r"\"[a-zA-Z0-9 .,\-\*\/\[\]\{\}\!\@\#\$\%\^\&\(\)\=\~\:\"\'\\\+\?\>\<\`\_\;]+\"" pattern2 = r'[ .,\-\*\/\[\]\{\}\!\@\#\$\%\^\&\(\)\=\~\:\"\'\\\+\?\>\<\`]+' stringList = re.findall(pattern1,code) if not stringList == []: for unique in stringList: if unique not in uniqueList: uniqueList.append(unique) name = re.sub(pattern2,"","_".join(uniqueList)) if len(name) > 15: name = name[:15] functionName = "rep_s_fun_" + str(function.getEntryPoint()) + "_" + name print functionName function.setName(functionName,USER_DEFINED) except: pass function = getFunctionAfter(function) return 0
def get_hfunction(self): decomplib = DecompInterface() decomplib.openProgram(currentProgram) timeout = self.timeout dRes = decomplib.decompileFunction(self.function, timeout, getMonitor()) hfunction = dRes.getHighFunction() return hfunction
class Decompiler: '''decompile binary into psuedo c using Ghidra API. Usage: >>> decompiler = Decompiler() >>> psuedo_c = decompiler.decompile() >>> # then write to file ''' def __init__(self, program=None, timeout=None): '''init Decompiler class. Args: program (ghidra.program.model.listing.Program): target program to decompile, default is `currentProgram`. timeout (ghidra.util.task.TaskMonitor): timeout for DecompInterface::decompileFunction ''' # initialize decompiler with current program self._decompiler = DecompInterface() self._decompiler.openProgram(program or ghidra_app.currentProgram) self._timeout = timeout def decompile_func(self, func): '''decompile one function. Args: func (ghidra.program.model.listing.Function): function to be decompiled Returns: string: decompiled psuedo C code ''' # decompile dec_status = self._decompiler.decompileFunction(func, 0, self._timeout) # check if it's successfully decompiled if dec_status and dec_status.decompileCompleted(): # get psuedo c code dec_ret = dec_status.getDecompiledFunction() if dec_ret: return dec_ret.getC() def decompile(self): '''decompile all function recognized by Ghidra. Returns: string: decompiled all function as psuedo C ''' # all decompiled result will be joined psuedo_c = '' # enum all functions and decompile each function funcs = ghidra_app.currentProgram.getListing().getFunctions(True) for func in funcs: dec_func = self.decompile_func(func) if dec_func: psuedo_c += dec_func return psuedo_c
def get_high_function(current_program, current_address): decomplib = DecompInterface() decomplib.openProgram(current_program) current_function = getFunctionContaining(current_address) decompile_res = decomplib.decompileFunction(current_function, 30, getMonitor()) high_function = decompile_res.getHighFunction() return high_function
def decompile_func(func): decompiler = DecompInterface() decompiler.openProgram(currentProgram) results = decompiler.decompileFunction(func, 0, monitor) if not results.decompileCompleted(): raise RuntimeError('failed to decompile function: {}'.format(func)) high_func = results.getHighFunction() return high_func
def colorize_blocks(self): global FINAL_MATCH_DICT global TABLE_DIALOG decompInterface = DecompInterface() decompInterface.openProgram(currentProgram) cov_block_list = [] for bb in self.basic_blocks.keys(): start_addr = toAddr(bb + self.program_base) block_size = self.basic_blocks[bb] - 1 function = getFunctionContaining(start_addr) self.set_basic_block_colors(start_addr, block_size) if function and not function in cov_block_list: cov_block_list.append(function) for function in cov_block_list: hfunction = decompInterface.decompileFunction( function, 30, TaskMonitor.DUMMY).getHighFunction() basic_blocks = hfunction.getBasicBlocks() basic_block_len = len(basic_blocks) total_block_size = 0 function_size = 0 total_cov_size = 0 for block in basic_blocks: block_size = int(block.getStop().toString(), 16) - int( block.getStart().toString(), 16) function_size += block_size bg_color = service.getBackgroundColor(block.getStart()) if bg_color and bg_color.getRGB() == -16711764: total_block_size += 1 total_cov_size += block_size block_hit = str(total_block_size) + "/" + str(basic_block_len) if total_cov_size > 0: total_cov_size = str( int(100 * float(total_cov_size) / float(function_size))) + "%" elif total_block_size == basic_block_len: total_cov_size = "100%" else: total_cov_size = "0%" FINAL_MATCH_DICT[function.getName()] = [ function.getName(), total_cov_size, block_hit, function.getEntryPoint() ] for key in FINAL_MATCH_DICT.keys(): init_obj = Initializer() init_obj.head = key init_obj.function_address = FINAL_MATCH_DICT[key][3] FINAL_MATCH_DICT[key].append(init_obj) TABLE_DIALOG.add(init_obj)
def initEmulator(self, program, address, clear_param_map=True): ''' Setup the emulator helper, symbol maps and fn related stuff ''' self.program = program self.function = self.program.getFunctionManager().getFunctionContaining(address) if self.function is None: function_name = self.plugin.askString("You are not in a function, please enter an address or a function name", "address or symbol name") for f in self.plugin.state.currentProgram.getFunctionManager().getFunctions(True): if function == f.getName(): self.plugin.state.setCurrentAddress(function.getEntryPoint()) self.doStart() return for f in self.plugin.state.currentProgram.getFunctionManager().getFunctions(True): if int(function, 16) == f.getEntryPoint().getOffset(): self.plugin.state.setCurrentAddress(function.getEntryPoint()) self.doStart() return self.entrypoint = self.program.getListing().getInstructionAt(self.function.getEntryPoint()) self.logger.info("Program: %s" % self.program) self.logger.info("Function: %s" % self.function) self.decompinterface = DecompInterface() self.decompinterface.openProgram(program) result = self.decompinterface.decompileFunction(self.function, 0, self.monitor) self.highFunction = result.getHighFunction() # self.logger.info(result) # self.logger.info(self.highFunction) self.decompiled = str(result.getCCodeMarkup()) # self.logger.info("Decompiled: %s" % self.decompiled) self.symbolMap = self.highFunction.getLocalSymbolMap() # self.logger.info(self.symbolMap) if clear_param_map: self.parameterMap = {} # fuzz = 0 self.emulatorHelper = EmulatorHelper(self.program) self.stackPointer = (((1 << (self.emulatorHelper.getStackPointerRegister().getBitLength() - 1)) - 1) ^ ((1 << (self.emulatorHelper.getStackPointerRegister().getBitLength()//2))-1)) self.returnAddressSize = program.getLanguage().getProgramCounter().getBitLength() NULL_PTR_RET = 0 self.emulatorHelper.writeRegister(self.emulatorHelper.getStackPointerRegister(), self.stackPointer) self.emulatorHelper.setBreakpoint(self.getStackAddress(NULL_PTR_RET)) self.emulatorHelper.enableMemoryWriteTracking(True) self.emulator_state = EmulatorState.WAITING_FOR_PARAM if not clear_param_map: self.emulator_state = EmulatorState.READY self.history = [] self.lastAddresses = [] # self.emulatorHelper.getEmulator().executeInstruction = executeInstruction self.hookExternalFunctions()
def get_decompilation(calle_addr, func_name): program = getCurrentProgram() ifc = DecompInterface() ifc.openProgram(program) # here we assume there is only one function named `main` function = getGlobalFunctions(func_name)[0] # decompile the function and print the pseudo C results = ifc.decompileFunction(function, 0, ConsoleTaskMonitor()) print(results.getDecompiledFunction().getC()) return results.getDecompiledFunction().getC()
def _decompile(): decompiler = DecompInterface() decompiler.openProgram(currentProgram) de_c = "" funcs = currentProgram.getListing().getFunctions(True) for func in funcs: decompiled_func = _decompile_func(decompiler, func) if decompiled_func: de_c += decompiled_func return de_c
def __init__(self, program=None, timeout=None): '''init Decompiler class. Args: program (ghidra.program.model.listing.Program): target program to decompile, default is `currentProgram`. timeout (ghidra.util.task.TaskMonitor): timeout for DecompInterface::decompileFunction ''' # initialize decompiler with current program self._decompiler = DecompInterface() self._decompiler.openProgram(program or ghidra_app.currentProgram) self._timeout = timeout
def get_decompile_interface(): # type: () -> DecompInterface interface = DecompInterface() options = DecompileOptions() interface.setOptions(options) interface.openProgram(currentProgram) interface.setSimplificationStyle("decompile") return interface
def get_decompiler(state, program): tool = state.getTool() options = DecompileOptions() decomp = DecompInterface() if tool is not None: service = tool.getService(OptionsService) if service is not None: opt = service.getOptions("Decompiler") options.grabFromToolAndProgram(None, opt, program) decomp.setOptions(options) decomp.toggleCCode(True) decomp.toggleSyntaxTree(True) decomp.setSimplificationStyle("decompile") return decomp
def stub(address): functionOffset = function.getEntryPoint().getOffset() while functionOffset not in function_arguments_cache and not monitor.isCancelled(): # program = currentProgram # function = currentProgram.getFunctionManager().getFunctionContaining(currentAddress) decompinterface = DecompInterface() decompinterface.openProgram(program) result = decompinterface.decompileFunction(function, 0, monitor) highFunction = result.getHighFunction() if not result.isCancelled() and not result.isTimedOut(): function_arguments_cache[functionOffset] = highFunction assert(functionOffset in function_arguments_cache) highFunction = function_arguments_cache[functionOffset] symbolMap = highFunction.getLocalSymbolMap() args = [] for parameter in [symbolMap.getParam(i) for i in range(symbolMap.getNumParams())]: emulator.logger.debug("Found parameter `%s` with size `%d` with type `%s`" % (parameter.getName(), parameter.getSize(), str(parameter.getDataType()))) param = getParam(parameter, emulator, monitor) args.append(param) emulator.logger.debug(str(args)) retval = func(*args) emulator.logger.debug('Finish execution of hook %s with return value %s' % (func.__name__, repr(retval))) pointerSize = emulator.program.getLanguage().getProgramCounter().getBitLength()//8 if type(retval) == int or type(retval) == long: retval = long_to_bytes(retval, pointerSize) if not emulator.program.getLanguage().isBigEndian(): retval = retval[::-1] offset = 0 for varnode in function.getReturn().getVariableStorage().getVarnodes(): emulator.emulatorHelper.writeMemory(varnode.getAddress(), retval[offset:offset+varnode.getSize()]) offset += varnode.getSize() emulator.logger.debug('Finish execution of hook %s we were at %s before' % (func.__name__, str(emulator.lastAddresses))) current = emulator.emulatorHelper.getExecutionAddress() for address in emulator.lastAddresses: emulator.logger.debug('Checking if %s is different from %s' % (address, current)) if str(address) != str(current): nextAddress = emulator.flatapi.getInstructionAfter(address).getAddress() emulator.logger.debug('I propose to go to %s now' % (str(nextAddress))) emulator.emulatorHelper.getEmulator().setExecuteAddress(nextAddress.getOffset()) emulator.logger.debug('Can you believe that we are at %s now?' % (str(emulator.emulatorHelper.getExecutionAddress()))) break return True
def get_high_function(func): options = DecompileOptions() monitor = ConsoleTaskMonitor() ifc = DecompInterface() ifc.setOptions(options) ifc.openProgram(getCurrentProgram()) res = ifc.decompileFunction(func, 60, monitor) return res.getHighFunction()
#@author Magnus "Nopey" Larsen #@category #@keybinding #@menupath Tools.Misc.Populate empty structs #@toolbar import re #gex from ghidra.util.task import ConsoleTaskMonitor from ghidra.app.decompiler import DecompileOptions, DecompInterface from ghidra.program.model.data import PointerDataType, Pointer from ghidra.program.database.data import StructureDB program = getCurrentProgram() dataManager = program.getDataTypeManager() # We use the decompiler to find accesses to fields. ifc = DecompInterface() ifc.openProgram(program) fm = program.getFunctionManager() # all_datatypes is just a way of skipping the paths from the DataTypeManager all_datatypes = dict() for d in dataManager.getAllDataTypes(): all_datatypes[d.getName()] = d all_datatypes["code"] = all_datatypes["void"] def getAddress(offset): return program.getAddressFactory().getDefaultAddressSpace().getAddress( offset)
import re import os # to decompile from ghidra.app.decompiler import DecompileOptions from ghidra.app.decompiler import DecompInterface # to rename function from ghidra.program.model.symbol import SourceType # to trace basic blocks from ghidra.program.model.block import BasicBlockModel from ghidra.program.model.pcode import HighFunctionDBUtil # logic to find and rename the main function ifc = DecompInterface() ifc.setOptions(DecompileOptions()) ifc.openProgram(currentProgram) try: entryfunction = getGlobalFunctions("entry")[0] except: # if binary has symbols if getGlobalFunctions("_start"): entryfunction = getGlobalFunctions("_start")[0] else: exit() res = ifc.decompileFunction(entryfunction, 60, monitor) m = re.search("__libc_start_main\((.+?),", res.getCCodeMarkup().toString()) if m.group(1)[0] != "main": getGlobalFunctions(m.group(1))[0].setName("main", SourceType.ANALYSIS) # for static blocks blockiterator = BasicBlockModel(currentProgram).getCodeBlocks(monitor) fun_blocks = {}
def fixUndefinedDataTypes(): monitor.setMessage("Fixing Undefined Data Types") function = getFirstFunction() decompinterface = DecompInterface() decompinterface.openProgram(currentProgram) # get var list from decompilation while function is not None: prt = False varList = [] try: tokengrp = decompinterface.decompileFunction(function, 0, ConsoleTaskMonitor()) code = tokengrp.getDecompiledFunction().getC() for line in code.split("\n"): if line == " \r": break if prt: varList.append(filter(None,line.split(";")[0].split(" "))) if line.startswith("{"): prt = True except: pass for var in function.getAllVariables(): varMsg = str(var) dt = str(var.getDataType()) inx = 0 if "undefined" in dt: for decVar in varList: if len(decVar) > 1: arr = False if len(decVar) == 3: arr = True inx = int(decVar[2].split("[")[1].split("]")[0]) if decVar[1].replace("*","") == var.getName(): if not "undefined" in decVar[0]: if '*' in decVar[1]: dt = getDataType("/" + decVar[0] + " " + ('*' * decVar[1].count("*")),arr,inx) else: dt = getDataType("/" + decVar[0],arr,inx) else: if '*' in decVar[1]: dtlen = decVar[0].replace("undefined","") if dtlen == "": dtlen = "1" dt = getDataTypeWrap(dtlen + ('*' * decVar[1].count("*")),arr,inx) else: dt = getDataTypeWrap(decVar[0],arr,inx) if type(dt) == str: dt = str(var.getDataType()) dt = dt.replace("undefined","") dt = getDataTypeWrap(dt) if dt: try: var.setDataType(dt,USER_DEFINED) print "[+] " + str(function.getName()) + ": " + varMsg + " -> " + str(dt) except: pass function = getFunctionAfter(function) return 0
from ghidra.program.model.pcode import PcodeOp from ghidra.program.model.symbol import SourceType from ghidra.program.model.listing.Function import FunctionUpdateType from ghidra.app.util.cparser.C import CParserUtils from ghidra.program.model.listing import ReturnParameterImpl from ghidra.program.model.listing import ParameterImpl TL_APIS = {} MAX_TL_API = 0xC2 DR_APIS = {} MAX_DR_API = 0x3D blockModel = BasicBlockModel(currentProgram) functionManager = currentProgram.getFunctionManager() decompInterface = DecompInterface() decompInterface.openProgram(currentProgram) def load_api_names_types(): curdir = os.path.dirname(os.path.abspath(inspect.getsourcefile(lambda: 0))) with open(os.path.join(curdir, 'tl_apis.json'), 'r') as f: TL_APIS.update({i: (n, t) for i, n, t in json.loads(f.read())}) print("[*] Loaded %s trustlets APIs names" % len(TL_APIS)) global DR_APIS with open(os.path.join(curdir, 'dr_apis.json'), 'r') as f: DR_APIS.update({i: (n, t) for i, n, t in json.loads(f.read())}) print("[*] Loaded %s drivers APIs names" % len(DR_APIS))
def prepare(self): Decompiler = DecompInterface() Decompiler.openProgram(currentProgram) Decompiled_Func = Decompiler.decompileFunction(self.function, 30, getMonitor()) self.highfunction = Decompiled_Func.getHighFunction()
u'TParamT'): newTypeName = sym.parentNamespace.getName(True) newTypeName = newTypeName[:newTypeName.find( '<')].replace( u'::', u'/') + newTypeName[newTypeName.find('<'):] newType = currentProgram.getDataTypeManager( ).getDataType("boot.dol/Demangler/" + newTypeName) print offset, newTypeName, newType thisType.replaceAtOffset(offset.value, newType, 0, None, None) inst = inst.next options = DecompileOptions() monitor = ConsoleTaskMonitor() ifc = DecompInterface() ifc.setOptions(options) ifc.openProgram(currentFunction.program) res = ifc.decompileFunction(currentFunction, 60, monitor) high_func = res.getHighFunction() inst = getInstructionAt(currentAddress) while inst.address < currentFunction.body.maxAddress: callConstructor = None if inst.getFlowType().isCall() and \ inst.getFlows()[0] == baseParamConstructor.entryPoint: callConstructor = inst print "Constructor is called at", callConstructor.address fieldOffset = None if callConstructor is not None:
def open_program(): iface = DecompInterface() iface.openProgram(currentProgram) return iface
instr_name = askString( "Instruction Name", "Enter the name of the first instruction you are looking for after resolving those bytes: ", "push").lower() # quit if we did not get even number of hex values is_hex = all(c in string.hexdigits for c in instr_bytes) is_even = len(instr_bytes) % 2 == 0 if not is_hex or not is_even: print "Error: Please only enter hex values." exit() instr_bytes = "".join( ["\\x" + instr_bytes[i:i + 2] for i in range(0, len(instr_bytes), 2)]) decompInterface = DecompInterface() decompInterface.openProgram(currentProgram) # ghidra options newOptions = DecompileOptions() # Current decompiler options newOptions.setMaxPayloadMBytes(max_payload_mbytes) decompInterface.setOptions(newOptions) listing = currentProgram.getListing() fpapi = FlatProgramAPI(currentProgram) address_factory = fpapi.getAddressFactory() psedu_disassembler = PseudoDisassembler(currentProgram) # search for the specified bytes minAddress = currentProgram.getMinAddress() instr_addresses = fpapi.findBytes(minAddress, instr_bytes, matchLimit)
class Emulator(object): def __init__(self, plugin, state=None, logger_fname="ghidra_emulator.txt"): self.plugin = plugin self.monitor = self.plugin.getMonitor() if state is None: state = self.plugin.getGhidraState() program = state.getCurrentProgram() address = state.getCurrentAddress() self.byte_substitution = {} self.initLogger(logger_fname) self.initEmulator(program, address) self.initCmdHandlers() self.emulator_state = EmulatorState.WAITING_FOR_PARAM self.flatapi = FlatProgramAPI(program) def initLogger(self, fname): self.logger_fname = fname self.logger = logging.getLogger(str(random.random()).replace(".","_")) self.logger.setLevel(logging.INFO) h_stdout = logging.StreamHandler(sys.stdout) h_stdout.setLevel(logging.INFO) self.logger.addHandler(h_stdout) if self.logger_fname: h_file = logging.FileHandler(self.logger_fname) h_file.setLevel(logging.INFO) self.logger.addHandler(h_file) def initEmulator(self, program, address, clear_param_map=True): ''' Setup the emulator helper, symbol maps and fn related stuff ''' self.program = program self.function = self.program.getFunctionManager().getFunctionContaining(address) if self.function is None: function_name = self.plugin.askString("You are not in a function, please enter an address or a function name", "address or symbol name") for f in self.plugin.state.currentProgram.getFunctionManager().getFunctions(True): if function == f.getName(): self.plugin.state.setCurrentAddress(function.getEntryPoint()) self.doStart() return for f in self.plugin.state.currentProgram.getFunctionManager().getFunctions(True): if int(function, 16) == f.getEntryPoint().getOffset(): self.plugin.state.setCurrentAddress(function.getEntryPoint()) self.doStart() return self.entrypoint = self.program.getListing().getInstructionAt(self.function.getEntryPoint()) self.logger.info("Program: %s" % self.program) self.logger.info("Function: %s" % self.function) self.decompinterface = DecompInterface() self.decompinterface.openProgram(program) result = self.decompinterface.decompileFunction(self.function, 0, self.monitor) self.highFunction = result.getHighFunction() # self.logger.info(result) # self.logger.info(self.highFunction) self.decompiled = str(result.getCCodeMarkup()) # self.logger.info("Decompiled: %s" % self.decompiled) self.symbolMap = self.highFunction.getLocalSymbolMap() # self.logger.info(self.symbolMap) if clear_param_map: self.parameterMap = {} # fuzz = 0 self.emulatorHelper = EmulatorHelper(self.program) self.stackPointer = (((1 << (self.emulatorHelper.getStackPointerRegister().getBitLength() - 1)) - 1) ^ ((1 << (self.emulatorHelper.getStackPointerRegister().getBitLength()//2))-1)) self.returnAddressSize = program.getLanguage().getProgramCounter().getBitLength() NULL_PTR_RET = 0 self.emulatorHelper.writeRegister(self.emulatorHelper.getStackPointerRegister(), self.stackPointer) self.emulatorHelper.setBreakpoint(self.getStackAddress(NULL_PTR_RET)) self.emulatorHelper.enableMemoryWriteTracking(True) self.emulator_state = EmulatorState.WAITING_FOR_PARAM if not clear_param_map: self.emulator_state = EmulatorState.READY self.history = [] self.lastAddresses = [] # self.emulatorHelper.getEmulator().executeInstruction = executeInstruction self.hookExternalFunctions() # def nopCallBack(BreakCallBack): # def __init__(self): # # BreakCallBack.__init__(self) # pass # def pcodeCallback(self, op): # return True # help(nopCallBack) # emulatorHelper.registerCallOtherCallback('HintPreloadData', nopCallBack(BreakCallBack())) def hookExternalFunctions(self): for externalFunction in list(self.program.getFunctionManager().getExternalFunctions()): self.logger.debug('Found external function `%s`' % (externalFunction.getName())) for library in lib.exports: self.logger.debug('Found library `%s`' % (library.name)) for function in library.exports: self.logger.debug('Found function `%s`' % (function.__name__)) if externalFunction.getName() == function.__name__: for address in externalFunction.getFunctionThunkAddresses(): self.logger.info('Hooked function `%s`@%s with implementation lib/%s/%s' % (externalFunction.getName(), str(address), library.name, function.__name__)) callback = DucktapeBreakCallback(function(self.program, self, self.program.getFunctionManager().getFunctionAt(address), self.monitor), lambda x: True) # callback.addressCallback = function(self.program, self, self.program.getFunctionManager().getFunctionAt(address), self.monitor) self.emulatorHelper.emulator.getBreakTable().registerAddressCallback(address, callback) # self.emulatorHelper.setBreakpoint(address) # break for thunkFunction in list(filter(lambda x: x.isThunk(), self.program.getFunctionManager().getFunctions(True))): for library in lib.exports: self.logger.debug('Found library `%s`' % (library.name)) for function in library.exports: self.logger.debug('Found function `%s`' % (function.__name__)) if thunkFunction.getName() == function.__name__: address = thunkFunction.getEntryPoint() self.logger.info('Hooked function `%s` at %s with implementation lib/%s/%s' % (thunkFunction.getName(), str(address), library.name, function.__name__)) callback = DucktapeBreakCallback(function(self.program, self, self.program.getFunctionManager().getFunctionAt(address), self.monitor), lambda x: True) # callback.addressCallback = function(self.program, self, self.program.getFunctionManager().getFunctionAt(address), self.monitor) self.emulatorHelper.emulator.getBreakTable().registerAddressCallback(address, callback) def initFunctionParameters(self, bytesValueBuffer=""): ''' Setup fn input parameters ''' self.input_wildcards = [] self.fnParametersAllBytesValue = "" for parameter in [self.symbolMap.getParam(i) for i in range(self.symbolMap.getNumParams())]: psize = self.parameterStorageSize(parameter) if len(bytesValueBuffer) < psize*2: bytesValueBuffer = self.plugin.askString('Setting Parameters for `{}` (size: {})'.format(parameter.name, psize), 'byte values') bytesValue = bytesValueBuffer[:psize*2] bytesValue = (bytesValue + "00"*psize)[:psize*2] assert(len(bytesValue) == psize*2) for i in range(0,len(bytesValue), 2): if bytesValue[i] in string.hexdigits and bytesValue[i+1] in string.hexdigits: continue self.input_wildcards.append(bytesValue[i:i+2]) self.parameterMap[parameter.name] = bytesValue self.fnParametersAllBytesValue += bytesValue bytesValueBuffer = bytesValueBuffer[psize*2:] # self.logger.info(self.parameterMap) if self.input_wildcards: self.logger.info("Found %d wildcards: %s" % (len(self.input_wildcards), self.input_wildcards)) self.logger.info("The next batch of cmds will be executed in fuzzing mode") for w in self.input_wildcards: self.byte_substitution[w] = "00" self.emulator_state = EmulatorState.READY # @staticmethod def parameterStorageSize(self, parameter): return sum(map(lambda x: x.getSize(), parameter.getStorage().getVarnodes())) def getAddress(self, offset): return self.program.getAddressFactory().getDefaultAddressSpace().getAddress(offset) def getStackAddress(self, offset): address = self.getAddress(self.emulatorHelper.readRegister(self.emulatorHelper.getStackPointerRegister()) + offset) orAddress = self.getAddress(self.stackPointer + offset) self.logger.debug('Stack address at {} or {}'.format(address, orAddress)) return orAddress def writeStackValue(offset, size, value): bytesValue = long_to_bytes(value, size) if not self.emulatorHelper.getLanguage().isBigEndian(): bytesValue = bytesValue[::-1] self.emulatorHelper.writeMemory(self.getStackAddress(offset), bytesValue) def applyByteSubstitution(self, bytesValue): for k,v in self.byte_substitution.items(): bytesValue = bytesValue.replace(k, v) return bytesValue.decode('hex') def start(self, byte_substitution=None): ''' Write the fn inputs in memory (eventually applying the byte substitution) and start the emulation, breaking at fn entry point''' assert(self.emulator_state == EmulatorState.READY) if byte_substitution is not None: self.byte_substitution = byte_substitution self.logger.info('Started with byte_sub: %r' % self.byte_substitution) for parameter in [self.symbolMap.getParam(i) for i in range(self.symbolMap.getNumParams())]: bytesValue = self.parameterMap[parameter.name] bytesValue = self.applyByteSubstitution(bytesValue) storage = parameter.getStorage() offset = 0 for varnode in storage.getVarnodes(): chunk = bytesValue[offset:offset+varnode.getSize()] if varnode.getAddress().isStackAddress(): self.emulatorHelper.writeMemory(self.getStackAddress(varnode.getAddress().getOffset()), chunk) else: self.emulatorHelper.writeMemory(varnode.getAddress(), chunk) offset += varnode.getSize() self.emulatorHelper.setBreakpoint(self.function.getEntryPoint()) self.emulatorHelper.run(self.function.getEntryPoint(), self.entrypoint, self.monitor) self.emulator_state = EmulatorState.EXECUTING def executeCmds(self, cmds): assert(self.emulator_state == EmulatorState.EXECUTING) cmds = cmds.strip().split(', ') for cmd_id, cmd in enumerate(cmds): cmd = cmd.strip().split() if cmd[0] not in self.cmd_handlers: self.logger.error("Unknown command %s (%r)" % (cmd[0], cmd)) self.cmdHelp(cmd) break res = self.cmd_handlers[cmd[0]](cmd) if res: self.last_result = res self.updateUI() # self.printState() self.logger.info('Stopping execution for {} at {:x} with error {}'.format(self.emulatorHelper.getEmulateExecutionState(), self.emulatorHelper.readRegister(self.emulatorHelper.getPCRegister()), self.emulatorHelper.getLastError())) def printState(self): for symbol in self.program.getSymbolTable().getAllSymbols(True): symbolObject = symbol.getObject() try: dataType = symbolObject.getDataType() name = symbol.getName() if name in self.decompiled and symbol.getAddress(): self.logger.debug('Found symbol name={} type={} location={}'.format(name, dataType, symbol.getAddress())) bytesValue = self.emulatorHelper.readMemory(symbol.getAddress(), dataType.getLength()) stringValue = bytesValue.tostring() printValue = repr(stringValue) if isPrintable(stringValue) else stringValue.encode('hex') self.logger.info('Variable {} has value `{}`'.format(name, printValue)) except AttributeError as e: self.logger.debug(str(e)) except Exception as e: self.logger.error(str(e)) writeSet = self.emulatorHelper.getTrackedMemoryWriteSet() for parameter in self.highFunction.getLocalSymbolMap().getSymbols(): if parameter.name not in self.decompiled: continue storage = parameter.getStorage() bytesValue = bytearray(0) for varnode in storage.getVarnodes(): if varnode.getAddress().isStackAddress(): bytesValue.extend(self.emulatorHelper.readMemory(self.getStackAddress(varnode.getAddress().getOffset()), varnode.getSize())) elif writeSet.contains(varnode.getAddress()): bytesValue.extend(self.emulatorHelper.readMemory(varnode.getAddress(), varnode.getSize())) stringValue = str(bytesValue) printValue = repr(stringValue) if isPrintable(stringValue) else stringValue.encode('hex') self.logger.info('Variable `{}` @ `{}` has value `{}`'.format(parameter.name, storage, printValue)) for register in self.emulatorHelper.getLanguage().getRegisters(): if register.isBaseRegister() and not register.isProcessorContext(): self.logger.debug(str(register)) self.logger.debug(str(self.emulatorHelper.readRegister(register))) self.logger.debug(str(self.emulatorHelper)) self.logger.debug(str(self.emulatorHelper.getLanguage())) self.logger.debug(str(self.emulatorHelper.getLanguage().getRegisters())) self.logger.info(str(['{} = {}'.format(register, self.emulatorHelper.readRegister(register)) for register in self.emulatorHelper.getLanguage().getRegisters() if register.isBaseRegister() and not register.isProcessorContext()])) self.logger.info('Stopping execution at {:x}'.format(self.emulatorHelper.readRegister(self.emulatorHelper.getPCRegister()))) self.logger.debug('Logged writes at {}'.format(self.emulatorHelper.getTrackedMemoryWriteSet())) def readMemory(self, from_, size): bytesValue = bytearray(0) bytesValue.extend(self.emulatorHelper.readMemory(self.getAddress(from_), size)) stringValue = str(bytesValue) self.logger.info('Reading from {} (size: {}): {}\n\thex={}'.format(from_, size, repr(stringValue), stringValue.encode("hex"))) return stringValue def readPointer(self, address): self.logger.debug('reading %d from address %s' % (self.program.getLanguage().getProgramCounter().getBitLength()//8, str(address))) packed = bytearray(0) packed.extend(self.emulatorHelper.readMemory(address, self.program.getLanguage().getProgramCounter().getBitLength()//8)) self.logger.debug('reading `%s` from address' % repr(str(packed))) if not self.program.getLanguage().isBigEndian(): packed = str(packed[::-1]) self.logger.debug('got pointer at `%s`' % repr(str(packed))) return int(packed.encode('hex'), 16) def writeMemory(self, from_, bytesValue): bytesValue = applyByteSubstitution(bytesValue) self.emulatorHelper.writeMemory(self.getAddress(from_), bytesValue) def updateUI(self): self.plugin.syncView(self.emulatorHelper.getExecutionAddress()) def initCmdHandlers(self): self.cmd_handlers = { 's': self.cmdStep, 'c': self.cmdContinue, 'n': self.cmdNext, 'b': self.cmdBreakpointAdd, 'd': self.cmdBreakpointRemove, 'x': self.cmdSleep, 'q': self.cmdQuit, 'r': self.cmdReadMem, 'w': self.cmdWriteMem, 'p': self.cmdPrintState, 'h': self.cmdHelp, 'l': self.cmdLogHistory, 'e': self.cmdEval, 'hook': self.cmdHook, 'list-hooks': self.cmdListHook, } @history def cmdHook(self, cmd): '''hook address module.function - replace a function with a python implementation e.g. hook 0x40000 libc6.puts ''' address = self.getAddress(int(cmd[1], 16)) library_name, function_name = cmd[2].split('.') thunkedFunction = self.program.getFunctionManager().getFunctionContaining(address) for library in lib.exports: if library_name == library_name: self.logger.debug('Found library `%s`' % (library.name)) for function in library.exports: self.logger.debug('Found function `%s`' % (function.__name__)) if function_name == function.__name__: self.logger.info('Hooked function `%s` at %s with implementation lib/%s/%s' % (thunkedFunction.getName(), str(address), library.name, function.__name__)) callback = DucktapeBreakCallback(function(self.program, self, thunkedFunction, self.monitor), lambda x: True) # callback.addressCallback = function(self.program, self, self.program.getFunctionManager().getFunctionAt(address), self.monitor) self.emulatorHelper.emulator.getBreakTable().registerAddressCallback(address, callback) break @history def cmdListHook(self, cmd): '''List available hooks ''' for library in lib.exports: self.logger.debug('Found library `%s`' % (library.name)) for function in library.exports: self.logger.debug('Found function `%s`' % (function.__name__)) self.logger.info('%s.%s - %s' % (library.name, function.__name__, function.__doc__)) @history def cmdStep(self, cmd): '''step''' self.emulatorHelper.step(self.monitor) def run(self, monitor): self.emulatorHelper.emulator.setHalt(False) while not self.emulatorHelper.emulator.getHalt(): self.emulatorHelper.step(monitor) currentAddress = self.emulatorHelper.getExecutionAddress() if len(self.lastAddresses) == 0 or self.lastAddresses[0] != currentAddress: self.lastAddresses = [currentAddress] + self.lastAddresses[:1] @history def cmdContinue(self, cmd): '''continue''' self.run(self.monitor) @history def cmdNext(self, cmd): '''step over/next''' address = self.flatapi.getInstructionAfter(self.emulatorHelper.getExecutionAddress()).getAddress() self.emulatorHelper.setBreakpoint(address) self.run(self.monitor) self.emulatorHelper.clearBreakpoint(address) @history def cmdBreakpointAdd(self, cmd): '''add breakpoint (`hex_address`)''' address = self.getAddress(int(cmd[1], 16)) self.emulatorHelper.setBreakpoint(address) @history def cmdBreakpointRemove(self, cmd): '''remove breakpoint (`hex_address`)''' address = self.getAddress(int(cmd[1], 16)) self.emulatorHelper.clearBreakpoint(address) @history def cmdSleep(self, cmd): '''sleep (`time(=5)`)''' for i in range(10000): self.monitor.isCancelled() # time.sleep(5 if len(cmd) == 1 else int(cmd[1])) @history def cmdQuit(self, cmd): '''quit''' self.printState() self.updateUI() self.emulator_state = EmulatorState.DONE @history def cmdReadMem(self, cmd): '''read memory addr (either `hex_from:hex_to` or `hex_from size`)''' if len(cmd) == 3: from_ = cmd[1] size = int(cmd[2], 16 if "0x" in cmd[2].lower() else 10) else: from_, to_ = map(lambda x: int(x,16), cmd[1].split(":")) size = to_-from_ from_ = hex(from_) return self.readMemory(from_.replace("0x",""), size) @history def cmdWriteMem(self, cmd): '''write memory addr (`hex_addr hex_bytes`)''' self.writeMemory(cmd[1], cmd[2]) @history def cmdPrintState(self, cmd): '''print state''' self.printState() @history def cmdEval(self, cmd): '''executes your command''' exec(' '.join(cmd[1:])) def cmdHelp(self, cmd): '''help''' self.logger.info("Commands:") for k,v in self.cmd_handlers.items(): self.logger.info("\t%s: %s" % (k, v.__doc__)) def cmdLogHistory(self, cmd): '''prints a serialized version of this debugging session''' self.logger.debug(self.history) self.logger.info("`%s`" % (', '.join(self.history)))
# Verify the '.text' section is loaded assert ('.text' in [b.name for b in getMemoryBlocks()]) # Verify the entry point has been marked entry = None for f in currentProgram.getFunctionManager().getFunctions(True): if f.name == 'entry': entry = f break assert (entry is not None) # Attempt to decompile the entry point function from ghidra.app.decompiler import DecompInterface di = DecompInterface() di.openProgram(currentProgram) print(di.decompileFunction(entry, 0, None).getDecompiledFunction().getC()) # Ghidra silently swallows exceptions, so create a file at the end of the test # to mark success open('TEST_PASS', 'w').write('pass')
#@author Magnus "Nopey" Larsen #@category #@keybinding #@menupath Tools.Misc.Yoink operator new() #@toolbar import re #gex from ghidra.app.decompiler import DecompileOptions, DecompInterface from ghidra.util.task import ConsoleTaskMonitor from ghidra.program.database.data import StructureDB program = getCurrentProgram() dataManager = program.getDataTypeManager() fm = program.getFunctionManager() program_name = program.getName() refman = program.getReferenceManager() ifc = DecompInterface() ifc.openProgram(program) # all_datatypes is just a way of skipping the paths from the DataTypeManager # (degenerate, I know ;) monitor.setMessage("enumerating all types to eliminate namespacing") all_datatypes = dict() for d in dataManager.getAllDataTypes(): all_datatypes[d.getName()] = d # ASK SECTION # is_client = "client" in program_name # hardcode the addres of operator.new to avoid ambiguity between its overloads # (I think the overloads are copy-new's?) op_new_addr = None
def generate_decomp_interface(): decompiler = DecompInterface() opts = DecompileOptions() opts.grabFromProgram(curr) decompiler.setOptions(opts) decompiler.toggleCCode(True) decompiler.toggleSyntaxTree(True) # - decompile -- The main decompiler action # - normalize -- Decompilation tuned for normalization # - jumptable -- Simplify just enough to recover a jump-table # - paramid -- Simplify enough to recover function parameters # - register -- Perform one analysis pass on registers, without stack variables # - firstpass -- Construct the initial raw syntax tree, with no simplification decompiler.setSimplificationStyle("decompile") decompiler.openProgram(curr) return decompiler
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())
break file_functions[function_name] = function print(len(file_functions)) return file_functions file_functions = getFileFunctions("C:/Users/kaiho/ghidra_scripts/stl.cpp") # file_functions = getFileFunctions("C:/Users/kaiho/source/repos/Test Solution/Test/hello.cpp") # getting a list of all the ghidra functions ghidra_functions = [] ghidra_names = [] # initalizing the decompiler program = getCurrentProgram() ifc = DecompInterface() ifc.openProgram(program) # getting each decompiled function func_iter = program.getListing().getFunctions(True) while (func_iter.hasNext()): func = func_iter.next() name = func.getName() if ('.' == name[0]): continue ghidra_names.append(name) results = ifc.decompileFunction(func, 0, monitor) c_func = results.getDecompiledFunction().getC()
def _decompiler(): ifc = DecompInterface() DecOptions = DecompileOptions() service = state.getTool().getService(OptionsService) opt = service.getOptions("Decompiler") DecOptions.grabFromToolAndProgram(None, opt, currentProgram) ifc.setOptions(DecOptions) ifc.toggleCCode(True) ifc.toggleSyntaxTree(True) ifc.setSimplificationStyle("decompile") ifc.openProgram(currentProgram) return ifc