def main(): kbase = min(Segments()) define_funcs = [] define_data = [] # Add functions for ea in Functions(): fname = idc.get_name(ea) ftype = idc.get_type(ea) fslide = ea - kbase if fname.startswith('sub_'): continue if ftype is None: if TYPED_FUNCS_ONLY: continue ftype = 'uint64_t (...)' define_funcs.append((fname, fslide, ftype)) # Add data for ea, _ in Names(): dname = idc.get_name(ea) dtype = idc.get_type(ea) dslide = ea - kbase flags = GetFlags(ea) if idc.is_code(flags) or idc.is_strlit(flags): continue if dtype is None: if TYPED_DATA_ONLY: continue dtype = 'void' define_data.append((dname, dslide, dtype)) # Generate source files generate_sdk(define_funcs, define_data)
def get_value_type(ea): addr_type = T_VALUE if not idaapi.is_loaded(ea): return addr_type segm_name = idc.get_segm_name(ea) segm = idaapi.getseg(ea) flags = idc.get_full_flags(ea) is_code = idc.is_code(flags) if "stack" in segm_name.lower() or \ (dbg.stack_segm and dbg.stack_segm.start_ea == segm.start_ea): addr_type = T_STACK elif "heap" in segm_name.lower(): addr_type = T_HEAP elif not is_code and segm.perm & idaapi.SEGPERM_READ and \ segm.perm & idaapi.SEGPERM_WRITE and \ segm.perm & idaapi.SEGPERM_EXEC: addr_type = T_RWX elif is_code or \ (segm.perm & idaapi.SEGPERM_READ and segm.perm & idaapi.SEGPERM_EXEC): addr_type = T_CODE elif segm.perm & idaapi.SEGPERM_READ and \ segm.perm & idaapi.SEGPERM_WRITE: addr_type = T_DATA elif segm.perm & idaapi.SEGPERM_READ: addr_type = T_RODATA return addr_type
def crefs_from(ea, only_one=False, check_fixup=True): flags = idc.get_full_flags(ea) if not idc.is_code(flags): return fixup_ea = idc.BADADDR seen = False has_one = only_one if check_fixup: fixup_ea = idc.get_fixup_target_off(ea) if not is_invalid_ea(fixup_ea) and is_code(fixup_ea): seen = only_one has_one = True yield fixup_ea if has_one and _stop_looking_for_xrefs(ea): return for target_ea in _xref_generator(ea, idaapi.get_first_cref_from, idaapi.get_next_cref_from): if target_ea != fixup_ea and not is_invalid_ea(target_ea): seen = only_one yield target_ea if seen: return if not seen and ea in _CREFS_FROM: for target_ea in _CREFS_FROM[ea]: seen = only_one yield target_ea if seen: return
def dump_type(ea): flags = idaapi.get_flags(ea) if idc.is_code(flags): return "block" if idaapi.get_func(ea) else "code" if idc.is_data(flags): return "data" return "unexplored"
def base64_decode(std): addr = idc.BADADDR ea = idc.get_screen_ea() flags = idaapi.get_flags(ea) if idc.is_strlit(flags): addr = ea # cursor is on the string elif idc.is_code(flags): addr = idc.get_first_dref_from(ea) # get data reference from the instruction if addr == idc.BADADDR: plg_print("No string or reference to the string found\n") return b64str_enc = None try: b64str_enc = idc.get_strlit_contents(addr, -1, idc.get_str_type(addr)) except: pass if not b64str_enc: plg_print("Could not get string at address 0x%X" % addr) return try: b64str_dec = base64.standard_b64decode(b64str_enc) if std else base64.urlsafe_b64decode(b64str_enc) except Exception as e: plg_print("Could not decode. %s" % str(e)) return if b64str_dec: plg_print("Base64 decode of string '%s':" % b64str_enc) process_data_result(ea, bytearray(b64str_dec))
def is_code(self): """ Property indicating if this element is some code. Wrapper on ``idc.is_code`` . :return: True if current element is code, False otherwise. :rtype: bool """ return idc.is_code(self.flags)
def instr_iter(self): """ Return a generator of :class:`BipInstr` corresponding to the instructions of the basicblock. This implementation will be just a little more performant than the :meth:`instr` property. :return: A generator of object :class:`BipInstr` . """ for h in idautils.Heads(self.ea, self.end): if idc.is_code(ida_bytes.get_full_flags(h)): yield bip.base.instr.BipInstr(h)
def instr(self): """ Return a list of :class:`BipInstr` corresponding to the instructions of the basicblock. :return: A list of object :class:`BipInstr` . """ return [ bip.base.instr.BipInstr(h) for h in idautils.Heads(self.ea, self.end) if idc.is_code(ida_bytes.get_full_flags(h)) ]
def convert_pointer_to_offset(ea): # If this is code, skip it. flags = idc.get_full_flags(ea) if idc.is_code(flags): return # If the value at this address does not point into the kernelcache, skip it. value = idc.get_qword(ea) if not is_mapped(value, 8): return # Convert this value to a qword (in case it's unaligned) and then convert it into an # offset. idc.create_qword(ea) idc.op_plain_offset(ea, 0, 0)
def trim_func(ea, GetHead): """ Description: Steps until it hits something not a nop or not starts with 90 (nop opcode) nor an align or not byte 0xCC (Align 'opcode'). Input: ea - The location to adjust for nops and Aligns. EA must be a head. GetHead - either prev_head or next_head Output: The corrected EA. """ while idc.print_insn_mnem(ea) == 'nop' or (idaapi.is_data(idc.get_full_flags(ea)) and idc.get_wide_byte(ea) == 0x90) or \ idc.is_align(idc.get_full_flags(ea)) or (not idc.is_code(idc.get_full_flags(ea)) and idc.get_wide_byte(ea) == 0xCC): ea = GetHead(ea) return ea
def get_ea_from_highlight(): view = idaapi.get_current_viewer() thing = ida_kernwin.get_highlight(view) if thing and thing[1]: # we have a highligh, is it a valid name ? ea = idc.get_name_ea_simple(thing[0]) if ea != idaapi.BADADDR: return ea else: # Try to get full highlight name place = idaapi.get_custom_viewer_place(view, False) if place and len(place) == 3: # (plate_t, x, y) ea = place[0].toea() far_code_refs = [xref.to for xref in idautils.XrefsFrom(ea, ida_xref.XREF_FAR) \ if idc.is_code(idc.get_full_flags(xref.to))] if far_code_refs: return far_code_refs[0] # Reach now, we do not have any valid name, return current screen ea return idc.get_screen_ea()
def make(cls, ea=None): """ Class method for defining an instruction. If auto-analysis is enable in IDA this may define also the following instructions. If the instruction is already define, this instruction just returns it. :param ea: The address at which to define the instruction, if None the current screen address is used. :return: The :class:`BipInstr` for this address. :raise RuntimeError: If it was not possible to define the address as code. """ if ea is None: ea = ida_kernwin.get_screen_ea() if idc.is_code( ida_bytes.get_full_flags(ea)): # if we already have code return cls(ea) if ida_ua.create_insn(ea) == 0: raise RuntimeError( "Unable to create instruction at 0x{:X}".format(ea)) return cls(ea)
def _ins2color(self, addr): col = _len = 0 acc = -1 head = get_item_head(addr) if can_decode(head): f = get_full_flags(head) if is_code(f): _len = decode_insn(self.insn, head) if _len: if self.insn.itype in [ida_allins.NN_mov ]: # TODO: add more instructions if self.insn.Op1.type in [o_mem, o_phrase, o_displ]: acc = ACC_WRITE col = self.insn_colors[acc] elif self.insn.Op2.type in [o_mem, o_phrase, o_displ]: acc = ACC_READ col = self.insn_colors[acc] else: acc = -1 return (col, _len, acc)
def check_vtable(start, end=None): # We recognize a vtable by looking for an array of at least 2 pointers to code followed by a # NULL. # If no end was specified, go until the end of the segment. if end is None: end = idc.get_segm_end(start) # Check each address in the table. Stop once we've found something other than a pointer to # code. ended_with_zero = False ea = start while ea < end: method = idc.get_qword(ea) if method == 0: ended_with_zero = True break if not idc.is_code(idc.get_full_flags(method)): break ea += 8 # Compute the length. length = (ea - start) / 8 possible_vtable = ended_with_zero and length >= 2 return possible_vtable, length
class_parent = NameEx(BADADDR, call[2]) class_parent_name = Demangle(class_parent, GetLongPrm(INF_LONG_DN)) if class_parent_name: class_parent = class_parent_name fd.write('class ' + class_name + ': public ' + class_parent.replace('__gMetaClass', '') + ' \n') class_size = call[3] class_vtable = call[4] for i in range(13): OpOff(class_vtable + i * 8, 0, 0) if i == 12: fptr = Qword(class_vtable + i * 8) if fptr != 0: if idc.is_code(fptr) == False: MakeUnknown(fptr, 1, idaapi.DOUNK_SIMPLE) # idaapi.autoWait() if fptr != Qword(class_vtable + i * 8): print("BBBBBBBBBBBBBBBBBBBBBBB") # fptr = Qword(class_vtable + i * 8) MakeCode(fptr) idaapi.autoWait() if idc.get_func_attr(fptr, FUNCATTR_START) == idc.BADADDR: MakeFunction(fptr) idaapi.autoWait() class_vtable_name = 'vtbl_' + class_name_meta MakeNameEx(class_vtable, class_vtable_name, 0)
def _is_this_elt(cls, ea): return idc.is_code(ida_bytes.get_full_flags(ea))
def is_code_ea(ea): if idaapi.cvar.inf.procname == "ARM": flags = idc.get_full_flags(ea & -2) # flags_t else: flags = idc.get_full_flags(ea) return idc.is_code(flags)
def is_code_by_flags(ea): if not is_code(ea): return False flags = idc.get_full_flags(ea) return idc.is_code(flags)
def filter_for_code(name_list): filtered = [] for name in name_list: ea = idc.get_name_ea_simple(name) if idc.is_code(ea): filtered.append(name)
def is_code_ptr(ea): return is_mapped_data(ea, 4) and idc.is_code( idc.get_full_flags(idc.get_qword(ea)))
def is_code(self, ea): flags = idc.get_full_flags(ea) return idc.is_code(flags)
def reconstruct_vtable(vtable_addr, current_class_name): vtable_addr_local = vtable_addr func = Qword(vtable_addr_local) vtable_functions = [] used_function_names = [] while func != 0 and (func & 0xfffffff000000000 ) == 0xfffffff000000000 and '__text' in SegName(func): # print(" Address = " + hex(func)) # func_addr = GetFunctionAttr(func, FUNCATTR_START) # MakeCode(func) # if add_func(func) != 0: # return False, [] if idc.is_code(func) == False: MakeUnknown(Qword(vtable_addr_local), 1, idaapi.DOUNK_SIMPLE) # idaapi.autoWait() # if fptr != Qword(class_vtable + i * 8): # print("BBBBBBBBBBBBBBBBBBBBBBB") # fptr = Qword(class_vtable + i * 8) MakeCode(Qword(vtable_addr_local)) idaapi.autoWait() # MakeCode(func) # idaapi.autoWait() MakeFunction(Qword(vtable_addr_local)) idaapi.autoWait() OpOff(vtable_addr_local, 0, 0) idaapi.autoWait() # func_name = GetFunctionName(func) # if func_name == '': func_name = NameEx(BADADDR, func) if func_name == '': func_name = 'sub_' + '%016X' % func print(" NNMNNMNNMNNMNNM => 0x%016x" % (func)) #func_name = 'unnamed_function' # print("No name :( " + hex(vtable_addr_local)) # sys.exit(0) if func_name[0:3] == 'loc': print(" LOCLOCLOCLOCLOC => %s" % (func_name)) if idc.get_func_attr(func, FUNCATTR_START) not in (func, idc.BADADDR): mainfunc = idc.get_func_attr(func, FUNCATTR_START) print(" SEPARATE FUNCTION => 0x%016x" % (mainfunc)) MakeUnknown(mainfunc, 1, idaapi.DOUNK_SIMPLE) idaapi.autoWait() MakeCode(Qword(vtable_addr_local)) idaapi.autoWait() MakeFunction(Qword(vtable_addr_local)) idaapi.autoWait() MakeCode(mainfunc) if MakeFunction(mainfunc): idaapi.autoWait() else: print(" NOT RECONSTRUCT => 0x%016x" % (mainfunc)) else: if MakeFunction(Qword(vtable_addr_local)): idaapi.autoWait() else: print(" NOT RECONSTRUCT => 0x%016x" % (Qword(vtable_addr_local))) func_name = func_name.replace('loc', 'sub') elif func_name[0:3] == 'unk': print(" SUBSUBSUBSUBSUB => %s" % (func_name)) func_name = func_name.replace('unk', 'sub') # func_name = 'unnamed_function' # print("No name :( " + hex(func)) # sys.exit(0) # # func_name = get_name(func) # if 'off' in func_name: # func_name = func_name.replace('off', 'sub') # elif 'loc' in func_name: # func_name = func_name.replace('loc', 'sub') # lif 'unk' in func_name: # func_name = func_name.replace('unk', 'sub') func_type = GetType(func) if func_type == None: func_type = '__int64 __fastcall()' if func_name[0:3] == '__Z': func_name = Demangle(func_name, 0) class_name, func_name = parse_demangled_name(func_name) if class_name != current_class_name: func_name = class_name + '::' + func_name new_func = func_name i = 0 while new_func in used_function_names: new_func = func_name + '_' + str(i) i += 1 vtable_functions.append([new_func, func_type]) used_function_names.append(new_func) # OpOff(vtable_addr_local, 0, 0) vtable_addr_local += 8 func = Qword(vtable_addr_local) return True, vtable_functions