首页
课程
问答
CTF
社区
招聘
峰会
发现
排行榜
知识库
工具下载
看雪20年
看雪商城
证书查询
登录
注册
首页
社区
课程
招聘
发现
问答
CTF
排行榜
知识库
工具下载
峰会
看雪商城
证书查询
社区
付费问答
发新帖
2
0
[旧帖]
[求助]驱动初学者,关于键盘过滤(Kbdclass)驱动的1个问题,请高手赐教。
0.00雪花
发表于: 2009-10-30 19:54
1623
[旧帖]
[求助]驱动初学者,关于键盘过滤(Kbdclass)驱动的1个问题,请高手赐教。
0.00雪花
天涯独行
2009-10-30 19:54
1623
驱动初学者,关于键盘过滤(Kbdclass)驱动的1个问题,请高手赐教。
问题请看代码中的注释(红色的文字),或者直接查找 问题 就可以了。
申明:本代码参考了《寒江独钓——Windows内核安全编程》
/*
描述 : 键盘过滤(Kbdclass)
*/
#include <ntddk.h>
#include <ntddkbd.h>
// 这个全局变量是存在的,声明一下就可以用
extern POBJECT_TYPE IoDriverObjectType;
// 这个例程是存在的,声明一下就可以用
extern NTKERNELAPI NTSTATUS ObReferenceObjectByName(
IN PUNICODE_STRING ObjectName, // 驱动对象的名字
IN ULONG Attributes, // OBJ_CASE_INSENSITIVE
IN PACCESS_STATE PassedAccessState OPTIONAL, // NULL
IN ACCESS_MASK DesiredAccess OPTIONAL, // 0
IN POBJECT_TYPE ObjectType OPTIONAL, // IoDriverObjectType
IN KPROCESSOR_MODE AccessMode, // KernelMode
IN OUT PVOID ParseContext OPTIONAL, // NULL
OUT PVOID *Object // 取得的对象指针的指针
);
// 过滤设备的设备扩展
typedef struct _KB_FILTER_DEV_EXT {
// 设备栈上位于过滤设备对象的下一层设备对象,过滤设备卸载时用
PDEVICE_OBJECT LowerDeviceObject;
} KB_FILTER_DEV_EXT, *PKB_FILTER_DEV_EXT;
// 按键处理计数器
ULONG gKeyCount = 0;
// 驱动入口例程
NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath);
// IRP处理例程
NTSTATUS Dispatch(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp);
// 驱动卸载例程
VOID DriverUnload(IN PDRIVER_OBJECT DriverObject);
// Kbdclass挂载例程
VOID AttachKbdclass(IN PDRIVER_OBJECT DriverObject);
// IRP_MJ_READ完成回调例程
NTSTATUS ReadCompletionRoutine(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PVOID Context);
// 定义各例程位于分页内存(PAGE)/非分页内存(???)/只运行一次就从内存释放(INIT)
#ifdef ALLOC_PRAGMA
#pragma alloc_text(INIT, DriverEntry)
#pragma alloc_text(PAGE, Dispatch)
#pragma alloc_text(PAGE, DriverUnload)
#pragma alloc_text(INIT, AttachKbdclass)
#pragma alloc_text(PAGE, ReadCompletionRoutine)
#endif
/*
驱动入口例程
*/
NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath)
{
USHORT idx;
// 所有IRP处理例程设置为Dispatch
KdPrint(("DriverEntry in\n"));
for (idx = 0; idx < IRP_MJ_MAXIMUM_FUNCTION; ++idx)
{
DriverObject->MajorFunction[idx] = Dispatch;
}
// 设置驱动卸载例程,否则无法动态卸载
DriverObject->DriverUnload = DriverUnload;
// 挂载Kbdclass
AttachKbdclass(DriverObject);
KdPrint(("DriverEntry end\n"));
return STATUS_SUCCESS;
}
/*
IRP处理例程
*/
NTSTATUS Dispatch(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
{
NTSTATUS status;
// 取得IRP对应的StackLocation
PIO_STACK_LOCATION irpsp = IoGetCurrentIrpStackLocation(Irp);
// 取得过滤设备的设备扩展
PKB_FILTER_DEV_EXT kbDevExt = (PKB_FILTER_DEV_EXT)DeviceObject->DeviceExtension;
switch (irpsp->MajorFunction)
{
case IRP_MJ_POWER :
KdPrint(("IRP=IRP_MJ_POWER\n"));
// IRP_MJ_POWER特别处理
// 准备处理下一个电源IRP
PoStartNextPowerIrp(Irp);
// 跳过当前堆栈,其实是为了平衡堆栈
IoSkipCurrentIrpStackLocation(Irp);
return PoCallDriver(kbDevExt->LowerDeviceObject, Irp);
break;
case IRP_MJ_READ :
KdPrint(("IRP=IRP_MJ_READ\n"));
++gKeyCount;
// 把当前StackLocation拷贝到下一个StackLocation
IoCopyCurrentIrpStackLocationToNext(Irp);
// 设置完成例程的回调
IoSetCompletionRoutine(Irp, ReadCompletionRoutine, DeviceObject, TRUE, TRUE, TRUE);
return IoCallDriver(kbDevExt->LowerDeviceObject, Irp);
break;
case IRP_MJ_PNP :
KdPrint(("IRP=IRP_MJ_PNP\n"));
// IRP_MJ_PNP中再分别处理irpsp->MinorFunction
switch (irpsp->MinorFunction)
{
case IRP_MN_REMOVE_DEVICE :
KdPrint(("IRP=<IRP_MJ_PNP>IRP_MN_REMOVE_DEVICE\n"));
// PNP 管理器要移除设备
IoSkipCurrentIrpStackLocation(Irp);
status = IoCallDriver(kbDevExt->LowerDeviceObject, Irp);
// 卸载过滤设备对象
IoDetachDevice(kbDevExt->LowerDeviceObject);
// 删除过滤设备对象
IoDeleteDevice(DeviceObject);
return status;
break;
default :
// 其他的IRP,默认不处理
KdPrint(("IRP=<IRP_MJ_PNP>Default\n"));
// 跳过当前堆栈,其实是为了平衡堆栈
IoSkipCurrentIrpStackLocation(Irp);
return IoCallDriver(kbDevExt->LowerDeviceObject, Irp);
break;
}
break;
default :
// 其他的IRP,默认不处理
KdPrint(("IRP=Default\n"));
// 跳过当前堆栈,其实是为了平衡堆栈
IoSkipCurrentIrpStackLocation(Irp);
return IoCallDriver(kbDevExt->LowerDeviceObject, Irp);
break;
}
}
/*
驱动卸载例程
*/
VOID DriverUnload(IN PDRIVER_OBJECT DriverObject)
{
PDEVICE_OBJECT DeviceObject;
LARGE_INTEGER inteval;
// 100ms延时
inteval.QuadPart = 100 * 1000 * (-10);
KdPrint(("DriverUnload in\n"));
// 把当前线程设置为低实时模式,让它的运行尽量少影响其他程序
KeSetPriorityThread(KeGetCurrentThread(), LOW_REALTIME_PRIORITY);
DeviceObject = DriverObject->DeviceObject;
while (DeviceObject != NULL)
{
PKB_FILTER_DEV_EXT kbDevExt = (PKB_FILTER_DEV_EXT)DeviceObject->DeviceExtension;
// 卸载设备
IoDetachDevice(kbDevExt->LowerDeviceObject);
// 删除设备
IoDeleteDevice(DeviceObject);
DeviceObject = DeviceObject->NextDevice;
}
// 直到没有按键在处理才退出驱动程序,因为键盘的处理方式是始终有一个IRP_MJ_READ,所以实际是
// 准备卸载驱动以后,直到按下一个键以后才会完成卸载
// 问题1 : 有没有更好的卸载方法呢?
while (gKeyCount > 0)
{
KdPrint(("DriverUnload delay...\n"));
KeDelayExecutionThread(KernelMode, FALSE, &inteval);
}
KdPrint(("DriverUnload end\n"));
}
/*
Kbdclass 挂载例程
*/
VOID AttachKbdclass(IN PDRIVER_OBJECT DriverObject)
{
NTSTATUS status;
UNICODE_STRING driverName;
PDEVICE_OBJECT targetDeviceObject = NULL;
PDEVICE_OBJECT lowerDeviceObject = NULL;
PDEVICE_OBJECT filterDeviceObject = NULL;
PKB_FILTER_DEV_EXT kbDevExt = NULL;
PDRIVER_OBJECT kbdDriverObject = NULL;
KdPrint(("AttachKbdclass in\n"));
// 键盘驱动串\\Driver\\Kbdclass
RtlInitUnicodeString(&driverName, L"\\Driver\\Kbdclass");
// 取得驱动对象
status = ObReferenceObjectByName(&driverName,
OBJ_CASE_INSENSITIVE,
NULL,
0,
IoDriverObjectType,
KernelMode,
NULL,
&kbdDriverObject
);
if (!NT_SUCCESS(status))
{
KdPrint(("ObReferenceObjectByName failed\n"));
// 根据名字取得驱动对象指针失败,退出
return;
}
targetDeviceObject = kbdDriverObject->DeviceObject;
while (targetDeviceObject != NULL)
{
status = IoCreateDevice(DriverObject,
sizeof(KB_FILTER_DEV_EXT),
NULL,
targetDeviceObject->Type,
targetDeviceObject->Characteristics,
FALSE,
&filterDeviceObject);
if (!NT_SUCCESS(status))
{
KdPrint(("IoCreateDevice failed\n"));
// 创建过滤对象失败,退出
return;
}
// 设置过滤设备对象的Flags属性和要绑定的对象的Flags属性一致
filterDeviceObject->Flags |= targetDeviceObject->Flags & (DO_BUFFERED_IO | DO_DIRECT_IO | DO_POWER_PAGABLE);
// 挂载
lowerDeviceObject = IoAttachDeviceToDeviceStack(filterDeviceObject, targetDeviceObject);
if (lowerDeviceObject == NULL)
{
// 绑定失败
KdPrint(("IoAttachDeviceToDeviceStack failed\n"));
// 删除已经创建的过滤设备对象
IoDeleteDevice(filterDeviceObject);
// 退出
return;
}
kbDevExt = (PKB_FILTER_DEV_EXT)filterDeviceObject->DeviceExtension;
kbDevExt->LowerDeviceObject = lowerDeviceObject;
// 设置过滤设备为已经启动的状态,可以接收IRP
filterDeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
// 循环下一个Kbdclass驱动对象的设备对象
targetDeviceObject = targetDeviceObject->NextDevice;
}
KdPrint(("AttachKbdclass end\n"));
}
/*
IRP_MJ_READ完成回调例程
*/
NTSTATUS ReadCompletionRoutine(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PVOID Context)
{
ULONG numKeys;
ULONG idx;
PUCHAR buf = NULL;
PIO_STACK_LOCATION irpsp = IoGetCurrentIrpStackLocation(Irp);
KdPrint(("ReadCompletionRoutine in\n"));
// 如果读请求是成功的
if (NT_SUCCESS(Irp->IoStatus.Status))
{
// 取得按键的个数
numKeys = Irp->IoStatus.Information / sizeof(KEYBOARD_INPUT_DATA);
// 取得缓冲区的内容
buf = (PUCHAR)Irp->AssociatedIrp.SystemBuffer;
// 输出
KdPrint(("numKeys : %d\n", numKeys));
for (idx = 0; idx < numKeys; ++idx)
{
PKEYBOARD_INPUT_DATA keyData = (PKEYBOARD_INPUT_DATA)(buf + idx * sizeof(KEYBOARD_INPUT_DATA));
KdPrint(("ScanCode : %x\n", keyData->MakeCode));
KdPrint(("PressState : %s\n", keyData->Flags == KEY_MAKE ? "DOWN" :
keyData->Flags == KEY_BREAK ? "UP" : "Unknown"));
// 这里只是个测试,按下a,会被修改为c
if (keyData->MakeCode == 30)
{
keyData->MakeCode = 46;
}
}
--gKeyCount;
if (Irp->PendingReturned)
{
IoMarkIrpPending(Irp);
}
}
KdPrint(("ReadCompletionRoutine end\n"));
return Irp->IoStatus.Status;
}
[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课
收藏
・
2
免费
・
0
支持
分享
分享到微信
分享到QQ
分享到微博
赞赏记录
参与人
雪币
留言
时间
查看更多
赞赏
×
1 雪花
5 雪花
10 雪花
20 雪花
50 雪花
80 雪花
100 雪花
150 雪花
200 雪花
支付方式:
微信支付
赞赏留言:
快捷留言
感谢分享~
精品文章~
原创内容~
精彩转帖~
助人为乐~
感谢分享~
最新回复
(
5
)
天涯独行
雪 币:
0
活跃值:
(10)
能力值:
( LV2,RANK:10 )
在线值:
发帖
2
回帖
15
粉丝
0
关注
私信
天涯独行
2
楼
高手呢?
2009-10-30 21:22
0
天涯独行
雪 币:
0
活跃值:
(10)
能力值:
( LV2,RANK:10 )
在线值:
发帖
2
回帖
15
粉丝
0
关注
私信
天涯独行
3
楼
自己顶
2009-10-31 08:28
0
天涯独行
雪 币:
0
活跃值:
(10)
能力值:
( LV2,RANK:10 )
在线值:
发帖
2
回帖
15
粉丝
0
关注
私信
天涯独行
4
楼
高手呢?不要沉
2009-10-31 21:19
0
天涯独行
雪 币:
0
活跃值:
(10)
能力值:
( LV2,RANK:10 )
在线值:
发帖
2
回帖
15
粉丝
0
关注
私信
天涯独行
5
楼
这个问题没有解了吗?
我睡不着啊,每天看几回,就是没人回贴
2009-11-1 11:18
0
天涯独行
雪 币:
0
活跃值:
(10)
能力值:
( LV2,RANK:10 )
在线值:
发帖
2
回帖
15
粉丝
0
关注
私信
天涯独行
6
楼
再顶一把,希望版主不要把我赶出去
2009-11-1 14:23
0
游客
登录
|
注册
方可回帖
回帖
表情
雪币赚取及消费
高级回复
返回
天涯独行
2
发帖
15
回帖
10
RANK
关注
私信
他的文章
[求助]驱动初学者,关于键盘过滤(Kbdclass)驱动的1个问题,请高手赐教。
1624
[求助]驱动初学者,关于串口过滤驱动的3个问题,请高手赐教。
1641
关于我们
联系我们
企业服务
看雪公众号
专注于PC、移动、智能设备安全研究及逆向工程的开发者社区
看原图
赞赏
×
雪币:
+
留言:
快捷留言
为你点赞!
返回
顶部