天天看点

键盘过滤驱动快捷实现

     最近在网上无意中看到一段代码,主要讲述的是Windows 下键盘过滤驱动的实现方式,这段代码很有意识,是一种比较好的一种方法,主要将获取的键盘驱动对象的所有分发函数替换,然后另行处理,具体的代码如下;

        //获取键盘驱动对象

    status = ObReferenceObjectByName(&uniNtNameString,

           OBJ_CASE_INSENSITIVE,

           NULL,

           0,

           IoDriverObjectType,

           KernelMode,

           (PVOID *)&KdbDriverObject);

        // 替换分发函数

    for (i=0;i<=IRP_MJ_MAXIMUM_FUNCTION;i++)

    {

          OldDispatchFunction[i] = KdbDriverObject->MajorFunction[i];

                  InterlockedExchangePointer(&KdbDriverObject->MajorFunction[i],

                 (PDRIVER_DISPATCH)c2pDispatchGeneral);

    }

      // 对IRP_MJ_READ分发例程单独处理

NTSTATUS   c2pDispatchGeneral(IN PDEVICE_OBJECT DeviceObject, IN PIRP irp)

{

    NTSTATUS status;

    PC2P_DEV_EXT devExt;

    PIO_STACK_LOCATION CurrentIrpStack; // 当前I/O堆栈

    KEVENT waitEvent;

    PIO_STACK_LOCATION iostack;

    iostack = IoGetCurrentIrpStackLocation(irp);

    KdPrint(("Other c2pDispatchGeneral/n/n/n"));

/*    IoSkipCurrentIrpStackLocation(irp);*/

    if (iostack->MajorFunction == IRP_MJ_READ)

        KeInitializeEvent(&waitEvent,NotificationEvent,FALSE);

        if (irp->CurrentLocation == 1)

        {

            ULONG ReturnedInformation = 0;

            KdPrint(("Dispatch encountered bogus current location/n"));

            status = STATUS_INVALID_DEVICE_REQUEST;

            irp->IoStatus.Status = status;

            irp->IoStatus.Information = ReturnedInformation;

            IoCompleteRequest(irp,IO_NO_INCREMENT);

            return status;

        }

        gC2pKeyCount ++;

        devExt = (PC2P_DEV_EXT)DeviceObject->DeviceExtension;

        CurrentIrpStack = IoGetCurrentIrpStackLocation(irp);

        IoCopyCurrentIrpStackLocationToNext(irp);

        KdPrint(("c2pDispatchRead->IoSetCompletionRoutine/n"));

       IoSetCompletionRoutine(irp,c2pReadComplete,DeviceObject,TRUE,TRUE,TRUE);

        return IoCallDriver(devExt->LowerDeviceObject,irp);

    // pLowerDeviceObject = IoAttachDeviceToDeviceStack(pFilterDeviceObject,pTargetDeviceObject);

    // 返回的低层驱动对象

    return IoCallDriver(((PC2P_DEV_EXT)DeviceObject->DeviceExtension)->LowerDeviceObject,irp);

}

     //完成例程函数处理

NTSTATUS c2pReadComplete(IN PDEVICE_OBJECT DeviceObject, IN PIRP irp, IN PVOID Context)

    PIO_STACK_LOCATION irpSp;

    PKEYBOARD_INPUT_DATA KeyData;

    int NumKeys;

    ULONG buf_len;

    size_t i;

    PUCHAR buf = NULL;

    buf_len = 0;

    irpSp = IoGetCurrentIrpStackLocation(irp);

    // 判断是否成功

    if (NT_SUCCESS(irp->IoStatus.Status))

       KeyData = (PKEYBOARD_INPUT_DATA)irp->AssociatedIrp.SystemBuffer;

        NumKeys =  irp->IoStatus.Information/sizeof(KEYBOARD_INPUT_DATA);

        KdPrint(("Nnmkeys : %d",NumKeys));

        KdPrint(("ScanCode : %x",KeyData->MakeCode));

        KdPrint(("%s/n",KeyData->Flags?"UP":"DOWN"));

        print_keystroke((UCHAR)KeyData->MakeCode);

        if (KeyData->MakeCode == CAPS_LOCK)

            KeyData->MakeCode = LCONTROL;

    gC2pKeyCount -- ;

    if (irp->PendingReturned)

        // 传递PENDING

        IoMarkIrpPending(irp);

    return irp->IoStatus.Status;

    简单吧,只需这几步就可以完成键盘过滤驱动,编写完之后,我利用PASSWORD对话框尝试过,竟然能捕获键盘输入的数据。那天要是能安装在网吧的机器上,岂不是可以盗取网管的密码!!!(现实并非这么简单)

继续阅读