天天看點

鍵盤過濾驅動快捷實作

     最近在網上無意中看到一段代碼,主要講述的是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對話框嘗試過,竟然能捕獲鍵盤輸入的資料。那天要是能安裝在網吧的機器上,豈不是可以盜取網管的密碼!!!(現實并非這麼簡單)

繼續閱讀