Exemplo n.º 1
0
    def extract_rtti_info_from_typeinfo(cls, typeinfo_ea):
        if typeinfo_ea in cls.found_classes:
            return None
        rtti_obj = cls.parse_typeinfo(typeinfo_ea)
        if rtti_obj is None:
            return None
        log.info("%s: Parsed typeinfo", rtti_obj.name)
        cls.found_classes.add(rtti_obj.typeinfo_ea)
        for parent_typeinfo_ea, _, offset in rtti_obj.raw_parents:
            parent_updated_name = None
            parent_rtti_obj = cls.extract_rtti_info_from_typeinfo(parent_typeinfo_ea)
            if parent_rtti_obj:
                parent_updated_name = parent_rtti_obj.name
            else:
                built_rtti_obj_name = ida_name.get_ea_name(parent_typeinfo_ea)
                if built_rtti_obj_name.endswith(cls.RTTI_OBJ_STRUC_NAME):
                    parent_updated_name = built_rtti_obj_name.rstrip("_" + cls.RTTI_OBJ_STRUC_NAME)
            if parent_updated_name is not None:
                rtti_obj.updated_parents.append((parent_updated_name, offset))

        log.debug("%s: Finish setup parents", rtti_obj.name)
        if not rtti_obj.create_structs():
            return None
        rtti_obj.make_rtti_obj_pretty()
        rtti_obj.find_vtables()
        return rtti_obj
Exemplo n.º 2
0
def get_ea_name(ea, fromaddr=idc.BADADDR, true=False, user=False):
    """Get the name of an address.

    This function returns the name associated with the byte at the specified address.

    Arguments:
        ea: The linear address whose name to find.

    Options:
        fromaddr: The referring address. Default is BADADDR. Some addresses have a
            location-specific name (for example, labels within a function). If fromaddr is not
            BADADDR, then this function will try to retrieve the name of ea from fromaddr's
            perspective. The global name will be returned if no location-specific name is found.
        true: Retrieve the true name rather than the display name. Default is False.
        user: Return "" if the name is not a user name.

    Returns:
        The name of the address or "".
    """
    if user and not idc.hasUserName(ida_bytes.get_full_flags(ea)):
        return ""
    if true:
        return ida_name.get_ea_name(fromaddr, ea)
    else:
        return idc.get_name(
            ea, ida_name.GN_VISIBLE | idc.calc_gtn_flags(fromaddr, ea))
Exemplo n.º 3
0
 def get_typeinfo_name(self, typeinfo_ea):
     name_ea = utils.get_ptr(typeinfo_ea + self.CLASS_TYPE_NAME_OFFSET)
     if name_ea is None or name_ea == BADADDR:
         mangled_class_name = ida_name.get_ea_name(typeinfo_ea)
     else:
         mangled_class_name = "_Z" + idc.get_strlit_contents(name_ea).decode()
     class_name = ida_name.demangle_name(mangled_class_name, idc.INF_LONG_DN)
     return GccRTTIParser.strip_class_name(class_name)
Exemplo n.º 4
0
def _variable_name(ea):
    """Return the name of a variable."""
    try:
        flags = ida_bytes.get_full_flags(ea)
        if ida_bytes.has_name(flags):
            return ida_name.get_ea_name(ea)
    except:
        pass
    return ""
Exemplo n.º 5
0
 def name(self):
     ea = self.address()
     try:
         flags = ida_bytes.get_full_flags(ea)
         if ida_bytes.has_name(flags):
             return ida_name.get_ea_name(ea)
     except:
         pass
     return ""
Exemplo n.º 6
0
 def visit_expr(self, e):
     if e.op == hr.cot_asg:
         # is x a var?
         if e.x.op == hr.cot_var:
             # handle "x = y" types of assignments
             if e.y.op == hr.cot_var:
                 # get variable indexes
                 x_idx = e.x.v.idx
                 y_idx = e.y.v.idx
                 # get lvar_t
                 var_x = self.lvars[x_idx]
                 var_y = self.lvars[y_idx]
                 """
                 debug("Found: %s (user: %s, nice: %s) = %s (user: %s, nice: %s)" % (
                     var_x.name,
                     var_x.has_user_name,
                     var_x.has_nice_name,
                     var_y.name,
                     var_y.has_user_name,
                     var_y.has_nice_name))
                 """
                 # if x has an autogenerated name and y has a custom name
                 if not var_x.has_user_name and var_y.has_user_name:
                     # rename x
                     set_var_unique_name(var_x, var_y, self.lvars)
                 else:
                     debug("Skipped: %s = %s " % (var_x.name, var_y.name))
             # handle "x = something.y" types of assignments
             elif e.y.op == hr.cot_memref:
                 pass
             # handle "x = something->y" types of assignments
             elif e.y.op == hr.cot_memptr:
                 #debug("Found: %s = [ %s (%s) and m = %d and ptrsize = %x ]" % (self.lvars[e.x.v.idx].name, get_expr_name_and_member(e.y), get_expr_struct_type(e.y, self.lvars), e.y.m, e.y.ptrsize))
                 # get var index and lvar_t
                 x_idx = e.x.v.idx
                 var_x = self.lvars[x_idx]
                 # rename x
                 set_struct_member_unique_name(var_x, e.y, self.lvars)
             # handle "x = y()" types of assignments
             elif e.y.op == hr.cot_call and e.y.x.op == hr.cot_obj:
                 # get name of called function
                 func_name = ida_name.get_ea_name(e.y.x.obj_ea)
                 # get var index and lvar_t
                 x_idx = e.x.v.idx
                 var_x = self.lvars[x_idx]
                 if not var_x.has_user_name:
                     # rename x
                     set_func_unique_name(var_x, func_name, self.lvars)
                 else:
                     debug("Skipped: %s = %s(...) " % (var_x.name, func_name))
     return 0
Exemplo n.º 7
0
 def visit_expr(self, e):
     if e.op == hr.cot_asg:
         # is x a var?
         if e.x.op == hr.cot_var:
             # handle "x = y" types of assignments
             if e.y.op == hr.cot_var:
                 # get variable indexes
                 x_idx = e.x.v.idx
                 y_idx = e.y.v.idx
                 # get lvar_t
                 var_x = self.lvars[x_idx]
                 var_y = self.lvars[y_idx]
                 """
                 debug_print("Found: %s (user: %s, nice: %s) = %s (user: %s, nice: %s)" % (
                     var_x.name,
                     var_x.has_user_name,
                     var_x.has_nice_name,
                     var_y.name,
                     var_y.has_user_name,
                     var_y.has_nice_name))
                 """
                 # if x has an autogenerated name and y has a custom name
                 if not var_x.has_user_name and var_y.has_user_name:
                     # rename x
                     set_var_unique_name(var_x, var_y, self.lvars)
                 else:
                     debug_print("Skipped: %s = %s " %
                                 (var_x.name, var_y.name))
             # handle "x = y()" types of assignments
             elif e.y.op in [hr.cot_call, hr.cot_cast]:
                 if e.y.op == hr.cot_call:
                     tmp_y = e.y
                 elif e.y.op == hr.cot_cast and e.y.x.op == hr.cot_call:
                     tmp_y = e.y.x
                 else:  # TBD
                     tmp_y = None
                 if tmp_y and tmp_y.x.op == hr.cot_obj:
                     # get name of called function
                     func_name = ida_name.get_ea_name(
                         tmp_y.x.obj_ea,
                         ida_name.GN_VISIBLE | ida_name.GN_LOCAL)
                     # get var index and lvar_t
                     x_idx = e.x.v.idx
                     var_x = self.lvars[x_idx]
                     if not var_x.has_user_name:
                         # rename x
                         set_func_unique_name(var_x, func_name, self.lvars)
                     else:
                         debug_print("Skipped: %s = %s(...) " %
                                     (var_x.name, func_name))
     return 0
Exemplo n.º 8
0
def _add_real_xref(ea, ref_ea, out_ref_eas):
    """Sometimes IDA will have a operand like `[foo+10]` and the xref collector
  will give us the address of `foo`, but not the address of `foo+10`, so we
  will try to find it here."""
    global _OPERANDS_NUMS, _REF_OPERAND_TYPES

    ref_name = ida_name.get_ea_name(ref_ea)
    for i in _OPERANDS_NUMS:

        try:
            op_type = idc.get_operand_type(ea, i)
        except:
            return

        if op_type not in _REF_OPERAND_TYPES:
            continue

        op_str = idc.print_operand(ea, i)
        if op_str is None:
            return

        if ref_name in op_str:
            op_val = idc.get_operand_value(ea, i)
            out_ref_eas.add(op_val)
Exemplo n.º 9
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()
Exemplo n.º 10
0
def update_func_name_with_class(func_ea, class_name):
    name = ida_name.get_ea_name(func_ea)
    if name.startswith("sub_"):
        new_name = class_name + VTABLE_DELIMITER + name
        return utils.set_func_name(func_ea, new_name), True
    return name, False
    def lvar_type_changed(self, vu, v, tif):
        if (vu.cfunc):
            func_tif = ida_typeinf.tinfo_t()
            vu.cfunc.get_func_type(func_tif)

            funcdata = idaapi.func_type_data_t()
            got_data = func_tif.get_func_details(funcdata)

            if (not got_data):
                # self._log("Didnt get the data")
                pass

            lvars = vu.cfunc.get_lvars()
            for j in range(len(vu.cfunc.argidx)):
                # for i in vu.cfunc.argidx:
                i = vu.cfunc.argidx[j]
                if (lvars[i].name == v.name):
                    #self._log("lvar_type_changed: function argument changed = %s, index = %s, atype = %s" % (lvars[i].name, i, funcdata[j].argloc.atype()))
                    if (funcdata[i].argloc.atype() == 3):
                        #    self._log("lvar_type_changed: reg is : %s" %(funcdata[i].argloc.reg1()))
                        pass

                    if (funcdata[i].argloc.atype() != 3
                            or funcdata[i].argloc.reg1() != RCX_REG):
                        break

                    #self._log("applyName = %s" % (applyName))

                    firstPtrRemove = ida_typeinf.remove_pointer(tif)
                    #self._log("type name = %s" % (firstPtrRemove._print()))
                    #self._log("remove_pointer.is_ptr = %s" % (firstPtrRemove.is_ptr()))
                    #self._log("remove_pointer.is_struct = %s" % (firstPtrRemove.is_struct()))
                    if (firstPtrRemove.is_struct()
                            and not firstPtrRemove.is_ptr()):
                        currentFuncName = ida_name.get_ea_name(
                            vu.cfunc.entry_ea)
                        # self._log("before demangle current func name = %s" % (currentFuncName))
                        demangled = idc.demangle_name(
                            currentFuncName,
                            idc.get_inf_attr(idc.INF_SHORT_DN))
                        if (demangled != None):
                            self._log("Overriding mangled name = %s" %
                                      (currentFuncName))
                            currentFuncName = demangled
                        # self._log("after demangle current func name = %s" % (currentFuncName))
                        tokens = currentFuncName.split("::")
                        if len(tokens) > 1:
                            currentFuncName = tokens[1]
                        currentFuncName = currentFuncName.split("(")[0]
                        # self._log("current func name = %s" % (currentFuncName))
                        idc.set_name(
                            vu.cfunc.entry_ea,
                            firstPtrRemove._print() + "::" + currentFuncName,
                            idc.SN_NOWARN)
                        idaapi.auto_wait()
                        # self._log("Decomp Res : %s" % idaapi.decompile(vu.cfunc.entry_ea))
                        idaapi.refresh_idaview_anyway()
                        vu.refresh_ctext()
                        idaapi.refresh_idaview_anyway()
                        vu.refresh_ctext()
                        vu.refresh_view(True)

                        current_widget = idaapi.get_current_widget()
                        vu1 = idaapi.get_widget_vdui(current_widget)
                        if vu1:
                            vu1.refresh_ctext()
                    break

        #self._log("lvar_type_changed: vu=%s, v=%s, tinfo=%s" % (vu, self._format_lvar(v), tif._print()))
        return 1