⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 kbfiltr.c

📁 Advance(LOVEHINA-AVC) 的kbFiltr WDM驱动源码
💻 C
📖 第 1 页 / 共 2 页
字号:
/*--

模块名称:

    kbfilter.c

代码模版:

		Windows XP DDK 2600 - KbFilter

作者:

		Advance(LOVEHINA-AVC)

环境:

    仅运行于内核模式

--*/

#include "kbfiltr.h"

//显式声明代码段所位于的页

NTSTATUS DriverEntry (PDRIVER_OBJECT, PUNICODE_STRING);

#pragma alloc_text (INIT, DriverEntry)
#pragma alloc_text (PAGE, KbFilter_CreateClose)
#pragma alloc_text (PAGE, KbFilter_IoCtl)
#pragma alloc_text (PAGE, KbFilter_Read)
#pragma alloc_text (PAGE, KbFilter_Unload)
#pragma alloc_text (PAGE, KbFilter_PnP)
#pragma alloc_text (PAGE, KbFilter_HookDevice)
#pragma alloc_text (PAGE, KbFilter_DispatchPassThrough)

NTSTATUS
DriverEntry (
    IN  PDRIVER_OBJECT  DriverObject,
    IN  PUNICODE_STRING RegistryPath
    )
/*++

例程描述:

    初始化各个例程入口

--*/
{
    PDEVICE_OBJECT  kbmDevice,kbdcDevice;
    PFILE_OBJECT    fileObject;
    UNICODE_STRING  deviceName,linkName;
    NTSTATUS        status;
    PKBMHOOK_DEVICE_EXTENSION  kbmDevExt;

    // 
    // 流经这个过滤驱动的IRP分发例程
    //
    DriverObject->MajorFunction [IRP_MJ_CREATE] =
    DriverObject->MajorFunction [IRP_MJ_CLOSE] =         KbFilter_CreateClose;
    DriverObject->MajorFunction [IRP_MJ_READ] =          KbFilter_Read;
    //
    // 微软注明若需要使用以下例程,则必须自行创建一个新的设备(避免与下层驱动协议冲突)。
    // 因此我们需要在DriverEntry中创建一个UNKNOWN设备,并调用IoCreateSymbolicLink暴露接口给Win32应用程序。
    //
    // *可通过调用IoBuildDeviceIoControlRequest来构造我们的内部控制请求,但我更倾向于直接修改设备扩展内容的通信方式。
    // 
    // DriverObject->MajorFunction [IRP_MJ_DEVICE_CONTROL] = KbFilter_IoCtl;
    //

    DriverObject->MajorFunction [IRP_MJ_DEVICE_CONTROL] = KbFilter_IoCtl;
    DriverObject->MajorFunction [IRP_MJ_PNP] =            KbFilter_PnP;
    DriverObject->DriverUnload =                          KbFilter_Unload;

    //
    // 创建我们的Keyboard Mapper Advance应用程序接口设备
    //
		RtlInitUnicodeString(&deviceName, L"\\Device\\kbmhook0");
		RtlInitUnicodeString(&linkName, L"\\DosDevices\\devKbmhook");

    status = IoCreateDevice(DriverObject,                   
                            sizeof(KBMHOOK_DEVICE_EXTENSION), 
                            &deviceName,                    
                            FILE_DEVICE_UNKNOWN,  
                            0,                     
                            TRUE,      // 在同一时刻仅允许单个线程访问
                            &kbmDevice              
                            );

    if (!NT_SUCCESS(status)) {
        return (status);
    }

    //
    // 创建符号连接,使Win32程序可以通过CreateFile来访问驱动。
    //
    status = IoCreateSymbolicLink(&linkName, &deviceName);

    if (!NT_SUCCESS(status)) {
        IoDeleteDevice(kbmDevice);
        return (status);
    }

    RtlZeroMemory(kbmDevice->DeviceExtension, sizeof(KBMHOOK_DEVICE_EXTENSION));

    kbmDevExt = (PKBMHOOK_DEVICE_EXTENSION)kbmDevice->DeviceExtension;

    //
    // 获得键盘类驱动KbdClass的首个实例设备对象指针
    //
    RtlInitUnicodeString(&deviceName, L"\\Device\\KeyboardClass0");

    status = IoGetDeviceObjectPointer(&deviceName,
                                      FILE_ALL_ACCESS,
                                      &fileObject,
                                      &kbdcDevice
                                      );

    if (!NT_SUCCESS(status)) {
        IoDeleteDevice(kbmDevice);
        IoDeleteSymbolicLink(&linkName);
        return (status);
    }

    ObDereferenceObject(fileObject);

    //
    // 将KbdClass的驱动对象存进设备扩展里,待会我们才要用到它。
    //
    kbmDevExt->IsFilterDevice =     FALSE;
    kbmDevExt->KbdClassDriver =     kbdcDevice->DriverObject;

    kbmDevice->Flags |= (DO_BUFFERED_IO | DO_POWER_PAGABLE);

    return STATUS_SUCCESS;
}

NTSTATUS
KbFilter_Complete (
    IN PDEVICE_OBJECT   DeviceObject,
    IN PIRP             Irp,
    IN PVOID            Context
    )
/*++

例程描述:

    我们通过这个完成例程来过滤Kbdclass对Win32k的键盘数据提交,
    当Kbdclass完成了读操作IRP时,这个例程即被IO管理器调用,使我们有机会修改提交的数据。
    
--*/
{
    ULONG                      i;
    PUCHAR                     dataPointer;
    PFILTER_DEVICE_EXTENSION   fltDevExt;
    PKBMHOOK_DEVICE_EXTENSION  kbmDevExt;
    USHORT                     makecode,keycode,flags;
    UCHAR                      kdflags,index,location;

    //
    // 必须的东西,在每个完成例程中设定正确的IRP返回状态。
    //
    if (Irp->PendingReturned)
    {
        IoMarkIrpPending(Irp);
    }

    //
    // AssociatedIrp.SystemBuffer里面存放的就是KEYDATA,IoStatus.Information域指出了这个数据块的实际大小。
    //
    fltDevExt =   (PFILTER_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
    kbmDevExt =   (PKBMHOOK_DEVICE_EXTENSION)fltDevExt->KbmDevExtPointer;
    dataPointer = (PUCHAR)Irp->AssociatedIrp.SystemBuffer;

    //
    // 如果开启了HOOK我们就尝试置换键位,否则将当前击键状态转存到设备扩展中供应用程序接收。
    //    
    if (kbmDevExt->HookSwitch == TRUE)
    {
        for (i = 0 ; i < (Irp->IoStatus.Information / sizeof(KEYBOARD_INPUT_DATA)) ; i++)
        {
            makecode = ((PKEYBOARD_INPUT_DATA)dataPointer)->MakeCode;
            flags =    ((PKEYBOARD_INPUT_DATA)dataPointer)->Flags;

            index = 0;
            if (flags & KEY_E0)
            {
                index = 1;
            } else if (flags & KEY_E1)
            {
                index = 2;
            }

            if (fltDevExt->KeyStore[index][makecode] != 0)
            {
                keycode = fltDevExt->KeyStore[index][makecode];

                ((PKEYBOARD_INPUT_DATA)dataPointer)->MakeCode = keycode;

                flags &= ~KEY_E0;
                flags &= ~KEY_E1;

                location = fltDevExt->KeyIndex[index][makecode];

                if (location == 1)
                {
                    flags |= KEY_E0;
                } else if (location == 2)
                {
                    flags |= KEY_E1;
                }

                ((PKEYBOARD_INPUT_DATA)dataPointer)->Flags = flags;

            } else if (kbmDevExt->KeyStore[index][makecode] != 0)
            {
                ((PKEYBOARD_INPUT_DATA)dataPointer)->MakeCode = 0;
            }
        
            dataPointer += sizeof(KEYBOARD_INPUT_DATA);
        }
    } else {
        makecode = ((PKEYBOARD_INPUT_DATA)dataPointer)->MakeCode;
        flags =    ((PKEYBOARD_INPUT_DATA)dataPointer)->Flags;
        kdflags =  0;

        if (flags & KEY_E0)
        {
            kdflags |= KEY_E0;
        } else if (flags & KEY_E1)
        {
            kdflags |= KEY_E1;
        }

        for (i = 0 ; i < 16 ; i++)
        {
            if (fltDevExt == kbmDevExt->FltDevExtPointer[i])
            {
                index = (UCHAR)i;
                break;
            }
        }

        if ((kbmDevExt->KeyDown.DeviceID == fltDevExt->DeviceID) && (kbmDevExt->KeyDown.DeviceIndex == index))
        {
            if ((kbmDevExt->KeyDown.KeyPressed == (UCHAR)makecode) && (kbmDevExt->KeyDown.Flags == kdflags))
            {
                if (flags & KEY_BREAK)
                    kbmDevExt->KeyDown.KeyPressed = 0;
            } else {
                if (!(flags & KEY_BREAK))
                {
                    kbmDevExt->KeyDown.KeyPressed = (UCHAR)makecode;
                    kbmDevExt->KeyDown.Flags =      kdflags;
                }
            }
        } else {
            kbmDevExt->KeyDown.DeviceIndex = index;
            kbmDevExt->KeyDown.DeviceID =    fltDevExt->DeviceID;
            kbmDevExt->KeyDown.KeyPressed =  (UCHAR)makecode;
            kbmDevExt->KeyDown.Flags =       kdflags;
        }
    }

    return STATUS_SUCCESS;
}

NTSTATUS
KbFilter_CreateClose (
    IN  PDEVICE_OBJECT  DeviceObject,
    IN  PIRP            Irp
    )
/*++
例程描述:

    暂时没有XD
    
--*/
{
    PKBMHOOK_DEVICE_EXTENSION  kbmDevExt;
    PIO_STACK_LOCATION         irpStack;
    NTSTATUS                   status = STATUS_SUCCESS;

    kbmDevExt = (PKBMHOOK_DEVICE_EXTENSION)DeviceObject->DeviceExtension;

    //
    // 无关的IRP就随它去吧
    //
    if (kbmDevExt->IsFilterDevice == TRUE)
        return KbFilter_DispatchPassThrough(DeviceObject, Irp);

    irpStack = IoGetCurrentIrpStackLocation(Irp);

    switch (irpStack->MajorFunction)
    {
         case IRP_MJ_CREATE:

             //
             // 如果是打开请求,就开始枚举新设备。
             //
             if (KeGetCurrentIrql() != PASSIVE_LEVEL)
             {
                 status = STATUS_UNSUCCESSFUL;
                 break;
             }

             if (kbmDevExt->DeviceCounter < 16)
                 status = KbFilter_HookDevice(DeviceObject, kbmDevExt);

             break;

         case IRP_MJ_CLOSE:

             kbmDevExt->HookSwitch = FALSE;

             break;
    }

    Irp->IoStatus.Status =      status;
    Irp->IoStatus.Information = 0;
    IoCompleteRequest(Irp, IO_NO_INCREMENT);

    return (status);
}

NTSTATUS
KbFilter_DispatchPassThrough(
        IN PDEVICE_OBJECT DeviceObject,
        IN PIRP Irp
        )

{
		PIO_STACK_LOCATION    irpStack = IoGetCurrentIrpStackLocation(Irp);

    IoSkipCurrentIrpStackLocation(Irp);
        
    return IoCallDriver(((PFILTER_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->LowerDeviceObject, Irp);
}

NTSTATUS
KbFilter_IoCtl(
    IN PDEVICE_OBJECT DeviceObject,
    IN PIRP Irp
    )

{
    UCHAR                      i,j,keyCode,keyCodeIndex,keyMappingIndex,keyFlags,keyMapping;
    ULONG                      copysize;
    PKBMHOOK_DEVICE_EXTENSION  kbmDevExt;
    PFILTER_DEVICE_EXTENSION   fltDevExt;
    PIO_STACK_LOCATION         irpStack;
    PVOID                      bufferPointer;
    PUCHAR                     sizePointer,dataPointer;
    NTSTATUS                   status = STATUS_SUCCESS;

    kbmDevExt = (PKBMHOOK_DEVICE_EXTENSION)DeviceObject->DeviceExtension;

    if (kbmDevExt->IsFilterDevice == TRUE)
        return KbFilter_DispatchPassThrough(DeviceObject, Irp);

    //
    // 这里是我为KBMHOOK应用程序构造的通信部分,相关的控制代码包括查询驱动版本、查询设备数量、设定映射键位、设定映射开关等。
    //

    irpStack = IoGetCurrentIrpStackLocation(Irp);

    bufferPointer = Irp->AssociatedIrp.SystemBuffer;

    switch (irpStack->Parameters.DeviceIoControl.IoControlCode)
    {
        case IOCTL_KBMHOOK_QUERY_VERSION:

            if (irpStack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(VERSION_DATA))
            {
                status = STATUS_BUFFER_TOO_SMALL;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -