我们从Python开源项目中,提取了以下25个代码示例,用于说明如何使用idc.GetMnem()。
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 GetInstructionType(instr_addr): instr_mnem = idc.GetMnem(instr_addr) if instr_mnem.startswith('call'): return CALL_INSTRUCTION elif instr_mnem.startswith('j'): # It seems that there is no other type of instructions # starting with j in x86/x86_64 return BRANCH_INSTRUCTION for assign_instr_mnem in assign_instructions_general: if instr_mnem.startswith(assign_instr_mnem): return ASSIGNMENT_INSTRUCTION for assign_instr_mnem in assign_instructions_fp: if instr_mnem.startswith(assign_instr_mnem): return ASSIGNMENT_INSTRUCTION for compare_instruction in compare_instructions: if instr_mnem.startswith(compare_instruction): return COMPARE_INSTRUCTION for stack_push_instruction in stack_push_instructions: if instr_mnem.startswith(stack_push_instruction): return STACK_PUSH_INSTRUCTION for stack_pop_instruction in stack_pop_instructions: if instr_mnem.startswith(stack_pop_instruction): return STACK_POP_INSTRUCTION return OTHER_INSTRUCTION
def find_shifts(functions): candidate_functions = {} # TODO better to compare number of shifts to overall instruction count? # TODO find shifts in tight loops shift_mnems = set(["shl", "shr", "sar", "sal", "rol", "ror"]) shift_mnems_len = len(shift_mnems) for fva in functions: found_shifts = set([]) cva = fva while cva != idaapi.BADADDR and cva < idc.FindFuncEnd(fva): i = idc.GetMnem(cva) if i in shift_mnems: found_shifts.add(i) g_logger.debug("shift instruction: %s va: 0x%x function: 0x%x", idc.GetDisasm(cva), cva, fva) cva = idc.NextHead(cva) candidate_functions[fva] = 1 - ((shift_mnems_len - len(found_shifts)) / float(shift_mnems_len)) 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 get_import_thunk(import_addr): ''' find import thunk for the given import pointer. this is a function that simply jumps to the external implementation of the routine. Args: import_addr (int): address of import table pointer. Returns: int: address of function thunk. Raises: ValueError: when the thunk does not exist. ''' for xref in idautils.XrefsTo(import_addr): if xref.type != 3: # XrefTypeName(3) == 'Data_Read' continue if idc.GetMnem(xref.frm) != 'jmp': continue return xref.frm raise ValueError('thunk does not exist')
def color_head(ea): flags = idc.GetFlags(ea) if not idc.isCode(flags): return mnem = idc.GetMnem(ea) if mnem == 'call': logger.debug('call: 0x%x', ea) idc.SetColor(ea, idc.CIC_ITEM, CALL_COLOR) elif mnem == 'xor': if idc.GetOpnd(ea, 0) != idc.GetOpnd(ea, 1): logger.debug('non-zero xor: 0x%x', ea) idc.SetColor(ea, idc.CIC_ITEM, ENCRYPT_COLOR) elif mnem in ('sdit', 'sgdt', 'sldt', 'smsw', 'str', 'in', 'cpuid'): logger.debug('anti-vm: 0x%x', ea) idc.SetColor(ea, idc.CIC_ITEM, ANTIANALYSIS_COLOR) elif mnem == 'in': if idc.GetOpnd(ea, 0) in ("3", "2D"): logger.debug('anti-debug: 0x%x', ea) idc.SetColor(ea, idc.CIC_ITEM, ANTIANALYSIS_COLOR) elif mnem in ('rdtsc', 'icebp'): logger.debug('anti-debug: 0x%x', ea) idc.SetColor(ea, idc.CIC_ITEM, ANTIANALYSIS_COLOR)
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 detect_start_and_stop(self): # FIXME:Duplicate code with core (or something similar) start, stop = 0, 0 if self.core.ftype == "PE": start, stop = self.core.fun_mapping["start"] else: if "main" in self.core.fun_mapping: start, stop = self.core.fun_mapping["main"] elif "start" in self.core.fun_mapping: if "__libc_start_main" in self.core.fun_mapping: instrs = list(idautils.FuncItems(self.core.fun_mapping["start"][0])) instrs.reverse() for inst in instrs: arg1 = idc.GetOperandValue(inst, 0) if idc.GetMnem(inst) == "push": start, stop = arg1, self.core.fun_mapping["start"][1] break else: start, stop = self.core.fun_mapping["start"] else: start, stop = idc.BeginEA(), 0 self.start, self.stop = start, stop
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 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 get_mnem(self, ea): return idc.GetMnem(ea)
def is_jump(va): ''' return True if the instruction at the given address appears to be a jump. ''' return idc.GetMnem(va).startswith('j')
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 prevMnemonic(ea, mnem, minaddr=0): res = idc.GetMnem(ea) #print "%x -> %s"% (ea, res) if res == "": return idc.BADADDR if res == mnem: return ea return prevMnemonic( idc.PrevHead(ea, minaddr), mnem, minaddr )
def getDispatchCode(ea): # get dispatch code out of an instruction first, second = (idc.GetOpnd(ea, 0), idc.GetOperandValue(ea, 1)) if first == 'eax': return second raise ValueError("Search resulted in address %08x, but instruction '%s' does fulfill requested constraints"% (ea, idc.GetMnem(ea)))
def FindLastAssignment(ea, register): start,end = database.guessrange(ea) while ea > start: ea = database.prev(ea) m = idc.GetMnem(ea) r = idc.GetOpnd(ea, 0) if m == 'mov' and r == register: return ea continue raise ValueError('FindLastAssignment(0x%x, %s) Found no matches'% (ea, register))
def process_routine(self, rtn_addr, pred_addr=None, rtn_i=1, total_rtn=1): if rtn_addr not in self.functions_cfg: self.functions_cfg[rtn_addr] = MyFlowGraph(rtn_addr) cfg = self.functions_cfg[rtn_addr] path_to = self.config_to_path_function(cfg) if pred_addr is None: candidates = {x for x in idautils.FuncItems(rtn_addr) if idc.GetMnem(x) in cond_jump} else: candidates = {pred_addr} nb_candidates = len(candidates) self.functions_candidates[rtn_addr] = set() self.functions_spurious_instrs[rtn_addr] = set() self.progressbar_loading.reset() self.progressbar_loading.setMaximum(len(candidates)) name = idc.GetFunctionName(rtn_addr) self.result_widget.webview.append("\n=> Function:%s\n" % name) self.log("[result]", "Start processing function: 0x%x" % rtn_addr) for i, addr in zip(xrange(len(candidates)), candidates): path = path_to(addr) res = self.process_addr(rtn_addr, addr, path) if self.STOP: return elif res is None: continue dead_br = "/" if res.dead_branch is None else "%x" % res.dead_branch self.result_widget.webview.append("%x:\t%s\t\tK:%d\tDead:%s" % (addr, to_status_name(res.status), res.k, dead_br)) self.result_widget.webview.verticalScrollBar().setValue(self.result_widget.webview.verticalScrollBar().maximum()) self.loading_stat.setText("Fun: %d/%d Addr: %d/%d" % (rtn_i, total_rtn, i+1, nb_candidates)) self.progressbar_loading.setValue(self.progressbar_loading.value()+1) self.functions_candidates[rtn_addr].add(addr)
def set_start_stop(self, ftype): assert_ida_available() import idc import idaapi import idautils fun_mapping = {idc.GetFunctionName(x): (idaapi.get_func(x).startEA, idaapi.get_func(x).endEA-1) for x in idautils.Functions()} start = idc.BeginEA() stop = 0 if ftype == PE: start, stop = fun_mapping["start"] else: if not idc.isCode(idc.GetFlags(start)): if idc.MakeCode(start) == 0: print "Fail to decode instr !" idaapi.autoWait() if idc.GetFunctionName(start) == "": if idc.MakeFunction(start) == 0: print "Fail to create function !" idaapi.autoWait() fun_mapping = {idc.GetFunctionName(x): (idaapi.get_func(x).startEA, idaapi.get_func(x).endEA-1) for x in idautils.Functions()} if "main" in fun_mapping: start, stop = fun_mapping["main"] elif "start" in fun_mapping: if "__libc_start_main" in fun_mapping: instrs = list(idautils.FuncItems(fun_mapping["start"][0])) instrs.reverse() for inst in instrs: arg1 = idc.GetOperandValue(inst, 0) if idc.GetMnem(inst) == "push": start, stop = arg1, fun_mapping["start"][1] break else: start, stop = fun_mapping["start"] self.config.start, self.config.stop = start, stop
def get_args(addr): """ Retreives the passed arguments to the decryption function. We are only interested in the key and offset to the encrypted string. addr: (int) Address at which the decryption function was called. Returns: key: (int) The key used to decrypt the string. enc_str: (list) Byte array of encrypted string. ins_addr: (int) Address at which the encrypted byte array is referenced. """ found = False foundstr = False foundkey = False while not found: addr = idc.PrevHead(addr) if idc.GetMnem(addr) == "mov" and "r8d" in idc.GetOpnd(addr,0): #print "[+] Found key: 0x%08x at 0x%016x" % (idc.GetOperandValue(addr,1)& 0xffffffff, addr) key = idc.GetOperandValue(addr,1) & 0xffffffff foundkey = True if idc.GetMnem(addr) == "lea" and "rdx" in idc.GetOpnd(addr,0): #print "[+] Found str: 0x%016x at 0x%016x" % (idc.GetOperandValue(addr,1), addr) enc_str_addr = idc.GetOperandValue(addr,1) enc_str = get_encoded_string(enc_str_addr) ins_addr = addr foundstr = True if foundkey and foundstr: found = True return key, enc_str, ins_addr
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 ''' #calculating code segment ranges every time is wasteful code_segs = [] for s in idautils.Segments(): if idaapi.segtype(s) == idaapi.SEG_CODE: s_end = idc.GetSegmentAttr(s, SEGATTR_END) code_segs.append({"start" : s, "end" : s_end}) if not reduce(lambda x, y: x or y, map(lambda x: (x["start"] <= ea) and (x["end"] > ea), code_segs)): return False ''' #this is-in-function check is enough (segment check redundant) if we trust function ID'ing anyway. 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 main(): base_addr = 0 ea = 0 idc.MakeFunction(ea) # heuristic while(true): mnemonic = idc.GetMnem(ea) if "LDR" in mnemonic: base_str = idc.GetOpnd(ea, 1) base_addr = int(base_str.split("=")[1], 16) break ea += 4 print("[+] rebasing to address 0x%x" % (base_addr)) idc.rebase_program(base_addr, idc.MSF_FIXONCE) idaapi.autoWait() segment_start = base_addr segment_end = idc.GetSegmentAttr(segment_start, idc.SEGATTR_END) ea = segment_start print("[+] searching and defining functions") while ea != idc.BADADDR: ea = idc.FindBinary(ea, idc.SEARCH_DOWN, "BF A9", 16) if ea != idc.BADADDR: ea = ea - 2 if (ea % 4) == 0 and idc.GetFlags(ea) < 0x200: # print("[+] defining a function at 0x%x" % (ea)) idc.MakeFunction(ea) ea = ea + 4 idc.AnalyzeArea(segment_start, segment_end) idaapi.autoWait()
def def_functions(s_start): num_added_functions = 0 s_addr = s_start s_end = idc.GetSegmentAttr(s_start, SEGATTR_END) #idc.SegEnd(segm) print "0x%08x 0x%08x" % (s_start, s_end) while (s_addr < s_end): print "Testing address 0x%08x" % s_addr #optimization assumes that function chunks are consecutive (no "function-in-function" monkey business) if (idaapi.get_func(s_addr)): next_func = idc.NextFunction(s_addr) ea = s_addr for c in idautils.Chunks(s_addr): #only use chunks in lookahead that do not jump over the next function and that are not smaller than where we are atm. if (c[1] > ea) and (c[1] <= next_func): ea = c[1] if ea == s_addr: s_addr += 2 else: s_addr = ea #s_addr += 4 continue else: #This is not a good optimization, there WILL be data refs to function start addresses sometimes. ''' if sum(1 for _ in (CodeRefsTo(s_addr, 1))) != 0: s_addr += 4 continue ''' #also add STMFD if ((idc.GetMnem(s_addr) == "STM") and ("SP!" in idc.GetOpnd(s_addr, 0)) and ("LR" in idc.GetOpnd(s_addr, 1))) or (((idc.GetMnem(s_addr) == "PUSH") or (idc.GetMnem(s_addr) == "PUSH.W") or (idc.GetMnem(s_addr) == "STR.W") ) and ("LR" in idc.GetOpnd(s_addr, 0))): print "Found function at 0x%08x" % s_addr idc.MakeFunction(s_addr) f = idaapi.get_func(s_addr) if (type(f) == type(None)): print "Failed to create function! Undefined instructions?" s_addr += 2 else: num_added_functions += 1 ea = -1 for c in idautils.Chunks(s_addr): if c[1] > ea: ea = c[1] if ea != -1: s_addr = ea #failed? else: s_addr += 2 else: s_addr += 2 print "finished segment" return num_added_functions