def get_items_for_ea(self, ea): frm = [x.frm for x in idautils.XrefsTo(self.__ea)] items = [] for ea in frm: try: cfunc = ida_hexrays.decompile(ea) self.functions.append(cfunc.entry_ea) self.items.append((ea, ida_funcs.get_func_name(cfunc.entry_ea) or "", self.get_decompiled_line(cfunc, ea))) except Exception as e: print('could not decompile: %s' % (str(e), )) raise return
def find_WdfDeviceInitSetIoInCallerContextCallback(): function_offset = OFFSET_WdfDeviceInitSetIoIncallerContextCallback try: call_pfn = idautils.XrefsTo(g_vars["_WDFFUNCTIONS"] + function_offset).next().frm except StopIteration: # this is case 2! call_pfn = find_wdf_callback_through_immediate("mov", 1, function_offset) if call_pfn is None: call_pfn = find_wdf_callback_through_immediate( "call", 0, function_offset) if call_pfn != None: idc.OpStroffEx(call_pfn, 0, (idaapi.get_struc_id("_WDFFUNCTIONS")), 0) lea_addr = find_function_arg(call_pfn, "lea", "r8", 0) EvtWdfIoInCallerContext = idc.get_operand_value(lea_addr, 1) idc.set_name(EvtWdfIoInCallerContext, 'EvtWdfIoInCallerContext')
def get_items_for_ea(self, ea): frm = [x.frm for x in idautils.XrefsTo(self.__ea)] items = [] for ea in frm: try: cfunc = idaapi.decompile(ea) self.functions.append(cfunc.entry_ea) self.items.append((ea, idc.GetFunctionName(cfunc.entry_ea), self.get_decompiled_line(cfunc, ea))) except Exception as e: print 'could not decompile: %s' % (str(e), ) raise return
def _build_string_xrefs(self): #print "Building string profiles..." #orig_functions_len = len(self.functions) for string in idautils.Strings(): keystr = str(string) for xref in idautils.XrefsTo(string.ea): func = idaapi.get_func(xref.frm) if func: if not self.functions.has_key(func.startEA): self.functions[func.startEA] = list() self.functions[func.startEA].append( IDAProfilerXref(ea=string.ea, string=keystr, xref=xref.frm, type=str))
def _build_paths(self, start, end=idc.BADADDR): partial_paths = [[start]] # Loop while there are still unresolve paths and while all path sizes have not exceeded ALLEYCAT_LIMIT while partial_paths and len( self.paths) < self.limit and len(partial_paths) < self.limit: # Initialize a unique set of callers for this iteration callers = set() # Callee is the last entry of the first path in partial paths. # The first path list will change as paths are completed and popped from the list. callee = partial_paths[0][-1] # Find all unique functions that reference the callee, assuming this path has not # exceeded ALLEYCAT_LIMIT. if len(partial_paths[0]) < self.limit: for xref in idautils.XrefsTo(callee): caller = self._get_code_block(xref.frm) if caller and caller.startEA not in callers: callers.add(caller.startEA) # If there are callers to the callee, remove the callee's current path # and insert new ones with the new callers appended. if callers: base_path = partial_paths.pop(0) for caller in callers: # Don't want to loop back on ourselves in the same path if caller in base_path: continue # If we've reached the desired end node, don't go any further down this path if caller == end: self._add_path((base_path + [caller])[::-1]) else: partial_paths.append(base_path + [caller]) # Else, our end node is not in this path, so don't include it in the finished path list. elif end not in partial_paths[0]: partial_paths.pop(0) # If there were no callers then this path has been exhaused and should be # popped from the partial path list into the finished path list. elif end in partial_paths[0]: # Paths start with the end function and end with the start function; reverse it. self._add_path(partial_paths.pop(0)[::-1])
def _build_paths(self, start, end=idc.BADADDR): partial_paths = [[start]] # Loop while there are still unresolve paths and while all path sizes # have not exceeded ALLEYCAT_LIMIT while partial_paths and \ len(self.paths) < self.limit and \ len(partial_paths) < self.limit: callers = set() # Callee is the last entry of the first path in partial paths. # The first path list will change as paths are completed and # popped from the list. callee = partial_paths[0][-1] # Find all unique functions that reference the callee, assuming this # path has not exceeded ALLEYCAT_LIMIT. if len(partial_paths[0]) < self.limit: for xref in idautils.XrefsTo(callee): caller = self._get_code_block(xref.frm) if caller: start_ea = ida_shims.start_ea(caller) if start_ea not in callers: callers.add(start_ea) # If there are callers to the callee, remove the callee's current # path and insert new ones with the new callers appended. if callers: base_path = partial_paths.pop(0) for caller in callers: # Don't want to loop back on ourselves in the same path if caller in base_path: continue if caller == end: self._add_path((base_path + [caller])[::-1]) else: partial_paths.append(base_path + [caller]) elif end not in partial_paths[0]: partial_paths.pop(0) elif end in partial_paths[0]: self._add_path(partial_paths.pop(0)[::-1])
def imp_cb(ea, name, ord): if name in funcs: for xref in idautils.XrefsTo(ea): call_addr = xref.frm caller_name = idc.GetFunctionName(call_addr) prev = idc.PrevHead(call_addr) for _ in range(10): if idc.Comment(prev) == 'Tag' and idc.GetOpType(prev, 1) == 5: tag_raw = idc.GetOperandValue(prev, 1) tag = '' for i in range(3, -1, -1): tag += chr((tag_raw >> 8 * i) & 0xFF) if tag in tags.keys(): tags[tag].add(caller_name) else: tags[tag] = set([caller_name]) break prev = idc.PrevHead(prev) return True
def post_func_type_change(pfn): ea = pfn.start_ea xrefs = idautils.XrefsTo(ea, ida_xref.XREF_USER) xrefs = list(filter(lambda x: x.type == ida_xref.dr_I and x.user == 1, xrefs)) args_list = [] if len(xrefs) == 0: return None, [] try: xfunc = ida_hexrays.decompile(ea) func_ptr_typeinf = utils.get_typeinf_ptr(xfunc.type) for xref in xrefs: member, old_name, struct = ida_struct.get_member_by_id(xref.frm) if member is not None and struct is not None: args_list.append( [struct, member, 0, func_ptr_typeinf, idaapi.TINFO_DEFINITE] ) except Exception: pass return ida_struct.set_member_tinfo, args_list
def build_xref_dict(strings): xrefs = {} for s in strings: xrefs[str(s)] = [] for xref in idautils.XrefsTo(s.ea): funcname = ida_funcs.get_func_name(xref.frm) if funcname is None: continue node = xrefs[str(s)] node.append(funcname) xrefs[str(s)] = node # Empty, trash, we don't want it if not len(xrefs[str(s)]): del xrefs[str(s)] return xrefs
def get_func_str_hack(ea): """ get all referenced strings within a function, actually works :param ea: offset within a function :return: return list of strings referenced in function """ offsets = [] status, ea_st = get_func_addr(ea) if status: status, ea_end = get_func_addr_end(ea) if status: for _str in idautils.Strings(): s_ea = _str.ea xref = idautils.XrefsTo(s_ea) for x in xref: temp_addr = x.frm if ea_st <= temp_addr <= ea_end: offsets.append((temp_addr, _str)) return offsets
def callback(addr, name, ordinal): if name: # Name will include a "__imp_" prefix if the import is accessed through # a thunk function. # Pull the address of the thunk function instead. raw_name = ida_name.get_name(addr) if raw_name.startswith("__imp_"): for xref in idautils.XrefsTo(addr): func = ida_funcs.get_func(xref.frm) if func and func.flags & ida_funcs.FUNC_THUNK: addr = func.start_ea name = ida_funcs.get_func_name(addr) break else: raise RuntimeError(f"Failed to find a thunk for {name} at 0x{addr:08X}") entries.append((addr, name)) return True # continue enumeration
def extract_info_from_IDA(self): for xref in idautils.XrefsTo(self.ea): frm = xref.frm if idc.SegName(frm) == '__objc_classrefs': self.classref = frm if idc.SegName(frm) == '__objc_superrefs': self.superref = frm base_ivars = ida_bytes.get_qword(self.info + 0x30) if base_ivars and idc.SegName(base_ivars) == '__objc_const': entrysize = ida_bytes.get_dword(base_ivars) count = ida_bytes.get_dword(base_ivars + 4) ea = base_ivars + 8 for i in range(count): offset = ida_bytes.get_dword(idc.get_qword(ea)) _type = idc.get_bytes(idc.Qword(ea + 0X10), idc.get_item_size(idc.Qword(ea + 0X10)) - 1) _name = idc.get_bytes(idc.Qword(ea + 0X08), idc.get_item_size(idc.Qword(ea + 0X08)) - 1) # self.ivars[offset] = _type self.ivars[_name] = _type ea += entrysize base_props = ida_bytes.get_qword(self.info + 0x40) if base_props and idc.SegName(base_props) == '__objc_const': entrysize = ida_bytes.get_dword(base_props) count = ida_bytes.get_dword(base_props + 4) ea = base_props + 8 for i in range(count): _type = idc.get_bytes(idc.Qword(ea + 0X08), idc.get_item_size(idc.Qword(ea + 0X08)) - 1) _name = idc.get_bytes(idc.Qword(ea), idc.get_item_size(idc.Qword(ea)) - 1) self.props[_name] = _type ea += entrysize base_prots = ida_bytes.get_qword(self.info + 0x28) if base_prots and idc.SegName(base_prots) == '__objc_const': count = ida_bytes.get_qword(base_prots) entrysize = 0x8 p_ea = base_prots + 8 for i in range(count): proto_ea = idc.get_qword(p_ea) self.prots.append(proto_ea) Protocol.add_implementing_class(proto_ea, self.ea) p_ea += entrysize
def list_xref_to_wdf_callback(function_offset): calls_to_pfn_list = [] try: for xref in idautils.XrefsTo(g_vars["_WDFFUNCTIONS"] + function_offset): calls_to_pfn_list.append(xref.frm) except StopIteration: # this is case 2 or 3 pass if len(calls_to_pfn_list) == 0: call_pfn = find_wdf_callback_through_immediate("call", 0, function_offset) if call_pfn != None: calls_to_pfn_list.append(call_pfn) if len(calls_to_pfn_list) == 0: call_pfn = find_wdf_callback_through_immediate("mov", 1, function_offset) if call_pfn != None: calls_to_pfn_list.append(call_pfn) return calls_to_pfn_list
def str2func(self, ea): ''' Identifies a unique function associated with a given string. @ea - The effective address of the string Returns the address of the associated function, or None. ''' functions = [] for xref in idautils.XrefsTo(ea): func = idaapi.get_func(xref.frm) if func and func.startEA not in functions: functions.append(func.startEA) # Each string must be referenced by only one function if len(functions) == 1: return functions[0] else: return None
def _search_for_immediates(self): self.funcs = {} for immediate in constants.constants.keys(): ea = 0 while ea != idc.BADADDR: (ea, n) = idc.FindImmediate(ea, idc.SEARCH_DOWN, self._twos_compliment(immediate)) if ea != idc.BADADDR: func = idaapi.get_func(ea) if func: s = self.funcs.get(func.startEA, set()) s.add(immediate) self.funcs[func.startEA] = s else: for xref in idautils.XrefsTo(ea): func = idaapi.get_func(xref.frm) if func: s = self.funcs.get(func.startEA, set()) s.add(immediate) self.funcs[func.startEA] = s
def find_stack_chk_fail(base_ea): ea_list = ida_search.find_imm(base_ea, ida_search.SEARCH_DOWN, 0x7CC8) if ea_list[0] != ida_idaapi.BADADDR: func_ea = ida_funcs.get_func(ea_list[0]).start_ea print("\t[+] _stack_chk_fail = 0x%x" % (func_ea)) idc.set_name(func_ea, "_stack_chk_fail", idc.SN_CHECK) return func_ea else: str_ea = ida_search.find_text(base_ea, 1, 1, "__stack_chk_fail", ida_search.SEARCH_DOWN) if str_ea != ida_idaapi.BADADDR: for xref in idautils.XrefsTo(str_ea): func = idaapi.get_func(xref.frm) print("\t[+] _stack_chk_fail = 0x%x" % (func.start_ea)) idc.set_name(func.start_ea, "_stack_chk_fail", idc.SN_CHECK) return func.start_ea return ida_idaapi.BADADDR
def find_do_go(base_ea): str_ea = idc.get_name_ea_simple("aCebilefciladrm") if str_ea != ida_idaapi.BADADDR: for xref in idautils.XrefsTo(str_ea): # IDA messes up this function, so I find it this way: func = idaapi.get_func(xref.frm) if func != none: dg_ea = ida_search.find_binary(xref.frm, func.start_ea, prologues[0], 16, ida_search.SEARCH_UP) if dg_ea != ida_idaapi.BADADDR: ida_funcs.add_func(dg_ea) print("\t[+] _do_go = 0x%x" % (dg_ea)) idc.set_name(dg_ea, "_do_go", idc.SN_CHECK) return dg_ea return ida_idaapi.BADADDR
def imp_cb(ea, name, ord): if name in funcs: for xref in idautils.XrefsTo(ea): call_addr = xref.frm caller_name = idc.get_func_name(call_addr) prev = idc.prev_head(call_addr) for _ in range(10): if idc.get_cmt(prev, 0) == 'Tag' and idc.get_operand_type( prev, 1) == 5: tag_raw = idc.get_operand_value(prev, 1) tag = '' for i in range(3, -1, -1): tag += chr((tag_raw >> 8 * i) & 0xFF) if tag in tags.keys(): tags[tag].add(caller_name) else: tags[tag] = set([caller_name]) break prev = idc.prev_head(prev) return True
def find_sel_ctx(self): if self.selector_str and not self.selector_ea: if self.selector_str in self.bin_data['selrefs']: self.selector_ea = self.bin_data['selrefs'][self.selector_str] else: print 'CANNOT FIND SELECTOR: ', self.selector_str return for xref in idautils.XrefsTo(self.selector_ea): if idc.SegName(xref.frm) == '__text': fi = idaapi.get_func(xref.frm).startEA if fi not in self.selector_ctx: self.selector_ctx[fi] = set([ xref.frm, ]) else: self.selector_ctx[fi].add(xref.frm) else: print 'XREF OF {} NOT IN TEXT SEGMENT: {}'.format( self.selector_str, hex(xref.frm))
def add_struc_descr(sid, structure, rep): """ Insert a (repeatable) comment descripting the structure whose id is sid. And name address in added segment annotated with structure description. Arguments: sid -- structure id which the added comment is describing structure -- structure object holding data rep -- add repeatable comment (True\False) Return: True -- if success; False otherwise """ # TODO correct or not descr = format_comment(structure.description) + '\n' if idc.SetStrucComment(sid, descr, rep): frm = [x.frm for x in idautils.XrefsTo(sid)] for ea in frm: # Added comment for global %structure.name% variable or pointer if ea > idc.MaxEA(): # getting 'member_t' using ea as 'mid' mptr = idaapi.get_member_by_id(ea) # IDA 6.8: setting member comment using 'mptr' as index idaapi.set_member_cmt(mptr, descr, rep) # IDA 6.9: mptr is type of list #idaapi.set_member_cmt(mptr[0], descr, rep) else: if not rep: idc.MakeComm(ea, descr) else: idc.MakeRptCmt(ea, descr) return True else: return False
def export_func_names(fname): s = idautils.Strings(False) s.setup(strtypes=idautils.Strings.STR_UNICODE | idautils.Strings.STR_C) jsontable = [] for v in s: if v is None: print("Failed to retrieve string index") else: xrefs = [x.frm for x in idautils.XrefsTo(v.ea)] ret = [idaapi.get_func(x) for x in xrefs if idaapi.get_func(x)] names = [] funcs = [] for func in ret: if idc.GetFunctionName(func.startEA) not in names: names.append(idc.GetFunctionName(func.startEA)) funcs.append(func) if (len(funcs) != 1): continue func = funcs[0] if idc.GetFunctionName(func.startEA).startswith("sub_"): continue print("%x: len=%d type=%d -> '%s'" % (v.ea, v.length, v.type, unicode(v))) d = {} d['string'] = unicode(v) d['str_type'] = v.type d['func_name'] = idc.GetFunctionName(func.startEA) d['func_demangled'] = demangle(d['func_name']) d['func_c_decl'] = idc.GetType(func.startEA) d['func_comment'] = idaapi.get_func_cmt(func, 1) jsontable.append(d) f = open(fname, 'w') json.dump(jsontable, f, indent=4) f.close()
def find_image4_validate_property_callback(base_ea, base_end_ea, ptr_ea): seq_ea = ida_search.find_binary(base_ea, base_end_ea, "?? 77 00 51", 16, ida_search.SEARCH_DOWN) func = none if seq_ea != ida_idaapi.BADADDR: func = idaapi.get_func(seq_ea) else: for xref in idautils.XrefsTo(ptr_ea): func = idaapi.get_func(xref.frm) break if func: print("\t[+] _image4_validate_property_callback = 0x%x" % (func.start_ea)) idc.set_name(func.start_ea, "_image4_validate_property_callback", idc.SN_CHECK) return func.start_ea print("\t[-] _image4_validate_property_callback = not found") return ida_idaapi.BADADDR
def find_import_ref(dllname): imports = find_imported_funcs(dllname) R = dict() for i, (ea, name, _) in enumerate(imports): #print "%x -> %s" % (ea, name) for xref in idautils.XrefsTo(ea): # check if referrer is a thunk ea = xref.frm f = idaapi.get_func(ea) if f and (f.flags & idaapi.FUNC_THUNK) != 0: imports.append([f.startEA, idaapi.get_func_name(f.startEA), 0]) #print "\t%x %s: from a thunk, parent added %x" % (ea, name, f.startEA) continue # save results if not R.has_key(i): R[i] = [] R[i].append(ea) return (imports, R)
def pointify(self): counter = 0 print "Renaming pointers...", for (name_ea, name) in idautils.Names(): for xref in idautils.XrefsTo(name_ea): xref_name = idc.Name(xref.frm) if xref_name and xref_name.startswith("off_"): i = 0 new_name = name + "_ptr" while idc.LocByName(new_name) != idc.BADADDR: new_name = name + "_ptr%d" % i i += 1 if idc.MakeName(xref.frm, new_name): counter += 1 #else: # print "Failed to create name '%s'!" % new_name print "renamed %d pointers" % counter
def main(): root = {} for s in idautils.Strings(): root[str(s)] = {} for xref in idautils.XrefsTo(s.ea): funcname = ida_funcs.get_func_name(xref.frm) if (funcname is None): continue demangled = idc.demangle_name(funcname, idc.get_inf_attr(idc.INF_SHORT_DN)) if demangled is None: demangled = funcname root[str(s)][demangled] = funcname with open("data.json", "w") as f: print("Dumping {} strings to data.json".format(len(root.items()))) json.dump(root, f, ensure_ascii=False, indent=4, separators=(",", ":"))
def has_loop(self, func): ''' A naive method for checking to see if a function contains a loop. Works pretty well for simple functions though. ''' func_start_ea = ida_shims.start_ea(func) blocks = [func_start_ea] for block in idaapi.FlowChart(func): end_ea = ida_shims.end_ea(block) blocks.append(end_ea) for block in blocks: for xref in idautils.XrefsTo(block): xref_func = idaapi.get_func(xref.frm) xref_start_ea = ida_shims.start_ea(xref_func) if xref_func and xref_start_ea == func_start_ea: if xref.frm >= block: return True return False
def handle(self, event, *args): hx_view = args[0] #vdui_t item = hx_view.item # ctree_item_t #cursor item .e - expression, x - first operand if item.citype == idaapi.VDI_EXPR and item.e.op in (idaapi.cot_memptr, idaapi.cot_memref): if item.e.x.op == idaapi.cot_memptr: print("2") vtable_tinfo = item.e.x.type if vtable_tinfo.is_ptr(): vtable_tinfo = vtable_tinfo.get_pointed_object() method_offset = item.e.m class_tinfo = item.e.x.x.type.get_pointed_object() vtable_offset = item.e.x.m #func_name = get_member_name(vtable_tinfo, method_offset) name = str(vtable_tinfo) #print(type(vtable_tinfo)) sid = idc.get_name_ea_simple(name) #print(sid) if sid == idaapi.BADADDR: print("[ERROR] struct {} not found".format(name)) return 1 xrefs = [x for x in idautils.XrefsTo(sid)] if len(xrefs) == 0: print( "[ERROR] xrefs to {} not found, please set type in ida view" .format(name)) return 1 #print(xrefs[0], hex(xrefs[0].frm), method_offset) func_ea = read_ptr(xrefs[0].frm + method_offset) #print(xrefs[0], hex(xrefs[0].frm), method_offset, xrefs[0].frm + method_offset, hex(func_ea)) if func_ea: idaapi.open_pseudocode(func_ea, 0) return 0 return 1
def global_vars(): gvars = {} known_segs = [".data", ".bss"] for seg_name in known_segs: seg = idaapi.get_segm_by_name(seg_name) if not seg: continue for seg_ea in range(seg.start_ea, seg.end_ea): xrefs = idautils.XrefsTo(seg_ea) try: next(xrefs) except StopIteration: continue name = idaapi.get_name(seg_ea) if not name: continue gvars[seg_ea] = GlobalVariable(seg_ea, name) return gvars
def __init__(self, ea, identifier=None, create_if_not_exists=True): super(SuperFunc_t, self).__init__() self.origin_ea = ea self.identifier = identifier self.function_obj = idaapi.get_func(ea) if not self.function_obj: if create_if_not_exists: if create_function_precise(ea, False): self.function_obj = idaapi.get_func(ea) logger.debug("Created function at 0x%X" % self.function_obj.start_ea) else: raise AttributeError("No function at 0x%X" % ea) else: raise AttributeError("No function at 0x%X" % ea) if self.function_obj: self.start_ea = self.function_obj.start_ea self.end_ea = self.function_obj.end_ea self.name = idaapi.get_func_name(self.function_obj.start_ea) self.xrefs_to = [ref.frm for ref in idautils.XrefsTo(self.function_obj.start_ea) if idaapi.get_func_name(ref.frm) != self.name] self.xref_count = len(self.xrefs_to) self._flowchart = None
def _find_system_calls(self, start_ea, end_ea): system_calls = [] system_load = MIPSInstruction("la", "$t9", "system") stack_arg_zero = MIPSInstruction("addiu", "$a0", "$sp") for xref in idautils.XrefsTo(idc.LocByName('system')): ea = xref.frm if ea >= start_ea and ea <= end_ea and idc.GetMnem(ea)[0] in ['j', 'b']: a0_ea = self._find_next_instruction_ea(ea+self.INSIZE, stack_arg_zero, ea+self.INSIZE) if a0_ea == idc.BADADDR: a0_ea = self._find_prev_instruction_ea(ea, stack_arg_zero, ea-(self.SEARCH_DEPTH*self.INSIZE)) if a0_ea != idc.BADADDR: control_ea = self._find_prev_instruction_ea(ea-self.INSIZE, system_load, ea-(self.SEARCH_DEPTH*self.INSIZE)) if control_ea != idc.BADADDR: system_calls.append(ROPGadget(self._get_instruction(control_ea), self._get_instruction(ea), self._get_instruction(a0_ea), description="System call", base=self.base)) ea += self.INSIZE else: break return system_calls