鼠标过滤器驱动程序在启动后获得IRP_MJ_CLOSE

yzxexxkh  于 2023-10-16  发布在  其他
关注(0)|答案(1)|浏览(98)

我有以下自定义鼠标驱动程序的Windows,我不能正确加载在Windows内核

#include <ntddk.h>
#include <ntstrsafe.h>

#pragma warning(disable : 4201)

typedef struct
{
    PDEVICE_OBJECT LowerKbdDevice;
} DEVICE_EXTENSION, * PDEVICE_EXTENSION;

PDEVICE_OBJECT myKbdDevice = NULL;
ULONG pendingkey = 0;
int first_time = TRUE;

typedef struct _MOUSE_INPUT_DATA {
    USHORT UnitId;
    USHORT Flags;
    union {
        ULONG Buttons;
        struct {
            USHORT ButtonFlags;
            USHORT ButtonData;
        };
    };
    ULONG  RawButtons;
    LONG   LastX;
    LONG   LastY;
    ULONG  ExtraInformation;
} MOUSE_INPUT_DATA, * PMOUSE_INPUT_DATA;

VOID DriverUnload(PDRIVER_OBJECT DriverObject)
{

    LARGE_INTEGER interval = { 0 };
    interval.QuadPart = -10 * 1000 * 1000; // 1 second

    PDEVICE_OBJECT DeviceObject = DriverObject->DeviceObject;
    IoDetachDevice(((PDEVICE_EXTENSION)DeviceObject->DeviceExtension)->LowerKbdDevice);

    while (pendingkey)
    {
        KeDelayExecutionThread(KernelMode, FALSE, &interval);
    }

    IoDeleteDevice(myKbdDevice);

    DbgPrintEx(0, 0, "Mouse filter unloaded\n");
}

NTSTATUS DispatchPass(PDEVICE_OBJECT DeviceObject, PIRP Irp)
{

    PIO_STACK_LOCATION sl = IoGetCurrentIrpStackLocation(Irp);
    DbgPrintEx(0, 0, "DispatchPass: %d\n", sl->MajorFunction);
    UNREFERENCED_PARAMETER(DeviceObject);

    IoCopyCurrentIrpStackLocationToNext(Irp);

    NTSTATUS status = IoCallDriver(((PDEVICE_EXTENSION)DeviceObject->DeviceExtension)->LowerKbdDevice, Irp);

    return status;
}


NTSTATUS ReadComplete(PDEVICE_OBJECT DeviceObject, PIRP Irp, PVOID Context)
{
    UNREFERENCED_PARAMETER(DeviceObject);
    UNREFERENCED_PARAMETER(Context);

    PMOUSE_INPUT_DATA Keys = (PMOUSE_INPUT_DATA)Irp->AssociatedIrp.SystemBuffer;
    int structnum = (ULONG)Irp->IoStatus.Information / sizeof(PMOUSE_INPUT_DATA);

    if (structnum == 0) {
        Irp->IoStatus.Status = STATUS_BUFFER_TOO_SMALL;
        Irp->IoStatus.Information = 0;
        IoCompleteRequest(Irp, IO_NO_INCREMENT);
        return STATUS_SUCCESS;
    }

    if (Irp->IoStatus.Status == STATUS_SUCCESS) {
        for (int i = 0; i < structnum; i++)
        {

            DbgPrintEx(0, 0, "The button state is %x\n", Keys->ButtonFlags);
        }
    }
    else {
        DbgPrintEx(0, 0, "Complete status not success: %d\n", Irp->IoStatus.Status);
    }

    if (Irp->PendingReturned) {
        IoMarkIrpPending(Irp);
    }

    pendingkey--;
    return STATUS_CONTINUE_COMPLETION;
}

NTSTATUS DispatchRead(PDEVICE_OBJECT DeviceObject, PIRP Irp)
{
    UNREFERENCED_PARAMETER(DeviceObject);

    IoCopyCurrentIrpStackLocationToNext(Irp);

    pendingkey++;

    IoSetCompletionRoutineEx(DeviceObject, Irp, ReadComplete, NULL, TRUE, TRUE, TRUE);
    NTSTATUS status = IoCallDriver(((PDEVICE_EXTENSION)DeviceObject->DeviceExtension)->LowerKbdDevice, Irp);
    DbgPrintEx(0, 0, "DispatchRead: IoCallDriver status is %d\n", status);

    return status;
}

NTSTATUS MyAttachDevice(PDRIVER_OBJECT DriverObject)
{
    UNICODE_STRING TargetDevice = RTL_CONSTANT_STRING(L"\\Device\\PointerClass0");

    PAGED_CODE();

    NTSTATUS status = IoCreateDevice(DriverObject, sizeof(DEVICE_EXTENSION), NULL, FILE_DEVICE_MOUSE, 0, FALSE, &myKbdDevice);
    if (!NT_SUCCESS(status)) {
        DbgPrintEx(0, 0, "IoCreateDevice failed\n");
        return status;
    }

    RtlZeroMemory(myKbdDevice->DeviceExtension, sizeof(DEVICE_EXTENSION));

    myKbdDevice->Flags |= DO_BUFFERED_IO;
    myKbdDevice->Flags &= ~DO_DEVICE_INITIALIZING;

    status = IoAttachDevice(myKbdDevice,&TargetDevice,&((PDEVICE_EXTENSION)myKbdDevice->DeviceExtension)->LowerKbdDevice);
    if (!NT_SUCCESS(status)) {
        DbgPrintEx(0, 0, "IoAttachDevice failed with status %d\n", status);
        IoDeleteDevice(myKbdDevice);
        return status;
    }

    return STATUS_SUCCESS;
}

NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath)
{
    UNREFERENCED_PARAMETER(RegistryPath);

    DriverObject->DriverUnload = DriverUnload;

    for (int i = 0; i < IRP_MJ_MAXIMUM_FUNCTION; i++)
    {
        DriverObject->MajorFunction[i] = DispatchPass;
    }

    DriverObject->MajorFunction[IRP_MJ_READ] = DispatchRead;
    NTSTATUS status = MyAttachDevice(DriverObject);
    if (!NT_SUCCESS(status)) {
        DbgPrintEx(0, 0, "MyAttachDevice failed\n");
        return status;
    }

    return STATUS_SUCCESS;
}

通过OSR加载器启动驱动程序后,我立即得到IRP_MJ_CLOSE IRP,不明白为什么。我用的是内置触摸板的笔记本电脑。据我所知,在这种情况下,PointerClass0设备应该代表笔记本电脑的触摸板(鼠标)。也许我需要使用其他类而不是PointerClass0?我也有PointerClass1和PointerClass2,但对于这些类,IoAttachDevice总是失败。有谁知道吗?

j2cgzkjk

j2cgzkjk1#

解决了。我改变了MyAttachDevice函数如下:

NTSTATUS MyAttachDevice(PDRIVER_OBJECT DriverObject)
{
    UNICODE_STRING MCName = RTL_CONSTANT_STRING(L"\\Driver\\Mouclass");
    PDRIVER_OBJECT TargetDriverObject;
    PDEVICE_OBJECT CurrentDeviceObject;
    PDEVICE_OBJECT myDeviceObject = NULL;

    DbgPrintEx(0, 0, "Before ObReferenceObjectByName\n");
    NTSTATUS status = ObReferenceObjectByName(&MCName, OBJ_CASE_INSENSITIVE, NULL, 0, *IoDriverObjectType, KernelMode, NULL, (PVOID*)&TargetDriverObject);
    if (!NT_SUCCESS(status)) {
        DbgPrintEx(0, 0, "ObReferenceObjectByName failed\n");
        return status;
    }

    CurrentDeviceObject = TargetDriverObject->DeviceObject;
    ObDereferenceObject(TargetDriverObject);

    while (CurrentDeviceObject)
    {
        status = IoCreateDevice(DriverObject, sizeof(DEVICE_EXTENSION), NULL, FILE_DEVICE_MOUSE, 0, FALSE, &myDeviceObject);
        if (!NT_SUCCESS(status)) {
            DbgPrintEx(0, 0, "IoCreateDevice failed\n");
            return status;
        }

        RtlZeroMemory(myDeviceObject->DeviceExtension, sizeof(DEVICE_EXTENSION));
        DbgPrintEx(0, 0, "Before IoAttachDeviceToDeviceStackSafe\n");
        status = IoAttachDeviceToDeviceStackSafe(myDeviceObject, CurrentDeviceObject, &((PDEVICE_EXTENSION)myDeviceObject->DeviceExtension)->LowerKbdDevice);

        if (!NT_SUCCESS(status)) {
            IoDeleteDevice(myDeviceObject);
            DbgPrintEx(0, 0, "IoAttachDeviceToDeviceStackSafe failed\n");
            return status;
        }

        myDeviceObject->Flags |= DO_BUFFERED_IO;
        myDeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;

        CurrentDeviceObject = CurrentDeviceObject->NextDevice;
    }

    return STATUS_SUCCESS;
}

简而言之:我们需要将设备连接到“\Driver\Mouclass”而不是“\Device\PointerClass0”中的设备
卸载函数应该是这样的:

VOID DriverUnload(PDRIVER_OBJECT DriverObject)
{

    LARGE_INTEGER interval = { 0 };
    PDEVICE_OBJECT DeviceObject = DriverObject->DeviceObject;
    interval.QuadPart = -10 * 1000 * 1000; // 1 second
    
    while (DeviceObject)
    {
        IoDetachDevice(((PDEVICE_EXTENSION)DeviceObject->DeviceExtension)->LowerKbdDevice);
        DeviceObject = DeviceObject->NextDevice;
    }

    while (pendingkey)
    {
        KeDelayExecutionThread(KernelMode, FALSE, &interval);
    }

    DeviceObject = DriverObject->DeviceObject;

    while (DeviceObject)
    {
        IoDeleteDevice(DeviceObject);
        DeviceObject = DeviceObject->NextDevice;
    }

    DbgPrintEx(0, 0, "Mouse filter unloaded\n");
}

此外,我们应该为未文档化的函数ObReferenceObjectByName添加原型

// undocumented function
NTSYSAPI NTSTATUS NTAPI ObReferenceObjectByName(
    PUNICODE_STRING ObjectName,
    ULONG Attributes,
    PACCESS_STATE AccessState,
    ACCESS_MASK DesiredAccess,
    POBJECT_TYPE ObjectType,
    KPROCESSOR_MODE AccessMode,
    PVOID ParseContext OPTIONAL,
    PVOID* Object
);

相关问题