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.get_full_flags(ea & -2) # flags_t else: flags = idaapi.get_full_flags(ea) return idaapi.is_code(flags)
def ForceQword(self, ea): if ea != BADADDR and ea != 0: if not isQwrd(get_full_flags(ea)): MakeUnknown(ea, 8, DOUNK_SIMPLE) MakeQword(ea) if isOff0(get_full_flags(ea)) and GetFixupTgtType(ea) == -1: # remove the offset OpHex(ea, 0)
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.get_full_flags(ea)) n = s / ss for i in xrange(n): yield ea + i * ss
def Code(*args): """ Enumerate code bytes @param <range>: see getrange @return: list of addresses of code bytes Example:: for ea in Code(): MakeUnkn(ea, DOUNK_EXPAND) Wait() Will delete all code in the selected area. len(list(MakeUnkn(ea, DOUNK_EXPAND) and Wait() for ea in enumerators.Code(idaapi.getseg(here())))) will delete all code in the current segment, and can be pasted in the command area of ida """ (first, last) = getrange(args) ea = first # explicitly testing first byte, since find_code # implicitly sets SEARCH_NEXT flag if ea < last and not idaapi.is_code(idaapi.get_full_flags(ea)): ea = idaapi.find_code(ea, idaapi.SEARCH_DOWN) while ea != idaapi.BADADDR and ea < last: yield ea ea = idaapi.find_code(ea, idaapi.SEARCH_DOWN)
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 ida_bytes.is_unknown(idaapi.get_full_flags(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 isVtable(self, addr): function = self.get_ptr(addr) # Check if vtable has ref and its first pointer lies within code segment if f_has_xref( get_full_flags(addr) ) and function >= self.text.start_ea and function <= self.text.end_ea: return True return False
def xref_or_find(self, addr, allow_many=False): lrefs = list(DataRefsTo(addr)) if len(lrefs) == 0: lrefs = list(idautils.refs(addr, self.ptrfirst, self.ptrnext)) if len(lrefs) > 1 and not allow_many: print("too many xrefs to %08X" % addr) return [] lrefs = [r for r in lrefs if not isCode(get_full_flags(r))] return lrefs
def findend(ea): ea0 = ea while True: ea = idc.NextAddr(ea) if XrefsTo(ea): break if idaapi.get_full_flags(ea) & idc.FF_ANYNAME: break return ea - ea0
def ForcePtr(self, ea, delta=0): if self.x64: self.ForceQword(ea) else: self.ForceDword(ea) if GetFixupTgtType(ea) != -1 and isOff0(get_full_flags(ea)): # don't touch fixups return pv = self.get_ptr(ea) if pv != 0 and pv != BADADDR: # apply offset again if idaapi.is_spec_ea(pv): delta = 0 OpOffEx(ea, 0, [REF_OFF32, REF_OFF64][self.x64], -1, 0, delta)
def locate_functions(segm): ss = find_probable_string_start(segm) print("[+] Strings = %s" % ss) for i in ["7F 23 03 D5", "BD A9", "BF A9"]: ea = segm.start_ea while ea != BADADDR: ea = ida_search.find_binary(ea, segm.end_ea, i, 16, ida_search.SEARCH_DOWN) if ea != BADADDR and ea <= ss: ea -= 2 if (ea % 4) == 0 and idaapi.get_full_flags(ea) < 0x200: # print("[+] Defining a function at 0x%x" % (ea)) ida_funcs.add_func(ea) ea += 4
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.is_head(idaapi.get_full_flags(ea)): ea = idaapi.next_head(ea, last) while ea != BADADDR and ea < last: yield ea ea = idaapi.next_head(ea, last)
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.is_tail(idaapi.get_full_flags(ea)): ea = idaapi.next_not_tail(ea) while ea != BADADDR and ea < last: yield ea ea = idaapi.next_not_tail(ea)
def NonFuncs(*args): """ Enumerate code which is not in a function @param <range>: see getrange @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.end_ea elif idaapi.is_code(idaapi.get_full_flags(ea)): yield ea ea = idaapi.next_head(ea, last) elif nextchunk is None: return elif nextcode < nextchunk.start_ea: yield nextcode ea = nextcode else: ea = nextchunk.end_ea
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.get_full_flags(ea)): ea = idaapi.nextthat(ea, last, callable) while ea != BADADDR and ea < last: yield ea ea = idaapi.nextthat(ea, last, callable)
def force_name(self, ea, name): if isTail(get_full_flags(ea)): MakeUnknown(ea, 1, DOUNK_SIMPLE) MakeNameEx(ea, name, SN_NOWARN)
def flags(self): """`FF_*` Flags. See `bytes.hpp`.""" return idaapi.get_full_flags(self.ea)
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.start_ea insn = idaapi.insn_t() while ea < block.end_ea: idaapi.decode_insn(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.print_insn_mnem(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.get_name(cref, ida_name.GN_VISIBLE) if not func_name: continue 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 dref in self.strings: 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.insn_t().ops)): opnd_text = idc.print_operand(ea, n) formal.append(opnd_text) if idaapi.insn_t().ops[n].type != idaapi.o_imm or opnd_text.startswith('-'): continue if idaapi.insn_t().ops[n].value < 0xFFFF: continue if idaapi.get_full_flags(idaapi.insn_t().ops[n].value) != 0: continue fuzzy.append(str(idaapi.insn_t().ops[n].value)) immediates.append(idaapi.insn_t().ops[n].value) ea = idc.next_head(ea) return self.sighash(''.join(formal)), self.sighash(''.join(fuzzy)), immediates, functions