我们从Python开源项目中,提取了以下50个代码示例,用于说明如何使用idaapi.get_func()。
def get_func_code_refs_from(func_ea, iaddrs): """Returns a set with the code references from this function""" code_refs = set() for addr in iaddrs: ref = idaapi.BADADDR for r in idautils.XrefsFrom(addr, idaapi.XREF_FAR): if r.iscode: to_func = idaapi.get_func(r.to) if not to_func or to_func.startEA != func_ea: ref = r.to else: ref = r.to if (ref != idaapi.BADADDR or idaapi.is_call_insn(addr) or idaapi.is_indirect_jump_insn(addr)): #print hex(i.addr), i, hex(ref) code_refs.add(ref) return code_refs
def get_func_code_refs_to(func_ea): """Returns a set with the code references to this function""" code_refs = set() for ref in idautils.CodeRefsTo(func_ea, 0): #callers func_ida = idaapi.get_func(ref) if not func_ida: #print "BUG?: coderef came from no function! %X->%X"%(ref, addr) continue #if func_ida.startEA not in functions: # print "BUG?: function %X not in our set (r=%X)!"%(func_ida.startEA, ref) # continue code_refs.add((ref, func_ida.startEA)) return code_refs
def enum_function_addrs(fva): ''' yield the effective addresses of each instruction in the given function. these addresses are not guaranteed to be in any order. Args: fva (int): the starting address of a function Returns: sequence[int]: the addresses of each instruction ''' f = idaapi.get_func(fva) if not f: raise ValueError('not a function') for block in idaapi.FlowChart(f): ea = block.startEA while ea <= block.endEA: yield ea ea = idc.NextHead(ea)
def rename(ea, newname): fl = database.type.flags(ea) labelQ, customQ = (fl & n == n for n in (idaapi.FF_LABL,idaapi.FF_NAME)) #r, fn = database.xref.up(ea), idaapi.get_func(ea) fn = idaapi.get_func(ea) # figure out whether a global or function name is being changed, otherwise it's the function's contents ctx = internal.comment.globals if not fn or (fn.startEA == ea) else internal.comment.contents # if a name is being removed if not newname: # if it's a custom name if (not labelQ and customQ): ctx.dec(ea, '__name__') return # if it's currently a label or is unnamed if (labelQ and not customQ) or all(not n for n in (labelQ,customQ)): ctx.inc(ea, '__name__') return
def extra_cmt_changed(ea, line_idx, cmt): # FIXME: persist state for extra_cmts in order to determine # what the original value was before modification oldcmt = internal.netnode.sup.get(ea, line_idx) ctx = internal.comment.contents if idaapi.get_func(ea) else internal.comment.globals MAX_ITEM_LINES = (idaapi.E_NEXT-idaapi.E_PREV) if idaapi.E_NEXT > idaapi.E_PREV else idaapi.E_PREV-idaapi.E_NEXT prefix = (idaapi.E_PREV, idaapi.E_PREV+MAX_ITEM_LINES, '__extra_prefix__') suffix = (idaapi.E_NEXT, idaapi.E_NEXT+MAX_ITEM_LINES, '__extra_suffix__') for l,r,key in (prefix,suffix): if l <= line_idx < r: if oldcmt is None and cmt: ctx.inc(ea, key) elif oldcmt and cmt is None: ctx.dec(ea, key) continue return ### function scope
def check_global(ea): if idaapi.get_func(ea): return False cache = internal.comment.decode(db.get_comment(db.top())) cache.update( internal.comment.decode(db.get_comment(db.bottom())) ) node = internal.netnode.get(internal.comment.globals.Node) tag = internal.comment.decode(db.get_comment(ea)) if cache and '__address__' not in cache: return False if not cache and tag: return False count = internal.netnode.alt.get(node, ea) if tag and not count: return False if len(tag['__address__']) != count: return False keys = tag['__tags__'] if any(t not in cache for t in keys): return False return True
def __init__(self, location): self.at = location # self.name = GetFunctionName(location) self.name = GetFuncOffset(location) self.start = 0 self.end = 0 self.func_offset = 0 try: _func = idaapi.get_func(location) self.start = _func.startEA self.end = _func.endEA # ==FindFuncEnd(location) self.func_offset = self.start - self.at except Exception, e: logger.exception(e) if not self.name: self.indirect = True else: self.indirect = False
def FuncItems(start): """ Get a list of function items @param start: address of the function @return: ea of each item in the function """ func = idaapi.get_func(start) if not func: return fii = idaapi.func_item_iterator_t() ok = fii.set(func) while ok: yield fii.current() ok = fii.next_code()
def DeleteAll(): """ Delete all segments, instructions, comments, i.e. everything except values of bytes. """ ea = idaapi.cvar.inf.minEA # Brute-force nuke all info from all the heads while ea != BADADDR and ea <= idaapi.cvar.inf.maxEA: idaapi.del_local_name(ea) idaapi.del_global_name(ea) func = idaapi.get_func(ea) if func: idaapi.del_func_cmt(func, False) idaapi.del_func_cmt(func, True) idaapi.del_func(ea) idaapi.del_hidden_area(ea) seg = idaapi.getseg(ea) if seg: idaapi.del_segment_cmt(seg, False) idaapi.del_segment_cmt(seg, True) idaapi.del_segm(ea, idaapi.SEGDEL_KEEP | idaapi.SEGDEL_SILENT) ea = idaapi.next_head(ea, idaapi.cvar.inf.maxEA)
def SetFunctionFlags(ea, flags): """ Change function flags @param ea: any address belonging to the function @param flags: see GetFunctionFlags() for explanations @return: !=0 - ok """ func = idaapi.get_func(ea) if not func: return 0 else: func.flags = flags idaapi.update_func(func) return 1
def GetFunctionCmt(ea, repeatable): """ Retrieve function comment @param ea: any address belonging to the function @param repeatable: 1: get repeatable comment 0: get regular comment @return: function comment string """ func = idaapi.get_func(ea) if not func: return "" else: comment = idaapi.get_func_cmt(func, repeatable) if not comment: return "" else: return comment
def GetFrameSize(ea): """ Get full size of function frame @param ea: any address belonging to the function @returns: Size of function frame in bytes. This function takes into account size of local variables + size of saved registers + size of return address + size of function arguments If the function doesn't have a frame, return size of function return address in the stack. If the function does't exist, return 0 """ func = idaapi.get_func(ea) if not func: return 0 else: return idaapi.get_frame_size(func)
def GetSpd(ea): """ Get current delta for the stack pointer @param ea: end address of the instruction i.e.the last address of the instruction+1 @return: The difference between the original SP upon entering the function and SP for the specified address """ func = idaapi.get_func(ea) if not func: return None return idaapi.get_spd(func, ea)
def GetSpDiff(ea): """ Get modification of SP made by the instruction @param ea: end address of the instruction i.e.the last address of the instruction+1 @return: Get modification of SP made at the specified location If the specified location doesn't contain a SP change point, return 0 Otherwise return delta of SP modification """ func = idaapi.get_func(ea) if not func: return None return idaapi.get_sp_delta(func, ea)
def SetFchunkOwner(tailea, funcea): """ Change the function chunk owner @param tailea: any address in the function chunk @param funcea: the starting address of the new owner @return: 0 if failed, 1 if success @note: The new owner must already have the chunk appended before the call """ tail = idaapi.get_func(tailea) if not tail: return 0 else: return idaapi.set_tail_owner(tail, funcea)
def FirstFuncFchunk(funcea): """ Get the first function chunk of the specified function @param funcea: any address in the function @return: the function entry point or BADADDR @note: This function returns the first (main) chunk of the specified function """ func = idaapi.get_func(funcea) fci = idaapi.func_tail_iterator_t(func, funcea) if fci.main(): return fci.chunk().startEA else: return BADADDR
def find_all_ioctls(): """ From the currently selected address attempts to traverse all blocks inside the current function to find all immediate values which are used for a comparison/sub immediately before a jz. Returns a list of address, second operand pairs. """ ioctls = [] # Find the currently selected function and get a list of all of it's basic blocks addr = idc.ScreenEA() f = idaapi.get_func(addr) fc = idaapi.FlowChart(f, flags=idaapi.FC_PREDS) for block in fc: # grab the last two instructions in the block last_inst = idc.PrevHead(block.endEA) penultimate_inst = idc.PrevHead(last_inst) # If the penultimate instruction is cmp or sub against an immediate value immediatly preceding a 'jz' # then it's a decent guess that it's an IOCTL code (if this is a disptach function) if idc.GetMnem(penultimate_inst) in ['cmp', 'sub'] and idc.GetOpType(penultimate_inst, 1) == 5: if idc.GetMnem(last_inst) == 'jz': ioctl_tracker.add_ioctl(penultimate_inst) for inst in ioctl_tracker.ioctl_locs: value = get_operand_value(inst) ioctls.append((inst, value)) return ioctls
def find_dispatch_by_struct_index(): """Attempts to locate the dispatch function based off it being loaded in a structure at offset 70h, based off of https://github.com/kbandla/ImmunityDebugger/blob/master/1.73/Libs/driverlib.py """ out = set() for function_ea in idautils.Functions(): flags = GetFunctionFlags(function_ea) # skip library functions if flags & FUNC_LIB: continue func = idaapi.get_func(function_ea) addr = func.startEA while addr < func.endEA: if GetMnem(addr) == 'mov': if '+70h' in GetOpnd(addr, 0) and idc.GetOpType(addr, 1) == 5: out.add(GetOpnd(addr, 1)) addr = idc.NextHead(addr) return out
def handleHookFuncLinkMemory(self): if self.hookedFunction() == False: return func = get_func(ScreenEA()) if func is None: return address = func.startEA; self.idbHookMap[address].mem_list = self.linkMemoryRanges(); entry = self.idbHookMap[address] outJSON = json.dumps({ "req_id": kFridaLink_UpdHookRequest, "data": entry.genUpdRequest(HookEntry.UPD_MEMLIST) }) self.clientSocket.sendto(outJSON, self.clientAddress)
def handleUnhookFunc(self, screenEA = None): if screenEA is not None: func = get_func(screenEA) else: func = get_func(ScreenEA()) if func is None: return address = func.startEA; if self.hookedFunction(address) == False: return entry = self.idbHookMap[address] outJSON = json.dumps({ "req_id": kFridaLink_DelHookRequest, "data": entry.genDelRequest() }) del self.idbHookMap[address] self.clientSocket.sendto(outJSON, self.clientAddress) SetColor(address, CIC_FUNC, kIDAViewColor_Reset) refresh_idaview_anyway() self.idbHooksView.setContent(self.idbHookMap)
def hookedFunction(self, screenEA = None): if screenEA is not None: func = get_func(screenEA) else: func = get_func(ScreenEA()) if func is None: return False; address = func.startEA; if address in self.idbHookMap: # can be start of the function, check hook type if self.idbHookMap[func.startEA].hook.type == "func": return True else: return False else: return False
def resolveStackAddress(self, address, symbol): if symbol[0] == "0x0": return None info = {} info['module'] = str(symbol[1]) segm = get_segm_by_name(info['module']) if segm is not None: locEA = segm.startEA delta = address - int(symbol[0], 16) + locEA func = get_func(delta) if func is not None: info['symbol'] = str(get_func_name(delta)) else: info['symbol'] = str(GetDisasm(delta)) elif symbol[2] != '': if symbol[2] == '<redacted>': info['symbol'] = "+0x%X" % (address - int(symbol[0], 16)) else: info['symbol'] = str(symbol[2]) else: info['symbol'] = '' return info
def GetIDX(self,ea): DEBUG_PRINT('IN GetIDX') idx = -1 comm = str(idc.GetCommentEx(ea, 0)) if '__' not in comm: print 'no comment here' return -1 DEBUG_PRINT(comm) start = comm.find(self._commMarker)+len(self._commMarker) if self._global == 1: end = comm.find('_g') idx = int(comm[start:end]) else: end = comm.find('_L') idx = int(comm[start:end]) + self._dbDict[idaapi.get_func(ea).startEA]._idx_list[0][0] return idx
def get_cursor_func_ref(): current_tform = idaapi.get_current_tform() tform_type = idaapi.get_tform_type(current_tform) # get the hexrays vdui (if available) vu = idaapi.get_tform_vdui(current_tform) if vu: cursor_addr = vu.item.get_ea() elif tform_type == idaapi.BWN_DISASM: cursor_addr = idaapi.get_screen_ea() op_addr = idc.GetOperandValue(cursor_addr, idaapi.get_opnum()) op_func = idaapi.get_func(op_addr) if op_func and op_func.startEA == op_addr: return op_addr else: return idaapi.BADADDR cursor_func = idaapi.get_func(cursor_addr) if cursor_func and cursor_func.startEA == cursor_addr: return cursor_addr return idaapi.BADADDR
def log_stack_chains(chains): f = open("%s/%s" % (LOG_PATH, "stack_chains"), "wb") long_chains = 0 for c in chains: if len(c) > 3: long_chains += 1 for a in c: if type(a) == type("x"): s = a else: s = "[0x%08x] %s+0x%x" % (a, str(idc.GetFunctionName(Dword(a))), Dword(a) - idaapi.get_func(Dword(a)).startEA) #print s f.write(s) f.write("\n") f.write("\n") print "%d chains found" % len(chains) print "%d long chains" % long_chains f.close()
def str_fun_xrefs(): str_fun_xref = {} for s in IDAStrings: for ref in idautils.DataRefsTo(s.ea): f = idaapi.get_func(ref) if not f: continue if idc.GetMnem(ref) == "": continue f_ea = f.startEA try: #because we are only carrying the string value itself, duplications should be removed. #This is important because of OFFS/ADR instruction double references being very typical, #and multiple allocations/frees in same function causing extra references too. str_fun_xref[f_ea].add(str(s)) except: str_fun_xref[f_ea] = set([str(s)]) return str_fun_xref
def ret_addr(ea): #we can't assume Thumb only, so we also keep ARM cases, just adjust addr in Thumb cases if (ea % 2) != 0: ea -= 1 f_ea = idaapi.get_func(ea) if not f_ea: return False #Preceding or Previous? # Not necessarily all preceding will be a call to a ret instruction, # but "the" prev should be always the one. i = idautils.DecodePreviousInstruction(ea) if i and "BL" in idc.GetMnem(i.ea): return True return False
def output_symbols(out): """Dump symbols.""" try: from idaapi import get_func_name2 as get_func_name # Since get_func_name is deprecated (at least from IDA 6.9) except ImportError: from idaapi import get_func_name # Older versions of IDA don't have get_func_name2 # so we just use the older name get_func_name def func_name_propagate_thunk(ea): current_name = get_func_name(ea) if current_name[0].isalpha(): return current_name func = idaapi.get_func(ea) temp_ptr = idaapi.ea_pointer() ea_new = idaapi.BADADDR if func.flags & idaapi.FUNC_THUNK == idaapi.FUNC_THUNK: ea_new = idaapi.calc_thunk_func_target(func, temp_ptr.cast()) if ea_new != idaapi.BADADDR: ea = ea_new propagated_name = get_func_name(ea) or '' # Ensure it is not `None` if len(current_name) > len(propagated_name) > 0: return propagated_name else: return current_name # Fallback to non-propagated name for weird times that IDA gives # a 0 length name, or finds a longer import name for ea in idautils.Segments(): fs = idautils.Functions(idc.SegStart(ea), idc.SegEnd(ea)) for f in fs: out.write('("%s" 0x%x 0x%x)\n' % ( func_name_propagate_thunk(f), idc.GetFunctionAttr(f, idc.FUNCATTR_START), idc.GetFunctionAttr(f, idc.FUNCATTR_END)))
def find_cfunc(ea): """Get cfuncptr_t from EA.""" func = idaapi.get_func(ea) if func: return idaapi.decompile(func)
def find_tight_loops(fva): """ Code from Willi Ballenthin """ tight_loops = [] function = idaapi.get_func(fva) for bb in idaapi.FlowChart(function): # bb.endEA is the first addr not in the basic block bb_end = idc.PrevHead(bb.endEA) for x in idautils.XrefsFrom(bb_end): if x.to == bb.startEA and bb.startEA < bb_end: tight_loops.append((bb.startEA, bb_end)) if tight_loops: g_logger.debug("Tight loops in 0x%x: %s", fva, ["0x%x - 0x%x" % (s, e) for (s, e) in tight_loops]) return tight_loops
def _get_blocks_codes_per_func_iter(): """ Iterative function to generate all blocks and opcodes :return: N/A """ all_blocks = {} all_codes = {} all_opcodes = [] for func in idautils.Functions(): # blocks_in_func contains # <idaapi.BasicBlock object at 0x0545F3F0>, ... blocks_in_func = idaapi.FlowChart(idaapi.get_func(func)) blocks = [] for block in blocks_in_func: # IDA BUG! block.startEA == block.endEA?? # Should be in the range "block.startEA <= block < block.endEA" if block.startEA != block.endEA: blocks.append((block.startEA, block.endEA)) for head in idautils.Heads(block.startEA, block.endEA): ibytes = idc.GetManyBytes(head, idc.ItemEnd(head) - head) spd = idc.GetSpd(head) all_codes[head] = insn.Instruction(head, ibytes, spd) # IDA BUG! all_codes[head].bytes == 0?? # The size of the code should be positive if all_codes[head].bytes != 0: all_opcodes.append((all_codes[head].addr, all_codes[head].addr + len(all_codes[head].bytes))) all_blocks[func] = blocks yield (all_blocks, all_opcodes)
def get_func_of(ea): """Return the function that this address belongs to, if any.""" func = idaapi.get_func(ea) if func: return func.startEA else: return None
def get_basic_blocks(fva): ''' return sequence of `BasicBlock` instances for given function. ''' ret = [] func = idaapi.get_func(fva) if func is None: return ret for bb in idaapi.FlowChart(func): ret.append(BasicBlock(va=bb.startEA, size=bb.endEA - bb.startEA)) return ret
def get_function(va): ''' return va for first instruction in function that contains given va. ''' return idaapi.get_func(va).startEA
def get_custom_viewer_hint(self, view, place): try: tform = idaapi.get_current_tform() if idaapi.get_tform_type(tform) != idaapi.BWN_DISASM: return None curline = idaapi.get_custom_viewer_curline(view, True) # sometimes get_custom_viewer_place() returns [x, y] and sometimes [place_t, x, y]. # we want the place_t. viewer_place = idaapi.get_custom_viewer_place(view, True) if len(viewer_place) != 3: return None _, x, y = viewer_place ea = place.toea() # "color" is a bit of misnomer: its the type of the symbol currently hinted color = get_color_at_char(curline, x) if color != idaapi.COLOR_ADDR: return None # grab the FAR references to code (not necessarilty a branch/call/jump by itself) far_code_references = [xref.to for xref in idautils.XrefsFrom(ea, ida_xref.XREF_FAR) if idc.isCode(idc.GetFlags(xref.to))] if len(far_code_references) != 1: return None fva = far_code_references[0] # ensure its actually a function if not idaapi.get_func(fva): return None # this magic constant is the number of "important lines" to display by default. # the remaining lines get shown if you scroll down while the hint is displayed, revealing more lines. return render_function_hint(fva), DEFAULT_IMPORTANT_LINES_NUM except Exception as e: logger.warning('unexpected exception: %s. Get in touch with @williballenthin.', e, exc_info=True) return None
def function(cls): """Current function""" ea = cls.address() res = idaapi.get_func(ea) if res is None: raise StandardError("{:s}.function : Not currently inside a function.".format('.'.join((__name__,cls.__name__)))) return res
def _is_repeatable(cls, ea): f = idaapi.get_func(ea) return True if f is None else False
def _update_refs(cls, ea, old, new): f = idaapi.get_func(ea) for key in old.viewkeys() ^ new.viewkeys(): if key not in new: if f: internal.comment.contents.dec(ea, key) else: internal.comment.globals.dec(ea, key) if key not in old: if f: internal.comment.contents.inc(ea, key) else: internal.comment.globals.inc(ea, key) continue return
def _create_refs(cls, ea, res): f = idaapi.get_func(ea) for key in res.viewkeys(): if f: internal.comment.contents.inc(ea, key) else: internal.comment.globals.inc(ea, key) return
def _delete_refs(cls, ea, res): f = idaapi.get_func(ea) for key in res.viewkeys(): if f: internal.comment.contents.dec(ea, key) else: internal.comment.globals.dec(ea, key) return
def changing(cls, cb, a, cmt, repeatable): fn = idaapi.get_func(a.startEA) oldcmt = idaapi.get_func_cmt(fn, repeatable) try: cls.event.send((fn.startEA, bool(repeatable), cmt)) except StopIteration, e: logging.fatal("{:s}.changing : Unexpected termination of event handler. Re-instantiating it.".format('.'.join((__name__,cls.__name__)))) cls.event = cls._event(); next(cls.event)
def changed(cls, cb, a, cmt, repeatable): fn = idaapi.get_func(a.startEA) newcmt = idaapi.get_func_cmt(fn, repeatable) try: cls.event.send((fn.startEA, bool(repeatable), None)) except StopIteration, e: logging.fatal("{:s}.changed : Unexpected termination of event handler. Re-instantiating it.".format('.'.join((__name__,cls.__name__)))) cls.event = cls._event(); next(cls.event) ### database scope
def do_data(): addr,tags = {},{} left, right = db.range() print 'fetching global tags' for ea in db.iterate(left, right-1): f = idaapi.get_func(ea) if f is not None: continue res = db.tag(ea) #res.pop('name', None) for k, v in res.iteritems(): addr[ea] = addr.get(ea, 0) + 1 tags[k] = tags.get(k, 0) + 1 continue return addr, tags
def customnames(): '''Add all custom names defined in the database to the tagcache as "__name__"''' # FIXME: first delete all the custom names '__name__' tag left, right = db.range() for ea in db.iterate(left, right-1): fn = idaapi.get_func(ea) ctx = internal.comment.globals if not fn or fn.startEA == ea else internal.comment.contents if db.type.has_customname(ea): ctx.inc(ea, '__name__') continue return
def extracomments(): '''Add all extra cmts in the database to the tagcache as "__name__"''' # FIXME: first delete all the custom names '__name__' tag left, right = db.range() for ea in db.iterate(left, right-1): fn = idaapi.get_func(ea) ctx = internal.comment.contents if fn else internal.comment.globals count = db.extra.count(ea, idaapi.E_PREV) if count: [ ctx.inc(ea, '__extra_prefix__') for i in xrange(count) ] count = db.extra.count(ea, idaapi.E_NEXT) if count: [ ctx.inc(ea, '__extra_suffix__') for i in xrange(count) ] return
def color_block(ea=None, color=0x55ff7f): """http://reverseengineering.stackexchange.com/questions/10662/change-block-node-color-with-idapython and WanderingGlitch for the tip of refresh_idaview_anyway()""" func_top = fn.top() f = idaapi.get_func(ea) g = idaapi.FlowChart(f, flags=idaapi.FC_PREDS) bb_id = get_bb_id(g, ea) p = idaapi.node_info_t() p.bg_color = color idaapi.set_node_info2(func_top, bb_id, p, idaapi.NIF_BG_COLOR | idaapi.NIF_FRAME_COLOR) idaapi.refresh_idaview_anyway()
def by_name(name): '''Return the function with the name ``name``.''' ea = idaapi.get_name_ea(-1, name) if ea == idaapi.BADADDR: raise LookupError("{:s}.by_name({!r}) : Unable to locate function".format(__name__, name)) return idaapi.get_func(ea)
def within(ea): '''Return True if the address ``ea`` is within a function.''' ea = interface.address.within(ea) return idaapi.get_func(ea) is not None # Checks if ea is contained in function or in any of it's chunks
def by_address(ea): '''Return the function containing the address ``ea``.''' ea = interface.address.within(ea) res = idaapi.get_func(ea) if res is None: raise LookupError("{:s}.by_address({:x}) : Unable to locate function".format(__name__, ea)) return res