コード例 #1
0
def apply_jni_func_sig():
    """ Apply the standard JNIEnv* and jobject signature to a function.
    """
    print("Function: {}".format(idc.get_func_name(here())))

    func = ida_hexrays.decompile(here())
    func_type = func.type
    funcdata = ida_typeinf.func_type_data_t()
    func_type.get_func_details(funcdata)

    jnienv = ida_typeinf.tinfo_t()
    jnienv.get_named_type(ida_typeinf.get_idati(), "JNIEnv")
    jnienv_ptr = ida_typeinf.tinfo_t()
    jnienv_ptr.create_ptr(jnienv)

    jobject = ida_typeinf.tinfo_t()
    jobject.get_named_type(ida_typeinf.get_idati(), "jobject")

    funcdata[0].type = jnienv_ptr
    funcdata[0].name = "env"
    funcdata[1].type = jobject
    funcdata[1].name = "thiz"
    new_tinfo = ida_typeinf.tinfo_t()
    new_tinfo.create_func(funcdata)
    ida_typeinf.apply_tinfo(here(), new_tinfo, ida_typeinf.TINFO_DEFINITE)
コード例 #2
0
def get_struct_size(struct_def):
    tif = ida_typeinf.tinfo_t()  # Prepare a container for the type
    til = ida_typeinf.get_idati()  # Get the "Local types" types library
    name = ida_typeinf.parse_decl(tif, til, struct_def,
                                  0)  # Parse the declaration, return its

    return tif.get_size()
コード例 #3
0
ファイル: events.py プロジェクト: deactivated/IDArling
    def __call__(self):
        from .core import Core

        dll = Core.get_ida_dll()

        get_idati = dll.get_idati
        get_idati.argtypes = []
        get_idati.restype = ctypes.c_void_p

        set_numbered_type = dll.set_numbered_type
        set_numbered_type.argtypes = [
            ctypes.c_void_p,
            ctypes.c_uint32,
            ctypes.c_int,
            ctypes.c_char_p,
            ctypes.c_char_p,
            ctypes.c_char_p,
            ctypes.c_char_p,
            ctypes.c_char_p,
            ctypes.c_int,
        ]
        set_numbered_type.restype = ctypes.c_int

        py_ti = ida_typeinf.get_idati()
        ordinal_qty = ida_typeinf.get_ordinal_qty(py_ti) - 1
        last_ordinal = self.local_types[-1][0]
        if ordinal_qty < last_ordinal:
            ida_typeinf.alloc_type_ordinals(py_ti, last_ordinal - ordinal_qty)
        else:
            for py_ordinal in range(last_ordinal + 1, ordinal_qty + 1):
                ida_typeinf.del_numbered_type(py_ti, py_ordinal)

        local_types = self.local_types
        for py_ord, name, type, fields, cmt, fieldcmts, sclass in local_types:
            if type:
                ti = get_idati()
                ordinal = ctypes.c_uint32(py_ord)
                ntf_flags = ctypes.c_int(ida_typeinf.NTF_REPLACE)
                name = ctypes.c_char_p(name)
                type = ctypes.c_char_p(type)
                fields = ctypes.c_char_p(fields)
                cmt = ctypes.c_char_p(cmt)
                fieldcmts = ctypes.c_char_p(fieldcmts)
                sclass = ctypes.c_int(sclass)
                set_numbered_type(
                    ti,
                    ordinal,
                    ntf_flags,
                    name,
                    type,
                    fields,
                    cmt,
                    fieldcmts,
                    sclass,
                )
            else:
                ida_typeinf.del_numbered_type(py_ti, py_ord)

        ida_kernwin.request_refresh(ida_kernwin.IWID_LOCTYPS)
コード例 #4
0
ファイル: biptype.py プロジェクト: xcode2010/bip
    def import_c_header(path,
                        pack=0,
                        raw_args=True,
                        silent=False,
                        autoimport=True):
        """
            Import a C header file.

            :param str path: The path to the C header file to import.
            :param int pack: The packing for the structure in the header. 0
                means default (from compiler/configuration), other values are
                power of 2 up to 16. No verification is made on that value.
            :param bool raw_args: Should leave the name of the argument
                unchanged: do not remove the _ in the name. True by default.
            :param bool silent: Should silently fails on error and mask
                warnings.
            :param bool autoimport: If True (the default), this function will
                import all new types in the IDB ("Structures", "Enums", ...
                Views), instead of only keeping them in the type
                library (til, the "Local Types" view).
            :return: The number of error which occur during parsing.
        """
        # This use the idc.parse_decls function, which is different of the
        #   ida_typeinf.parse_decls function, this one should be implemented
        #   using the type library
        flags = ida_typeinf.PT_FILE | ida_typeinf.PT_REPLACE
        if raw_args:
            flags |= ida_typeinf.PT_RAWARGS
        if silent:
            flags |= ida_typeinf.PT_SIL

        # handle pack conversion, hugly but should be ok
        if pack <= 2:
            flags |= (pack << 4) & ida_typeinf.PT_PACKMASK
        else:
            if pack == 4:
                flags |= (3 << 4) & ida_typeinf.PT_PACKMASK
            elif pack == 8:
                flags |= (4 << 4) & ida_typeinf.PT_PACKMASK
            elif pack == 16:
                flags |= (5 << 4) & ida_typeinf.PT_PACKMASK

        if autoimport:
            tidft = ida_typeinf.get_idati()  # default type lib of the idb
            # we get the nb of ordinal type, before parsing
            nb_typ = ida_typeinf.get_ordinal_qty(tidft)
            # now we make the parsing
            nb_error = idc.parse_decls(path, flags)
            # get the new number of types after it has been parsed
            nb_typ_after = ida_typeinf.get_ordinal_qty(tidft)
            # now we can import all of them
            for i in range(nb_typ, nb_typ_after):
                # get the name of the type
                na = ida_typeinf.get_numbered_type_name(tidft, i)
                # import the type, put it at the end
                ida_typeinf.import_type(tidft, -1, na)
            return nb_error
        else:
            return idc.parse_decls(path, flags)
コード例 #5
0
def ImportLocalType(idx):
    name = ida_typeinf.get_numbered_type_name(ida_typeinf.get_idati(), idx)
    # todo: doing something with empty and error types
    ret = ida_typeinf.get_numbered_type(ida_typeinf.get_idati(), idx)
    if ret is not None:
        typ_type, typ_fields, typ_cmt, typ_fieldcmts, typ_sclass = ret
        if typ_type is None:
            typ_type = b""
        if typ_fields is None:
            typ_fields = b""
        if typ_cmt is None:
            typ_cmt = b""
        if typ_fieldcmts is None:
            typ_fieldcmts = b""
        return LocalType(name, typ_type, typ_fields, typ_cmt, typ_fieldcmts,
                         typ_sclass)
    return None
コード例 #6
0
    def local_types_changed(self):
        from .core import Core

        dll = Core.get_ida_dll()

        get_idati = dll.get_idati
        get_idati.argtypes = []
        get_idati.restype = ctypes.c_void_p

        get_numbered_type = dll.get_numbered_type
        get_numbered_type.argtypes = [
            ctypes.c_void_p,
            ctypes.c_uint32,
            ctypes.POINTER(ctypes.c_char_p),
            ctypes.POINTER(ctypes.c_char_p),
            ctypes.POINTER(ctypes.c_char_p),
            ctypes.POINTER(ctypes.c_char_p),
            ctypes.POINTER(ctypes.c_int),
        ]
        get_numbered_type.restype = ctypes.c_bool

        local_types = []
        py_ti = ida_typeinf.get_idati()
        for py_ord in range(1, ida_typeinf.get_ordinal_qty(py_ti)):
            name = ida_typeinf.get_numbered_type_name(py_ti, py_ord)

            ti = get_idati()
            ordinal = ctypes.c_uint32(py_ord)
            type = ctypes.c_char_p()
            fields = ctypes.c_char_p()
            cmt = ctypes.c_char_p()
            fieldcmts = ctypes.c_char_p()
            sclass = ctypes.c_int()
            get_numbered_type(
                ti,
                ordinal,
                ctypes.pointer(type),
                ctypes.pointer(fields),
                ctypes.pointer(cmt),
                ctypes.pointer(fieldcmts),
                ctypes.pointer(sclass),
            )
            local_types.append(
                (
                    py_ord,
                    name,
                    type.value,
                    fields.value,
                    cmt.value,
                    fieldcmts.value,
                    sclass.value,
                )
            )
        self._send_packet(evt.LocalTypesChangedEvent(local_types))
        return 0
コード例 #7
0
 def local_types_changed(self):
     local_types = []
     ti = ida_typeinf.get_idati()
     for ordinal in range(1, ida_typeinf.get_ordinal_qty(ti)):
         name = ida_typeinf.get_numbered_type_name(ti, ordinal)
         type_info = ida_typeinf.tinfo_t()
         type_info.get_numbered_type(ti, ordinal)
         ret = type_info.serialize()
         local_types.append((ordinal, name, ret))
     self._send_packet(evt.LocalTypesChangedEvent(local_types))
     return 0
コード例 #8
0
def create_struct(name, struct_def, ordinal=0, overwrite=True):

    if overwrite and ordinal:
        print "overwriting: {}".format(name)
        tif = ida_typeinf.tinfo_t()  # Prepare a container for the type
        til = ida_typeinf.get_idati()  # Get the "Local types" types library
        name = ida_typeinf.parse_decl(
            tif, til, struct_def,
            ida_typeinf.PT_SIL)  # Parse the declaration, return its
        #   name and fill the tinfo_t object

        #   for storing it
        res = tif.set_numbered_type(til, ordinal, ida_typeinf.NTF_REPLACE,
                                    name)  # ...and store it

    else:
        print "Creating new struct - {}".format(name)
        # Helpful for debugging
        #print "<start>{}<end>".format(struct_def)

        tif = ida_typeinf.tinfo_t()  # Prepare a container for the type
        til = ida_typeinf.get_idati()  # Get the "Local types" types library
        name = ida_typeinf.parse_decl(
            tif, til, struct_def,
            ida_typeinf.PT_SIL)  # Parse the declaration, return its
        #   name and fill the tinfo_t object
        if not name:
            print "Failed to create structure"
            return False
        ordinal = ida_typeinf.alloc_type_ordinal(
            til)  # Make room in the "Local types" library,
        #   for storing it
        res = tif.set_numbered_type(til, ordinal, 0, name)  # ...and store it

    if res == -1:
        print "Failed to create structure"
        return False

    ida_typeinf.import_type(idaapi.cvar.idati, -1, name)

    return True
コード例 #9
0
    def __process_types(self):
        localtypes = []

        ti_lib_obj = ida_typeinf.get_idati()
        ti_lib_count = ida_typeinf.get_ordinal_qty(ti_lib_obj)

        for ti_ordinal in range(1, ti_lib_count + 1):
            ti_info = ida_typeinf.tinfo_t()
            if ti_info.get_numbered_type(ti_lib_obj, ti_ordinal):
                localtypes.append(self.__process_types_tinfo(ti_info))

        return localtypes
コード例 #10
0
    def local_types_changed(self):
        print("local type changed")
        return

        changed_types = []
        # self._plugin.logger.trace(self._plugin.core.local_type_map)
        for i in range(1,
                       ida_typeinf.get_ordinal_qty(ida_typeinf.get_idati())):
            t = ImportLocalType(i)
            if t and t.name and ida_struct.get_struc_id(
                    t.name) == ida_idaapi.BADADDR and ida_enum.get_enum(
                        t.name) == ida_idaapi.BADADDR:
                if i in self._plugin.core.local_type_map:
                    t_old = self._plugin.core.local_type_map[i]
                    if t_old and not t.isEqual(t_old):
                        changed_types.append((t_old.to_tuple(), t.to_tuple()))
                    elif t_old is None and i in self._plugin.core.delete_candidates:
                        if not self._plugin.core.delete_candidates[i].isEqual(
                                t):
                            changed_types.append(
                                (self._plugin.core.delete_candidates[i].
                                 to_tuple(), t.to_tuple()))
                        del self._plugin.core.delete_candidates[i]

                else:
                    changed_types.append((None, t.to_tuple()))
            if t is None:
                assert i in self._plugin.core.local_type_map
                if i in self._plugin.core.local_type_map:
                    t_old = self._plugin.core.local_type_map[i]
                    if t_old != t:
                        self._plugin.core.delete_candidates[i] = t_old
                    elif i in self._plugin.core.delete_candidates:
                        # changed_types.append((self._plugin.core.delete_candidates[i],None))
                        del self._plugin.core.delete_candidates[i]

                    # t_old = self._plugin.core.local_type_map[i]
                    # changed_types.append((t_old,None))
        # self._plugin.logger.trace(changed_types)
        if fDebug:
            pydevd_pycharm.settrace('localhost',
                                    port=2233,
                                    stdoutToServer=True,
                                    stderrToServer=True,
                                    suspend=False)
        self._plugin.logger.trace("Changed_types: %s" % list(
            map(
                lambda x: (x[0][0] if x[0] else None, x[1][0]
                           if x[1] else None), changed_types)))
        if len(changed_types) > 0:
            self._send_packet(evt.LocalTypesChangedEvent(changed_types))
        self._plugin.core.update_local_types_map()
        return 0
コード例 #11
0
    def declaration(self, decl):
        """
        Changes the declaration of the function internally.
        """
        # Ensure ends with ';'
        if not decl.endswith(";"):
            decl += ";"

        tif = ida_typeinf.tinfo_t()
        til = ida_typeinf.get_idati()
        func_type_data = ida_typeinf.func_type_data_t()
        ida_typeinf.parse_decl(tif, til, decl, ida_typeinf.PT_SIL)
        tif.get_func_details(func_type_data)
        self._tif = tif
        self._func_type_data = func_type_data
コード例 #12
0
    def type(self, value):
        """
        Sets FunctionArg to a new type.

        NOTE: Setting the type here has no affect on the FunctionSignature object this came from.
        """
        is_ptr = value.endswith("*")
        value = value.strip(" *")

        # Create new tinfo object of type.
        tif = ida_typeinf.tinfo_t()
        tif.get_named_type(ida_typeinf.get_idati(), value)

        # If a pointer, create another tinfo object that is the pointer of the first.
        if is_ptr:
            tif2 = ida_typeinf.tinfo_t()
            tif2.create_ptr(tif)
            tif = tif2

        self._funcarg_obj.type = tif
コード例 #13
0
def InsertType(type_obj, fReplace=False):
    # print("Insert type %s." % type_obj.name)
    wrapperTypeString = b'\x0d\x01\x01'
    if getTypeOrdinal(type_obj.name) != 0:
        idx = getTypeOrdinal(type_obj.name)
        t = ImportLocalType(idx)
        if (t.TypeFields is None or t.TypeFields == "") and t.is_sue():
            fReplace = True
        if t.isEqual(type_obj) or type_obj.TypeString == wrapperTypeString:
            return 1
        if not fReplace:
            type_obj = DuplicateResolver(t, type_obj, False)
    else:
        idx = ida_typeinf.alloc_type_ordinals(idaapi.get_idati(), 1)
    tif = ida_typeinf.tinfo_t()
    ret = tif.deserialize(ida_typeinf.get_idati(), type_obj.GetTypeString(),
                          type_obj.TypeFields, type_obj.fieldcmts)
    if not ret:
        idaapi.warning(
            "Error on tinfo deserilization, type name = %s, ret = %d" %
            (type_obj.name, ret))
        ret = -1
    else:
        ret = tif.set_numbered_type(idaapi.get_idati(), idx, 0x4,
                                    type_obj.name)
    del tif
    # ret = idaapi.set_numbered_type(
    #     my_ti,
    #     idx,
    #     0x4,
    #     type_obj.name,
    #     type_obj.GetTypeString(),
    #     type_obj.TypeFields,
    #     type_obj.cmt,
    #     type_obj.fieldcmts
    # )
    # print "Insert type %s. ret = %d"%(type_obj.name,ret)
    if (ida_pro.IDA_SDK_VERSION < 700
            and ret != 1) or (ida_pro.IDA_SDK_VERSION >= 700 and ret != 0):
        print("bad insert: %s; ret = %d" % (type_obj.name, ret))
    return ret
コード例 #14
0
ファイル: events.py プロジェクト: xabiugarte/IDArling
    def __call__(self):
        ti = ida_typeinf.get_idati()

        ordinal_qty = ida_typeinf.get_ordinal_qty(ti)
        last_ordinal = self.local_types[-1][0]
        if ordinal_qty < last_ordinal:
            ida_typeinf.alloc_type_ordinals(ti, last_ordinal - ordinal_qty)
        else:
            for ordinal in range(last_ordinal + 1, ordinal_qty + 1):
                ida_typeinf.del_numbered_type(ti, ordinal)

        for ordinal, name, ret in self.local_types:
            name = Event.encode_bytes(name)
            type, fields, fieldcmts = ret
            type = Event.encode_bytes(type)
            fields = Event.encode_bytes(fields)
            fieldcmts = Event.encode_bytes(fieldcmts)

            type_info = ida_typeinf.tinfo_t()
            type_info.deserialize(ti, type, fields, fieldcmts)
            type_info.set_numbered_type(ti, ordinal, 0, name)

        ida_kernwin.request_refresh(ida_kernwin.IWID_LOCTYPS)
コード例 #15
0
def import_type(type_name):
    if ida_typeinf.import_type(ida_typeinf.get_idati(), 0, type_name) == \
       0xffffffffffffffff:
        return False
    return True
コード例 #16
0
def parse_struct(struct_def):
    tif = ida_typeinf.tinfo_t()
    til = ida_typeinf.get_idati()
    name = ida_typeinf.parse_decl(tif, til, struct_def,
                                  0)  # Parse the declaration, return its
    return (til, tif, name)
コード例 #17
0
def getTypeOrdinal(name):
    my_ti = ida_typeinf.get_idati()
    return ida_typeinf.get_type_ordinal(my_ti, name)
コード例 #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()
コード例 #19
0
 def _deser(self, typ, fields):
     tif = ida_typeinf.tinfo_t()
     if not tif.deserialize(ida_typeinf.get_idati(), typ, fields):
         tif = None
     return tif
コード例 #20
0
ファイル: ida_plugin.py プロジェクト: doronz88/fa
    def export(self):
        """
        Show an export dialog to export symbols and header file for given
        IDB.
        :return: None
        """
        class ExportForm(Form):
            def __init__(self):
                description = '''
                <h2>Export</h2>

                Select a directory to export IDB data into.
                '''

                Form.__init__(self,
                              r"""BUTTON YES* Save
                              Export
                              {StringLabel}
                              <#Symbols#Symbols filename:{iSymbolsFilename}>
                              <#C Header#C Header filename:{iHeaderFilename}>
                              <#ifdef_macro#ifdef'ed:{iIfdef}>
                              <#Select dir#Browse for dir:{iDir}>
                              """, {
                                  'iDir': Form.DirInput(),
                                  'StringLabel':
                                      Form.StringLabel(description,
                                                       tp=Form.FT_HTML_LABEL),
                                  'iSymbolsFilename': Form.StringInput(
                                      value='symbols.txt'),
                                  'iHeaderFilename': Form.StringInput(
                                      value='fa_structs.h'),
                                  'iIfdef': Form.StringInput(
                                      value='FA_STRUCTS_H'),
                              })
                self.__n = 0

            def OnFormChange(self, fid):
                return 1

        form = ExportForm()
        form, args = form.Compile()
        ok = form.Execute()
        if ok == 1:
            # save symbols
            symbols_filename = os.path.join(form.iDir.value,
                                            form.iSymbolsFilename.value)
            with open(symbols_filename, 'w') as f:
                results = IdaLoader.extract_all_user_names(None)
                for k, v in sorted(results.items()):
                    f.write('{} = 0x{:08x};\n'.format(k, v))

            # save c header
            idati = ida_typeinf.get_idati()
            c_header_filename = os.path.join(form.iDir.value,
                                             form.iHeaderFilename.value)

            consts_ordinal = None
            ordinals = []
            for ordinal in range(1, ida_typeinf.get_ordinal_qty(idati) + 1):
                ti = ida_typeinf.tinfo_t()
                if ti.get_numbered_type(idati, ordinal):
                    if ti.get_type_name() == 'FA_CONSTS':
                        # convert into macro definitions
                        consts_ordinal = ordinal
                    elif ti.get_type_name() in ('__va_list_tag',
                                                'va_list'):
                        continue
                    elif '$' in ti.get_type_name():
                        # skip deleted types
                        continue
                    else:
                        ordinals.append(str(ordinal))

            with open(c_header_filename, 'w') as f:
                ifdef_name = form.iIfdef.value.strip()

                if len(ifdef_name) > 0:
                    f.write('#ifndef {ifdef_name}\n'
                            '#define {ifdef_name}\n\n'
                            .format(ifdef_name=ifdef_name))

                if consts_ordinal is not None:
                    consts = re.findall('\s*(.+?) = (.+?),',
                                        idc.print_decls(
                                            str(consts_ordinal), 0))
                    for k, v in consts:
                        f.write('#define {} ({})\n'.format(k, v))

                    # ida exports using this type
                    f.write('#define _BYTE char\n')
                    f.write('\n')

                structs_buf = idc.print_decls(','.join(ordinals),
                                              idc.PDF_DEF_BASE)

                for struct_type, struct_name in re.findall(
                        r'(struct|enum) .*?([a-zA-Z0-9_\-]+?)\s+\{',
                        structs_buf):
                    f.write(
                        'typedef {struct_type} {struct_name} {struct_name};\n'
                        .format(struct_type=struct_type,
                                struct_name=struct_name))

                structs_buf = structs_buf.replace('__fastcall', '')
                f.write('\n')
                f.write(structs_buf)
                f.write('\n')

                if len(ifdef_name) > 0:
                    f.write('#endif // {ifdef_name}\n'
                            .format(ifdef_name=ifdef_name))

        form.Free()
コード例 #21
0
ファイル: core.py プロジェクト: dmxcsnsbh/IDArling
 def update_local_types_map(self):
     for i in range(1,
                    ida_typeinf.get_ordinal_qty(ida_typeinf.get_idati())):
         t = ImportLocalType(i)
         self.local_type_map[i] = t