windows键盘过滤

介绍

主要是用来过滤键盘按键,或者修改按键用的

原理

本质是通过创建过滤设备来绑定\Driver\Kbdclass中的所有设备来实现过滤

绑定

先通过ObReferenceObjectByName来获取目标设备的驱动对象

//获取驱动对象
status = ObReferenceObjectByName(
	&ObjName,
	OBJ_CASE_INSENSITIVE,
	NULL,
	0,
	*IoDriverObjectType,
	KernelMode,
	NULL,
	(PVOID*)&pKbdclassDriver);
if (status != STATUS_SUCCESS)
{
	KdPrint(("ObReferenceObjectByName failed: %x", status));
	return status;
}

//解引用
ObDereferenceObject(pKbdclassDriver);

然后再遍历该驱动对象下所有设备,全部进行绑定,再设置设备扩展

//遍历设备
pTargetDevObj = pKbdclassDriver->DeviceObject;
while (pTargetDevObj)
{
	//创建过滤设备
	status = IoCreateDevice(
		pDriver,
		sizeof(DEV_EXT),
		NULL,
		pTargetDevObj->DeviceType,
		pTargetDevObj->Characteristics,
		FALSE,
		&pFltDevObj
	);
	if (status != STATUS_SUCCESS)
	{
		KdPrint(("ObReferenceObjectByName failed"));
		return status;
	}

	//绑定设备
	status = IoAttachDeviceToDeviceStackSafe(pFltDevObj, pTargetDevObj, &pLowerDevObj);
	if (status != STATUS_SUCCESS)
	{
		KdPrint(("IoAttachDeviceToDeviceStackSafe failed"));
		IoDeleteDevice(pFltDevObj);
		return status;
	}

	//获取设备扩展
	pDevExt = (PDEV_EXT)(pFltDevObj->DeviceExtension);
	//初始化设备扩展
	InitDevExt(pDevExt, pFltDevObj, pTargetDevObj, pLowerDevObj);
	pFltDevObj->DeviceType = pLowerDevObj->DeviceType;
	pFltDevObj->Characteristics = pLowerDevObj->Characteristics;
	pFltDevObj->StackSize = pLowerDevObj->StackSize + 1;
	pFltDevObj->Flags |= pLowerDevObj->Flags & (DO_BUFFERED_IO | DO_DIRECT_IO | DO_POWER_PAGABLE);

	//继续下一个设备
	pTargetDevObj = pTargetDevObj->NextDevice;
}

分发

这之后你还需要写几个分发函数,大概是以下几种

常规分发

直接下发即可,不用管

//常规分发
NTSTATUS DispatchGeneral(PDEVICE_OBJECT pDevObj, PIRP pIrp)
{
	PDEV_EXT pDevExt = (PDEV_EXT)pDevObj->DeviceExtension;
	PDEVICE_OBJECT pLowerDevObj = pDevExt->pLowerDevObj;

	KdPrint(("DispatchGeneral"));

	IoSkipCurrentIrpStackLocation(pIrp);
	
	return IoCallDriver(pLowerDevObj, pIrp);
}

电源分发

单独处理就行,也是直接下发

NTSTATUS DispatchPower(PDEVICE_OBJECT pDevObj, PIRP pIrp)
{
	PDEV_EXT pDevExt = (PDEV_EXT)pDevObj->DeviceExtension;

	KdPrint(("DispatchPower"));

	PoStartNextPowerIrp(pIrp);
	IoSkipCurrentIrpStackLocation(pIrp);

	return PoCallDriver(pDevExt->pTargetDevObj, pIrp);
}

即插即用分发

这里主要是处理有设备移除的时候,解绑并且删除过滤设备

NTSTATUS DispatchPNP(PDEVICE_OBJECT pDevObj, PIRP pIrp)
{
	PIO_STACK_LOCATION stack;
	PDEV_EXT pDevExt = NULL;
	NTSTATUS status = STATUS_SUCCESS;

	pDevExt = (PDEV_EXT)pDevObj->DeviceExtension;
	stack = IoGetCurrentIrpStackLocation(pIrp);

	switch (stack->MajorFunction)
	{
	//移除
	case IRP_MN_REMOVE_DEVICE:
		//先发送请求下去
		IoSkipCurrentIrpStackLocation(pIrp);
		IoCallDriver(pDevExt->pLowerDevObj, pIrp);
		//解除绑定
		IoDetachDevice(pDevExt->pLowerDevObj);
		//删除过滤设备
		IoDeleteDevice(pDevObj);
		break;

	default:
		//直接下发
		IoSkipCurrentIrpStackLocation(pIrp);
		IoCallDriver(pDevExt->pLowerDevObj, pIrp);
		break;
	}

	return status;
}

读分发

这里不是直接下发,而是设置个回调,当下层完成请求时,调用该回调,咱再进行处理

NTSTATUS DispatchRead(PDEVICE_OBJECT pDevObj, PIRP pIrp)
{
	PDEV_EXT pDevExt = NULL;
	PIO_STACK_LOCATION stack;
	NTSTATUS status = STATUS_SUCCESS;

	if (pIrp->CurrentLocation == 1)
	{
		KdPrint(("pIrp->CurrentLocation == 1"));
		status = STATUS_INVALID_DEVICE_REQUEST;

		pIrp->IoStatus.Status = status;
		pIrp->IoStatus.Information = 0;
		IoCompleteRequest(pIrp, IO_NO_INCREMENT);
		return status;
	}

	g_nCount++;

	pDevExt = (PDEV_EXT)pDevObj->DeviceExtension;
	stack = IoGetCurrentIrpStackLocation(pIrp);

	//复制IRP
	IoCopyCurrentIrpStackLocationToNext(pIrp);
	//设置完成回调
	IoSetCompletionRoutine(pIrp, ReadComplete, pDevObj, TRUE, TRUE, TRUE);
	//下发
	return IoCallDriver(pDevExt->pLowerDevObj, pIrp);
}

读完成回调

这里就是处理

NTSTATUS
ReadComplete(
	__in PDEVICE_OBJECT DeviceObject,
	__in PIRP pIrp,
	__in_xcount_opt("varies") PVOID Context
)
{
	ULONG i;
	
	PKEYBOARD_INPUT_DATA pKey;
	ULONG uKeySize;

	PIO_STACK_LOCATION stack;
	
	stack = IoGetCurrentIrpStackLocation(pIrp);

	//判断是否成功
	if (pIrp->IoStatus.Status != STATUS_SUCCESS)
	{
		if (pIrp->PendingReturned)
		{
			IoMarkIrpPending(pIrp);
		}
		return pIrp->IoStatus.Status;
	}

	//获取缓冲区和大小
	pKey = (PKEYBOARD_INPUT_DATA)pIrp->AssociatedIrp.SystemBuffer;

	//获取键个数
	uKeySize = pIrp->IoStatus.Information / sizeof(KEYBOARD_INPUT_DATA);

	//打印
	for (i = 0; i < uKeySize; i++)
	{
		KdPrint(("ScanCode: %x", pKey->MakeCode));
		KdPrint(("%s", pKey->Flags ? "up" : "down"));
		
		//s修改为d
		if (pKey->MakeCode == 0x1F)
		{
			pKey->MakeCode = 0x20;
		}
	}

	g_nCount--;

	if (pIrp->PendingReturned)
	{
		IoMarkIrpPending(pIrp);
	}
	return pIrp->IoStatus.Status;
}

动态卸载

卸载直接放在源码里了,可以自行下载

完整代码

下载地址: 完整代码

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值