串行端口过滤器的研究与实现
摘 要:针对在不影响系统现有驱动程序接口的前提下实现串行端口传输数据过滤功能的目的,通过对Win32驱动程序模型的驱动程序分层和IRP结构的分析,结合驱动程序处理IRP结构数据的方法,得出了在功能驱动程序的上层增加过滤器可以过滤串行端口传输数据的结论,并介绍了串行端口过滤器驱动程序的开发方法。
关键词:串行端口;过滤器;驱动程序;IRP
中图分类号:TP309
用户使用计算机串行端口传输数据信息时,可能存在监视传输数据的内容或防止敏感数据通过串行端口流出等需求。禁止使用串行端口的方法很多,如从物理上封堵串行端口,或者编写一个始终独占串行端口的程序等。但是如果用户希望记录串行端口传输的数据而不影响其它程序使用串行端口,或者希望有区别地处理数据,允许普通数据流出而禁止敏感数据流出,就存在一定的技术难度,这通常需要使用过滤器驱动程序开发的相关技术。
1 过滤器技术基础
Windows系统的每个通信资源都有一个由库或驱动构成的服务提供者,使应用程序能够访问该资源。该服务提供者即通信资源对应的Windows系统的设备对象,用于接收外部中断请求并完成实际硬件功能。对于串行端口的数据传输而言,应用程序进程可以调用CreateFile、ReadFile、WriteFile和DeviceIoControl等相关的Win32 API函数访问相应的系统设备对象,设备驱动程序向串行端口发出中断请求完成数据传输操作并返回给API函数。为了使用户能够监控串行端口的传输数据,可以考虑在应用程序进程和系统设备对象之间增加一个过滤器来实现该功能。
1997年微软公司推出了名为Win32驱动程序模型(Win32 Driver Model,WDM)的技术[1],该项技术引入了硬件抽象层(HAL)的概念,并在后续的Windows系统中的得到了广泛应用。WDM是一个基于设备对象的分层化的驱动程序模型,驱动程序的层或堆栈一起工作处理I/O请求[2]。
1.1 驱动程序分层
WDM根据设备对象堆栈进行分层。设备对象是系统为帮助软件为管理硬件而创建的数据结构,代表了系统中一个物理的或逻辑的设备,并描述其特征。处于堆栈最底层的设备对象称为物理设备对象(Physical Device Object,PDO),在设备对象堆栈中间的某处有一个对象称为功能设备对象(Functional Device Object,FDO),在FDO的上面和下面可以有一些过滤器设备对象(Filter Device Object,FiDO),一个硬件设备可以有多个FDO或FiDO,但只允许有一个PDO。每个硬件设备至少有两个驱动程序,一个是总线驱动程序,负责管理PDO代表的设备与计算机的连接;一个是功能驱动程序,负责管理FDO代表的设备,初始化I/O操作,处理I/O操作完成时产生的中断事件。设备除了上述的两种驱动程序外,还可以有过滤器驱动程序。过滤器驱动程序可以监视或修改功能驱动程序执行I/O操作时的行为。位于功能驱动程序上面和下面的过滤器驱动程序分别称为上层过滤器和下层过滤器。上层过滤器可以提供功能驱动程序之外的特性,而下层过滤器则可以修改功能驱动程序将要执行的总线操作流[3]。
1.2 I/O Request Packet(IRP)
Windows的I/O子系统是一个I/O请求包(I/O Request Packet,IRP)驱动的系统,每个I/O操作都使用一个IRP结构数据描述。I/O管理器响应一个I/O请求并进行参数匹配和操作的安全性检查,然后从系统内存分配的一块大小可变的IRP结构内存,存放I/O请求的类型、用户缓冲区的首地址、用户请求数据的长度等信息。
IRP结构数据由两部分组成:固定部分和一个I/O堆栈。IRP的固定部分包含如下一些请求的相关信息:该请求的类型和大小,同步或异步,一个用于缓冲类型I/O的缓冲区指针,以及一些在请求处理过程中会被改变的状态信息。I/O堆栈包含一系列I/O堆栈单元,单元数目与驱动程序堆栈中处理该I/O请求的驱动程序数目相同,每个单元对应一个将处理该IRP的驱动程序。IRP当前堆栈单元中包含一个I/O功能代码、与功能相关的参数,以及一个指向调用者文件对象的指针,用以判定即将发生在特定文件对象上的特定I/O操作。I/O功能代码由一个主功能代码和一个次功能代码组成。主功能代码标识了当I/O管理器将一个IRP传递给一个驱动程序时应该调用该驱动程序的分发例程,以IRP_MJ_开头的符号常量进行定义。次功能代码是可选的,有时被用作主功能代码的一个修饰符,以IRP_MN_开头的符号常量进行定义。
I/O管理器接收一个I/O请求后,分配并初始化一个IRP结构数据,并把该数据发送到合适的设备对象堆栈的最上层驱动程序,然后逐步进行过滤到下面的各层驱动程序,每层驱动程序都可以处理IRP结构数据。根据硬件设备本身和IRP的内容,驱动程序可以只向下层传递IRP,也可以处理完IRP后不再向下层传递,或者既处理IRP又向下层传递。驱动程序处理完一个I/O请求后,在IRP结构中添加处理结果的有关信息,并将其返回I/O管理器,设备操作的I/O请求随即返回[4]。
2 串行端口过滤器的实现
要对串行端口的传输数据进行监视,可以在系统的通用串行端口驱动程序上面增加一个上层过滤器,截取流经它的IRP中的串行端口数据,将所截取的数据通过进程间通信的方式传送到应用进程进行分析显示,同时将数据向下层驱动程序发送完成正常的数据传输,这样可以在不影响串行端口功能的情况下实现监视数据的功能。如果要对串行端口的传输数据进行区别处理,可以先将所截取的数据传送到应用进程根据某种规则进行处理后,再传送回过滤器并向下层驱动程序发送。
串行端口过滤器可以按照功能分为三部分实现:(1)生成过滤器设备对象并绑定;(2)获取传输数据并处理;(3)入口例程DriverEntry。
2.1 生成过滤器设备对象并绑定
Windows系统中已经许多提供了各种功能的设备对象来接收中断请求,并完成对应的硬件设备的功能。为了截取中断请求,可以生成一个虚拟的设备对象,并绑定到真实的设备对象上。绑定后,要发送到真实的设备对象的中断请求会首先被发送到该虚拟的设备对象上。实现该功能需要自定义一个函数,如定义为FilterAttachCom(PDRIVER_OBJECT device),其参数device是一个驱动程序对象的指针,由系统在入口例程DriverEntry中传入。
首先,调用内核API函数IoGetDeviceObjectPointer获取一个串行端口的设备对象指针。
函数参数中,ObjectName是命名设备的名称,Windows系统的第一个串行端口名称是”\\Device\\Serial0”,第二个是”\\Device\\Serial1”,以此类推;DesiredAccess是期望访问权限,可以赋值为FILE_ALL_ACCESS;FileObject是返回的文件对象指针,实现串行端口过滤器不需要使用该参数,但调用该函数后必须调用函数ObDereferenceObject以解除对此文件对象的引用,否则会发生内存泄漏;DeviceObject返回希望获取的设备对象指针。
其次,调用内核API函数IoCreateDevice生成串行端口过滤器的虚拟设备对象,并把该虚拟设备对象的多个子域(主要是标志和特征)设置成和要绑定的设备对象一致。
函数参数中,DriverObject是系统中一个单独的驱动程序对象的指针,描述了驱动程序对象在物理内存中的载入位置、大小和主要入口点等信息,每个驱动程序都要从DriverEntry例程接收该指针;DeviceExtensionSize是设备对象扩展的大小,置为0;DeviceName是设备名称,因为过滤器设备通常不需要名称,所以置为NULL;DeviceType是设备类型,应与被绑定的设备类型一致;DeviceObject返回希望生成的过滤器虚拟设备对象。
该函数调用结束后,应测试要绑定的设备对象的Flags子域是否有DO_BUFFERED_IO和DO_DIRECT_IO标志,Characteristics子域是否有FILE_DEVICE_SECURE_OPEN标志,如果有这些标志,需要为过滤器的虚拟设备对象的相应子域设置这些标志。
此外,还需要为过滤器的虚拟设备对象的Flags子域设置DO_POWER_PAGABLE标志。
最后,调用内核API函数IoAttachDeviceToDeviceStack把过滤器虚拟设备对象绑定到串行端口的设备对象上。
函数参数中,SourceDevice是生成的过滤器虚拟设备对象的指针;TargetDevice是要被绑定的命名设备对象的指针;函数返回值是被绑定后的设备对象指针。该函数总是绑定设备对象堆栈的最顶层的设备对象。
2.2 获取传输数据并处理
I/O管理器在响应来自串行端口的I/O请求时构造一个IRP,并将其作为参数传给驱动程序的分发例程。IRP在系统处理I/O请求的过程中代表此请求,请求中包含要发送的数据,对请求的响应中则包含要接收的数据。在过滤器虚拟设备对象绑定到串行端口设备对象后,首先接收到IRP的是过滤器设备对象,通过分析流经过滤器的IRP结构数据可以得到流经串行端口的所有数据并进行处理。实现该功能需要自定义一个分发函数,如定义为ComFilterDispatch(PDEVICE_OBJECT device,PIRP irp),其参数device和irp由系统从入口例程DriverEntry传入。
IRP中的I/O堆栈由一系列I/O堆栈单元构成。I/O堆栈单元由IO_STACK_LOCATION结构定义,每个堆栈单元都对应一个将处理该IRP的驱动程序。I/O管理器在构造IRP时,分配IRP结构内存并初始化IRP固定部分和第一个I/O堆栈单元,这个单元中的信息与要传递到驱动程序堆栈的第一个驱动程序的信息相对应,第一个驱动程序将要处理该I/O请求。当IRP到达最高层的驱动程序时,调用内核API函数IoGetCurrentIrpStackLocation返回指向当前的I/O堆栈单元的指针。
期刊库(http://www.zgqkk.com),是一个专门从事期刊推广、投稿辅导的网站。
本站提供如何投稿辅导,寻求投稿辅导合作,快速投稿辅导,投稿辅导格式指导等解决方案:省级投稿辅导/国家级投稿辅导/核心期刊投稿辅导//职称投稿辅导。
【免责声明】本文仅代表作者本人观点,与投稿辅导_期刊发表_中国期刊库专业期刊网站无关。投稿辅导_期刊发表_中国期刊库专业期刊网站站对文中陈述、观点判断保持中立,不对所包含内容的准确性、可靠性或完整性提供任何明示或暗示的保证。请读者仅作参考,并请自行承担全部责任。
投稿辅导服务咨询与期刊合作加盟
陆老师联系QQ: 913775405(普刊)
蒋老师联系QQ: 867306987(核心)
刘老师联系QQ: 271374912(核心)
联系电话:18015016272
17327192284
投稿辅导投稿邮箱:zgqkk365@126.com
期刊推荐
- 《课程教育研究》 旬刊 国家级
- 《网络空间安全》(信息安全与技术)月刊 国
- 《价值工程》旬刊 国家级 科技统计源期刊
- 《高教论坛》 月刊 省级
- 《法制与社会》旬刊 省级
- 《中国教育学刊》月刊 14版北大核心
- 《语文建设》 旬刊 14版北大核心
- 《中国绿色画报》 月刊 国家级
- 《社科纵横》季刊 社科类优秀期刊
- 《求索》月刊 14版北大核心期刊
- 《财会月刊》旬刊 14版北大核心
- 《艺术品鉴》 月刊 省级
- 《中华建设》月刊 国家级 建设类优秀期刊
- 《教学与管理》旬刊 北大核心
- 《当代经济》 旬刊 省级
- 《新课程研究》旬刊 省级 教育类优秀学术期
- 《文教资料》 旬刊 省级
- 《学术界》 月刊 双核心
- 《吉林教育》旬刊 省级 教育类学术期刊
- 《中国农业资源与区划》 月刊 14版北大核心
- 《继续教育研究》月刊 北大核心期刊
- 《财经界(学术版)》半月刊 国家级
- 《电影评介》半月刊 14版北大核心
- 《公路交通科技》 月刊 北大核心
- 《新闻传播》月刊 省级 新闻类优秀期刊