通过修改i8042prt端口驱动中类驱动Kbdclass的回调函数地址,达到过滤键盘操作的例子
同样也是寒江独钓的例子,但只给了思路,现贴出实现代码
原理是通过改变端口驱动中本该调用类驱动回调函数的地方下手
//替换分发函数 来实现过滤
#include <wdm.h>
#include <ntddk.h>
#include <Ntddkbd.h>
#include <windef.h>
// Kbdclass驱动的名字
#define KBD_DRIVER_NAME L"\\Driver\\Kbdclass"
//ps2的端口驱动
#define PS2_DRIVER_NAME L"\\Driver\\i8042prt"
//usb的端口驱动
#define USB_DRIVER_NAME L"\\Driver\\Kbdhid"
// 这个函数是事实存在的,只是文档中没有公开。声明一下
// 就可以直接使用了。 PVOID pOldFucAddr;
PVOID pOldValue;
NTSTATUS
ObReferenceObjectByName(
PUNICODE_STRING ObjectName,
ULONG Attributes,
PACCESS_STATE AccessState,
ACCESS_MASK DesiredAccess,
POBJECT_TYPE ObjectType,
KPROCESSOR_MODE AccessMode,
PVOID ParseContext,
PVOID *Object
);
BOOLEAN MmIsAddressValid(
PVOID VirtualAddress
);
extern POBJECT_TYPE *IoDriverObjectType; //定义要查找的回调函数的类型
typedef VOID(_stdcall *KEYBOARDCLASSSERVICECALLBACK)
(IN PDEVICE_OBJECT DeviceObject,
IN PKEYBOARD_INPUT_DATA InputDataStart,
IN PKEYBOARD_INPUT_DATA InputDataEnd,
IN OUT PULONG InputDataConsumed); typedef struct _KBD_CALLBACK
{
PDEVICE_OBJECT classDeviceObject;
KEYBOARDCLASSSERVICECALLBACK serviceCallBack;
BOOLEAN bSearch;
}KBD_CALLBACK,PKBD_CALLBACK;
KBD_CALLBACK g_KbdCallBack; #define DELAY_ONE_MICROSECOND (-10)
#define DELAY_ONE_MILLISECOND (DELAY_ONE_MICROSECOND*1000)
#define DELAY_ONE_SECOND (DELAY_ONE_MILLISECOND*1000)
//卸载时候 要替换回来
VOID c2pUnload(IN PDRIVER_OBJECT DriverObject)
{
KdPrint(("DriverEntry unLoading...\n"));
InterlockedExchangePointer(pOldFucAddr,g_KbdCallBack.serviceCallBack);
} VOID _stdcall MyCallBackFun
(IN PDEVICE_OBJECT DeviceObject,
IN PKEYBOARD_INPUT_DATA InputDataStart,
IN PKEYBOARD_INPUT_DATA InputDataEnd,
IN OUT PULONG InputDataConsumed)
{
DbgPrint("makecode %d flags %d\n",InputDataStart->MakeCode,InputDataStart->Flags);
g_KbdCallBack.serviceCallBack(DeviceObject,InputDataStart,InputDataEnd,InputDataConsumed);
}
NTSTATUS SearchKbdDevice()
{
//定义一些局部变量
NTSTATUS status = STATUS_UNSUCCESSFUL;
UNICODE_STRING uniNtNameString;
PDEVICE_OBJECT pUsingDeviceObject = NULL;//目标设备
PDRIVER_OBJECT KbdDriverObject = NULL;//类驱动
PDRIVER_OBJECT KbdhidDriverObject = NULL;//USB 端口驱动
PDRIVER_OBJECT Kbd8042DriverObject = NULL;//PS/2 端口驱动
PDRIVER_OBJECT UsingDriverObject = NULL; PVOID KbdDriverStart = NULL;//类驱动起始地址
ULONG KbdDriverSize = ;
PBYTE UsingDeviceExt = NULL;
ULONG i=;
PVOID pTemp;
PDEVICE_OBJECT pAttachedKbdDevice;
//这部分代码打开PS/2键盘的驱动对象
RtlInitUnicodeString(&uniNtNameString,PS2_DRIVER_NAME);
status = ObReferenceObjectByName(
&uniNtNameString,
OBJ_CASE_INSENSITIVE,
NULL,
,
*IoDriverObjectType,
KernelMode,
NULL,
(PVOID*)&Kbd8042DriverObject
);
if (!NT_SUCCESS(status))
{
DbgPrint("Couldn't get the PS/2 driver Object\n");
}
else
{
//解除引用
ObDereferenceObject(Kbd8042DriverObject);
DbgPrint("Got the PS/2 driver Object\n");
} //打开USB 键盘的端口驱动
RtlInitUnicodeString(&uniNtNameString,USB_DRIVER_NAME);
status = ObReferenceObjectByName(
&uniNtNameString,
OBJ_CASE_INSENSITIVE,
NULL,
,
*IoDriverObjectType,
KernelMode,
NULL,
(PVOID*)&KbdhidDriverObject
);
if (!NT_SUCCESS(status))
{
DbgPrint("Couldn't get the USB driver Object\n");
}
else
{
ObDereferenceObject(KbdhidDriverObject);
DbgPrint("Got the USB driver Object\n");
} //如果同时有两个键盘,使用i8042prt
if (Kbd8042DriverObject && KbdhidDriverObject)
{
DbgPrint("More than one keyboard!\n");
} //两种键盘都没有 也返回失败
if (!Kbd8042DriverObject && KbdhidDriverObject)
{
DbgPrint("Not found keyboard!\n");
return STATUS_UNSUCCESSFUL;
} //找到合适的驱动对象
UsingDriverObject = Kbd8042DriverObject ? Kbd8042DriverObject : KbdhidDriverObject; RtlInitUnicodeString(&uniNtNameString, KBD_DRIVER_NAME);
status = ObReferenceObjectByName (
&uniNtNameString,
OBJ_CASE_INSENSITIVE,
NULL,
,
*IoDriverObjectType,
KernelMode,
NULL,
(PVOID*)&KbdDriverObject
);
// 如果失败了就直接返回
if(!NT_SUCCESS(status))
{
DbgPrint("Couldn't get the MyTest Device Object\n");
return STATUS_UNSUCCESSFUL;
}
else
{
// 这个打开需要解应用。
ObDereferenceObject(KbdDriverObject);
}
//如果成功,找到Kbdclass开始地址和大小
KbdDriverStart =KbdDriverObject->DriverStart;
KbdDriverSize = KbdDriverObject->DriverSize; //遍历UsingDriverObject下的设备对象,找到Kbdclass Attach的那个设备对象
pUsingDeviceObject = UsingDriverObject->DeviceObject; while (pUsingDeviceObject)
{
Label_Continue:
pAttachedKbdDevice=KbdDriverObject->DeviceObject;
while(pAttachedKbdDevice)
{
PDEVICE_OBJECT pAttached=pUsingDeviceObject->AttachedDevice;
while(pAttached)
{
if(pAttachedKbdDevice==pAttached)
{
DbgPrint("pAttachedKbdDevice :%8x\n",pAttachedKbdDevice); UsingDeviceExt=(PBYTE)pUsingDeviceObject->DeviceExtension;
//遍历找到的端口驱动设备扩展下的每个指针
for (i=;i<;i++,UsingDeviceExt += sizeof(PBYTE))
{
if (!MmIsAddressValid(UsingDeviceExt))
{
pUsingDeviceObject=pUsingDeviceObject->AttachedDevice;
goto Label_Continue;
} //在端口驱动的设备扩展中,找到了类驱动的设备对象,填好类驱动设备对象后继续 pTemp = *(PVOID*)UsingDeviceExt;
if (pTemp == pAttachedKbdDevice)
{
g_KbdCallBack.classDeviceObject = (PDEVICE_OBJECT)pTemp;
DbgPrint("classDeviceObject %8x\n",pTemp); pTemp = *(PVOID*)(UsingDeviceExt+);
if ((pTemp > KbdDriverStart)&&(pTemp < (PBYTE)KbdDriverStart+KbdDriverSize)&&MmIsAddressValid(pTemp))
{
//记录回调函数的地址
g_KbdCallBack.serviceCallBack = (KEYBOARDCLASSSERVICECALLBACK)pTemp;
g_KbdCallBack.bSearch=TRUE;
status=STATUS_SUCCESS;
DbgPrint("serviceCallBack :%8x\n",pTemp); DbgPrint("替换函数");
pOldFucAddr=(PVOID*)(UsingDeviceExt+);
InterlockedExchangePointer((PVOID*)(UsingDeviceExt+),MyCallBackFun);
goto Label_Exit;
}
break;
}
}
pUsingDeviceObject=pUsingDeviceObject->AttachedDevice;
goto Label_Continue;
}
pAttached=pAttached->AttachedDevice;
}
pAttachedKbdDevice=pAttachedKbdDevice->NextDevice;
}
pUsingDeviceObject=pUsingDeviceObject->NextDevice;
} Label_Exit:
//如果成功找到,可以返回了
return status;
}
//驱动程序入口
NTSTATUS DriverEntry(
IN PDRIVER_OBJECT DriverObject,
IN PUNICODE_STRING RegistryPath
)
{
// 卸载函数。
DriverObject->DriverUnload = c2pUnload; return SearchKbdDevice();
}
通过修改i8042prt端口驱动中类驱动Kbdclass的回调函数地址,达到过滤键盘操作的例子的更多相关文章
- Linux驱动 - SPI驱动 之三 SPI控制器驱动
通过第一篇文章,我们已经知道,整个SPI驱动架构可以分为协议驱动.通用接口层和控制器驱动三大部分.其中,控制器驱动负责最底层的数据收发工作,为了完成数据的收发工作,控制器驱动需要完成以下这些功能:1. ...
- 利用模块加载回调函数修改PE导入表实现注入
最近整理PE文件相关代码的时候,想到如果能在PE刚刚读进内存的时候再去修改内存PE镜像,那不是比直接对PE文件进行操作隐秘多了么? PE文件在运行时会根据导入表来进行dll库的"动态链接&q ...
- 通过修改CR0寄存器绕过SSDT驱动保护
为了安全起见,Windows XP及其以后的系统将一些重要的内存页设置为只读属性,这样就算有权力访问该表也不能随意对其修改,例如SSDT.IDT等.但这种方法很容易被绕过,我们只要将这些部分修改为可写 ...
- 分享CCNTFS小工具,在 macOS 中完全读写、修改、访问Windows NTFS硬盘的文件,无须额外的驱动(原生驱动)更稳定,简单设置即可高速传输外接NTFS硬盘文件
CCNTFS [ 下载 ] 在 macOS 中完全读写.修改.访问Windows NTFS硬盘的文件,无须额外的驱动(原生驱动)更稳定,安装后进行简单设置即可高速传输外接NTFS硬盘文件,可全程离线使 ...
- liunx驱动----USB驱动
现象:把usb设备接入电脑 1.Windows发现设备 2.跳出一个对话框提示安装驱动程序 问1:既然没有驱动程序,为什么了够知道是什么驱动了?? 答1:Windows里面已经有了usb总线驱动程序, ...
- (笔记)linux设备驱动--LED驱动
linux设备驱动--LED驱动 最近正在学习设备驱动开发,因此打算写一个系列博客,即是对自己学习的一个总结,也是对自己的一个督促,有不对,不足,需要改正的地方还望大家指出,而且希望结识志同道合的朋友 ...
- 基于OMAPL138的Linux字符驱动_GPIO驱动AD9833(一)之miscdevice和ioctl
基于OMAPL138的Linux字符驱动_GPIO驱动AD9833(一)之miscdevice和ioctl 0. 导语 在嵌入式的道路上寻寻觅觅很久,进入嵌入式这个行业也有几年的时间了,从2011年后 ...
- Android驱动学习-app调用内核驱动过程(驱动框架回顾)
考研已经过去了,android驱动的学习也断了半年多了,现在重新捡起来学习,回顾一下Android驱动的大体框架. Android系统的核心是java,其有一个David虚拟机.Android-app ...
- Linux 驱动框架---驱动中的异步
异步IO是对阻塞和轮询IO的机制补充,所谓异步IO就是在设备数据就绪时主动通知所属进程进行处理的机制.之所以说是异步是相对与被通知进程的,因为进程不知道也无法知道什么时候会被通知:这一机制非常类似于硬 ...
随机推荐
- 关于mysql MYISAM引擎的锁问题
CREATE TABLE `citymy` ( `city_id` smallint(5) unsigned NOT NULL DEFAULT '0', `city` varchar(50) CHAR ...
- 正则-RegExp()构造函数
上次写了js正则的字面量声明,今天说说RegExp()构造函数声明: var p=/cat/g; //字面量声明var p=new RegExp('cat','g') //构造函数声明 它两所表达 ...
- android Sqlite小记
1.android.database.sqlite.SQLiteException: near "": syntax error (code 1): 语法错误,如果你的报了这个错误 ...
- MapReduce工作原理图文详解
目录:1.MapReduce作业运行流程2.Map.Reduce任务中Shuffle和排序的过程 1.MapReduce作业运行流程 流程示意图: 流程分析: 1.在客户端启动一个作业. 2.向Job ...
- WinForm中重绘TabControl选项卡标题
最近开发WinForm频繁使用了TabControl控件,这个控件的选项卡没有BackgroundImage这个属性,那么如何为其各个选项卡添加背景图片呢?(这里说的是每个TabPage的头部,也就是 ...
- resharper 改为VS自带的F12功能(转到定义)
1:如何设置vs默认的快捷键方式: 2:重新设置resharper的F12及其其它选项设置: 3.如果还需要使用快捷键 Alt+ENTER 1.帮你实现某个接口或抽象基类的方法 2.提供你处理当 ...
- 网站跨站点脚本,Sql注入等攻击的处理
从360安全论坛里找到的一段代码,经过整理封装,直接在站点Global.asax文件或写一个HttpModule来拦截恶意请求即可: http://bbs.webscan.360.cn/forum.p ...
- JS根据经纬度获取地址信息
<!DOCTYPE HTML> <html> <head> <meta http-equiv="Content-Type" content ...
- POJ 2991–Crane【线段树+几何】
题意: 把手臂都各自看成一个向量,则机械手的位置正好是手臂向量之和.旋转某个关节,其实就是把关节到机械手之间的手臂向量统统旋转. 由于手臂很多,要每个向量做相同的旋转操作很费时间.这时就可以想到用线段 ...
- 忘记XP密码的解决方案
仅供教学与研究用,后果自负! !! USE AT YOUR OWN RISK !! !! ONLY FOR EDUCATIONAL PURPOSE !! 介绍 获取SYSTEM权限.测试通过. 进入G ...