我们从Python开源项目中,提取了以下28个代码示例,用于说明如何使用idaapi.FlowChart()。
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 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 get_cfg(function_start, function_end): f_name = GetFunctionName(function_start) cfg = idaapi.FlowChart(idaapi.get_func(function_start)) return list(cfg)
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_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 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 bottom(func): '''Return the exit-points of the function ``func``.''' fn = by(func) fc = idaapi.FlowChart(f=fn, flags=idaapi.FC_PREDS) exit_types = (fc_block_type_t.fcb_ret,fc_block_type_t.fcb_cndret,fc_block_type_t.fcb_noret,fc_block_type_t.fcb_enoret,fc_block_type_t.fcb_error) return tuple(database.address.prev(n.endEA) for n in fc if n.type in exit_types)
def iterate(cls, func): '''Returns each idaapi.BasicBlock for the function ``func``.''' fn = by(func) fc = idaapi.FlowChart(f=fn, flags=idaapi.FC_PREDS) for bb in fc: yield bb return
def flow(func): '''Return a flow chart object for the function ``func``.''' fn = by(func) fc = idaapi.FlowChart(f=fn, flags=idaapi.FC_PREDS) return fc
def flow(func): '''Return a flow chart object for the function ``func``.''' fn = by(func) fc = idaapi.FlowChart(f=fn, flags=idaapi.FC_PREDS) return fc # FIXME: document this #def refs(func, member): # xl, fn = idaapi.xreflist_t(), by(func) # idaapi.build_stkvar_xrefs(xl, fn, member.ptr) # x.ea, x.opnum, x.type # ref_types = { # 0 : 'Data_Unknown', # 1 : 'Data_Offset', # 2 : 'Data_Write', # 3 : 'Data_Read', # 4 : 'Data_Text', # 5 : 'Data_Informational', # 16 : 'Code_Far_Call', # 17 : 'Code_Near_Call', # 18 : 'Code_Far_Jump', # 19 : 'Code_Near_Jump', # 20 : 'Code_User', # 21 : 'Ordinary_Flow' # } # return [(x.ea,x.opnum) for x in xl]
def find_bbls(function_ea): ''' yields all basic blocks that belong to the given function. The blocks are returned in a 2-tuple like: (start_address, end_address) Both start and end address are RELATIVE offsets from the image base. ''' # get image base from IDA image_base = idaapi.get_imagebase() function_ea += image_base # get flow chart from IDA flow_chart = idaapi.FlowChart( idaapi.get_func(function_ea), flags=idaapi.FC_PREDS ) # iterate through all basic blocks in # the current routine for block in flow_chart: start_addr = block.startEA - image_base end_addr = block.endEA - image_base if start_addr != end_addr: yield start_addr, end_addr
def __init__(self, fun_addr): super(MyFlowGraph, self).__init__() self.fun = idaapi.get_func(fun_addr) self.startEA = self.fun.startEA self.endEA = self.fun.endEA for bb in idaapi.FlowChart(self.fun): self.__setitem__(bb.id, MyBasicBlock(bb)) self._compute_links() self.edge_map = self.make_graph() self.shortest_path_map = self.dijkstra(self.edge_map) self.size = sum([x.size() for x in self.values()]) self.viewer = MyFlowGraphViewer(self, "Extract(%s)" % idc.GetFunctionName(self.startEA))
def get_code_and_blocks(ea): """Extracts the control flow graph for the function at the given address. Returns a dictionary with the instructions (ea->insn.Instruction) and a list of the basic blocs (bbl.BasicBlock).""" code = {} blocks = {} ida_blocks = set(idaapi.FlowChart(idaapi.get_func(ea))) for bb in ida_blocks: # XXX: it seems that it's not a bug but inter-function jumps! if bb.startEA == bb.endEA: # skip that .. it's IDA's bug #print "skipping block %x : %x in func %x"%(bb.startEA, bb.endEA, ea) continue blocks[bb.startEA] = bbl.BasicBlock(bb.startEA, bb.endEA, {}) for head in idautils.Heads(bb.startEA, bb.endEA): ibytes = idc.GetManyBytes(head, idc.ItemEnd(head) - head) spd = idc.GetSpd(head) code[head] = insn.Instruction(head, ibytes, spd) blocks[bb.startEA].instrs.append(code[head]) next_head = idc.NextHead(head, bb.endEA) if idaapi.isFlow(idc.GetFlags(next_head)): code[head].succ.add(next_head) for suc_bb in (s for s in bb.succs() if s.startEA != s.endEA): #assume head is the last instruction of the block code[head].succ.add(suc_bb.startEA) for bb in (b for b in ida_blocks if b.startEA != b.endEA): for suc_bb in (s for s in bb.succs() if s.startEA != s.endEA): # a jump with zero offset (like, jz 0) gives two succs to the same bb if blocks[suc_bb.startEA] not in blocks[bb.startEA].successors: blocks[bb.startEA].successors.append(blocks[suc_bb.startEA]) blocks[bb.startEA].successors.sort(key=lambda x: x.begin, reverse=True) #FIXME: find a better way .. for block in blocks.itervalues(): if block.instrs[0].addr == ea: #print "found the entry!:", block.instrs block.instrs[0].f_entry = True block.type |= bbl.BasicBlock.ENTRY break else: print "BUG: could not find function entry in instrs!!" #print "blocks:", blocks return code, blocks.values() #XXX: good test function in 0x070016E7 (BIB.dll)