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