键盘过滤驱动快捷实现

来源:互联网 发布:软件视频会议 编辑:程序博客网 时间:2024/06/09 20:57

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

        //获取键盘驱动对象

    status = ObReferenceObjectByName(&uniNtNameString,
           OBJ_CASE_INSENSITIVE,
           NULL,
           0,
           IoDriverObjectType,
           KernelMode,
           NULL,
           (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对话框尝试过,竟然能捕获键盘输入的数据。那天要是能安装在网吧的机器上,岂不是可以盗取网管的密码!!!(现实并非这么简单)