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 hex_ray(self, start, end): contents = '' current = start self.last_branch = start while current < end: # if current != start: # Write reference addresses contents = self.AppendRefAddr(current, self.func_ref_list, contents) # assmbly dispatch line, n_addr = self.asm.dispatch(current, self.reg, self.func) # apply dispatch result contents = self.AppendNewLine(line, contents) if n_addr: current = idc.NextHead(n_addr, end) else: current = idc.NextHead(current, end) self.bmgr.InsertRegStatus(self.last_branch, self.reg) return contents
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 _split_basic_block(start_ea, end_ea): """ IDA Pro's ``idaapi.Flowchart`` does not consider function calls as basic block boundaries. This function takes an address range and splits the basic blocks found within that range so that function calls are considered basic block boundaries. """ split_bbs = [] func_name = idc.GetFunctionName(start_ea) demangled_name = idc.Demangle(func_name, idc.GetLongPrm(idc.INF_SHORT_DN)) if demangled_name: func_name = demangled_name bb_start_addr = start_ea block = idautils.Heads(start_ea, end_ea) for inst in block: mnem = idc.GetMnem(inst) if mnem == 'call' and inst != end_ea: split_bbs.append( dict(start_addr=bb_start_addr, end_addr=idc.NextHead(inst, end_ea + 1) - 1, function=func_name)) bb_start_addr = idc.NextHead(inst, end_ea + 1) if bb_start_addr < end_ea: split_bbs.append( dict(start_addr=bb_start_addr, end_addr=end_ea - 1, function=func_name)) return split_bbs
def functionDummyTracer(self, addr, debug=False): idx = 0 depth = self.depth result = [] ep = addr dummy = False while idx < depth: idx = idx + 1 #print( 'DUMMY : {0} {1} {2} {3}'.format(idx, hex(addr).rstrip('L'), idc.GetDisasm(addr), hex(get_operand_value(addr,0)) )) if debug is True: print('{0} {1} {2} {3}'.format(idx, hex(addr).rstrip('L'), idc.GetDisasm(addr), hex(get_operand_value(addr, 0)))) #dummy = self.findDummyGadget(addr) if idc.GetDisasm(addr)[:4] == "retn": break elif idc.GetDisasm(addr)[:3] == "jmp" or idc.GetDisasm( addr)[:4] == "call": #print get_operand_value(addr,0) addr = get_operand_value(addr, 0) elif self.findFirstDummyGadget(addr) == True: #print "MATCH FIRST" if len(result) > 0: result = [] result.append(self.getGadget(addr, ep, 1)) addr = idc.NextHead(addr) elif len(result) == 1 and self.findSecondDummyGadget( addr, result[0]['reg']) == True: #input gadget result.append(self.getGadget(addr, ep, 2)) addr = idc.NextHead(addr) elif len(result) == 2 and self.findThirdDummyGadget( addr, result[0]['reg']) == True: result.append(self.getGadget(addr, ep, 3)) addr = idc.NextHead(addr) else: addr = idc.NextHead(addr) if debug is True and len(result) > 0: for x in result: print("{0} : {1} {2} ".format( hex(x['addr']).rstrip('L'), hex(x['const']), x['gadget'])) print "" if len(result) == 3: return result else: return False
def add_xrefs(addr, end=idc.BADADDR): """ https://github.com/xyzz/vita-ida-physdump/blob/master/vita_phys_dump.py Searches for MOV / MOVT pair, probably separated by few instructions, and adds xrefs to things that look like addresses """ while addr < end and addr != BADADDR: addr = idc.NextHead(addr) if idc.GetMnem(addr) in ["MOV", "MOVW"]: reg = idc.GetOpnd(addr, 0) if idc.GetOpnd(addr, 1)[0] != "#": continue val = idc.GetOperandValue(addr, 1) found = False next_addr = addr for x in range(16): next_addr = idc.NextHead(next_addr) if idc.GetMnem(next_addr) in ["B", "BX"]: break # TODO: we could handle a lot more situations if we follow branches, but it's getting complicated # if there's a function call and our register is scratch, it will probably get corrupted, bail out if idc.GetMnem(next_addr) in ["BL", "BLX"] and reg in [ "R0", "R1", "R2", "R3" ]: break # if we see a MOVT, do the match! if idc.GetMnem(next_addr) in ["MOVT", "MOVT.W"] and idc.GetOpnd( next_addr, 0) == reg: if idc.GetOpnd(next_addr, 1)[0] == "#": found = True val += idc.GetOperandValue(next_addr, 1) * (2**16) break # if we see something other than MOVT doing something to the register, bail out if idc.GetOpnd(next_addr, 0) == reg or idc.GetOpnd( next_addr, 1) == reg: break if val & 0xFFFF0000 == 0: continue if found: # pair of MOV/MOVT try: idc.OpOffEx(addr, 1, idc.REF_LOW16, val, 0, 0) idc.OpOffEx(next_addr, 1, idc.REF_HIGH16, val, 0, 0) except: print "Failed xref @ %x next_addr %x val %x" % ( addr, next_addr, val) else: # a single MOV instruction try: idc.OpOff(addr, 1, 0) except: print "Failed xref at addr %x" % (addr)
def nextProcName(startAddr, endAddr): addr = startAddr while addr < endAddr: mnem = idc.GetMnem(addr) if mnem == 'push': optype = idc.GetOpType(addr, 0) if optype == 5: procaddr = idc.GetOperandValue(addr, 0) procname = idc.GetString(procaddr, -1, idc.ASCSTR_C) return (procname, idc.NextHead(addr)) addr = idc.NextHead(addr) return ('', addr)
def _find_force_end(loc): """ Locate the first "ret" instruction down from the input location :param loc: Location a function is needed at :return: ItemEnd of the return location. """ loc = idc.NextHead(loc) while not idc.isAlign(idc.GetFlags(loc)) and not idaapi.get_func(loc): if "ret" in idc.GetMnem(loc): return idc.ItemEnd(loc) loc = idc.NextHead(loc) return idc.ItemEnd(idc.PrevHead(loc))
def nextProcAddr(startAddr, endAddr): addr = startAddr while addr < endAddr: mnem = idc.GetMnem(addr) if mnem == 'mov': op1type = idc.GetOpType(addr, 0) op2type = idc.GetOpType(addr, 1) if op1type == 4 and op2type == 1: regname = idc.GetOpnd(addr, 1) if regname == 'eax': offset = idc.GetOperandValue(addr, 0) return (IMPORTS_START + offset, idc.NextHead(addr)) addr = idc.NextHead(addr) return (-1, addr)
def _find_leafs(self): # Loop through every function for func_ea in idautils.Functions(): # Count the number of xrefs to this function func = idaapi.get_func(func_ea) if func: leaf_function = True ea = func.startEA # Loop through all instructions in this function looking # for call instructions; if found, then this is not a leaf. while ea <= func.endEA: idaapi.decode_insn(ea) if idaapi.is_call_insn(ea): leaf_function = False break ea = idc.NextHead(ea) if leaf_function: self.functions.append( Function(start=func.startEA, end=func.endEA, leaf=True, loop=self.has_loop(func), argc=self.argp.argc(func))) # Sort leafs by xref count, largest first self.functions.sort(key=lambda f: f.xrefs, reverse=True)
def GetBranchList(self, start=None, end=None): branch_list = list() current = start if self.arc == ARCHITECTURE['MIPS']: branch_obj = self.asm.mips_asm_class['branch'] jump_obj = self.asm.mips_asm_class['jump'] while current <= end: method = 'do_' + idc.GetMnem(current) if hasattr(branch_obj, method) or hasattr(jump_obj, method): if idc.GetOpType(current, 0) == ASM_TYPE['Imm_Near_Addr']: opr = idc.LocByName(idc.GetOpnd(current, 0)) if opr in self.func_ref_list: branch_list.append(hex(opr)) elif idc.GetOpType(current, 1) == ASM_TYPE['Imm_Near_Addr']: opr = idc.LocByName(idc.GetOpnd(current, 1)) if opr in self.func_ref_list: branch_list.append(hex(opr)) elif idc.GetOpType(current, 2) == ASM_TYPE['Imm_Near_Addr']: opr = idc.LocByName(idc.GetOpnd(current, 2)) if opr in self.func_ref_list: branch_list.append(hex(opr)) current = idc.NextHead(current, end) branch_list = list(set(branch_list)) branch_list.sort() return branch_list
def search_function(): curr_addr = MinEA() end = MaxEA() current_func_name = "" while curr_addr < end: if curr_addr == idc.BADADDR: break elif idc.GetMnem(curr_addr) == 'call': if idc.GetOpnd(curr_addr, 0) in FUNCTIONS_REGISTERS.keys(): func_name_addr = get_string_for_function( curr_addr, FUNCTIONS_REGISTERS[idc.GetOpnd(curr_addr, 0)].lower()) if func_name_addr: try: function_start = idc.GetFunctionAttr( curr_addr, idc.FUNCATTR_START) new_filename = get_fixed_source_filename( func_name_addr) current_func_name = idc.GetFunctionName(function_start) if is_function_name(current_func_name): idaapi.set_name(function_start, new_filename, idaapi.SN_FORCE) else: print "Function:", current_func_name, "was not changed" except: print "failed at address " + hex(curr_addr), \ "function:", current_func_name, "call:", idc.GetOpnd(curr_addr, 0) curr_addr = idc.NextHead(curr_addr)
def ChunkMovePart(inner_start, inner_end_ex, function_address): # maybe the given range covers multiple chunks result = [] fn_print("MACRO move 0x%x-0x%x to 0x%x" % (inner_start, inner_end_ex, function_address)) DisableAutoAnalysis() current_inner_start = inner_start while current_inner_start < inner_end_ex: chunk_start = idc.GetFchunkAttr(current_inner_start, idc.FUNCATTR_START) chunk_end_ex = idc.GetFchunkAttr(current_inner_start, idc.FUNCATTR_END) new_inner_end_ex = inner_end_ex if chunk_end_ex < inner_end_ex: new_inner_end_ex = chunk_end_ex result.extend( _ChunkMovePart(current_inner_start, new_inner_end_ex, function_address)) current_inner_start = idc.GetFchunkAttr(current_inner_start, idc.FUNCATTR_END) while not InsIsCode(current_inner_start): current_inner_start = idc.NextHead(current_inner_start) assert current_inner_start != BADADDR #endwhile #endwhile EnableAutoAnalysis() return result
def FunctionAppendChunk(function_address, A, B_ex): # CAVEAT this function also adds successor hanging instructions! if idaapi.get_func(A) is not None: fn_print("0x%x-0x%x already in function" % (A, B_ex)) return False fn_print("append chunk 0x%x-0x%x to function 0x%x" % (A, B_ex, function_address)) # watch out with hanging instructions if (idaapi.get_func(A) is None) and (idaapi.get_func(idc.PrevHead(B_ex)) is not None): fn_print("chunk 0x%x-0x%x is part hanging, only moving hanging part" % (A, B_ex)) B_ex = A while idaapi.get_func(B_ex) is None: B_ex = idc.NextHead(B_ex) fn_print(" ... instead moving 0x%x-0x%x" % (A, B_ex)) result = idc.AppendFchunk(function_address, A, B_ex) if do_wait: idc.Wait() fn_print("append-chunk 0x%x-0x%x to 0x%x: %d" % (A, B_ex, function_address, result)) if result: now_address = idc.GetFunctionAttr(A, idc.FUNCATTR_START) f2 = idc.GetFunctionAttr(function_address, idc.FUNCATTR_START) assert f2 == now_address, "0x%x/0x%x/0x%x" % (function_address, now_address, f2) return result
def GetBranchList(self, start=None, end=None): self.branch_list = list() current = start if self.arc == ARCHITECTURE['MIPS']: o_iasm = mips_iasm.MIPS_IAsm() branch_obj = o_iasm.mips_asm_class['branch'] jump_obj = o_iasm.mips_asm_class['jump'] while current <= end: method = 'do_' + idc.GetMnem(current) if hasattr(branch_obj, method) or hasattr(jump_obj, method): if self.isNearAddr(idc.GetOpType(current, 0)): opr = idc.LocByName(idc.GetOpnd(current, 0)) if opr in self.func_ref_list: self.branch_list.append(hex(opr)) elif self.isNearAddr(idc.GetOpType(current, 1)): opr = idc.LocByName(idc.GetOpnd(current, 1)) if opr in self.func_ref_list: self.branch_list.append(hex(opr)) elif self.isNearAddr(idc.GetOpType(current, 2)): opr = idc.LocByName(idc.GetOpnd(current, 2)) if opr in self.func_ref_list: self.branch_list.append(hex(opr)) current = idc.NextHead(current, end) self.branch_list = list(set(self.branch_list)) self.branch_list.sort() return self.branch_list
def NthHead(ea, dist): if dist == 0: return ea elif dist < 0: return NthHead(idc.PrevHead(ea), dist + 1) elif dist > 0: return NthHead(idc.NextHead(ea), dist - 1)
def run(self): self.loadInstructionList() self.loadInstructionGroups() functionNamesToEA = {} ea = idc.BeginEA() count = 0 for funcea in Functions(idc.SegStart(ea), idc.SegEnd(ea)): functionInstructions = copy.deepcopy(self.instructions) functionGroups = copy.deepcopy(self.groups) sum = 0 allGroupSum = 0 functionName = idc.GetFunctionName(funcea) functionNamesToEA[functionName] = funcea originalfuncea = funcea currentea = funcea while currentea != idc.BADADDR and currentea < idc.FindFuncEnd( funcea): currentInstruction = idc.GetMnem(currentea) if currentInstruction in self.instructions.keys(): functionInstructions[currentInstruction] += 1 sum += 1 for group in self.groups.keys(): if currentInstruction in self.groups[group][0].keys(): functionGroups[group][1] += 1 functionGroups[group][0][currentInstruction] += 1 allGroupSum += 1 currentea = idc.NextHead(currentea) self.writeInstructionFeatures(self.instructions, sum, functionInstructions, functionName) self.writeInstructionGroupFeatures(self.groups, allGroupSum, functionGroups, functionName) return functionNamesToEA
def calBasicBlockFeature_gemini(block): numericNum = 0 stringNum = 0 transferNum = 0 callNum = 0 InstrNum = 0 arithNum = 0 logicNum = 0 curEA = block.startEA while curEA <= block.endEA: # 数值常量 , 字符常量的数量 numer, stri = calConstantNumber(curEA) numericNum = numericNum + numer stringNum = stringNum + stri # 转移指令的数量 if idc.GetMnem(curEA) in config_for_feature.Gemini_allTransferInstr: transferNum = transferNum + 1 # 调用的数量 if idc.GetMnem(curEA) == 'call': callNum = callNum + 1 # 指令的数量 InstrNum = InstrNum + 1 # 算术指令的数量 if idc.GetMnem(curEA) in config_for_feature.Gemini_arithmeticInstr: arithNum = arithNum + 1 # 逻辑指令 if idc.GetMnem(curEA) in config_for_feature.Gemini_logicInstr: logicNum = logicNum + 1 curEA = idc.NextHead(curEA, block.endEA) fea_str = str(numericNum) + "," + str(stringNum) + "," + str( transferNum) + "," + str(callNum) + "," + str(InstrNum) + "," + str( arithNum) + "," + str(logicNum) + "," return fea_str
def BackwardAnalysis(target_addr, target_reg, start_addr=None, state_cache={}): possible_vals = [] # Obtain backward path # print("calculate the backward path") target_bbl = GetBBLFromEA(target_addr) backward_path = SampleBackwardPath(target_bbl.startEA, start_addr) backward_path = backward_path[1:] backward_path.reverse() # Prepate state # print("pre-execute") state = ExecuteSymbolicBBLeas(backward_path, state_cache=state_cache) # print("execute ok") # state = ExecuteSymbolicBBLs(backward_path) addr = target_bbl.startEA if start_addr != None and target_bbl.startEA <= start_addr and start_addr < target_bbl.endEA: addr = start_addr while addr < target_addr: state = ExecuteSymbolicSingleStep(addr, state) addr = idc.NextHead(addr) possible_val = None if target_reg in state: possible_val = state[target_reg] # Minimalize while possible_val in state.keys(): possible_val = state[possible_val] return [possible_val]
def gen_skeleton_and_eas(reg): ea = idc.ScreenEA() start = idc.GetFunctionAttr(ea, idc.FUNCATTR_START) end = idc.GetFunctionAttr(ea, idc.FUNCATTR_END) ea = start eas = [] skeleton = {} while ea <= end: if idaapi.decode_insn(ea) == 0: print 'error in {0}'.format(GetDisasm(ea)) else: for opn in (0, 1): op = idaapi.cmd.Operands[opn] offset = 0 if op.type == idaapi.o_idpspec3: continue if op.type in (idaapi.o_phrase, idaapi.o_displ) and op.phrase == phrase[reg]: skeleton[op.addr] = ('field_{0}'.format(hex(op.addr)), dtyp[op.dtyp]) eas.append((ea, opn, offset)) ea = idc.NextHead(ea) skeleton = [(elem[0], elem[1][0], elem[1][1]) for elem in sorted(skeleton.items(), key=lambda x: x[0])] return [skeleton, eas]
def revBlock(self): cur_addr = idc.GetRegValue(self.PC) f = idaapi.get_func(cur_addr) if f is None: print( 'Ida analysis sees no function, cannot perform this function') return fc = idaapi.FlowChart(f) block_start = None prev_addr = None prev_block = None for block in fc: block_start = block.startEA #print('block_start 0x%x, cur_addr is 0x%x' % (block_start, cur_addr)) if block_start > cur_addr: break prev_addr = block_start prev_block = block if prev_addr == cur_addr: self.doRevStepInto() elif prev_addr is not None: next_addr = idc.NextHead(prev_addr) if next_addr == cur_addr: ''' reverse two to get there? ''' print('revBlock rev two?') self.doRevStepInto() self.doRevStepInto() else: print('revBlock rev to 0x%x' % prev_addr) self.doRevToAddr(prev_addr, extra_back=0) else: print('must have been top, uncall') self.doRevFinish()
def find_interesting_xors(self): next_xor = idc.FindText(idc.MinEA(), idc.SEARCH_DOWN | idc.SEARCH_NEXT, 0, 0, "xor") while next_xor != idc.BADADDR: if idc.GetOpnd(next_xor, 0) != idc.GetOpnd(next_xor, 1): entry = { "func": "", "addr": next_xor, "loop": False, "disasm": idc.GetDisasm(next_xor) } func = idaapi.get_func(next_xor) if func: entry["func"] = idaapi.get_name(idc.BADADDR, func.startEA) heads = idautils.Heads(next_xor, func.endEA) lxors = [] for head in heads: if idc.GetMnem(head).startswith('j'): jmp_addr = idc.GetOperandValue(head, 0) if jmp_addr < next_xor and jmp_addr > func.startEA: entry["loop"] = True break self._interesting_xors.append(entry) next_xor = idc.FindText(idc.NextHead(next_xor), idc.SEARCH_DOWN | idc.SEARCH_NEXT, 0, 0, "xor")
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 SetAllConditionBpt(): ea = 0x2C13000 while ea < 0x357D000: mnem = idc.GetMnem(ea) if mnem == 'retn': idc.add_bpt(ea) ea = idc.NextHead(ea)
def DelAllConditionBpt(): ea = 0x2C13000 while ea < 0x357D000: mnem = idc.GetMnem(ea) if mnem == 'jmp' or mnem == 'retn': idc.DelBpt(ea) ea = idc.NextHead(ea)
def extract_smi_number(emu, start, end, start_pseudo_taint, dispatch_proto_offset): """ Find call(s) to Register(). Since we are dealing with 64-bit binaries and the address of Register() is the first member of a struct, a call to it will require a dereferencement of the struct pointer with a 'qword ptr' instruction. Here we are looking for which register contains the address of the struct and then identify all the 'qword ptr' on that register (before any other modifications are made to it). """ reg_called = "" call_to_register = "" nb_calls = 0 addr_tmp = start_pseudo_taint while addr_tmp <= end: addr_tmp = idc.NextHead(addr_tmp) # Exit when 'reg_called' is being modified a second time (it doesn't # contains the address we are looking for anymore. if GetOpnd(addr_tmp, 0) == reg_called: reg_called = "" # A register is being set with the interface's address if GetOpnd(addr_tmp, 1) == dispatch_proto_offset: reg_called = GetOpnd(addr_tmp, 0) # This is what we are looking for elif reg_called != "" and GetMnem(addr_tmp) == "call" and GetOpnd( addr_tmp, 0) == "qword ptr [{}]".format(reg_called): next_call = addr_tmp f.write(" [+] Register() is called at : {}\n".format( hex(addr_tmp))) nb_calls += 1 # Get SMI input value f.write(" [+] Starting emulation from {} to {}\n".format( hex(start), hex(addr_tmp))) #emu.hook_add(UC_HOOK_CODE, hook_debug) emu.hook_add(UC_HOOK_CODE, hook_skip_calls) emu.hook_add( UC_HOOK_MEM_READ_UNMAPPED | UC_HOOK_MEM_WRITE_UNMAPPED, hook_mem_invalid) emu.emu_start(start, addr_tmp) r8 = emu.reg_read(UC_X86_REG_R8) if r8 == 0xffffffff: f.write(" [-] SMI number unknown (-1).\n") continue if r8 > STACK_ADDR and r8 < STACK_ADDR + STACK_SIZE: smi_number = emu.mem_read(r8, 1) else: smi_number = r8 f.write(" [+] SMI number : {}.\n".format(hex(ord(smi_number)))) # If there is another call to Register() we will start the emulation # from here start = addr_tmp return nb_calls
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 cls_split_block(fp, startEA, endEA): curName = GetFunctionName(startEA) dem = idc.Demangle(curName, idc.GetLongPrm(INF_SHORT_DN)) if dem != None: curName = dem first = startEA h = idautils.Heads(startEA, endEA) for i in h: mnem = idc.GetMnem(i) if mnem == "call" and i != endEA: print >> fp, "%#010x %#010x %s" % ( first, idc.NextHead(i, endEA + 1) - 1, curName) first = idc.NextHead(i, endEA + 1) if first < endEA: print >> fp, "%#010x %#010x %s" % (first, endEA - 1, curName)
def __init__(self, addr, dispatch, o_reg, o_func): super(MIPS_Asm_Branch, self).__init__(addr) self.branch_reg = o_reg.copy() self.next_addr = idc.NextHead(addr) self.next_result, n_addr = dispatch(self.next_addr, self.branch_reg, o_func) # check_assert("[-] address({0}), dispatch error in branch".format(hex(self.next_addr)), result is None) check_assert("[-] address({0}), dispatch error in branch".format(hex(self.next_addr)), n_addr is None)
def add_xrefs(): """ Searches for MOV / MOVT pair, probably separated by few instructions, and adds xrefs to things that look like addresses """ addr = 0 while addr != idc.BADADDR: addr = idc.NextHead(addr) if idc.GetMnem(addr) in ["MOV", "MOVW"]: reg = idc.GetOpnd(addr, 0) if idc.GetOpnd(addr, 1)[0] != "#": continue val = idc.GetOperandValue(addr, 1) found = False next_addr = addr for x in range(16): next_addr = idc.NextHead(next_addr) if idc.GetMnem(next_addr) in ["B", "BX"]: break # TODO: we could handle a lot more situations if we follow branches, but it's getting complicated # if there's a function call and our register is scratch, it will probably get corrupted, bail out if idc.GetMnem(next_addr) in ["BL", "BLX"] and reg in [ "R0", "R1", "R2", "R3" ]: break # if we see a MOVT, do the match! if idc.GetMnem(next_addr) in ["MOVT", "MOVT.W"] and idc.GetOpnd( next_addr, 0) == reg: if idc.GetOpnd(next_addr, 1)[0] == "#": found = True val += idc.GetOperandValue(next_addr, 1) * (2**16) break # if we see something other than MOVT doing something to the register, bail out if idc.GetOpnd(next_addr, 0) == reg or idc.GetOpnd( next_addr, 1) == reg: break if val & 0xFFFF0000 == 0: continue if found: # pair of MOV/MOVT idc.OpOffEx(next_addr, 1, idc.REF_HIGH16, val, 0, 0) else: # a single MOV instruction idc.OpOff(addr, 1, 0)