Example #1
0
def kernelcache_find_virtual_method_overrides(classname=None, method=None):
    import idc
    import idaapi
    import ida_kernelcache as kc

    # Define the form to ask for the arguments.
    class MyForm(idaapi.Form):
        def __init__(self):
            swidth = 40
            idaapi.Form.__init__(
                self, r"""STARTITEM 0
Find virtual method overrides

<#The class#Class :{classname}>
<#The virtual method#Method:{method}>""", {
                    'classname':
                    idaapi.Form.StringInput(tp=idaapi.Form.FT_IDENT,
                                            swidth=swidth),
                    'method':
                    idaapi.Form.StringInput(tp=idaapi.Form.FT_IDENT,
                                            swidth=swidth),
                })

        def OnFormChange(self, fid):
            return 1

    kc.collect_class_info()

    if any(arg is None for arg in (classname, method)):
        f = MyForm()
        f.Compile()
        f.classname.value = classname or ''
        f.method.value = method or ''
        ok = f.Execute()
        if ok != 1:
            print 'Cancelled'
            return False
        classname = f.classname.value
        method = f.method.value
        f.Free()

    if classname not in kc.class_info:
        print 'Not a valid class: {}'.format(classname)
        return False

    print 'Subclasses of {} that override {}:'.format(classname, method)
    baseinfo = kc.class_info[classname]
    found = False
    for classinfo in baseinfo.descendants():
        for _, override, _ in kc.vtable.class_vtable_overrides(
                classinfo, superinfo=baseinfo, methods=True):
            name = idc.NameEx(idc.BADADDR, override)
            demangled = idc.Demangle(name, idc.GetLongPrm(idc.INF_SHORT_DN))
            name = demangled if demangled else name
            if method in name:
                print '{:#x}  {}'.format(override, classinfo.classname)
                found = True
    if not found:
        print 'No subclass of {} overrides {}'.format(classname, method)
    return found
def kernelcache_find_virtual_method_overrides(classname=None, method=None):
    import idc
    import ida_kernelcache as kc

    kc.collect_class_info()

    if not classname:
        classname = idc.AskStr('IOUserClient', 'Enter class name')
    if classname not in kc.class_info:
        print 'Not a valid class: {}'.format(classname)
        return False

    if not method:
        method = idc.AskStr('externalMethod', 'Enter method name')

    print 'Subclasses of {} that override {}:'.format(classname, method)
    baseinfo = kc.class_info[classname]
    found = False
    for classinfo in baseinfo.descendants():
        for _, override, _ in kc.vtable.class_vtable_overrides(
                classinfo, superinfo=baseinfo, methods=True):
            name = idc.NameEx(idc.BADADDR, override)
            demangled = idc.Demangle(name, idc.GetLongPrm(idc.INF_SHORT_DN))
            name = demangled if demangled else name
            if method in name:
                print '{:#x}  {}'.format(override, classinfo.classname)
                found = True
    if not found:
        print 'No subclass of {} overrides {}'.format(classname, method)
    return found
def kernelcache_populate_struct(struct=None,
                                address=None,
                                register=None,
                                delta=None):
    import idc
    import idautils
    import idaapi
    import ida_kernelcache as kc
    import ida_kernelcache.ida_utilities as idau

    # Define the form to ask for the arguments.
    class MyForm(idaapi.Form):
        def __init__(self):
            swidth = 40
            idaapi.Form.__init__(
                self, r"""STARTITEM 0
Automatically populate struct fields

<#The name of the structure#Structure:{structure}>
<#The address of the instruction at which the register points to the structure#Address  :{address}>
<#The register containing the pointer to the structure#Register :{register}>
<#The offset of the pointer from the start of the structure#Delta    :{delta}>""",
                {
                    'structure':
                    idaapi.Form.StringInput(tp=idaapi.Form.FT_IDENT,
                                            swidth=swidth),
                    'address':
                    idaapi.Form.NumericInput(
                        tp=idaapi.Form.FT_ADDR, swidth=swidth, width=1000),
                    'register':
                    idaapi.Form.StringInput(tp=idaapi.Form.FT_IDENT,
                                            swidth=swidth),
                    'delta':
                    idaapi.Form.NumericInput(tp=idaapi.Form.FT_INT64,
                                             swidth=swidth),
                })

        def OnFormChange(self, fid):
            return 1

    # If any argument is unspecified, get it using the form.
    if any(arg is None for arg in (struct, address, register, delta)):
        f = MyForm()
        f.Compile()
        f.structure.value = struct or ''
        f.address.value = address or idc.get_screen_ea()
        f.register.value = register or 'X0'
        f.delta.value = delta or 0
        ok = f.Execute()
        if ok != 1:
            print 'Cancelled'
            return False
        struct = f.structure.value
        address = f.address.value
        register = f.register.value
        delta = f.delta.value
        f.Free()

    # Check whether this struct is a class.
    kc.collect_class_info()
    is_class = struct in kc.class_info

    # Open the structure.
    sid = idau.struct_open(struct, create=True)
    if sid is None:
        print 'Could not open struct {}'.format(struct)
        return False

    # Check that the address is in a function.
    if not idaapi.get_func(address):
        print 'Address {:#x} is not a function'.format(address)
        return False

    # Get the register id.
    register_id = None
    if type(register) is str:
        register_id = idaapi.str2reg(register)
    elif type(register) is int:
        register_id = register
        register = idaapi.get_reg_name(register_id, 8)
    if register_id is None or register_id < 0:
        print 'Invalid register {}'.format(register)
        return False

    # Validate delta.
    if delta < 0 or delta > 0x1000000:
        print 'Invalid delta {}'.format(delta)
        return False
    elif is_class and delta != 0:
        print 'Nonzero delta not yet supported'
        return False

    type_name = 'class' if is_class else 'struct'
    print '{} = {}, address = {:#x}, register = {}, delta = {:#x}'.format(
        type_name, struct, address, register, delta)

    if is_class:
        # Run the analysis.
        kc.class_struct.process_functions([(address, struct, register_id)])
    else:
        # Run the data flow to collect the accesses and then add those fields to the struct.
        accesses = kc.data_flow.pointer_accesses(
            function=address, initialization={address: {
                register_id: delta
            }})
        kc.build_struct.create_struct_fields(sid, accesses=accesses)

        # Set the offsets to stroff.
        for addresses_and_deltas in accesses.values():
            for ea, delta in addresses_and_deltas:
                insn = idautils.DecodeInstruction(ea)
                if insn:
                    for op in insn.Operands:
                        if op.type == idaapi.o_displ:
                            idau.insn_op_stroff(insn, op.n, sid, delta)

    # All done! :)
    print 'Done'
    return True