def is_code_ea(ea): if idaapi.cvar.inf.procname == "ARM": # In case of ARM code in THUMB mode we sometimes get pointers with thumb bit set flags = idaapi.getFlags(ea & -2) # flags_t else: flags = idaapi.getFlags(ea) return idaapi.isCode(flags)
def __new__(cls, ea): """Return the values of the array at address ``ea``""" numerics = { idaapi.FF_BYTE: 'B', idaapi.FF_WORD: 'H', idaapi.FF_DWRD: 'L', idaapi.FF_QWRD: 'Q', idaapi.FF_FLOAT: 'f', idaapi.FF_DOUBLE: 'd', } strings = { 1: 'c', 2: 'u', } fl = idaapi.getFlags(ea) elesize = idaapi.get_full_data_elsize(ea, idaapi.getFlags(ea)) if fl & idaapi.FF_ASCI == idaapi.FF_ASCI: t = strings[elesize] elif fl & idaapi.FF_STRU == idaapi.FF_STRU: t = type.structure.id(ea) raise TypeError, 'array : Unable to handle an array of structure type %x' % t else: ch = numerics[fl & idaapi.DT_TYPE] t = ch.lower() if idaapi.is_signed_data(fl) else ch res = array.array(t, read(ea, cls.size(ea))) if len(res) != cls.length(ea): logging.warn('array : Unexpected length : (%d != %d)', len(res), cls.length(ea)) return res
def apply(ea, st): """Apply the structure ``st`` to the address at ``ea``""" ti = idaapi.opinfo_t() res = idaapi.get_opinfo(ea, 0, idaapi.getFlags(ea), ti) ti.tid = st.id return idaapi.set_opinfo(ea, 0, idaapi.getFlags(ea) | idaapi.struflag(), ti)
def make_view(self, object_version, address): # apply view ri = idaapi.refinfo_t() ri.target = idc.BADADDR ri.base = 0 ri.tdelta = 0 for ((view_offset, operand), view_value) in object_version.get_offset_valueviews().iteritems(): if view_value == 'signeddecimal': if not (idaapi.is_invsign( address + view_offset, idaapi.getFlags(address + view_offset), operand)): idaapi.op_dec(address + view_offset, operand) # we assume defaut operand is unsigned ! idaapi.toggle_sign(address + view_offset, operand) elif view_value == 'unsigneddecimal': idaapi.op_dec(address + view_offset, operand) elif view_value == 'signedhexadecimal': idaapi.op_hex(address + view_offset, operand) if not (idaapi.is_invsign( address + view_offset, idaapi.getFlags(address + view_offset), operand)): idaapi.toggle_sign(address + view_offset, operand) elif view_value == 'unsignedhexadecimal': idaapi.op_hex(address + view_offset, operand) if idaapi.is_invsign(address + view_offset, idaapi.getFlags(address + view_offset), operand): idaapi.toggle_sign(address + view_offset, operand) elif view_value.startswith('offset'): dash = view_value.find("-") if dash != -1: op_type_str = view_value[dash + 1:] op_type = YaToolIDATools.OFFSET_TYPE_MAP[op_type_str] else: op_type = idc.REF_OFF32 ri.flags = op_type idaapi.op_offset_ex(address + view_offset, 1, ri) # idaapi.set_op_type(address + view_offset, idaapi.offflag(), operand) elif view_value == 'char': idaapi.op_chr(address + view_offset, operand) elif view_value == 'binary': idaapi.op_bin(address + view_offset, operand) elif view_value == 'octal': idaapi.op_oct(address + view_offset, operand) for ((register_offset, register_name), (end_offset, new_name) ) in object_version.get_offset_registerviews().iteritems(): func = idaapi.get_func(address) funcEA = func.startEA ret = idaapi.add_regvar(func, funcEA + register_offset, funcEA + end_offset, register_name, new_name, None) if ret != REGVAR_ERROR_OK: logger.warning( "make register_view failed: func=0x%08X, 0x%08X->0x%08X %s->%s, error=%d" % (funcEA, funcEA + register_offset, funcEA + end_offset, register_name, new_name, ret))
def _handle_calls(self, fn, fn_an): num_calls = len(fn_an['calls']) if num_calls != 1: return dis = fn_an['calls'][0] if dis.Op1.type not in (o_imm, o_far, o_near, o_mem): return ea = dis.Op1.value if not ea and dis.Op1.addr: ea = dis.Op1.addr if idaapi.has_dummy_name(idaapi.getFlags(ea)): return # TODO: check is there jmp, push+retn then don't rename the func if fn_an['strange_flow']: return possible_name = idaapi.get_ea_name(ea) if not possible_name or possible_name in blacklist: return normalized = self.normalize_name(possible_name) # if self._cfg.get('auto_rename'): if len(fn_an['math']) < self._MIN_MAX_MATH_OPS_TO_ALLOW_RENAME: idaapi.do_name_anyway(fn.startEA, normalized) # TODO: add an API to the view print 'fn: %#08x: %d calls, %d math%s possible name: %s, normalized: %s' % ( fn.startEA, len(fn_an['calls']), len(fn_an['math']), 'has bads' if fn_an['has_bads'] else '', possible_name, normalized)
def Undefs(*args): """ Enumerate undefined bytes @param <range>: see getrange @return: list of addresses of undefined bytes Example:: for ea in Undefs(FirstSeg(), BADADDR): if isCode(GetFlags(PrevHead(ea))) and (ea%4)!=0 and iszero(ea, 4-(ea%4)): MakeAlign(ea, 4-(ea%4), 2) Will add alignment directives after code. """ (first, last) = getrange(args) ea = first # explicitly testing first byte, since find_unknown # implicitly sets SEARCH_NEXT flag if ea < last and not isUnknown(idaapi.getFlags(ea)): ea = idaapi.find_unknown(ea, idaapi.SEARCH_DOWN) while ea != idaapi.BADADDR and ea < last: yield ea ea = idaapi.find_unknown(ea, idaapi.SEARCH_DOWN)
def yara_sig_code_selection(): """Return some internal details for how we want to signature the selection""" cur_ea = SelStart() end_ea = SelEnd() d = i386DisasmParts() comments = [] rulelines = [] # Iterate over selected code bytes while cur_ea < end_ea: # Did we inadvertently select something that wasn't code? if not idc.isCode(idaapi.getFlags(cur_ea)): noncodebytes = "".join([chr(Byte(x)) for x in xrange(cur_ea, NextHead(cur_ea, end_ea))]) comments.append("Non-code at %08X: %d bytes" % (cur_ea, len(noncodebytes))) rulelines.append(binhex_spaced(noncodebytes)) else: curlen = idaapi.decode_insn(cur_ea) # Match IDA's disassembly format comments.append(GetDisasm(cur_ea)) # But we need our custom object to process curbytes = "".join([chr(Byte(b)) for b in xrange(cur_ea, cur_ea + curlen)]) codefrag = d.disasm(curbytes, 0, cur_ea) rulelines.append(yara_wildcard_instruction(codefrag)) # move along cur_ea = NextHead(cur_ea, end_ea) return (SelStart(), comments, rulelines)
def __init__(self, func): self.src = func ea = func.startEA self.ea = ea self.name = idaapi.get_func_name(ea) self.elts = [] if idaapi.is_func_tail(func): self.name += "_tail_" + str(ea) fr = idaapi.get_frame(func) struc_vars = [] if fr == None: self.frame = None else: self.frame = struct.frame_node(fr, func) struc_vars = self.frame.struct_vars while ea < func.endEA: if idaapi.isData(idaapi.getFlags(ea)): self.elts.append(data.data_node(ea, idaapi.next_not_tail(ea))) else: if ea == func.startEA and not (idaapi.is_func_tail(func)): self.elts.append(insn.insn_node(ea, struc_vars)) else: self.elts.append( names.name_wrap_insn(ea, insn.insn_node(ea, struc_vars))) ea = idaapi.next_head(ea, func.endEA)
def ArrayItems(*args): """ Enumerate array items @param ea: address of the array you want the items enumerated, defaults to here() @return: list of each item in the array. Example:: for ea in ArrayItems(): pname= GetString(Dword(ea)) MakeName(Dword(ea+4)&~1, "task_%s" % pname) MakeName(Dword(ea+8), "taskinfo_%s" % pame) MakeName(Dword(ea+12), "stack_%s" % pame) Assuming the cursor is on an array of structs, in which the first struct item points to a name, this will name the other items in the struct. """ ea = args[0] if len(args)>0 else idc.here() s= idc.ItemSize(ea) ss= idaapi.get_data_elsize(ea, idaapi.getFlags(ea)) n= s/ss for i in range(n): yield ea+i*ss
def getType(ea): module, F = idaapi, (idaapi.getFlags(ea) & idaapi.DT_TYPE) res, = itertools.islice( (v for n, v in itertools.imap(lambda n: (n, getattr(module, n)), dir(module)) if n.startswith('FF_') and (F == v & 0xffffffff)), 1) return res
def __init__(self, func): self.src = func ea = func.startEA self.ea = ea self.name = idaapi.get_func_name(ea) self.elts = [] if idaapi.is_func_tail(func): self.name += "_tail_"+str(ea) fr = idaapi.get_frame(func) struc_vars = [] if fr == None: self.frame = None else: self.frame = struct.frame_node(fr, func) struc_vars = self.frame.struct_vars while ea < func.endEA: if idaapi.isData(idaapi.getFlags(ea)): self.elts.append(data.data_node(ea, idaapi.next_not_tail(ea))) else: if ea == func.startEA and not (idaapi.is_func_tail(func)): self.elts.append(insn.insn_node(ea, struc_vars)) else: self.elts.append(names.name_wrap_insn(ea, insn.insn_node(ea, struc_vars))) ea = idaapi.next_head(ea, func.endEA)
def GetInstructions(start_ea, end_ea): ins = [] for head in idautils.Heads(start_ea, end_ea): if idaapi.isCode(idaapi.getFlags(head)): ins.append(Instruction(head, GetDisasm(head))) return ins
def yara_sig_code_selection(): """Return some internal details for how we want to signature the selection""" cur_ea = SelStart() end_ea = SelEnd() d = i386DisasmParts() comments = [] rulelines = [] # Iterate over selected code bytes while cur_ea < end_ea: # Did we inadvertently select something that wasn't code? if not idc.isCode(idaapi.getFlags(cur_ea)): noncodebytes = "".join([ chr(Byte(x)) for x in xrange(cur_ea, NextHead(cur_ea, end_ea)) ]) comments.append("Non-code at %08X: %d bytes" % (cur_ea, len(noncodebytes))) rulelines.append(binhex_spaced(noncodebytes)) else: curlen = idaapi.decode_insn(cur_ea) # Match IDA's disassembly format comments.append(GetDisasm(cur_ea)) # But we need our custom object to process curbytes = "".join( [chr(Byte(b)) for b in xrange(cur_ea, cur_ea + curlen)]) codefrag = d.disasm(curbytes, 0, cur_ea) rulelines.append(yara_wildcard_instruction(codefrag)) # move along cur_ea = NextHead(cur_ea, end_ea) return (SelStart(), comments, rulelines)
def run(self, arg): """ loop through all functions, collect "self._data", then show view @param: arg : -- """ try: self._data = dict() count = idaapi.get_func_qty() for i in xrange(count): fn = idaapi.getn_func(i) fn_an = self.analyze_func(fn) # if fn_an['math']: # print 'fn: %#08x has math' % fn.startEA if idaapi.has_dummy_name(idaapi.getFlags(fn.startEA)): self._handle_calls(fn, fn_an) self._handle_tags(fn, fn_an) if self.view: self.view.Close(idaapi.PluginForm.FORM_NO_CONTEXT) self.view = AutoREView(self._data) self.view.Show() except: idaapi.msg('AutoRE: error: %s\n' % traceback.format_exc())
def ArrayItems(*args): """ Enumerate array items @param ea: address of the array you want the items enumerated, defaults to here() @return: list of each item in the array. Example:: for ea in ArrayItems(): pname= GetString(Dword(ea)) MakeName(Dword(ea+4)&~1, "task_%s" % pname) MakeName(Dword(ea+8), "taskinfo_%s" % pame) MakeName(Dword(ea+12), "stack_%s" % pame) Assuming the cursor is on an array of structs, in which the first struct item points to a name, this will name the other items in the struct. """ ea = args[0] if len(args) > 0 else idc.here() s = idc.ItemSize(ea) ss = idaapi.get_data_elsize(ea, idaapi.getFlags(ea)) n = s / ss for i in range(n): yield ea + i * ss
def Undefs(*args): """ Enumerate undefined bytes @param <range>: see getrange @return: list of addresses of undefined bytes Example:: for ea in Undefs(FirstSeg(), BADADDR): if isCode(GetFlags(PrevHead(ea))) and (ea%4)!=0 and iszero(ea, 4-(ea%4)): MakeAlign(ea, 4-(ea%4), 2) Will add alignment directives after code. """ (first, last)= getrange(args) ea= first # explicitly testing first byte, since find_unknown # implicitly sets SEARCH_NEXT flag if ea<last and not isUnknown(idaapi.getFlags(ea)): ea= idaapi.find_unknown(ea, idaapi.SEARCH_DOWN) while ea!=idaapi.BADADDR and ea<last: yield ea ea= idaapi.find_unknown(ea, idaapi.SEARCH_DOWN)
def findUnidentifiedFunctions(): # just get all not-function code and convert it to functions next = idaapi.cvar.inf.minEA while next != idaapi.BADADDR: next = idaapi.find_not_func(next, 1) flags = idaapi.getFlags(next) if idaapi.isCode(flags): idc.MakeFunction(next)
def Run(self): for function_ea in idautils.Functions(): for inst_ea in idautils.FuncItems(function_ea): if idaapi.isCode(idaapi.getFlags(inst_ea)): mnemonic = idc.GetMnem(inst_ea) if (mnemonic == 'rdmsr' or mnemonic == 'wrmsr'): msr_code = self.GetMsrCodeFromOperand(inst_ea) self.PrintMsrTable(msr_code, function_ea, inst_ea)
def isDefined(ea): flags = idaapi.getFlags(ea) if not idc.isStruct(flags): return False if not idc.isHead(flags): return False # TODO: verify the actual struct type. return True
def highlight(self, color=COLOR): for ea in idautils.Heads(): if idaapi.isCode(idaapi.getFlags(ea)) and idaapi.is_call_insn(ea): current_color = idaapi.get_item_color(ea) if current_color == self.COLOR: idaapi.set_item_color(ea, idc.DEFCOLOR) elif current_color == idc.DEFCOLOR: idaapi.set_item_color(ea, self.COLOR)
def isVtable(self, addr): function = self.get_ptr(addr) # Check if vtable has ref and its first pointer lies within code segment if hasRef( getFlags(addr) ) and function >= self.text.startEA and function <= self.text.endEA: return True return False
def findUnidentifiedFunctions(): # just get all not-function code and convert it to functions next = idaapi.cvar.inf.minEA while next != idaapi.BADADDR: next = idaapi.find_not_func(next, SEARCH_DOWN) flags = idaapi.getFlags(next) if idaapi.isCode(flags): idc.MakeFunction(next)
def iterate(ea, start, next): ea = ea if (idaapi.getFlags(ea)&idaapi.FF_DATA) else idaapi.prev_head(ea,0) addr = start(ea) while addr != idaapi.BADADDR: yield addr addr = next(ea, addr) return
def isDefined(ea): flags = idaapi.getFlags(ea) if not idc.isStruct(flags): return False if not idc.isHead(flags): return False if idaapi.get_name(idaapi.BADADDR, ea) != TypeDescriptor.makeName(ea): return False return True
def __getlabel(cls, ea): try: f = idaapi.getFlags(ea) if idaapi.has_dummy_name(f) or idaapi.has_user_name(f): r, = xref.data_up(ea) return cls.__getarray(r) except TypeError: pass raise TypeError, "Unable to instantiate a switch_info_ex_t at target label : %x" % ea
def GetInstructions(self, start_ea, end_ea): # #Returns a List of all instructions in the Range start_ea, end_ea # ins = [] for head in idautils.Heads(start_ea, end_ea): if idaapi.isCode(idaapi.getFlags(head)): ins.append(GetDisasm(head)) return ins
def process_func(i): """Convert function i into a mega file line.""" func = idaapi.getn_func(i) if not func: return if idaapi.has_name(idaapi.getFlags(func.startEA)) and \ not (func.flags & idaapi.FUNC_LIB): return create_func_signature(func.startEA, func.endEA - func.startEA)
def id(ea): """Return the identifier of the structure at address ``ea``""" assert type( ea ) == idaapi.FF_STRU, 'Specified IDA Type is not an FF_STRU(%x) : %x' % ( idaapi.FF_STRU, type(ea)) ti = idaapi.opinfo_t() res = idaapi.get_opinfo(ea, 0, idaapi.getFlags(ea), ti) assert res, 'idaapi.get_opinfo returned %x at %x' % (res, ea) return ti.tid
def GetInstructions(start_ea, end_ea): """ Return a list of all the instructions in the range [start_ea, end_ea]. """ ins = [] for head in idautils.Heads(start_ea, end_ea): if idaapi.isCode(idaapi.getFlags(head)): ins.append(Instruction(head, GetDisasm(head))) return ins
def handleDebugStepOver(self): if self.clientSocket is None: return if self.debugBreakId is None: return cur_ea = self.debugBreakId decode_insn(cur_ea) next_ea = cur_ea + idaapi.cmd.size if isCode(getFlags(next_ea)) == False: return entry = None # remove current if self.debugBreakId in self.idbHookMap: entry = self.idbHookMap[self.debugBreakId] outJSON = json.dumps({ "req_id": kFridaLink_DelHookRequest, "data": entry.genDelRequest() }) del self.idbHookMap[self.debugBreakId] self.clientSocket.sendto(outJSON, self.clientAddress) SetColor(self.debugBreakId, CIC_ITEM, kIDAViewColor_Reset) refresh_idaview_anyway() offset, moduleName = self.getAddressDetails(next_ea) # install next if entry == None: hook = InstHook() hook.id = next_ea hook.once = once hook.breakpoint = True entry = HookEntry(hook) entry.hook.id = next_ea entry.hook.mnemonic = GetDisasm(next_ea) entry.hook.address = offset entry.hook.module = moduleName outJSON = json.dumps({ "req_id": kFridaLink_SetHookRequest, "data": entry.genSetRequest() }) self.clientSocket.sendto(outJSON, self.clientAddress) self.idbHookMap[next_ea] = entry self.idbHooksView.setContent(self.idbHookMap) self.handleDebugContinue()
def applied_structs(): dataseg = sark.Segment(name='seg004') for line in dataseg.lines: ti = idaapi.opinfo_t() f = idaapi.getFlags(line.ea) if idaapi.get_opinfo(line.ea, 0, f, ti): struct_name = idaapi.get_struc_name(ti.tid) if struct_name: print (line.ea - dataseg.ea, struct_name) yield line.ea - dataseg.ea, struct_name
def _check_is_jmp_wrapper(self, dis): # checks instructions like `jmp API` if dis.itype not in self._JMP_TYPES: return # handle call wrappers like jmp GetProcAddress if dis.Op1.type == idaapi.o_mem and dis.Op1.addr: # TODO: check is there better way to determine is the function a wrapper v = dis.Op1.addr if v and dis.itype == idaapi.NN_jmpni and idaapi.isData(idaapi.getFlags(v)) and self.__is_ptr_val(idaapi.getFlags(v)): v = self.__get_ptr_val(v) return v
def get_fptrs(): d = {} nn = idaapi.netnode('$ mips') for fn in idautils.Functions(): for ea in idautils.FuncItems(fn): if not idc.isCode(idaapi.getFlags(ea)): continue target = nn.altval(ea) - 1 if target != -1: d[ea] = idc.Name(target) return d
def populate(self): address = self.address while True: if Const.EA64: func_address = idaapi.get_64bit(address) else: func_address = idaapi.get_32bit(address) flags = idaapi.getFlags(func_address) # flags_t if idaapi.isCode(flags): self.virtual_functions.append(VirtualFunction(func_address, address - self.address)) address += Const.EA_SIZE else: break
def run(self, arg): idaapi.msg("[i2q Plugin] Syncing ...\n") self.addr = idaapi.get_screen_ea() if (self.old_addr != self.addr): if (idaapi.isCode(idaapi.getFlags(self.addr))): #idaapi.msg("[i2q Plugin] update instrunction address\n") update_address("iaddr", self.addr) else: # Data Address #idaapi.msg("[i2q Plugin] update data address\n") update_address("daddr", self.addr) self.old_addr = self.addr
def run(self, arg): idaapi.msg("[QIRA Plugin] Syncing with Qira\n") self.addr = idaapi.get_screen_ea() if (self.old_addr != self.addr): if (idaapi.isCode(idaapi.getFlags(self.addr))): # don't update the address if it's already the qira address if (self.addr != qira_address): # Instruction Address set_qira_address(self.addr) update_address("iaddr", self.addr) else: # Data Address update_address("daddr", self.addr) self.old_addr = self.addr
def OnViewCurpos(self): self.addr = idaapi.get_screen_ea() if (self.old_addr != self.addr): if (idaapi.isCode(idaapi.getFlags(self.addr))): # don't update the address if it's already the qira address or None if (self.addr is not None) and (self.addr != qira_address): #idaapi.msg("[QIRA Plugin] Qira Address %x \n" % (self.addr)) # Instruction Address set_qira_address(self.addr) update_address("iaddr", self.addr) else: # Data Address update_address("daddr", self.addr) self.old_addr = self.addr
def Heads(*args): """ Enumerate array items @param <range>: see getrange @return: list of all heads """ (first, last)= getrange(args) ea= first if ea<last and not idaapi.isHead(idaapi.getFlags(ea)): ea= idaapi.next_head(ea, last) while ea!=BADADDR and ea<last: yield ea ea= idaapi.next_head(ea, last)
def define(ea, count): # TODO: sanity checks idaapi.do_unknown_range(ea, count * 4, idaapi.DOUNK_DELNAMES) idaapi.doDwrd(ea, 4) idaapi.do_data_ex(ea, idaapi.getFlags(ea), count * 4, idaapi.BADADDR) # TODO: rewrite into idaapi calls idc.SetArrayFormat(ea, idc.AP_INDEX | idc.AP_IDXDEC, 1, 0) # Entry 0 describes the class itself => I can find out the class name. bcd = BaseClassDescriptor(idaapi.get_full_long(ea)) idaapi.set_name(ea, "??_R2" + bcd.typeDescriptor.baseMangledName + "8", 0) i = 1 while i < count: bcd = BaseClassDescriptor(idaapi.get_full_long(ea + i * 4)) i += 1
def create_68k_jump_table(idiom_ea): """ Create a jump table at the current address in the database. This function sets the switch idiom attributes for the current address in the database. If switch_base is none, find_switch_attributes() was not successful. """ switch_base, max_offset, value_base, value_width, defjump = _find_switch_attributes(idiom_ea) if switch_base != None: jump_table_size = max_offset + 1 total_switch_size = 2 * (max_offset + 1) switch_base_ea = idc.GetOperandValue(idiom_ea, 0) _make_offset_table(switch_base, jump_table_size) # create the switch info object si = idaapi.switch_info_ex_t() si.set_jtable_element_size(2) si.startea = idiom_ea si.jumps = switch_base si.elbase = switch_base si.ncases = jump_table_size si.regnum = 1 # 1 is IDA's representation of d1 # added by gph Message("default jump: %08X\n" % defjump) si.flags |= idaapi.SWI_DEFAULT si.defjump = defjump # if we found a value table... if value_base != None and value_width != None: si.values = value_base si.set_vtable_element_size(value_width) total_switch_size = jump_table_size * (2 + value_width) si.flags |= idaapi.SWI_ELBASE | idaapi.SWI_SPARSE idaapi.set_switch_info_ex(idiom_ea, si) idaapi.create_switch_table(idiom_ea, si) idaapi.setFlags(idiom_ea, idaapi.getFlags(idiom_ea) | idaapi.FF_JUMP) # go to the end of the switch statement and make an instruction idaapi.create_insn(switch_base + total_switch_size) return True else: print "Error: Could not get jump table size." return False
def NotTails(*args): """ Enumerate array items @param <range>: see getrange @return: list of all not-tails Note that NotTails includes all Heads plus all undefined bytes """ (first, last)= getrange(args) ea= first if ea<last and idaapi.isTail(idaapi.getFlags(ea)): ea= idaapi.next_not_tail(ea) while ea!=BADADDR and ea<last: yield ea ea= idaapi.next_not_tail(ea)
def find_unmapped_funcs(): funcs = {} i = 0 ea = 0 max_ea = 0xFFFFFFFF while True: ea = NextHead(ea, max_ea) if ea == BADADDR: break flags = idaapi.getFlags(ea) if idaapi.isCode(flags): if not idaapi.get_func(ea): s = util.scan_insn_for_debug_ref(ea) if s != None: if not s in funcs: funcs[s] = ea return funcs
def NonFuncs(*args): """ Enumerate code which is not in a function @param ea: where to start @param endea: BADADDR, or end address @return: list of addresses containing code, but not in a function Example:: for ea in NonFuncs(FirstSeg(), BADADDR): if not MakeFunction(ea): Jump(ea) break Wait() Will try to change non-function code to function until MakeFunction fails """ (first, last)= getrange(args) ea = first while ea!=idaapi.BADADDR and ea<last: nextcode= idaapi.find_code(ea, idaapi.SEARCH_NEXT|idaapi.SEARCH_DOWN) thischunk= idaapi.get_fchunk(ea) nextchunk= idaapi.get_next_fchunk(ea) if thischunk: ea= thischunk.endEA elif idaapi.isCode(idaapi.getFlags(ea)): yield ea ea= idaapi.next_head(ea, last) elif nextchunk is None: return elif nextcode<nextchunk.startEA: yield nextcode ea= nextcode else: ea= nextchunk.endEA
def run(self, arg): idaapi.msg("[%s] Syncing with WS Server\n" % (self.wanted_name,)) self.addr = idaapi.get_screen_ea() if self.old_addr != self.addr: # check against idc.BADADDR and None before going if (self.addr is not None) and (self.addr != idc.BADADDR): # Code Address if idaapi.isCode(idaapi.getFlags(self.addr)): # don't set the address if it's already the qira_address if self.addr != self.qira_address: # debugging if DEBUG: idaapi.msg( "[%s] Qira Address 0x%x \n" % (self.wanted_name, self.addr,)) # Instruction Address self.set_qira_address(self.addr) self.update_address("iaddr", self.addr) # Data Address elif idaapi.isData(idaapi.getFlags(self.addr)): self.update_address("daddr", self.addr) # Tail Address elif idaapi.isTail(idaapi.getFlags(self.addr)): self.update_address("taddr", self.addr) # Unknown Address elif idaapi.isUnknown(idaapi.getFlags(self.addr)): self.update_address("uaddr", self.addr) # Head Address elif idaapi.isHead(idaapi.getFlags(self.addr)): self.update_address("haddr", self.addr) # Flow Address elif idaapi.isFlow(idaapi.getFlags(self.addr)): self.update_address("faddr", self.addr) # Var Address elif idaapi.isVar(idaapi.getFlags(self.addr)): self.update_address("vaddr", self.addr) # Data Address else: self.update_address("daddr", self.addr) self.old_addr = self.addr
def BytesThat(*args): """ Enumerate array items @param <range>: see getrange @param callable: function which tests the flags @return: list of all addresses where callable(GetFlags(ea)) is True """ (first, last)= getrange(args) i= getcallablepos(args) if i<0: raise Exception("missing callable") callable= args[i] ea= first if ea<last and not callable(idaapi.getFlags(ea)): ea= idaapi.nextthat(ea, last, callable) while ea!=BADADDR and ea<last: yield ea ea= idaapi.nextthat(ea, last, callable)
def fix_all(): # wait till autoanalysis is done idaapi.autoWait() ea = 0 numInst = 0 numAddRegPc = 0 numFixed = 0 t0 = time.clock() # last MOV/MOVT inst targeting the register, key=register number movVal = dict() movtVal = dict() global refs cnt = 0 while True: cnt += 1 ea = idc.NextHead(ea) if cnt & 0xfff == 0: print "[progress] ea: %x" % ea if ea == idc.BADADDR: break if not idaapi.isCode(idaapi.getFlags(ea)): continue numInst += 1 # slow, is there any way to avoid it?.. i = idautils.DecodeInstruction(ea) if not i: continue mnem = i.get_canon_mnem() if i[0].type != 1: # only interested in register target operands continue target_reg = i[0].phrase if mnem == 'ADD': if i[1].type == 1 and i[1].phrase == 15: numAddRegPc += 1 (val, mov_ea) = movVal.get(target_reg, (0, 0)) (val_t, movt_ea) = movtVal.get(target_reg, (0, 0)) if not mov_ea: # No preceding MOV, bailing.. continue numFixed += 1 target_addr = 0xffffFFFF & (ea + 4 + val + 0x10000 * val_t) # could be THUMB proc.. if target_addr & 1 and idaapi.isCode(idaapi.getFlags(target_addr - 1)): target_name = idaapi.get_name(target_addr - 1, target_addr - 1) else: target_name = idaapi.get_name(target_addr,target_addr) refs.append((ea, target_addr, target_name)) if i[1].type == 5: if mnem == 'MOV': movVal[target_reg] = (i[1].value, ea) movtVal[target_reg] = (0, 0) # since movw clears top bits anyway elif mnem == 'MOVT': movtVal[target_reg] = (i[1].value, ea) else: movVal[target_reg] = (0, 0) movtVal[target_reg] = (0, 0) print "%u instructions scanned in %f seconds" % (numInst, time.clock() - t0) add_refs() # work around an IDA bug for i in range (1, 5): idaapi.autoWait() add_refs() if numAddRegPc == 0: successRate = 100 else: successRate = numFixed * 100.0 / numAddRegPc print "%u 'ADD Reg, PC' found, %u fixed: %u%%" % (numAddRegPc, numFixed, successRate) global g_done g_done = 1
def is_code(ea): return idaapi.getFlags(ea) & idaapi.MS_CLS == idaapi.FF_CODE
def isData(ea): '''True if ea marked as data''' return idaapi.getFlags(ea)&idaapi.MS_CLS == idaapi.FF_DATA
def isUnknown(ea): '''True if ea marked unknown''' return idaapi.getFlags(ea)&idaapi.MS_CLS == idaapi.FF_UNK
def block(self, block): ''' Returns a tuple: ([formal, block, signatures], [fuzzy, block, signatures], set([unique, immediate, values]), [called, function, names]) ''' formal = [] fuzzy = [] functions = [] immediates = [] ea = block.startEA while ea < block.endEA: idaapi.decode_insn(ea) # Get a list of all data/code references from the current instruction drefs = [x for x in idautils.DataRefsFrom(ea)] crefs = [x for x in idautils.CodeRefsFrom(ea, False)] # Add all instruction mnemonics to the formal block hash formal.append(idc.GetMnem(ea)) # If this is a call instruction, be sure to note the name of the function # being called. This is used to apply call-based signatures to functions. # # For fuzzy signatures, we can't use the actual name or EA of the function, # but rather just want to note that a function call was made. # # Formal signatures already have the call instruction mnemonic, which is more # specific than just saying that a call was made. if idaapi.is_call_insn(ea): for cref in crefs: func_name = idc.Name(cref) if func_name: functions.append(func_name) fuzzy.append("funcref") # If there are data references from the instruction, check to see if any of them # are strings. These are looked up in the pre-generated strings dictionary. # # String values are easily identifiable, and are used as part of both the fuzzy # and the formal signatures. # # It is more difficult to determine if non-string values are constants or not; # for both fuzzy and formal signatures, just use "data" to indicate that some data # was referenced. elif drefs: for dref in drefs: if self.strings.has_key(dref): formal.append(self.strings[dref].value) fuzzy.append(self.strings[dref].value) else: formal.append("dataref") fuzzy.append("dataref") # If there are no data or code references from the instruction, use every operand as # part of the formal signature. # # Fuzzy signatures are only concerned with interesting immediate values, that is, values # that are greater than 65,535, are not memory addresses, and are not displayed as # negative values. elif not drefs and not crefs: for n in range(0, len(idaapi.cmd.Operands)): opnd_text = idc.GetOpnd(ea, n) formal.append(opnd_text) if idaapi.cmd.Operands[n].type == idaapi.o_imm and not opnd_text.startswith('-'): if idaapi.cmd.Operands[n].value >= 0xFFFF: if idaapi.getFlags(idaapi.cmd.Operands[n].value) == 0: fuzzy.append(str(idaapi.cmd.Operands[n].value)) immediates.append(idaapi.cmd.Operands[n].value) ea = idc.NextHead(ea) return (self.sighash(''.join(formal)), self.sighash(''.join(fuzzy)), immediates, functions)
def flags(self): """`FF_*` Flags. See `bytes.hpp`.""" return idaapi.getFlags(self.ea)