def set_sig(addr, name, sig): try: typeSig = CParserUtils.parseSignature(None, currentProgram, sig, False) except ghidra.app.util.cparser.C.ParseException: print("Warning: Unable to parse") print(sig) print("Attempting to modify...") # try to fix by renaming the parameters try: newSig = sig.replace(", ", "ext, ").replace("\)", "ext\)") typeSig = CParserUtils.parseSignature(None, currentProgram, newSig, False) except: print("Warning: also unable to parse") print(newSig) print("Skipping.") return if typeSig is not None: try: typeSig.setName(name) ApplyFunctionSignatureCmd(addr, typeSig, USER_DEFINED, False, True).applyTo(currentProgram) except: print( "Warning: unable to set Signature. ApplyFunctionSignatureCmd() Failed." )
def parse_scatterload_table(self): """ Go through the scatterload table and identify the calls to unpack the init data and clear the bss section. """ self.data_init_start = None self.data_size_packed = None self.data_size_unpacked = None self.ram_clear_start = None self.ram_clear_size = None if self.scatterload_table.getLength() % 0x10: yikes("Scatterload table size not a multiple of 0x10") scatterload_nentries = self.scatterload_table.getLength() / 0x10 if scatterload_nentries < 2: yikes("Scatterload table too small to contain a decompress and clear entry") # Actually iterating might be unnecessary because the table layout is identical # in all targets I've seen so far, but what do I know. # The one assumption in here is that the unpack call comes _before_ the clear call. for entry in range(scatterload_nentries): addr = self.scatterload_table.getMinAddress().add(entry * 0x10) listing.clearCodeUnits(addr, addr.add(0x10), False) listing.createData(addr, self.table_entry_type) entry = read_uints(addr, 4) function_name = None is_rwdata_init_function = False if entry[1] == self.ram_block.getStart().getOffset(): print("Init data call found:", entry) is_rwdata_init_function = True self.data_init_start = addr.getNewAddress(entry[0]) self.data_size_unpacked = entry[2] elif self.data_init_start and entry[1] == self.ram_block.getStart().getOffset() + self.data_size_unpacked: print("Clear memory call found:", entry) function_name = "__scatterload_zeroinit" self.data_size_packed = entry[0] - self.data_init_start.getOffset() self.ram_clear_start = addr.getNewAddress(entry[1]) self.ram_clear_size = entry[2] function_addr = addr.getNewAddress(entry[3]) function = createFunction(function_addr, function_name) # Using commands for high-level operations is the "Ghidra Way" it seems: # https://github.com/NationalSecurityAgency/ghidra/issues/1126 ApplyFunctionSignatureCmd(function_addr, self.function_type, SourceType.USER_DEFINED, True, False).applyTo(currentProgram) if is_rwdata_init_function: self.rwdata_init_function = function or getFunctionAt(function_addr)
def checkFixReturn(func, ret_varnode): hf = get_highfunction(func) func_proto = hf.getFunctionPrototype() # Check return types for i in hf.getPcodeOps(): if i.getOpcode() == PcodeOp.RETURN: if len(i.getInputs()) < 2: print(func, "has no return value, fixing type...", i.getInputs()[0].getPCAddress()) sig = func.getSignature() sig.setReturnType( Undefined.getUndefinedDataType(ret_varnode.getSize())) ApplyFunctionSignatureCmd( func.getEntryPoint(), sig, SourceType.USER_DEFINED).applyTo(currentProgram)
def SetFunctionType(addr, sig): MakeFunction(addr) typeSig = CParserUtils.parseSignature(None, currentProgram, sig) ApplyFunctionSignatureCmd(toAddr(addr), typeSig, SourceType.USER_DEFINED, False, True).applyTo(currentProgram)
def fixLabel(data): name = getSymbolAt(data).getName() labelAddress = getSymbolAt(data).getAddress() #print labelAddress, name # ghidra refers to some functions as data, I've seen only one case if ("LAB_" not in name): currentProgram.getListing().clearCodeUnits(data, data.add(8), False) name = name.split("_")[1] ret = createFunction(labelAddress, "LAB_" + name) labelName = name.replace("LAB_", "FUN_") #print disassemble(labelAddress) if disassemble(labelAddress) == False: popup("This Label " + labelAddress + "cannot be disassembled !") return -1 #print "labelName:",labelName ret = createFunction(labelAddress, labelName) func = getFunctionAt(labelAddress) if func == None: # Calling CreateFunction twice will force function creation # Don't ask me,ask NSA ret = createFunction(labelAddress, labelName) # why it sometimes returns None ? last chance func = getFunctionAt(labelAddress) if (func == None): listing = currentProgram.getListing() blockModelService = state.getTool().getService(BlockModelService) cbm = blockModelService.getActiveSubroutineModel() cbIter = cbm.getCodeBlocksContaining(labelAddress, monitor) l = labelAddress currentProgram.getListing().clearCodeUnits(l, l.add(8), True) createFunction(labelAddress, "FUN_" + name) #x = getFunctionAt(labelAddress) #print cbIter #x = CreateFunctionCmd(labelAddress,False) #print type(x) #funcBody = x.getFunctionBody(currentProgram,labelAddress) #print funcBody #mgr = currentProgram.getFunctionManager() #mgr.createFunction("test",labelAddress,funcBody,SourceType.USER_DEFINED) #raise Exception("Unable to create a function 0x%s" %(labelAddress.toString())) #x = ApplyFunctionSignatureCmd(labelName) #print x #return func = getFunctionAt(labelAddress) assert (func != None) func.setCustomVariableStorage(False) #params = func.getParameters() df = FunctionDefinitionDataType(func, False) # TODO : remove the below line , no need to change calling convention #df.setGenericCallingConvention(GenericCallingConvention.thiscall) df.setReturnType(func.getReturnType()) #df = FunctionDefinitionDataType(func,False) """ func.replaceParameters(FunctionUpdateType.DYNAMIC_STORAGE_ALL_PARAMS,#CUSTOM_STORAGE, True, SourceType.USER_DEFINED, params) """ x = ApplyFunctionSignatureCmd(func.getEntryPoint(), df, SourceType.USER_DEFINED) x.applyTo(func.getProgram())
dwordDef = ParameterDefinitionImpl(None, dword, "double word") # list of functions to change signatures functionsToChange = [ "foo", "bar" #... ] #function definitions fooDef = FunctionDefinitionDataType("foo") fooDef.setArguments([pointer32Def, dwordDef]) barDef = FunctionDefinitionDataType("bar") barDef.setArguments([pointer32Def]) functionDefs = [fooDef, barDef] func = getFirstFunction() #loop though functions looking names that match our list while func is not None: func_name = func.getName() if func_name in functionsToChange: for defi in functionDefs: if func_name == defi.getName(): cmd = ApplyFunctionSignatureCmd(func.getEntryPoint(), defi, SourceType.USER_DEFINED) runCommand(cmd) if debug == True: print "Address {} -> Name {}".format( func.getEntryPoint(), defi.getName()) print cmd.getStatusMsg() func = getFunctionAfter(func)