Beispiel #1
0
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
Beispiel #2
0
    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()
Beispiel #3
0
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
Beispiel #4
0
    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)
Beispiel #5
0
 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()
Beispiel #6
0
    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
Beispiel #7
0
    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)
Beispiel #8
0
    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)
Beispiel #9
0
    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()
Beispiel #10
0
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)
Beispiel #11
0
    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)
Beispiel #12
0
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'
Beispiel #13
0
    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")
Beispiel #16
0
 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
Beispiel #17
0
        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")
Beispiel #18
0
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()
Beispiel #19
0
 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
Beispiel #21
0
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))