我们从Python开源项目中,提取了以下18个代码示例,用于说明如何使用idc.NextHead()。
def find_unusual_xors(functions): # TODO find xors in tight loops candidate_functions = [] for fva in functions: cva = fva while cva != idaapi.BADADDR and cva < idc.FindFuncEnd(fva): if idc.GetMnem(cva) == "xor": if idc.GetOpnd(cva, 0) != idc.GetOpnd(cva, 1): g_logger.debug("suspicious XOR instruction at 0x%08X in function 0x%08X: %s", cva, fva, idc.GetDisasm(cva)) ph = idc.PrevHead(cva) nh = idc.NextHead(cva) ip = idc.GetDisasm(ph) ia = idc.GetDisasm(nh) if ip and ia: g_logger.debug("Instructions: %s; %s; %s", ip, idc.GetDisasm(cva), ia) if ph or nh: if is_security_cookie(cva, ph, nh): g_logger.debug("XOR related to security cookie: %s", idc.GetDisasm(cva)) else: g_logger.debug("unusual XOR: %s", idc.GetDisasm(cva)) candidate_functions.append(fva) break cva = idc.NextHead(cva) return candidate_functions
def find_suspicous_movs(functions): candidate_functions = [] regs = ["esp", "ebp", "rsp", "rbp"] for fva in functions: for (loopStart, loopEnd) in find_tight_loops(fva): cva = loopStart while cva <= loopEnd: if idc.GetMnem(cva) == "mov": if is_list_item_in_s(regs, idc.GetOpnd(cva, 0)): cva = idc.NextHead(cva) continue # identify register dereferenced writes to memory, e.g. mov [eax], cl if idc.GetOpType(cva, 0) == OP_TYPE.BASE_INDEX.value: if idc.GetOpType(cva, 1) not in [OP_TYPE.IMMEDIATE.value, OP_TYPE.IMMEDIATE_FAR.value, OP_TYPE.IMMEDIATE_NEAR.value]: g_logger.debug("suspicious MOV instruction at 0x%08X in function 0x%08X: %s", cva, fva, idc.GetDisasm(cva)) candidate_functions.append(fva) break cva = idc.NextHead(cva) return candidate_functions
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 revise_syscall(rename=False): if not rename: print('Change the function name with `CGCHeler.revise_syscall(True)`.') # visit all instructions start_ea, end_ea = utils.get_seg_range('.text') eax = -1 ip = start_ea while ip < end_ea and ip != idaapi.BADADDR: if 'int' in idc.GetMnem(ip) and '80h' == idc.GetOpnd(ip, 0): if eax != -1: # fix comment and function name print('{}: {}'.format(hex(ip), syscall_table[eax])) idc.MakeComm(ip, 'CGC syscall: {}'.format(syscall_table[eax])) if rename: print('Change {} to {}'.format(idc.GetFunctionName(ip), syscall_table[eax])) idc.MakeName(idc.GetFunctionAttr(ip, idc.FUNCATTR_START), syscall_table[eax]) elif 'mov' in idc.GetMnem(ip) and 'eax' == idc.GetOpnd(ip, 0) and 5 == idc.GetOpType(ip, 1): value = idc.GetOpnd(ip, 1) if re.search('^[0-9]+$', value) != None: eax = int(value) if eax > 7 or eax < 1: eax = -1 ip = idc.NextHead(ip)
def create_call_map(self, ftype): assert_ida_available() import idc import idautils seg_mapping = {idc.SegName(x): (idc.SegStart(x), idc.SegEnd(x)) for x in idautils.Segments()} imports = seg_mapping[".idata"] if ftype == PE else seg_mapping['.plt'] start, stop = seg_mapping[".text"] current = start while current <= stop: inst = current if idc.GetMnem(inst) in ["call", "jmp"]: value = idc.GetOperandValue(inst, 0) name = idc.GetOpnd(inst, 0) if imports[0] <= value <= imports[1]: entry = self.config.call_map.add() entry.address = inst entry.name = name current = idc.NextHead(current, stop)
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 highlight_non_zero_xor(self, ea): highlight_eas = [] if self.get_mnem(ea) == "xor": if idc.GetOpnd(ea, 0) != idc.GetOpnd(ea, 1): ph = idc.PrevHead(ea) nh = idc.NextHead(ea) ip = idc.GetDisasm(ph) ia = idc.GetDisasm(nh) if ph or nh: if not self.is_security_cookie(ea, ph, nh): highlight_eas.append(ea) MySetColor(ea, self.color) return highlight_eas
def is_security_cookie(self, va, ph, nh): # for security cookie check the xor should use ESP or EBP if idc.GetOpnd(va, 1) not in ["esp", "ebp", "rsp", "rbp"]: return False if "security" in idc.GetOpnd(ph, 1): return True elif "security" in idc.GetDisasm(nh): return True elif "security" in idc.GetDisasm(idc.NextHead(nh)): return True return False
def highlight_instructions(highlighters): ea = idc.NextHead(0) while ea != idaapi.BADADDR: for h in highlighters: h.highlight(ea) ea = idc.NextHead(ea)
def is_security_cookie(va, ph, nh): # for security cookie check the xor should use ESP or EBP if idc.GetOpnd(va, 1) not in ["esp", "ebp", "rsp", "rbp"]: return False if "security" in idc.GetOpnd(ph, 1): return True elif "security" in idc.GetDisasm(nh): return True elif "security" in idc.GetDisasm(idc.NextHead(nh)): return True return False
def nextMnemonic(ea, mnem, maxaddr=0xc0*0x1000000): res = idc.GetMnem(ea) if res == "": return idc.BADADDR if res == mnem: return ea return nextMnemonic( idc.NextHead(ea, maxaddr), mnem, maxaddr )
def save_function_addr(addr, func): max_addr = addr + 30 while True: addr = idc.NextHead(addr) if addr < max_addr: if GetMnem(addr) == "mov" and "eax" in GetOpnd(addr, 1): MakeName(GetOperandValue(addr,0), "p_"+dec) break else: break
def iter_lines(): """ Iterate through all line addresses in the IDB Yields addresses of all lines. """ for ea in idautils.Segments(): seg_start = idc.SegStart(ea) seg_end = idc.SegEnd(ea) cur_addr = seg_start while (cur_addr < seg_end) and (cur_addr != idaapi.BADADDR): yield cur_addr cur_addr = idc.NextHead(cur_addr)
def compute_nb_instr(self): return 0 # FIXME: by iterating all segments count = 0 start, stop = self.seg_mapping[".text"] # TODO: Iterate all executable segs current = start while current <= stop: if idc.isCode(idc.GetFlags(current)): count += 1 current = idc.NextHead(current, stop) return count
def generate_dead_alive_dump(self): f = Path("dead_or_alive_dump.txt") handle = f.open("w") for cfg in self.functions_cfg.values(): for bb in cfg.values(): for i in bb.instrs: status = bb.instrs_status[i] if bb.is_alive() else Status.DEAD size = idc.NextHead(i)-i handle.write(u"%x,%d,%s\n" % (i, size, status)) handle.close()
def decode_here_clicked(self): inst = idc.here() if not idc.isCode(idc.GetFlags(inst)): print "Not code instruction" else: raw = idc.GetManyBytes(inst, idc.NextHead(inst)-inst) s = to_hex(raw) self.decode_ir(s)
def _fill_instrs(self): cur_addr = self.startEA while cur_addr != idc.BADADDR: self.instrs.append(cur_addr) cur_addr = idc.NextHead(cur_addr, self.endEA)
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)