关于键盘过滤驱动卸载后敲击键盘蓝屏的解决方案

最近在学习驱动开发时,看到了一个键盘过滤驱动的文章((4条消息) Windows驱动学习(五)-- 键盘过滤_G4rb3n的博客-CSDN博客),于是尝试跑了下代码,发现代码在跑起来时没有问题,但卸载后任意敲击一个按键都会导致蓝屏,因此尝试寻找解决方法。

首先要搞清楚蓝屏的原因,这一点在(4条消息) 键盘过滤驱动学习_说白了不够黑的博客-CSDN博客_generaldispatch函数这篇文章里已经解释过了,简单来说就是无论何时总有一个IRP_MJ_READ保存在栈底,卸载驱动后敲击键盘时,这个IRP_MJ_READ会按照驱动存在时的思路寻找完成例程然后再返回数据,但由于驱动已经卸载因此会导向一个不存在的例程地址导致电脑蓝屏。因此我们要想办法解决这个IRP_MJ_READ或者干脆不让IRP_MJ_READ调用完成例程,大佬也提出两种解决方法:构造自己的IRP代替原来的IRP_MJ_READ完成工作或使用计数器。

关于构造IRP,由于我个人能力有限,没有尝试出相应的解决方法,如果有此类解决方法希望有大佬指出;关于计数器,上文中的代码应该是按照此思路修改的,但我没有看到最关键的unload部分代码,因此这里给出另一篇文章[原创]windows内核编程之[键盘信息过滤]-编程技术-看雪论坛-安全社区|安全招聘|bbs.pediy.com (kanxue.com),这里有计数器相关思路的代码,可以参照进行更改,本人测试有效,大体思路就是read派遣函数计数++,完成例程计数--,驱动卸载时会保持线程等待直到计数器归零再继续卸载驱动。这种方法的效果是,在一般情况下加载驱动并且使用过键盘后,卸载驱动时计数会为1,因此卸载驱动的函数中会保持当前线程(也就是驱动卸载程序)等待,直到计数器归零,也就是再次敲击键盘后才会继续卸载驱动,卸载之后敲击键盘一切正常;而此次敲击键盘的IRP依旧会按照我们之前设置的完成例程进行处理。

在完成上述修改后,我在思考既然这里线程挂起后还需要手动敲击键盘才可以继续卸载,那为什么我不直接在卸载的函数里模拟键盘敲击来完成IRP_MJ_READ然后再卸载驱动呢,这样和让线程等待直到敲击键盘效果是一样的,都是解决了留存在栈底的IRP_MJ_READ。因此,只需要在驱动卸载部分添加一行键盘敲击模拟代码就可以:

NTSTATUS DriverUnload(PDRIVER_OBJECT pDriver, PUNICODE_STRING RegPath)
{
	PDEVICE_OBJECT pDevice;
	PDEV_EXTENSION devExt;
	UNREFERENCED_PARAMETER(pDriver);
	DbgPrint("DriverEntry Unloading...\n");

	pDevice = pDriver->DeviceObject;
	while (pDevice)
	{
		DeAttach(pDevice);
		pDevice = pDevice->NextDevice;
	}
	//用于防止卸载驱动后蓝屏
	PressKeyByScanCode(0x1f);

	pDriver->DeviceObject = NULL;

	return STATUS_SUCCESS;
}

键盘敲击模拟的代码我是参考了这篇文章(4条消息) 驱动中实现模拟键盘按键_iiprogram的博客-CSDN博客_通过网卡驱动模拟键盘按键的第一种方案

#define defI8042_DATA_PORT ((PUCHAR)0x60)
#define defI8042_CTRL_PORT ((PUCHAR)0x64)
#define defOBUFFER_FULL 0x01

BOOLEAN
WaitForKeyboardWrite(VOID)
{
	INT i;
	UCHAR c;

	for (i = 0; i < 1000; ++i)
	{
		KeStallExecutionProcessor(50);
		c = READ_PORT_UCHAR(defI8042_CTRL_PORT);
		if ((c & defOBUFFER_FULL) == defOBUFFER_FULL)
			break;
	}

	return i ? TRUE : FALSE;
}

VOID PressKeyByScanCode(
	IN CONST BYTE ScanCode
)
{
	WRITE_PORT_UCHAR(defI8042_CTRL_PORT, 0xd2);

	WaitForKeyboardWrite();

	WRITE_PORT_UCHAR(defI8042_DATA_PORT, ScanCode);
}

这样在卸载时驱动会再次模拟敲击一次键盘,卸载后系统以就可以正常运行,使用键盘不受影响。在此感谢以上4位大佬的文章的帮助,没有他们的指点我这个入门者不知道要自己探索多久……

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值