def install_plugin(): """Installs script to IDA userdir as a plugin.""" dst = get_dest_filename() src = SELF if is_installed(): btnid = kw.ask_yn(kw.ASKBTN_NO, "File exists:\n\n%s\n\nReplace?" % dst) if btnid is not kw.ASKBTN_YES: return False else: btnid = kw.ask_yn(kw.ASKBTN_NO, "This plugin is about to be installed to:\n\n%s\n\nInstall now?" % dst) if btnid is not kw.ASKBTN_YES: return False usrdir = os.path.dirname(dst) kw.msg("%s: copying script from \"%s\" to \"%s\" ..." % (PLUGIN_NAME, src, usrdir)) if not os.path.exists(usrdir): try: os.path.makedirs(usrdir) except OSError as e: if e.errno != errno.EEXIST: kw.msg("failed (mkdir)!\n") return False try: shutil.copy(src, dst) except: kw.msg("failed (copy)!\n") return False kw.msg(("done\n" "Plugin installed - please restart this instance of IDA.\n")) return True
def btn_export_ida_to_xml(self, code=0): """ 导出XML到Ghidra """ def do_export(): st = ida_auto.set_ida_state(idc.IDA_STATUS_WORK) xml = XmlExporter(1) try: try: xml.export_xml() FELogger.info("已导出IDA数据到XML") except Cancelled: ida_kernwin.hide_wait_box() FELogger.warn("已取消XML导出") except Exception as e: ida_kernwin.hide_wait_box() FELogger.warn("导出XML失败 %s" % e) finally: xml.cleanup() ida_auto.set_ida_state(st) cur_workpath = os.getcwd() xml_filepath = os.path.join(cur_workpath, '%s.xml' % ida_nalt.get_input_file_path()) bin_filepath = os.path.join( cur_workpath, '%s.bytes' % ida_nalt.get_input_file_path()) if os.path.isfile(xml_filepath) and os.path.isfile(bin_filepath): if ida_kernwin.ask_yn(0, '导出文件已存在,是否覆盖?') == 1: do_export() else: do_export()
def install_plugin(): """Installs script to IDA userdir as a plugin.""" if is_plugin(): kw.msg("Command not available. Plugin already installed.\n") return False src = SELF if is_installed(): btnid = kw.ask_yn( kw.ASKBTN_NO, "File exists:\n\n%s\n\nReplace?" % get_target_filename()) if btnid is not kw.ASKBTN_YES: return False dst = get_target_filename() usrdir = os.path.dirname(dst) kw.msg("Copying script from \"%s\" to \"%s\" ..." % (src, usrdir)) if not os.path.exists(usrdir): try: os.path.makedirs(usrdir) except OSError as e: if e.errno != errno.EEXIST: kw.msg("failed (mkdir)!\n") return False try: shutil.copy(src, dst) except: kw.msg("failed (copy)!\n") return False kw.msg(("done\n" "Plugin installed - please restart this IDA instance now.\n")) return True
def prompt_save_signature(self): with open(TEMP_SIG_FILENAME) as f: sig = hjson.load(f) if ida_kernwin.ask_yn(1, 'Are you sure you want ' 'to save this signature?') != 1: return self.save_signature(sig)
def OniButtonApply(self, code=0): current_func_addr = self.strings_manager.get_current_function_addr() current_func_name = self.strings_manager.get_current_function_name() func_name_to_set = self.GetControlValue(self.iFunctionNameToSet) if ida_kernwin.ask_yn( 0, "Rename function '{}' --to--> '{}' ?".format( current_func_name, func_name_to_set)) == 1: # user pressed 'Yes' self.strings_manager.rename_current_address(func_name_to_set) self.strings_manager.next_function() self._update_view()
def _loadLocals(self): to_load = bool(ida_kernwin.ask_yn(1, "load address table?")) addressTable = {} if to_load is 1: addressTable = ImportModule.unpickle() else: self.imInstance.analyze_imports_all() addressTable = self.imInstance.getFunctionsAsAddressTable(False) for addr, fObj in addressTable.items(): self._functionsMap[Fnc.va_to_rva(addr)] = fObj self.funcList = addressTable
def prompt_save_signature(self): """ Save last-created-temp-signature if user agrees to in IDA prompt :return: None """ self.verify_project() if ida_kernwin.ask_yn(1, 'Are you sure you want ' 'to save this signature?') != 1: return self.save_signature(TEMP_SIG_FILENAME)
def activate(self, ctx): user_input = ida_kernwin.ask_yn( ida_kernwin.ASKBTN_YES, "Would you like to export all functions?") if user_input == ida_kernwin.ASKBTN_CANCEL: return 1 output_file_name_hint = "" p = anvill.get_program() if user_input == ida_kernwin.ASKBTN_NO: screen_cursor = ida_kernwin.get_screen_ea() function_name = ida_funcs.get_func_name(screen_cursor) if function_name is None: print("anvill: The cursor is not located inside a function") return 1 output_file_name_hint = function_name + ".json" try: p.add_function_definition(screen_cursor) except: print( "anvill: Failed to process the function at address {0:x}". format(screen_cursor)) return 1 else: function_address_list = idautils.Functions() for function_address in function_address_list: try: p.add_function_definition(function_address) except: print( "anvill: Failed to process the function at address {0:x}" .format(function_address)) output_file_name_hint = "program.json" output_path = ida_kernwin.ask_file( True, output_file_name_hint, "Select where to save the spec file") if not output_path: return 1 output = json.dumps(p.proto(), sort_keys=False, indent=2) print("anvill: Saving the spec file to {}".format(output_path)) with open(output_path, "w") as f: f.write(output)
def activate(self, ctx): if self.get_xdbg_hook_status(): FELogger.info('关闭调试事件记录') self.dbg_hook.unhook() else: FELogger.info('启用调试事件记录') if ida_kernwin.ask_yn(0, '是否单步调试?') == 1: self.dbg_hook.step_dbg = True else: self.dbg_hook.step_dbg = False self.dbg_hook.hook() self.set_xdbg_hook_status()
def create_struct(name, fields, size): struct_id = idaapi.get_struc_id(name) # print struct_id if struct_id != idaapi.BADADDR: i = ida_kernwin.ask_yn( 0, "A class structure for %s already exists. Are you sure you want to remake it?" % name) if i == idaapi.BADADDR: return if i == 1: idaapi.del_struc_members(idaapi.get_struc(struct_id), 0, idaapi.get_struc_size(struct_id)) # struct_id = idc.AddStrucEx(idaapi.BADADDR, name + "_vtbl", 0) else: struct_id = idaapi.add_struc(idaapi.BADADDR, name, 0) if struct_id == idaapi.BADADDR: Warning( "Could not create the class structure!.\nPlease check something.") return sptr = idaapi.get_struc(struct_id) for off in fields: off, type_name, type_kind, field_name = fields[off] print( "Process field. Off = 0x%04X, type_name = %s (%d: %s), field_name = %s" % (off, type_name, type_kind, type_sizes[type_kind][0], field_name)) type_size = type_sizes[type_kind][1] ret = ida_struct.add_struc_member(sptr, field_name.decode(), off, flags_dict[type_size], None, type_size) if ret != 0: ida_kernwin.warning("Unknown error! Err = %d" % ret) return mptr = ida_struct.get_member(sptr, off) ida_struct.set_member_cmt( mptr, " --> %s (%d: %s)" % (type_name.decode(), type_kind, type_sizes[type_kind][0]), False) struct_size = ida_struct.get_struc_size(sptr) if size < struct_size: ida_kernwin.warning( "Struct create error! final size (%d) > instanse size (%d)" % (struct_size, size)) elif size > struct_size: for i in range(size - struct_size): ida_struct.add_struc_member(sptr, "dummy%d" % i, idaapi.BADADDR, idaapi.FF_BYTE, None, 1)
def _prepare_ida_type(self): if hasattr(self, "tid") and self.tid is not None: raise RuntimeError("May not call _prepare_ida_type twice") # Find existing structure self.tid = ida_struct.get_struc_id(self.name) if self.tid != BADADDR: # Grab structure pointer self._get_sptr() # Struct with given name already exists, validate it if self._validate_ida_type(): self.log.info("Found struct '%s' with ID %d", self.name, self.tid) return # Successful # Existing struct not valid, ask user whether to overwrite query = ida_kernwin.ask_yn( ida_kernwin.ASKBTN_NO, "A structure named '{}' already exists but does not match the needed format. Do you wish to overwrite it?" .format(self.name)) if query != ida_kernwin.ASKBTN_YES: raise RuntimeError("User cancelled operation") # Delete existing struct if not ida_struct.del_struc(self.sptr): raise RuntimeError( "Could not delete existing structure '{}'".format( self.name)) self.log.info("Deleted struct '%s' (ID=%d)", self.name, self.tid) self.tid = None self.sptr = None # Create struct self.tid = ida_struct.add_struc(BADADDR, self.name) if self.tid is None or self.tid == BADADDR: raise RuntimeError("Could not create structure '{}'".format( self.name)) # Grab structure pointer self._get_sptr() # Create members for f in self.members_array: f._prepare_ida_type() self.log.info("Created struct '%s' of size %d", self.name, self.size)
def main(): print 'Start' ans = ida_kernwin.ask_yn(0, 'define only selected function?') if ans: va = ScreenEA() fva = get_function(va) print('-' * 80) rule = create_yara_rule_for_function(fva) if rule: print(rule) if test_yara_rule(rule): logging.info('success: validated the generated rule') else: logging.error('error: failed to validate generated rule') else: for fva in idautils.Functions(): print('-' * 80) rule = create_yara_rule_for_function(fva) if rule: print(rule) print 'Done'
def find_symbol(self): """ Find the last create symbol signature. :return: """ with open(TEMP_SIG_FILENAME) as f: sig = hjson.load(f) results = self.find_from_sig_json(sig, decremental=True) for address in results: self.log('Search result: 0x{:x}'.format(address)) self.log('Search done') if len(results) == 1: # if remote sig has a proper name, but current one is not if not sig['name'].startswith('sub_') and \ idc.get_func_name(results[0]).startswith('sub_'): if ida_kernwin.ask_yn(1, 'Only one result has been found. ' 'Rename?') == 1: idc.set_name(results[0], str(sig['name']), idc.SN_CHECK)
def ask_save_binaries(li): message = "Would you like to save the extracted binaries to disk?" choice = ida_kernwin.ask_yn(ida_kernwin.ASKBTN_YES, message) return choice == ida_kernwin.ASKBTN_YES
# -------------------------------------------------------------------------- def ProcessUiActions(actions, flags=0): """ @param actions: A string containing a list of actions separated by semicolon, a list or a tuple @param flags: flags to be passed to process_ui_action() @return: Boolean. Returns False if the action list was empty or execute_ui_requests() failed. """ # Instantiate a helper helper = __process_ui_actions_helper(actions, flags) return False if len(helper) < 1 else ida_kernwin.execute_ui_requests((helper,)) # -------------------------------------------------------------------------- class print_req_t(object): def __init__(self, s): self.s = s def __call__(self): ida_kernwin.msg("%s" % self.s) return False # Don't reschedule if ida_kernwin.ask_yn( 1, ("HIDECANCEL\nDo you want to run execute_ui_requests() example?\n" "Press NO to execute ProcessUiActions() example\n")): ida_kernwin.execute_ui_requests( (print_req_t("Hello"), print_req_t(" world\n")) ) else: ProcessUiActions("JumpQ;Breakpoints")
def on_mb_click(self, event, addr, size, mouse_offs): if event.button() == Qt.RightButton: if ask_yn(1, "Clear trace?") == 1: self.hook.hits = {} return
cls.append(VtableClass(l)) print("\n%d classes identified\n\n" % len(cls)) def do_the_deal(): for c in cls: c.colorize() print(c) ipo = SaveClasses(cls) ipo.json() sr = SubRenamer() sr.load_json() sr.prepare() sr.rename_functions() return sr.rename_counter f_count = sum([len(c.functions) for c in cls]) to_proceed = bool( ida_kernwin.ask_yn( 1, "Identified %d classes %d unnamed subs. Wanna proceed?" % (len(cls), f_count))) print("to proceed?", to_proceed) if to_proceed: qty_of_success = do_the_deal() ida_kernwin.ask_yn(1, "Renamed %d of %d" % (qty_of_success, f_count)) else: print("I am done")
def main(): global til til = ida_typeinf.get_idati() capstone_init() unicorn_init() all_names = list(idautils.Names()) # First, get inheritance tree for all classes # We do this in two passes: # First pass: for each class, gather class name, parent class name, # and superclass name, and connect them # Second pass: for each inheritance hierarchy object, we check # if the parent pointer is None (signaling a top-level # class), and add that to the `ihs` list # We can do this whole thing by processing xrefs to OSMetaClass::OSMetaClass OSMetaClass_ctor = get_OSMetaClass_ctor() if OSMetaClass_ctor == 0: print("Could not find OSMetaClass::OSMetaClass") return print("Got OSMetaClass::OSMetaClass at {}".format(hex(OSMetaClass_ctor))) # key,value pairs of all inheritance hierarchy objects ih_dict = {} # only those inheritance hierarchy objects which represent # a top-level parent class (aka inheriting from OSObject) ihs = [] xrefs = list(idautils.XrefsTo(OSMetaClass_ctor)) num = 0 for xref in xrefs: frm = xref.frm # test # frm = 0x63920 # print("xref from {}".format(hex(frm))) args = get_OSMetaClass_ctor_args(frm) pname = args[0] cname = args[1] if cname == "OSMetaClassBase": print("xref from {}".format(hex(frm))) print(args) if pname == cname: continue csz = args[2] # if pname == "AUAUnitDictionary" and cname == "AUAMixerUnitDictionary": # print(args) # return new_parent = pname is not None and pname not in ih_dict new_child = cname not in ih_dict if new_parent: ih_dict[pname] = InheritanceHierarchy(None, pname, csz, csz) if new_child: ih_dict[cname] = InheritanceHierarchy(None, cname, csz) else: # Update class size for only child classes ih_dict[cname].sz = csz if pname == None: # If this class has no superclass, it must be parent class, # so make its InheritanceHierarchy object ih_dict[cname] = InheritanceHierarchy(None, cname, csz) else: child_ih = ih_dict[cname] parent_ih = ih_dict[pname] parent_ih.add_child(child_ih) child_ih.parent = parent_ih child_ih.totsz = child_ih.sz + parent_ih.totsz # if cname == "AUAUnitDictionary": # print("AUAUnitDictionary sz: {}".format(ih_dict[pname].sz)) # print(args) # return # if cname == "AUAMixerUnitDictionary": # print("AUAMixerUnitDictionary sz: {}".format(ih_dict[cname].sz)) # print(args) # return num += 1 # if num == 10: # break print("First pass: {} classes processed".format(num)) num = 0 # Second pass for ih in ih_dict.values(): if ih.parent == None: # print("Adding {} to the ihs list".format(ih.name)) num += 1 ihs.append(ih) print("Second pass: {} classes added to ihs list".format(num)) num = 0 wants_class_hierarchy = ida_kernwin.ask_yn(0, "Dump class hierarchy?") if wants_class_hierarchy: hierch_file = open( "{}/iOS/Scripts/iokit_hier.txt".format(str(Path.home())), "w") for ih in ihs: dump_hierarchy_to_file(hierch_file, ih, 0) print("File written to {}".format(hierch_file.name)) hierch_file.close() return vtables = [] for cur_name in all_names: ea = cur_name[0] name = cur_name[1] if "ZTV" in name: vtables.append(cur_name) struct_file = open( "{}/iOS/Scripts/structs_from_vtabs.h".format(str(Path.home())), "w") is_standalone_kext = ida_kernwin.ask_yn(0, "Standalone kext?") if is_standalone_kext: # If this is from a standalone kext, I need to write some # definitions for common objects that follow my struct format, # otherwise, things get really screwed struct_file.write( "struct __cppobj ExpansionData {};\n\n" "struct __cppobj OSMetaClassBase_vtbl;\n\n" "struct __cppobj OSMetaClassBase_mbrs {};\n\n" "struct __cppobj OSMetaClassBase {\n" "\tOSMetaClassBase_vtbl *__vftable /*VFT*/;\n" "\tOSMetaClassBase_mbrs m;\n" "};\n\n" "struct __cppobj OSObject_mbrs : OSMetaClassBase_mbrs {\n" "\tint retainCount;\n" "};\n\n" "struct __cppobj OSObject_vtbl : OSMetaClassBase_vtbl {};\n\n" "struct __cppobj OSObject {\n" "\tOSObject_vtbl *__vftable;\n" "\tOSObject_mbrs m;\n" "};\n\n" "struct __cppobj OSMetaClass_mbrs : OSMetaClassBase_mbrs {\n" "\tExpansionData *reserved;\n" "\tconst OSMetaClass *superClassLink;\n" "\tconst OSSymbol *className;\n" "\tunsigned int classSize;\n" "\tunsigned int instanceCount;\n" "};\n\n" "struct __cppobj OSMetaClass {\n" "\tOSMetaClassBase_vtbl *__vftable;\n" "\tOSMetaClass_mbrs m;\n" "};\n\n" "struct __cppobj OSCollection_vtbl;\n" "struct __cppobj OSCollection_mbrs : OSObject_mbrs {\n" "\tunsigned int updateStamp;\n" "\tunsigned int fOptions;\n" "};\n\n" "struct __cppobj OSCollection {\n" "\tOSCollection_vtbl *__vftable;\n" "\tOSCollection_mbrs m;\n" "};\n\n" "struct __cppobj OSArray_vtbl;\n" "struct __cppobj OSArray_mbrs : OSCollection_mbrs {\n" "\tunsigned int count;\n" "\tunsigned int capacity;\n" "\tunsigned int capacityIncrement;\n" "\tvoid *array;\n" "};\n\n" "struct __cppobj OSArray {\n" "\tOSArray_vtbl *__vftable;\n" "\tOSArray_mbrs m;\n" "};\n\n" "struct __cppobj OSDictionary::dictEntry {\n" "\tconst OSSymbol *key;\n" "\tconst OSMetaClassBase *value;\n" "};\n\n" "struct __cppobj OSDictionary_vtbl;\n" "struct __cppobj OSDictionary_mbrs : OSCollection_mbrs {\n" "\tunsigned int count;\n" "\tunsigned int capacity;\n" "\tunsigned int capacityIncrement;\n" "\tOSDictionary::dictEntry *dict;\n" "};\n\n" "struct __cppobj OSDictionary {\n" "\tOSDictionary_vtbl *__vftable;\n" "\tOSDictionary_mbrs m;\n" "};\n\n" "struct __cppobj OSSet_vtbl;\n" "struct __cppobj OSSet_mbrs : OSCollection_mbrs {\n" "\tOSArray *members;\n" "};\n\n" "struct __cppobj OSSet {\n" "\tOSSet_vtbl *__vftable;\n" "\tOSSet_mbrs m;\n" "};\n\n" "struct __cppobj OSString_mbrs : OSObject_mbrs {\n" "\tunsigned __int32 flags : 14;\n" "\tunsigned __int32 length : 18;\n" "\tchar *string;\n" "};\n\n" "struct __cppobj OSString {\n" "\tOSObject_vtbl *__vftable;\n" "\tOSString_mbrs m;\n" "};\n\n" "struct __cppobj OSSymbol : OSString {};\n\n") num_failed_get_type = 0 cnt = 0 for vtable in vtables: demangled_name = idc.demangle_name(vtable[1], get_inf_attr(idc.INF_LONG_DN)) # unless this is a vtable for OSMetaClassBase, OSMetaClassMeta, # or OSMetaClass, skip anything metaclass related if "::MetaClass" in demangled_name: continue class_name = ida_name.extract_name(demangled_name, len("`vtable for'")) if class_name in BLACKLIST: continue ea = vtable[0] #+ 8; while ida_bytes.get_qword(ea) == 0: ea += 8 # print("EA: {}".format(hex(ea))) if is_unknown(ida_bytes.get_flags(ea)): continue # if class_name != "IOSkywalkPacket": # continue # if class_name != "AHTHSBufferStatic": # continue # if class_name != "HSMSPITest": # continue # if class_name != "AppleMesa": # continue # if class_name != "AppleUSBHostController": # continue # if class_name != "AppleEmbeddedPCIE": # continue # if class_name != "SimpleEval": # continue # if class_name != "AppleUSBCDCControl": # continue # if class_name != "IOHDCP2TransmitterAuthSession": # continue # if class_name != "IOAVService::DisplayIDParser::readDisplayID": # continue # if class_name != "IOMFB::TypedProp": # continue # if class_name != "IOMFB::UPBlock_GenPipe_v2": # continue # if class_name != "AppleMesaSEPDriver": # continue # if class_name != "IOAVController": # continue # if class_name != "AppleConvergedIPCICEBBBTIInterface": # continue # if class_name != "ApplePPM": # continue cnt += 1 # print("{}".format(class_name)) # skip NULL pointers until we hit a function while ida_bytes.get_qword(ea) == 0: ea += 8 num_virts = 0 num_dtors = 0 num_untyped = 0 num_noname = 0 fxn_name_list = [] fxn_name_dict = {} struct_fields = [] fwd_decls = set() fwd_decls.add(class_name) svt = SymbolicatedVtable(class_name) ioc = IOKitClass(svt) ioc.svt = svt # vtables seem to be NULL terminated while True: fxn_ea = ida_bytes.get_qword(ea) # end of vtable for this class if fxn_ea == 0: break # print("Type for {}/{} @ {}: {}".format(hex(fxn_ea), fxn_name, hex(ea), fxn_type)) # if fxn_type == None: # num_failed_get_type += 1 # ea += 8 # continue # default to this for ___cxa_pure_virtual fxn_args = "void" fxn_call_conv = "" fxn_mangled_name = ida_name.get_ea_name(fxn_ea) fxn_name = ida_name.demangle_name(fxn_mangled_name, get_inf_attr(idc.INF_LONG_DN)) if fxn_name == None: # ___cxa_pure_virtual fxn_name = ida_name.get_ea_name(fxn_ea) # some other thing? if len(fxn_name) == 0: fxn_name = "noname{}".format(num_noname) else: fxn_type = idc.get_type(fxn_ea) if fxn_type == None: # sometimes this happens, don't know why # the only thing fxn_type would have provided was # the calling convention, so we need to manually # reconstruct parameter list, and assume calling # convention is __fastcall # if mangled_fxn_name == "__ZN25IOGeneralMemoryDescriptor7doUnmapEP7_vm_mapyy": # exit(0) fxn_return_type = "__int64" fxn_call_conv = "__fastcall" fxn_args_string = fxn_name[fxn_name.find("(") + 1:fxn_name.rfind(")")] # if fxn_args_string == "IOService *, unsigned int, void *, void (*)(OSObject *, AppleUSBCDCControl*, void *, USBCDCNotification *)": # # print("Hello") # fxn_args_string = "IOService *, unsigned int, void *, void (*)(OSObject *, void (*)(TestType *, AppleUSBCDCControl*, void *, USBCDCNotification *), AppleUSBCDCControl*, void *, USBCDCNotification *)" # print("fxn args: {}".format(fxn_args_string)) # if fxn_args_string == "OSObject *, void (*)(OSObject *, IOHDCPAuthSession *), IOHDCPMessageTransport *, IOHDCPInterface *": # fxn_args_string = "OSObject *, void (*)(OSObject *, IOHDCPAuthSession *), IOHDCPMessageTransport *, IOHDCPInterface *, unsigned long long" fxn_args_string = fxn_args_string.replace( "{block_pointer}", "*") if fxn_args_string.find(",") != -1: # print("More than one arg: {}".format(fxn_args_list)) # extra comma makes the parser happy fxn_args_types_list = get_arg_type_list( fxn_args_string + ",") # print("More than one arg for {}: {}".format(fxn_name, fxn_args_types_list)) # print() fxn_args = "" argnum = 0 # print(type(fxn_args_types_list)) to_fwd_decl = get_fwd_decls(fxn_args_types_list) if len(to_fwd_decl) > 0: fwd_decls.update(to_fwd_decl) for arg_type in fxn_args_types_list: if argnum == 0: fxn_args += "{} *__hidden this, ".format( class_name) else: fxn_args += "{}, ".format(fix_type(arg_type)) argnum += 1 fxn_args = fxn_args[:-2] else: fxn_args = "{} *__hidden this".format(class_name) arg_type = fxn_name[fxn_name.find("(") + 1:fxn_name.rfind(")")] # print("Only one arg for {}: {}".format(fxn_name, arg_type)) arg_type_list = [arg_type] # print("Only one arg: {}".format(arg_type_list)) to_fwd_decl = get_fwd_decls(arg_type_list) if len(to_fwd_decl) > 0: fwd_decls.update(to_fwd_decl) if arg_type != "void" and len(arg_type) > 0: fxn_args += ", {}".format(fix_type(arg_type)) else: all_except_args = fxn_type[:fxn_type.find("(")] # first, if there's no spaces, there's no calling # convention specifed if all_except_args.find(" ") == -1: fxn_return_type = all_except_args # Also, this having no spaces could mean IDA messed # up, so we should use the demangled name instead # and parse that fxn_type = "(" + fxn_name[fxn_name.find("(") + 1:] # print("No spaces in args, using {} as fxn_type".format(fxn_type)) else: double_underscore = all_except_args.rfind("__") if double_underscore != -1: fxn_return_type = all_except_args[: double_underscore] fxn_call_conv = all_except_args[double_underscore:] else: fxn_return_type = all_except_args # get args # print("fxn_type: {}".format(fxn_type)) fxn_args = fxn_type[fxn_type.find("(") + 1:fxn_type.rfind(")")] fxn_args_type_list = get_arg_type_list(fxn_args + ",") fixed_fxn_args_type_list = [] # Fix up args for arg_type in fxn_args_type_list: # Remove __hidden arg_type = arg_type.replace("__hidden", "") # Check for a pointer. This is an easy case, we # just delete everything from the first * star = arg_type.find("*") if star != -1: arg_type = arg_type[0:star] else: # Otherwise, find the last space, and delete # from there # But in case there was no name for this # parameter, check if the token after the last # space is not an IDA type or primitive type lspace = arg_type.rfind(" ") if lspace != -1: token = arg_type[lspace:].replace(" ", "") if not is_primitive_type( token) and not is_ida_type(token): arg_type = arg_type[0:lspace] # print("arg_type: {}".format(arg_type)) fixed_fxn_args_type_list.append(arg_type) # to_fwd_decl = get_fwd_decls(fxn_args_type_list) to_fwd_decl = get_fwd_decls(fixed_fxn_args_type_list) if len(to_fwd_decl) > 0: fwd_decls.update(to_fwd_decl) # print("fxn_type is not None for {}: fxn args: {}".format(fxn_name, fxn_args_type_list)) # print("fxn_type is not None: will fwd declare: {}".format(to_fwd_decl)) # get function name # remove 'classname::' and params fxn_name = fxn_name[fxn_name.find("::") + 2:fxn_name.find("(") + 1] fxn_name = fxn_name[:fxn_name.find("(")] # replace any '~' fxn_name = fxn_name.replace("~", "DTOR{}_".format(num_dtors)) # remove any < and > fxn_name = fxn_name.replace("<", "") fxn_name = fxn_name.replace(">", "") if fxn_name in list(fxn_name_dict.keys()): fxn_name_dict[fxn_name] += 1 fxn_name += "_{}".format(fxn_name_dict[fxn_name]) else: fxn_name_dict[fxn_name] = -1 if "DTOR" in fxn_name: num_dtors += 1 curfield = "" if fxn_name == "___cxa_pure_virtual": # struct_fields.append("\tvoid __noreturn (__cdecl *___cxa_pure_virtual{})({});".format(num_virts, # fxn_args)) curfield = "\tvoid __noreturn (__cdecl *___cxa_pure_virtual{})({});".format( num_virts, fxn_args) num_virts += 1 else: # struct_fields.append("\t{} ({} *{})({});".format(fxn_return_type, # fxn_call_conv, fxn_name, fxn_args)) curfield = "\t{} ({} *{})({});".format(fxn_return_type, fxn_call_conv, fxn_name, fxn_args) svt.add(curfield) ea += 8 # return # Some classes won't have xrefs to OSMetaClass::OSMetaClass, # like OSMetaClassBase if class_name in ih_dict: ih_dict[class_name].ioc = ioc # Just write forward decls for now for decl in fwd_decls: struct_file.write("struct __cppobj {};\n".format(decl)) struct_file.write("\n") # cnt += 1 # if cnt == 5: # break print("{} IOKit vtables".format(len(vtables))) # Now create the header file to import into IDA # for ih in ihs: # dump_ih(ih, 0) generate_header_file(struct_file, ihs) # fixup_header_file(struct_file) struct_file.close()
def ask(text): return ida_kernwin.ask_yn(0, text) == 1
import idaapi import ida_kernwin import idc struct_name = ida_kernwin.ask_str("", 4, "Enter struct name") start = ida_kernwin.ask_addr(0, "Enter start address") num_structs = ida_kernwin.ask_long(0, "Enter struct count") should_number = ida_kernwin.ask_yn(0, "Number the structs as they're created?") cur_struct_num = 0 struct_id = idaapi.get_struc_id(struct_name) if struct_id == -1: exit("No such struct {}".format(struct_name)) struct_size = idaapi.get_struc_size(struct_id) cur = start for i in range(num_structs): create_struct(cur, struct_size, struct_name) if should_number: set_cmt(cur, str(cur_struct_num), 0) cur_struct_num += 1 cur += struct_size
def main(): u32 = lambda x: struct.unpack("<I", x)[0] u64 = lambda x: struct.unpack("<Q", x)[0] image_base = idaapi.get_imagebase() assert get_bytes(image_base, 4) == b"\x7fELF", "The file looks like non-ELF binary" assert get_byte(image_base + 4) == 2, "Only support 64bit ELF binary" if get_word(image_base + 0x12) != 0x3e: res = ida_kernwin.ask_yn( ida_kernwin.ASKBTN_NO, "Only x86-64 machine type has been tested.\nContinue?") if res != ida_kernwin.ASKBTN_YES: return pht_base = image_base + get_qword(image_base + 0x20) pht_entry_size = get_word(image_base + 0x36) pht_entry_count = get_word(image_base + 0x38) jmprel = None for i in range(pht_entry_count): current = pht_base + pht_entry_size * i if get_dword(current) != 2: continue dynamic = get_qword(current + 0x10) j = 0 tag = -1 while tag != 0: tag = get_qword(dynamic + 0x10 * j) if tag == 0x17: jmprel = get_qword(dynamic + 0x10 * j + 0x8) break j += 1 else: continue break else: ida_kernwin.warning("Cannot find DYNAMIC PHT Entry") return got_start_ea = SegByBase(SegByName(".got")) got_end_ea = SegEnd(got_start_ea) extern_start_ea = SegByBase(SegByName("extern")) extern_end_ea = SegEnd(extern_start_ea) cur = got_start_ea + 0x18 fails = [] # Handle .got for full RELRO while cur < got_end_ea: plt_offset = u64(get_bytes(cur, 8)) if get_segm_name(plt_offset) == "extern": cur += 0x8 continue gen = FuncItems(plt_offset) gen.next() extern_idx = GetOperandValue(gen.next(), 0) del gen func_offset = ida_funcs.get_func(XrefsTo(cur, 0).next().frm).startEA real_func_name = GetCommentEx( jmprel + get_struc_size(get_struc_id("Elf64_Rela")) * extern_idx, 0).split()[-1] extern_ea = extern_start_ea while extern_ea < extern_end_ea: if get_name(extern_ea) == real_func_name: func_type = get_type(extern_ea) break extern_ea = NextNotTail(extern_ea) if extern_ea == BADADDR: fails.append((cur, real_func_name)) cur += 0x8 continue MakeNameEx(extern_ea, "__imp_" + real_func_name, 0) MakeNameEx(plt_offset, real_func_name + "_plt", 0) MakeNameEx(cur, real_func_name + "_ptr", 0) MakeNameEx(func_offset, real_func_name, 0) apply_type(func_offset, get_tinfo(extern_ea)) cur += 0x8 got_start_ea = SegByBase(SegByName(".got.plt")) got_end_ea = SegEnd(got_start_ea) cur = got_start_ea + 0x18 # Handle .got for full RELRO while cur < got_end_ea: plt_offset = u64(get_bytes(cur, 8)) if get_segm_name(plt_offset) == "extern": cur += 0x8 continue gen = FuncItems(plt_offset) gen.next() extern_idx = GetOperandValue(gen.next(), 0) del gen func_offset = ida_funcs.get_func(XrefsTo(cur, 0).next().frm).startEA real_func_name = GetCommentEx( jmprel + get_struc_size(get_struc_id("Elf64_Rela")) * extern_idx, 0).split()[-1] print(real_func_name) extern_ea = extern_start_ea while extern_ea < extern_end_ea: if get_name(extern_ea) == real_func_name: func_type = get_type(extern_ea) break extern_ea = NextNotTail(extern_ea) if extern_ea == BADADDR: fails.append((cur, real_func_name)) cur += 0x8 continue MakeNameEx(extern_ea, "__imp_" + real_func_name, 0) MakeNameEx(plt_offset, real_func_name + "_plt", 0) MakeNameEx(cur, real_func_name + "_ptr", 0) MakeNameEx(func_offset, real_func_name, 0) apply_type(func_offset, get_tinfo(extern_ea)) cur += 0x8 print("DONE") if fails: print("Fails: {}".format(fails))