📄 kbfiltr.c
字号:
/*--
模块名称:
kbfilter.c
代码模版:
Windows XP DDK 2600 - KbFilter
作者:
Advance(LOVEHINA-AVC)
环境:
仅运行于内核模式
--*/
#include "kbfiltr.h"
//显式声明代码段所位于的页
NTSTATUS DriverEntry (PDRIVER_OBJECT, PUNICODE_STRING);
#pragma alloc_text (INIT, DriverEntry)
#pragma alloc_text (PAGE, KbFilter_CreateClose)
#pragma alloc_text (PAGE, KbFilter_IoCtl)
#pragma alloc_text (PAGE, KbFilter_Read)
#pragma alloc_text (PAGE, KbFilter_Unload)
#pragma alloc_text (PAGE, KbFilter_PnP)
#pragma alloc_text (PAGE, KbFilter_HookDevice)
#pragma alloc_text (PAGE, KbFilter_DispatchPassThrough)
NTSTATUS
DriverEntry (
IN PDRIVER_OBJECT DriverObject,
IN PUNICODE_STRING RegistryPath
)
/*++
例程描述:
初始化各个例程入口
--*/
{
PDEVICE_OBJECT kbmDevice,kbdcDevice;
PFILE_OBJECT fileObject;
UNICODE_STRING deviceName,linkName;
NTSTATUS status;
PKBMHOOK_DEVICE_EXTENSION kbmDevExt;
//
// 流经这个过滤驱动的IRP分发例程
//
DriverObject->MajorFunction [IRP_MJ_CREATE] =
DriverObject->MajorFunction [IRP_MJ_CLOSE] = KbFilter_CreateClose;
DriverObject->MajorFunction [IRP_MJ_READ] = KbFilter_Read;
//
// 微软注明若需要使用以下例程,则必须自行创建一个新的设备(避免与下层驱动协议冲突)。
// 因此我们需要在DriverEntry中创建一个UNKNOWN设备,并调用IoCreateSymbolicLink暴露接口给Win32应用程序。
//
// *可通过调用IoBuildDeviceIoControlRequest来构造我们的内部控制请求,但我更倾向于直接修改设备扩展内容的通信方式。
//
// DriverObject->MajorFunction [IRP_MJ_DEVICE_CONTROL] = KbFilter_IoCtl;
//
DriverObject->MajorFunction [IRP_MJ_DEVICE_CONTROL] = KbFilter_IoCtl;
DriverObject->MajorFunction [IRP_MJ_PNP] = KbFilter_PnP;
DriverObject->DriverUnload = KbFilter_Unload;
//
// 创建我们的Keyboard Mapper Advance应用程序接口设备
//
RtlInitUnicodeString(&deviceName, L"\\Device\\kbmhook0");
RtlInitUnicodeString(&linkName, L"\\DosDevices\\devKbmhook");
status = IoCreateDevice(DriverObject,
sizeof(KBMHOOK_DEVICE_EXTENSION),
&deviceName,
FILE_DEVICE_UNKNOWN,
0,
TRUE, // 在同一时刻仅允许单个线程访问
&kbmDevice
);
if (!NT_SUCCESS(status)) {
return (status);
}
//
// 创建符号连接,使Win32程序可以通过CreateFile来访问驱动。
//
status = IoCreateSymbolicLink(&linkName, &deviceName);
if (!NT_SUCCESS(status)) {
IoDeleteDevice(kbmDevice);
return (status);
}
RtlZeroMemory(kbmDevice->DeviceExtension, sizeof(KBMHOOK_DEVICE_EXTENSION));
kbmDevExt = (PKBMHOOK_DEVICE_EXTENSION)kbmDevice->DeviceExtension;
//
// 获得键盘类驱动KbdClass的首个实例设备对象指针
//
RtlInitUnicodeString(&deviceName, L"\\Device\\KeyboardClass0");
status = IoGetDeviceObjectPointer(&deviceName,
FILE_ALL_ACCESS,
&fileObject,
&kbdcDevice
);
if (!NT_SUCCESS(status)) {
IoDeleteDevice(kbmDevice);
IoDeleteSymbolicLink(&linkName);
return (status);
}
ObDereferenceObject(fileObject);
//
// 将KbdClass的驱动对象存进设备扩展里,待会我们才要用到它。
//
kbmDevExt->IsFilterDevice = FALSE;
kbmDevExt->KbdClassDriver = kbdcDevice->DriverObject;
kbmDevice->Flags |= (DO_BUFFERED_IO | DO_POWER_PAGABLE);
return STATUS_SUCCESS;
}
NTSTATUS
KbFilter_Complete (
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN PVOID Context
)
/*++
例程描述:
我们通过这个完成例程来过滤Kbdclass对Win32k的键盘数据提交,
当Kbdclass完成了读操作IRP时,这个例程即被IO管理器调用,使我们有机会修改提交的数据。
--*/
{
ULONG i;
PUCHAR dataPointer;
PFILTER_DEVICE_EXTENSION fltDevExt;
PKBMHOOK_DEVICE_EXTENSION kbmDevExt;
USHORT makecode,keycode,flags;
UCHAR kdflags,index,location;
//
// 必须的东西,在每个完成例程中设定正确的IRP返回状态。
//
if (Irp->PendingReturned)
{
IoMarkIrpPending(Irp);
}
//
// AssociatedIrp.SystemBuffer里面存放的就是KEYDATA,IoStatus.Information域指出了这个数据块的实际大小。
//
fltDevExt = (PFILTER_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
kbmDevExt = (PKBMHOOK_DEVICE_EXTENSION)fltDevExt->KbmDevExtPointer;
dataPointer = (PUCHAR)Irp->AssociatedIrp.SystemBuffer;
//
// 如果开启了HOOK我们就尝试置换键位,否则将当前击键状态转存到设备扩展中供应用程序接收。
//
if (kbmDevExt->HookSwitch == TRUE)
{
for (i = 0 ; i < (Irp->IoStatus.Information / sizeof(KEYBOARD_INPUT_DATA)) ; i++)
{
makecode = ((PKEYBOARD_INPUT_DATA)dataPointer)->MakeCode;
flags = ((PKEYBOARD_INPUT_DATA)dataPointer)->Flags;
index = 0;
if (flags & KEY_E0)
{
index = 1;
} else if (flags & KEY_E1)
{
index = 2;
}
if (fltDevExt->KeyStore[index][makecode] != 0)
{
keycode = fltDevExt->KeyStore[index][makecode];
((PKEYBOARD_INPUT_DATA)dataPointer)->MakeCode = keycode;
flags &= ~KEY_E0;
flags &= ~KEY_E1;
location = fltDevExt->KeyIndex[index][makecode];
if (location == 1)
{
flags |= KEY_E0;
} else if (location == 2)
{
flags |= KEY_E1;
}
((PKEYBOARD_INPUT_DATA)dataPointer)->Flags = flags;
} else if (kbmDevExt->KeyStore[index][makecode] != 0)
{
((PKEYBOARD_INPUT_DATA)dataPointer)->MakeCode = 0;
}
dataPointer += sizeof(KEYBOARD_INPUT_DATA);
}
} else {
makecode = ((PKEYBOARD_INPUT_DATA)dataPointer)->MakeCode;
flags = ((PKEYBOARD_INPUT_DATA)dataPointer)->Flags;
kdflags = 0;
if (flags & KEY_E0)
{
kdflags |= KEY_E0;
} else if (flags & KEY_E1)
{
kdflags |= KEY_E1;
}
for (i = 0 ; i < 16 ; i++)
{
if (fltDevExt == kbmDevExt->FltDevExtPointer[i])
{
index = (UCHAR)i;
break;
}
}
if ((kbmDevExt->KeyDown.DeviceID == fltDevExt->DeviceID) && (kbmDevExt->KeyDown.DeviceIndex == index))
{
if ((kbmDevExt->KeyDown.KeyPressed == (UCHAR)makecode) && (kbmDevExt->KeyDown.Flags == kdflags))
{
if (flags & KEY_BREAK)
kbmDevExt->KeyDown.KeyPressed = 0;
} else {
if (!(flags & KEY_BREAK))
{
kbmDevExt->KeyDown.KeyPressed = (UCHAR)makecode;
kbmDevExt->KeyDown.Flags = kdflags;
}
}
} else {
kbmDevExt->KeyDown.DeviceIndex = index;
kbmDevExt->KeyDown.DeviceID = fltDevExt->DeviceID;
kbmDevExt->KeyDown.KeyPressed = (UCHAR)makecode;
kbmDevExt->KeyDown.Flags = kdflags;
}
}
return STATUS_SUCCESS;
}
NTSTATUS
KbFilter_CreateClose (
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
/*++
例程描述:
暂时没有XD
--*/
{
PKBMHOOK_DEVICE_EXTENSION kbmDevExt;
PIO_STACK_LOCATION irpStack;
NTSTATUS status = STATUS_SUCCESS;
kbmDevExt = (PKBMHOOK_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
//
// 无关的IRP就随它去吧
//
if (kbmDevExt->IsFilterDevice == TRUE)
return KbFilter_DispatchPassThrough(DeviceObject, Irp);
irpStack = IoGetCurrentIrpStackLocation(Irp);
switch (irpStack->MajorFunction)
{
case IRP_MJ_CREATE:
//
// 如果是打开请求,就开始枚举新设备。
//
if (KeGetCurrentIrql() != PASSIVE_LEVEL)
{
status = STATUS_UNSUCCESSFUL;
break;
}
if (kbmDevExt->DeviceCounter < 16)
status = KbFilter_HookDevice(DeviceObject, kbmDevExt);
break;
case IRP_MJ_CLOSE:
kbmDevExt->HookSwitch = FALSE;
break;
}
Irp->IoStatus.Status = status;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return (status);
}
NTSTATUS
KbFilter_DispatchPassThrough(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
{
PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation(Irp);
IoSkipCurrentIrpStackLocation(Irp);
return IoCallDriver(((PFILTER_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->LowerDeviceObject, Irp);
}
NTSTATUS
KbFilter_IoCtl(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
{
UCHAR i,j,keyCode,keyCodeIndex,keyMappingIndex,keyFlags,keyMapping;
ULONG copysize;
PKBMHOOK_DEVICE_EXTENSION kbmDevExt;
PFILTER_DEVICE_EXTENSION fltDevExt;
PIO_STACK_LOCATION irpStack;
PVOID bufferPointer;
PUCHAR sizePointer,dataPointer;
NTSTATUS status = STATUS_SUCCESS;
kbmDevExt = (PKBMHOOK_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
if (kbmDevExt->IsFilterDevice == TRUE)
return KbFilter_DispatchPassThrough(DeviceObject, Irp);
//
// 这里是我为KBMHOOK应用程序构造的通信部分,相关的控制代码包括查询驱动版本、查询设备数量、设定映射键位、设定映射开关等。
//
irpStack = IoGetCurrentIrpStackLocation(Irp);
bufferPointer = Irp->AssociatedIrp.SystemBuffer;
switch (irpStack->Parameters.DeviceIoControl.IoControlCode)
{
case IOCTL_KBMHOOK_QUERY_VERSION:
if (irpStack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(VERSION_DATA))
{
status = STATUS_BUFFER_TOO_SMALL;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -