《寒江独钓_Windows内核安全编程》中修改类驱动分发函数

最近在阅读《寒江独钓_Windows内核安全编程》一书的过程中,发现修改类驱动分发函数这一技术点,书中只给出了具体思路和部分代码,没有完整的例子。

按照作者的思路和代码,将例子补充完整,发现将驱动安装在WIN7 32位环境下,键盘失效。

经调试发现,可能的原因是替换了\\Driver\\Kbdclass类驱动的所有分发函数导致,如果只替换分发IRP_MJ_READ的函数,不会有问题,以下为代码

  1 //替换分发函数  来实现过滤
  2 #include <wdm.h>
  3 #include <Ntddkbd.h>
  4 // Kbdclass驱动的名字
  5 #define KBD_DRIVER_NAME  L"\\Driver\\Kbdclass"
  6 //旧的函数地址
  7 PDRIVER_DISPATCH OldDispatchFun[IRP_MJ_MAXIMUM_FUNCTION+1];
  8 extern POBJECT_TYPE *IoDriverObjectType;
  9 PDRIVER_DISPATCH OldDIspatchRead;
 10 // 这个函数是事实存在的,只是文档中没有公开。声明一下
 11 // 就可以直接使用了。
 12 NTSTATUS
 13 ObReferenceObjectByName(
 14                         PUNICODE_STRING ObjectName,
 15                         ULONG Attributes,
 16                         PACCESS_STATE AccessState,
 17                         ACCESS_MASK DesiredAccess,
 18                         POBJECT_TYPE ObjectType,
 19                         KPROCESSOR_MODE AccessMode,
 20                         PVOID ParseContext,
 21                         PVOID *Object
 22                         );
 23 //新的分发函数地址
 24 NTSTATUS c2pDispatchGeneral(
 25                                  IN PDEVICE_OBJECT DeviceObject,
 26                                  IN PIRP Irp
 27                                  )
 28 {
 29     PIO_STACK_LOCATION irpStack=IoGetCurrentIrpStackLocation(Irp);
 30     DbgPrint("irpStack->MinorFunction=%x\n",irpStack->MinorFunction);
 31     return OldDIspatchRead(DeviceObject,Irp);
 32     //return OldDispatchFun[irpStack->MinorFunction](DeviceObject,Irp);
 33 }
 34 #define  DELAY_ONE_MICROSECOND  (-10)
 35 #define  DELAY_ONE_MILLISECOND (DELAY_ONE_MICROSECOND*1000)
 36 #define  DELAY_ONE_SECOND (DELAY_ONE_MILLISECOND*1000)
 37 //卸载时候   要替换回来
 38 VOID  c2pUnload(IN PDRIVER_OBJECT DriverObject)
 39 {
 40     NTSTATUS Status = STATUS_UNSUCCESSFUL;
 41     int nIndex = 0;
 42     PDRIVER_OBJECT KeyBoardDriverObject = NULL;
 43     UNICODE_STRING KeyBoardName;
 44     LARGE_INTEGER Delay;
 45
 46     RtlInitUnicodeString(&KeyBoardName, L"\\Driver\\Kbdclass");
 47
 48     Status = ObReferenceObjectByName(&KeyBoardName, OBJ_CASE_INSENSITIVE, NULL, 0, *IoDriverObjectType,
 49         KernelMode, NULL, &KeyBoardDriverObject);
 50
 51     if (!NT_SUCCESS(Status))
 52     {
 53         DbgPrint("UnloadDriver Get Keyboard Driver Object Error\n");
 54         return;
 55     }
 56
 57
 58     //交换原来的分发函数
 59
 60     // for (nIndex; nIndex < IRP_MJ_MAXIMUM_FUNCTION; nIndex++)
 61     // {
 62         // InterlockedExchangePointer(&KeyBoardDriverObject->MajorFunction[nIndex], OldDispatchFun[nIndex]);
 63     // }
 64     InterlockedExchangePointer(&KeyBoardDriverObject->MajorFunction[IRP_MJ_READ], OldDIspatchRead);
 65     DbgPrint("Change MajorFunction Successful!\n");
 66
 67     Delay = RtlConvertLongToLargeInteger(5* DELAY_ONE_MILLISECOND);
 68     // 延时等待完成
 69     KeDelayExecutionThread(KernelMode, FALSE, &Delay);
 70     ObReferenceObject(KeyBoardDriverObject);
 71 }
 72 //驱动程序入口
 73 NTSTATUS DriverEntry(
 74                      IN PDRIVER_OBJECT DriverObject,
 75                      IN PUNICODE_STRING RegistryPath
 76                      )
 77 {
 78     ULONG i;
 79     NTSTATUS status;
 80
 81     UNICODE_STRING uniNtNameString;
 82     //返回kdbclass驱动对象
 83     PDRIVER_OBJECT KbdDriverObject = NULL;
 84
 85     KdPrint(("MyAttach\n"));
 86
 87     // 初始化一个字符串,就是Kdbclass驱动的名字。
 88     #if DBG
 89     _asm int 3;
 90 #endif
 91     RtlInitUnicodeString(&uniNtNameString, KBD_DRIVER_NAME);
 92     // 请参照前面打开设备对象的例子。只是这里打开的是驱动对象。
 93     status = ObReferenceObjectByName (
 94         &uniNtNameString,
 95         OBJ_CASE_INSENSITIVE,
 96         NULL,
 97         0,
 98         *IoDriverObjectType,
 99         KernelMode,
100         NULL,
101         &KbdDriverObject
102         );
103     // 如果失败了就直接返回
104     if(!NT_SUCCESS(status))
105     {
106         DbgPrint("MyAttach: Couldn‘t get the MyTest Device Object %x\n",status);
107         return( status );
108     }
109     else
110     {
111         // 这个打开需要解应用。早点解除了免得之后忘记。
112         //解释为  可能导致DriverObject引用计数加1
113
114     }
115
116
117
118     OldDIspatchRead=KbdDriverObject->MajorFunction[IRP_MJ_READ];
119     InterlockedExchangePointer(&KbdDriverObject->MajorFunction[IRP_MJ_READ],c2pDispatchGeneral);
120     ObDereferenceObject(KbdDriverObject);
121     // 卸载函数。
122     DriverObject->DriverUnload = c2pUnload;
123
124
125     return status;
126 }
时间: 2024-11-05 16:03:20

《寒江独钓_Windows内核安全编程》中修改类驱动分发函数的相关文章

寒江独钓--Windows内核安全编程笔记(一)

第一章:内核上级指导 1.如果没有设置DriverUnload函数指针,则一个内核模块一旦被加载就不能卸载了. 2.makefile文件内容永远也不需要改动. 3.设置断点之前系统必须已经中断. 4.驱动加载之前,设置断点不方便,手工断点如下: #if DBG _asm int 3 #endif 如果不是调试状态执行会直接蓝屏,断点弹出之后可以设置新的断点 5.WinDbg为双机调试,Softice可以进行单机调试但已经不再更新,吴岩峰等人开发的Syser也可以进行单机调试,100%国产 第二章

寒江独钓Windows内核编程——串口过滤

一.过滤的概念: 过滤是在不影响上层和下层接口的情况下,在Windows系统内核中加入新的层,从而不需要修改上层的软件或者下层的真是驱动程序,就加入了新的功能. 1.1 设备绑定的内核API 进行过滤的最主要的方法是对一个设备对象(Device Object)进行绑定.通过编程可以生成一个虚拟设备对象,并“绑定”(Attach)在一个真实的设备上.一旦绑定,则本来操作系统发送给真实设备的请求,就会首先发送到这个虚拟设备. 在WDK中,有多个内核API能实现绑定的功能.以下三个绑定API是从WDK

寒江独钓:键盘的过滤 学习笔记

先来名词热身: 一.符号链接:其实就是一个别名.可以用一个不同的名字来代表一个设备对象 二.PDO:是物理设备对象,可以理解为是设备栈最下面的那个设备对象. 函数介绍: 内核中:ZwCreateFile是很重要的函数,不但可以打开文件,还可以打开设备对象.在应用程序中跟它对应的是CreateFile函数.. 接下来是记录Windows如何获得按键,然后传递给各个应用程序. csrss这个进程里有个线程叫win32k!RawInputThread,这个线程总是调用nt!ZwReadFile来读入数

Windows驱动过滤--kdbclass过滤,寒江独钓加强版

寒江独钓键盘过滤,修改了下,过滤QQ密码写入buff,有 回车 或者buff满写入文件,因为irp完成,irp对应的内存快回收,所以用全局缓冲区.开启一个线程写入,开始打算用队例一个一个处理irp的,但是发现那样比较缓慢,只好这样了..创建进程回调代码加几行就行,这里没写,因为代码丢失了,算是个大概的代码吧.给初学的分享下.有错指出,谢谢. 前辈们不要见笑了. struct.h /************************************/ //author:DuanYueming

网络编程中的read,write函数

关于TCP/IP协议,建议参考Richard Stevens的<TCP/IP Illustrated,vol1>(TCP/IP详解卷1). 关于第二层面,依然建议Richard Stevens的<Unix network proggramming,vol1>(Unix网络编程卷1),这两本书公认是Unix网络编程的圣经. 至于第三个层面,UNP的书中有所提及,也有著名的C10K问题,业界也有各种各样的框架和解决方案,本人才疏学浅,在这里就不一一敷述. 本文的重点在于第二个层面,主要

Cocos2d-x编程中CCRemoveSelf与CCCallFunc系列函数不能一起使用

可能是"头晕"了,我在编码中随意写出了如下代码:     CCLabelTTF* lbl=CCLabelTTF::create("Hi, you have succeeded in buying this Power-up!", "Arial", 32);     lbl->setColor(ccc3(255,0,0));     lbl->setPosition(VisibleRect::center());     ul2->

VC++编程中常用的字符串转换函数

VC++编程中经常遇到不同编码编码的字符串之间需要转换的情况,以下简单提供几个不同编码字符串之间的转换函数: ANSI 字符串和Unicode字符串之间的转换 //Convert wide char string to ANSI string BOOL WCharToMByte(LPCWSTR lpcwszStr,Std::string &str) { DWORD dwMinSize=0; LPSTR lpszStr=NULL; dwMinSize= WideCharToMultiByte(CP

DataTable数据检索的性能分析(转寒江独钓)

我们知道在.NET平台上有很多种数据存储,检索解决方案-ADO.NET Entity Framework,ASP.NET Dynamic Data,XML, NHibernate,LINQ to SQL 等等,但是由于一些原因,如平台限制,比如说必须基于.NET Framework2.0及以下平台:遗留的或者第三方数据接口采用的就是DataTable等等,仍然需要使用DataTable作为数据存储结构.另一方面DataTable比较容易使用,一些数据访问的接口可能直接采用了DataTable结构

JAVA编程中的类和对象

1:初学JAVA,都知道JAVA是面向对象的编程.笔者这节开始说说类和对象.(实例仅供参考,如若复制粘贴记得修改包名和类名,避免出错) 学习JAVA的快捷键,Alt+/代码补全功能,其实此快捷键启动了Eclipse代码辅助菜单,Shift+Ctrl+o快捷键导入包 Ctrl+F可以快速查找API,中文版API,百度云链接:http://pan.baidu.com/s/1slQWhCL 密码:cfxo 首先 对象的创建:类名  对象名=new 类名();也许大多数学习java的都会写,但是理解方面