Ejemplo n.º 1
0
def find_WdfControlDeviceInitAllocate():
    function_offset = OFFSET_WdfControlDeviceInitAllocate
    call_pfn = None
    try:
        for xref in idautils.XrefsTo(g_vars["_WDFFUNCTIONS"] +
                                     function_offset):
            call_pfn = xref.frm
    except StopIteration:
        # this is case 2 or 3
        pass
    if call_pfn is None:
        call_pfn = find_wdf_callback_through_immediate("call", 0,
                                                       function_offset)
        if call_pfn:
            idc.OpStroffEx(call_pfn, 0, (idaapi.get_struc_id("_WDFFUNCTIONS")),
                           0)

    if call_pfn is None:
        call_pfn = find_wdf_callback_through_immediate("mov", 1,
                                                       function_offset)
        if call_pfn:
            idc.OpStroffEx(call_pfn, 1, (idaapi.get_struc_id("_WDFFUNCTIONS")),
                           0)

    lea_sddl = find_function_arg(call_pfn, "lea", "r8", 0)
    unicode_sddl = idc.get_operand_value(lea_sddl, 1)
    idc.set_name(unicode_sddl, 'control_device_sddl')
    assign_struct_to_address(unicode_sddl, "_UNICODE_STRING")
    print("Control Device SDDL at: ", hex(unicode_sddl))
Ejemplo n.º 2
0
def find_WdfDeviceCreateDeviceInterface():
    function_offset = OFFSET_WdfDeviceCreateDeviceInterface

    calls_to_pfn_list = []
    try:
        for xref in idautils.XrefsTo(g_vars["_WDFFUNCTIONS"]+function_offset):
            call_pfnWdfDeviceCreateDeviceInterface = xref.frm
            calls_to_pfn_list.append(call_pfnWdfDeviceCreateDeviceInterface)
    except StopIteration:
        # this is case 2 or 3
        pass
    if len(calls_to_pfn_list) == 0:
        call_pfnWdfDeviceCreateDeviceInterface = find_wdf_callback_through_immediate("call", 0, function_offset)
        if call_pfnWdfDeviceCreateDeviceInterface:
            calls_to_pfn_list.append(call_pfnWdfDeviceCreateDeviceInterface)
            idc.OpStroffEx(call_pfnWdfDeviceCreateDeviceInterface,0,(idaapi.get_struc_id("_WDFFUNCTIONS")),0)

    if len(calls_to_pfn_list) == 0:
        call_pfnWdfDeviceCreateDeviceInterface = find_wdf_callback_through_immediate("mov", 1,function_offset)
        if call_pfnWdfDeviceCreateDeviceInterface:
            calls_to_pfn_list.append(call_pfnWdfDeviceCreateDeviceInterface)
            idc.OpStroffEx(call_pfnWdfDeviceCreateDeviceInterface,1,(idaapi.get_struc_id("_WDFFUNCTIONS")),0)

    for k, pfn_call in enumerate(calls_to_pfn_list):
        lea_guid = find_function_arg(pfn_call, "lea", "r8", 0)
        interface_guid = idc.GetOperandValue(lea_guid, 1)
        idc.MakeName(interface_guid, '_InterfaceGUID' + str(k))
        assign_struct_to_address(interface_guid, "GUID")
        g_vars["_InterfaceGUID" + str(k)] = interface_guid
        print("_InterfaceGUID: ", hex(interface_guid))
        guid_bytes = idc.GetManyBytes(interface_guid, 0x10)
        print_guid(guid_bytes)
Ejemplo n.º 3
0
def find_WdfDriverCreate():
    function_offset = OFFSET_WdfDriverCreate

    # If the XREF to wdfFunctions + function_offset exists.. then we're in case 1!
    try:
        call_pfnWdfDriverCreate = idautils.XrefsTo(g_vars["_WDFFUNCTIONS"]+function_offset).next().frm
    except StopIteration:
        # this is case 2!
        call_pfnWdfDriverCreate = find_wdf_callback_through_immediate("mov", 1,function_offset)
        if call_pfnWdfDriverCreate != None:
            idc.OpStroffEx(call_pfnWdfDriverCreate,1,(idaapi.get_struc_id("_WDFFUNCTIONS")),0)
        else:
            call_pfnWdfDriverCreate = find_wdf_callback_through_immediate("call", 0, function_offset)
            idc.OpStroffEx(call_pfnWdfDriverCreate,0,(idaapi.get_struc_id("_WDFFUNCTIONS")),0)

    if call_pfnWdfDriverCreate != None:
        # First identify the RealDriverEntry :)
        current_func = idaapi.get_func(call_pfnWdfDriverCreate)
        idc.MakeName(current_func.startEA, "_DriverEntry_")

        argument_DriverConfig_addr = find_function_arg_with_operand_value(call_pfnWdfDriverCreate, "mov", "rsp", 0x20, 0)
        register_DriverConfig = idc.GetOpnd(argument_DriverConfig_addr, 1)
        lea_DriverConfig_addr = find_function_arg(argument_DriverConfig_addr, "lea", register_DriverConfig, 0)

        # Get stack and the stack operand offset
        current_func = idaapi.get_func(lea_DriverConfig_addr)
        stack_id = idc.GetFrame(current_func)
        opnd = idc.GetOpnd(lea_DriverConfig_addr, 1)
        if "rsp" in opnd:
            stack_member_offset = idc.GetOperandValue(lea_DriverConfig_addr, 1)
        elif "rbp" in opnd:
            var_x = opnd.split("+")[-1][:-1] # [rbp+57h+var_80] -> var_80
            members, _ = retrieve_stack_members(current_func)
            inverted_members = {v:k for k, v in members.items()}
            try:
                stack_member_offset = inverted_members[var_x]
            except KeyError as msg:
                print msg
                return

        else:
            print("+] WdfDriverCreate() Unidentified register stack layout")
            return

        #idc.SetMemberName(stack_id, stack_member_offset, "_DriverConfig")
        struct_id = idaapi.get_struc_id("_WDF_DRIVER_CONFIG")
        struct_size = idc.GetStrucSize(struct_id)

        # First check if we have already touch this function stack before
        #if function_stack_erased(current_func):
            # need to take care of the already defined structs
        #    pass
        #else:
        delete_all_function_stack_members(current_func, force=True)
        idc.AddStrucMember(stack_id, "driver_config",
                           stack_member_offset, idc.FF_BYTE|idc.FF_DATA,
                           -1, struct_size)
        idc.SetMemberType(stack_id, stack_member_offset, idc.FF_STRU|idc.FF_DATA, struct_id, 1)
Ejemplo n.º 4
0
def find_WdfIoQueueCreate():
    function_offset = OFFSET_WdfIoQueueCreate

    calls_to_pfn_list = []
    try:
        for xref in idautils.XrefsTo(g_vars["_WDFFUNCTIONS"] +
                                     function_offset):
            call_pfnWdfIoQueueCreate = xref.frm
            calls_to_pfn_list.append(call_pfnWdfIoQueueCreate)
    except StopIteration:
        # this is case 2 or 3
        pass
    if len(calls_to_pfn_list) == 0:
        call_pfnWdfIoQueueCreate = find_wdf_callback_through_immediate(
            "call", 0, function_offset)
        if call_pfnWdfIoQueueCreate:
            calls_to_pfn_list.append(call_pfnWdfIoQueueCreate)
            idc.OpStroffEx(call_pfnWdfIoQueueCreate, 0,
                           (idaapi.get_struc_id("_WDFFUNCTIONS")), 0)

    if len(calls_to_pfn_list) == 0:
        call_pfnWdfIoQueueCreate = find_wdf_callback_through_immediate(
            "mov", 1, function_offset)
        if call_pfnWdfIoQueueCreate:
            calls_to_pfn_list.append(call_pfnWdfIoQueueCreate)
            idc.OpStroffEx(call_pfnWdfIoQueueCreate, 1,
                           (idaapi.get_struc_id("_WDFFUNCTIONS")), 0)

    for pfn_call in calls_to_pfn_list:
        lea_argument_addr = find_function_arg(pfn_call, "lea", "r8", 0)

        # Get stack and the stack operand offset
        current_func = idaapi.get_func(lea_argument_addr)
        stack_id = idc.GetFrame(current_func)
        stack_member_offset = idc.get_operand_value(lea_argument_addr, 1)

        struct_id = idaapi.get_struc_id("_WDF_IO_QUEUE_CONFIG")
        struct_size = idc.GetStrucSize(struct_id)

        # First check if we have already touch this function stack before
        if function_stack_erased(current_func):
            # need to take care of the already defined structs
            # If the arguments collide then this will fail
            pass
        else:
            delete_all_function_stack_members(current_func)
            print("Erased the stack members")

        idc.AddStrucMember(stack_id, "queue_config", stack_member_offset,
                           idc.FF_BYTE | idc.FF_DATA, -1, struct_size)
        idc.SetMemberType(stack_id, stack_member_offset,
                          idc.FF_STRU | idc.FF_DATA, struct_id, 1)
        print("IOQueue Creation at: " + hex(pfn_call))
Ejemplo n.º 5
0
def _convert_operands_to_struct_offsets(access_addresses):
    """Convert the operands that generated struct accesses into struct offsets."""
    for classname, addresses_and_deltas in access_addresses.items():
        sid = idau.struct_open(classname)
        if sid is not None:
            for ea, delta in addresses_and_deltas:
                insn = idautils.DecodeInstruction(ea)
                if insn:
                    for op in insn.Operands:
                        if op.type == idaapi.o_displ:
                            if not idc.OpStroffEx(ea, op.n, sid, delta):
                                _log(1, 'Could not convert {:#x} to struct offset for class {} '
                                        'delta {}', ea, classname, delta)
Ejemplo n.º 6
0
def find_WdfDeviceInitSetIoInCallerContextCallback():
    function_offset = OFFSET_WdfDeviceInitSetIoIncallerContextCallback
    try:
        call_pfn = idautils.XrefsTo(g_vars["_WDFFUNCTIONS"]+function_offset).next().frm
    except StopIteration:
        # this is case 2!
        call_pfn = find_wdf_callback_through_immediate("mov", 1,function_offset)
        if call_pfn is None:
            call_pfn = find_wdf_callback_through_immediate("call", 0, function_offset)

    if call_pfn != None:
        idc.OpStroffEx(call_pfn,0,(idaapi.get_struc_id("_WDFFUNCTIONS")),0)
        lea_addr = find_function_arg(call_pfn, "lea", "r8", 0)
        EvtWdfIoInCallerContext = idc.GetOperandValue(lea_addr, 1)
        idc.MakeName(EvtWdfIoInCallerContext, 'EvtWdfIoInCallerContext')
Ejemplo n.º 7
0
    def yatest_apply_struct(self):
        addrs = []
        # -1: struct, n: union
        for k in range(-1, 4):
            # find an integer operand in any function
            addr = self.find_operand_addr()
            addrs.append(addr)

            # create struct
            sid = idc.AddStrucEx(-1, 'apply_struct_%x' % (k + 1), 0)
            self.assertNotEqual(sid, -1)
            ftype = idaapi.FF_BYTE | idaapi.FF_DATA

            # apply struct only
            if k == -1:
                # add struct fields
                for x in xrange(0, 0x60):
                    self.assertEqual(
                        idc.AddStrucMember(sid, 'field_%x' % x, -1, ftype, -1,
                                           1), 0)
                # apply struct
                self.assertNotEqual(idc.OpStroffEx(addr, 1, sid, 0),
                                    idaapi.BADADDR)
                continue

            # create union
            uid = idc.AddStrucEx(-1, 'apply_union_%x' % (k + 1), 1)
            self.assertNotEqual(uid, -1)
            for x in xrange(1, 0x10):
                self.assertEqual(
                    idc.AddStrucMember(uid, 'union_%x' % x, -1, ftype, -1, 1),
                    0)

            # add struct fields
            for x in xrange(0, 0x60):
                self.assertEqual(
                    idc.AddStrucMember(sid, 'field_%x' % x, -1,
                                       idaapi.struflag(), uid, 1), 0)

            # apply selected union field
            fid = idc.GetMemberId(uid, k)
            self.assertNotEqual(fid, -1)
            path = idaapi.tid_array(2)
            path[0] = sid
            path[1] = fid
            self.assertNotEqual(idaapi.op_stroff(addr, 1, path.cast(), 2, 0),
                                idaapi.BADADDR)
        yaunit.save('apply_struct', addrs)
Ejemplo n.º 8
0
def _insn_op_stroff_695(insn, n, sid, delta):
    """A wrapper of idc.OpStroffEx for IDA 6.95."""
    return idc.OpStroffEx(insn.ea, n, sid, delta)
Ejemplo n.º 9
0
def _insn_op_stroff_700(insn, n, sid, delta):
    """A wrapper of idc.OpStroffEx for IDA 7."""
    return idc.OpStroffEx(insn, n, sid, delta)
Ejemplo n.º 10
0
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.ScreenEA()
        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:
                            idc.OpStroffEx(ea, op.n, sid, delta)

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