def Functions(start=None, end=None): """ Get a list of functions @param start: start address (default: inf.min_ea) @param end: end address (default: inf.max_ea) @return: list of heads between start and end @note: The last function that starts before 'end' is included even if it extends beyond 'end'. Any function that has its chunks scattered in multiple segments will be reported multiple times, once in each segment as they are listed. """ if not start: start = ida_ida.cvar.inf.min_ea if not end: end = ida_ida.cvar.inf.max_ea # find first function head chunk in the range chunk = ida_funcs.get_fchunk(start) if not chunk: chunk = ida_funcs.get_next_fchunk(start) while chunk and chunk.start_ea < end and (chunk.flags & ida_funcs.FUNC_TAIL) != 0: chunk = ida_funcs.get_next_fchunk(chunk.start_ea) func = chunk while func and func.start_ea < end: startea = func.start_ea yield startea func = ida_funcs.get_next_func(startea)
def __process_functions(self): functions = list() start = ida_ida.cvar.inf.min_ea end = ida_ida.cvar.inf.max_ea # find first function head chunk in the range chunk = ida_funcs.get_fchunk(start) if not chunk: chunk = ida_funcs.get_next_fchunk(start) while chunk and chunk.start_ea < end and (chunk.flags & ida_funcs.FUNC_TAIL) != 0: chunk = ida_funcs.get_next_fchunk(chunk.start_ea) func = chunk while func and func.start_ea < end: start_ea = func.start_ea func_flags = ida_bytes.get_full_flags(start_ea) func_name = ida_funcs.get_func_name(start_ea) func_name_demangled = ida_name.get_demangled_name( start_ea, 0xFFFF, 0, 0) func_autonamed = func_flags & ida_bytes.FF_LABL != 0 func_public = ida_name.is_public_name(start_ea) function = { 'start_rva': start_ea - self._base, 'name': func_name, 'name_demangled': func_name_demangled, 'is_public': func_public, 'is_autonamed': func_autonamed } # PE32/PE32+ only support binaries up to 2GB if function['start_rva'] >= 2**32: print('RVA out of range for function: ' + function['name'], file=sys.stderr) self.__process_function_typeinfo(function, func) function['labels'] = self.__process_function_labels(func) functions.append(function) func = ida_funcs.get_next_func(start_ea) return functions
def dump_func_info(ea): "dump info about function chunk at address 'ea'" pfn = ida_funcs.get_fchunk(ea) if pfn is None: print("No function at %08X!" % ea) return print("current chunk boundaries: %08X..%08X" % (pfn.start_ea, pfn.end_ea)) dump_flags(pfn) if (ida_funcs.is_func_entry(pfn)): print("This is an entry chunk") dump_tails(pfn) dump_frame(pfn) dump_regvars(pfn) dump_regargs(pfn) dump_stkpnts(pfn) elif (ida_funcs.is_func_tail(pfn)): print("This is a tail chunk") dump_parents(pfn)
def StartPtAnalysis(self, startEa): curEa = startEa nextEa = 0 # Next IDA Address while True: #Read next packet line = self.hTraceFile.readline() if (line == '' or line.strip() == 'END'): break line = line.strip() if (line == ''): continue nextPck = self.GetPacket(line) self.lineNumber += 1 nextEa = self.AnalyseNextChunk(curEa, nextPck) if (nextEa == 0): # Here it means that we are in 2 totally different points in the code (kernel drivers are a good example) if (nextPck[1][:3] != "fup" and nextPck[1][:3] != "tip"): print( "I found an internal error. Packet ID: %s, type: %s, current IP: %s" % (hex(nextPck[0]), nextPck[1], hex(curEa)[:-1])) break completePtAddr = self.GetPtPckFullIP(nextPck) nextEa = self.GetIdaAddress(completePtAddr) print( "Found another unrelated block of code in the DUMP. Start at %s. Line #%d in the dump file." % (hex(nextEa)[:-1], self.lineNumber)) elif (nextEa == -1): # Some errors or we are done break self.lastPtPck = nextPck curEa = nextEa # Complete this dump if the last packet is a pgd lastEa = ida_funcs.get_fchunk(curEa).endEA if (nextPck[1][-3:] == "pgd" and curEa != lastEa): while (curEa < lastEa): mnem = idc.GetMnem(curEa) self.ColorInstruction(curEa) if (mnem[0] == "j" or mnem[:4] == "loop" or mnem == "call" or mnem == "ret" or mnem == "retn"): break curEa = idc.NextHead(curEa) return True
def fix_func_prolog(ea, end_ea=idc.BADADDR): global FUNC_BY_LS func_cnt = 0 func = ida_funcs.get_fchunk(ea) if func is None: func = ida_funcs.get_next_func(ea) ea = func.start_ea while func is not None and ea < end_ea: # if current function is small enough and there exists a function right # next to current function if (func.size() <= 8 and idc.get_func_attr( func.end_ea, idc.FUNCATTR_START) != idc.BADADDR): # If the next function can be connected, there must be a basic block reference. # xref.type == 21 means 'fl_F', which is an ordinary flow. if all( (func.start_ea <= xref.frm < func.end_ea) and xref.type == 21 for xref in XrefsTo(func.end_ea)): if func_cnt > 0 and func_cnt % 1000 == 0: print("%x <- %x: prolog merging (%d)." % (func.start_ea, func.end_ea, func_cnt)) ida_bytes.del_items(func.end_ea, ida_bytes.DELIT_EXPAND) ida_bytes.del_items(func.start_ea, ida_bytes.DELIT_EXPAND) ida_auto.auto_wait() status = idc.add_func(func.start_ea) if not status: print("Error merging 0x%x <- 0x%x" % (func.start_ea, func.end_ea)) else: func_cnt += 1 FUNC_BY_LS.discard(func.end_ea) ida_auto.auto_wait() func = ida_funcs.get_next_func(ea) if func: ea = func.start_ea print("Fixed %d functions" % func_cnt)
def analyze_ida_str(): global all_str if "all_str" not in globals(): all_str = idautils.Strings() str_cnt = 0 start_time = time.time() for s in all_str: # check if there exists already assigned function or string if any( ida_funcs.get_fchunk(ea) or (idc.get_str_type(ea) is not None) for ea in (s.ea, s.ea + s.length)): continue if check_string(30) and create_string(s.ea): str_cnt += 1 if str_cnt % 1000 == 0: print("%x: %d strings has been found. (%0.3f secs)" % (s.ea, str_cnt, time.time() - start_time)) print("Created %d strings. (%0.3f secs)" % (str_cnt, time.time() - start_time))
def processFunctions(): functions = list() start = ida_ida.cvar.inf.min_ea end = ida_ida.cvar.inf.max_ea # find first function head chunk in the range chunk = ida_funcs.get_fchunk(start) if not chunk: chunk = ida_funcs.get_next_fchunk(start) while chunk and chunk.start_ea < end and (chunk.flags & ida_funcs.FUNC_TAIL) != 0: chunk = ida_funcs.get_next_fchunk(chunk.start_ea) func = chunk while func and func.start_ea < end: start_ea = func.start_ea flags = ida_bytes.get_full_flags(start_ea) function = { 'start_ea': start_ea, 'name': ida_funcs.get_func_name(start_ea), 'is_public': ida_name.is_public_name(start_ea), 'is_autonamed': flags & ida_bytes.FF_LABL != 0 } processFunctionTypeinfo(function) functions.append(function) func = ida_funcs.get_next_func(start_ea) return functions
def __call__(self): tail = ida_funcs.get_fchunk(self.tail_ea) ida_funcs.set_tail_owner(tail, self.owner_func)
def _on_tailownerchanged(self, tail_ea, owner_func): tail = ida_funcs.get_fchunk(tail_ea) ida_funcs.set_tail_owner(tail, owner_func)