def _convert_address_to_function(func): """Convert an address that IDA has classified incorrectly into a proper function.""" # If everything goes wrong, we'll try to restore this function. orig = idc.FirstFuncFchunk(func) # If the address is not code, let's undefine whatever it is. if not idc.isCode(idc.GetFlags(func)): if not is_mapped(func): # Well, that's awkward. return False item = idc.ItemHead(func) itemend = idc.ItemEnd(func) if item != idc.BADADDR: _log(1, 'Undefining item {:#x} - {:#x}', item, itemend) idc.MakeUnkn(item, idc.DOUNK_EXPAND) idc.MakeCode(func) # Give IDA a chance to analyze the new code or else we won't be able to create a # function. idc.Wait() idc.AnalyseArea(item, itemend) else: # Just try removing the chunk from its current function. IDA can add it to another function # automatically, so make sure it's removed from all functions by doing it in loop until it # fails. for i in range(1024): if not idc.RemoveFchunk(func, func): break # Now try making a function. if idc.MakeFunction(func) != 0: return True # This is a stubborn chunk. Try recording the list of chunks, deleting the original function, # creating the new function, then re-creating the original function. if orig != idc.BADADDR: chunks = list(idautils.Chunks(orig)) if idc.DelFunction(orig) != 0: # Ok, now let's create the new function, and recreate the original. if idc.MakeFunction(func) != 0: if idc.MakeFunction(orig) != 0: # Ok, so we created the functions! Now, if any of the original chunks are not # contained in a function, we'll abort and undo. if all(idaapi.get_func(start) for start, end in chunks): return True # Try to undo the damage. for start, _ in chunks: idc.DelFunction(start) # Everything we've tried so far has failed. If there was originally a function, try to restore # it. if orig != idc.BADADDR: _log(0, 'Trying to restore original function {:#x}', orig) idc.MakeFunction(orig) return False
def ida_make_function(location): ''' Description: From the first non-function byte, attempt to make a function. Input: location - The EA at which IDA should attempt to make a function. Output: True if it succeeded, False otherwise. ''' function_start = location ea = location while not (idaapi.get_func(ea) or idc.isAlign(idc.GetFlags(ea))): function_start = ea ea = idc.PrevHead(ea) function_start = _un_nop(function_start, idc.NextHead) if idc.MakeFunction(function_start): last_mnem = idc.GetMnem( idc.ItemHead(idaapi.get_func(function_start).endEA - 1)) if 'ret' not in last_mnem and 'jmp' not in last_mnem: idc.DelFunction(function_start) append_debug( 'Created a function at 0x%X, but there wasn\'t a jmp or ret at the end.' % function_start) return False else: append_debug('Created a function 0x%X.' % function_start) return True else: return False
def OnDeleteLine(self, n): ans = idaapi.askyn_c( 1, "HIDECANCEL\nAre you sure you want to delete function [%s] @ [%s]?" % (self.items[n][3], self.items[n][4])) if ans == 1: asms = Assembler.LoadSavedAssemblers() item = int(self.items[n][2], 16) if asms != None and len(asms.keys()) > 0: for asm in asms.itervalues(): if asm.functions.has_key(item): print "Removed [%08x]!" % item del asm.functions[item] asm.SaveState() opty_ea = int(self.items[n][4], 16) print "set_name[%08x]" % opty_ea idc.MakeComm(opty_ea, "") idaapi.set_name(opty_ea, "") idc.DelFunction(opty_ea) comment = idc.Comment(item) comment = re.sub(r"(?i)OPTY@\[[\d+abcdef]+\];\s*", "", comment) idc.MakeComm(item, comment) self.populate_items() return n
def try_make_function(function_start, function_end=idc.BADADDR, target_location=None, require_term=True, end_mnem_bytes=None): """ Description: Given a function location, attempt to create a function. If function creation fails, delete any partially created functions. If function creation succeeds, ensure all of the function's bytes are analyzed as code. Input: function_start - The startEA of the function to create function_end - The endEA of the function to create. IDA will calculate if not provided. target_location - If provided, fail function creation if it does not include this EA require_term - If provided, fail function creation if the last instruction is not a ret or jmp end_mnem_bytes - If provided, fail function creation if the last instruction is not the provided bytes Instructions are entered as space separated bytes (i.e. '55' for 'push ebp') Output: Returns a tuple (function_start, function_end) for the created function if successful, None otherwise """ if function_start <= function_end: if idc.MakeFunction(function_start, function_end): append_debug('Created a function 0x%X - 0x%X.' % (function_start, function_end)) if require_term: last_mnem_ea = idc.ItemHead(idaapi.get_func(function_start).endEA - 1) last_mnem = idc.GetMnem(last_mnem_ea) if (end_mnem_bytes is None and 'ret' not in last_mnem and 'jmp' not in last_mnem) or \ (end_mnem_bytes and idaapi.get_many_bytes(last_mnem_ea, idc.ItemSize(last_mnem_ea)).encode('hex').upper() != end_mnem_bytes.upper()): idc.DelFunction(function_start) append_debug( 'Deleted function at 0x%X - the function didn\'t end with the correct mnem/bytes.' % function_start) return if target_location is not None: if function_start <= target_location < idaapi.get_func(function_start).endEA: idc.AnalyzeArea(function_start, idaapi.get_func(function_start).endEA) return function_start, function_end else: idc.DelFunction(function_start) append_debug( 'Deleted function at 0x%X - the function didn\'t contain the target location.' % function_start) return else: append_debug( 'Tried to create a function 0x%X - 0x%X, but IDA wouldn\'t do it.' % (function_start, function_end)) else: append_debug('The end address was not greater than the start address!')
def split_funcs(startEA, endEA): ''' Description: Attempt to split the function we created into a bunch of smaller functions based on aligns we find in the middle of the func. If we do successfully split, recurse on the remainder of the original function. Input: startEA - The beginning of the function endEA - The end of the function Output: The IDB is updated with the resulting functions ''' ea = startEA while ea < endEA: # We found an align so delete the function and try to make 2 new ones in its place. if idaapi.isAlign(idc.GetFlags(ea)) and idc.DelFunction(startEA): # Make the first function. if idc.MakeFunction(startEA, _un_nop(ea, idc.NextHead)): # We found an align, now get past them. while idaapi.isAlign(idc.GetFlags(ea)): ea += idc.ItemSize(ea) # Make the second function and recurse to ensure it doesn't need split too. if idc.MakeFunction(_un_nop(ea, idc.PrevHead), endEA): append_debug('Split 0x%X - 0x%X at 0x%X.' % (startEA, endEA, ea)) split_funcs(ea, endEA) return else: # We failed to make the second function, so delete the first. idc.DelFunction(startEA) # Splitting failed - rebuild the original function. idc.MakeFunction(startEA, endEA) append_debug('Almost split 0x%X - 0x%X at 0x%X.' % (startEA, endEA, ea)) ea += idc.ItemSize(ea)
def make_code(self, object_version, address): # delete function if previously defined idc.DelFunction(address) # make code if not already exist idc.MakeCode(address) # code label name self.make_name(object_version, address, False) # apply view self.make_view(object_version, address) # apply hidden area self.make_hidden_area(object_version, address)
def OnDeleteLine(self, n): ea = self.items[n][2] idc.DelFunction(ea) return n