文件系统过滤驱动
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
1 引言文件系统过滤概述
文件安全性问题已成为当今信息科学领域最重要的课题之一。
目前,解决这个问题的主要技术手段有两种:一是利用应用层HOOK(钩子)技术,对Windows 提供的文件操作函数(API)及由文件操作所触发的Windows消息进行HOOK,经过适当的处理达到预期目的,缺点是效率低、稳定性和一致性差,不适合于大型系统的开发;另一种是开发文件过滤驱动程序,文件过滤驱动作为一种内核态中间层驱动,不需要改变下层驱动或用户程序而增加新的功能,具有效率高、可靠性强、可扩充等特点,成为现阶段信息安全技术研究的热点。
1.1 文件过滤驱动在信息安全领域的应用
1 文件加/解密
文件过滤驱动程序可以实现对指定文件、目录,甚至整个逻辑盘的加/解密功能。
当文件在写入磁盘的过程中,截获所有对该文件的IRP_MJ_WRITE,在其分发例程中对IRP携带的数据进行加密处理后写入磁盘;文件被从磁盘读取的过程中,截获所有对该文件的IRP_MJ_READ,在其分发例程中对IRP携带的数据进行解密处理后向上层返回。
加密后的文件在磁盘中以密文形式存储,保证了数据存储的安全性。
2 病毒防护
应用程序在创建一个新文件或打开一个已存在文件时,文件系统过滤驱动程序截获IRP_MJ_create,判断被打开文件是否存在和病毒特征代码库相匹配的特征,若存在,说明文件感染了病毒,失败掉该IRP,拒绝打开;否则,使IRP继续向下传递,完成正常的打开操作。
3 进程控制
为了防止恶意进程的破坏,有时需要规定只允许某些经过安全验证的特定进程对受保护的文件进行访问,其他不在规则范围内的进程不允许访问。
我们可以通过系统提供的PsGetCurrentProcessId、PsGetCurrentThreadId等API函数得到发起I/O请求的进程及线程的相关信息,如:获得发起进程名称,与安全访问规则(进程白名单)中的可信进程相比较,若该进程位于规则中,说明信任其行为是安全的,允许访问受保护文件;否则,拒绝访问。
4 访问审计
对受保护的文件或是对系统安全有影响的系统配置文件、注册表文件以及一些容易受病毒感染的dll和exe文件进行访问操作的事后收集工作。
文件系统过滤驱动程序针对所关心的文件及访问操作,在相应的IRP分发例程中收集访问信息,以日志的格式呈现给用户。
有了足够多的访问记录,管理员或审计员就可以采取各种分析方法,如病毒特征关键字匹配、访问行为统计等来识别出可疑的行为动作,从而采取适当的措施来确保以后访问的安全性。
1.2 何谓文件系统过滤驱动以及与设备驱动的异同
1 文件系统过滤驱动的定义
文件系统过滤驱动是一种可选的,为文件系统提供具有附加值功能的驱动程序。
文件系统过滤驱动是一种核心模式组件,它作为Windows NT执行体的一部分运行。
文件系统过滤驱动可以过滤一个或多个文件系统或文件系统卷的I/O操作。
按不同的种类划分,文件系统过滤驱动可以分成日志记录、系统监测、数据修改或事件预防几类。
通常,以文件系统过滤驱动为核心的应用程序有防毒软件、加密程序、分级存储管理系统等。
2 文件过滤驱动与设备驱动的比较
设备驱动是用来控制特定硬件I/O设备的软件组件。
例如:DVD存储设备驱动是一个DVD驱动。
相反,文件系统过滤驱动与一个或多个文件系统协同工作来处理文件I/O操作。
这些操作包括:创建、打开、关闭、枚举文件和目录;获取和设置文件、目录、卷的相关信息;向文件中读取或写入数据。
另外,文件系统过滤驱动必须支持文件系统特定的功能,例如缓存、锁定、稀疏文件、磁盘配额、压缩、安全、可恢复性、还原点和卷装载等。
下面详细的阐述文件系统过滤驱动和设备驱动之间的相似点与不同点。
1、文件系统过滤驱动同设备驱动的相似点:
(1)、类似的结构
类似于设备驱动,文件系统过滤驱动有着属于自己的DriverEntry、Dispatch和I/O组件例程。
文件系统过滤驱动同设备驱动一样调用许多相同的系统核心例程,它们都会过滤发送给它们所关联的设备的I/O请求。
(2)、类似的功能:
文件系统过滤驱动和设备驱动都是I/O子系统的组成部分,因此它们都接收和作用于I/O请求包(IRP)。
类似于设备驱动,文件系统过滤驱动同样可以创建它们自己的IRP并将该IRP发送到低层驱动。
这两种驱动均可以通过注册回调函数来接收多种系统事件的通知。
(3)、其它类似点:
同设备驱动类似,文件系统过滤驱动可以接收传入的I/O控制码(IOCTLs)。
而且,文件系统过滤驱动还可以接收和定义文件系统控制码(FSCTLs)。
同设备驱动类似,文件系统过滤驱动可以被配置为在系统引导过程中加载或者在系统启动过程完成后加载。
2、文件系统过滤驱动同设备驱动之间的不同点:
(1)、无需电源管理
由于文件系统过滤驱动并不是真正的设备驱动,而且它们不需要直接控制硬件设备,因此它们并不接收IRP_MJ_POWER请求。
(电源管理IRP将直接发送到存储设备堆栈中。
但是,在非常罕见的情况下,文件系统过滤驱动有可能会影响到电源管理。
)由此,文件系统过滤驱动并不注册IRP_MJ_POWER相关例程,它们也不会调用PoXxx例程。
(2)、非WDM
文件系统过滤驱动并不是WDM驱动程序,WDM驱动模型仅适用于设备驱动。
(3)、没有AddDevice或StartIo例程
由于文件系统过滤驱动并不是设备驱动,而且它们并不直接控制硬件设备,因此它们没有AddDevice或StartIo例程。
(4)、创建不同的设备对象
虽然文件系统过滤驱动和设备驱动均需要创建设备对象,但是它们所创建的设备对象的种类和数量都是不同的。
设备驱动创建物理和功能设备对象来描述设备。
即插即用(PnP)管理器将构建一个设备树来存放所有由设备驱动所创建的设备对象。
文件系统过滤驱动所创建的设备对象,并不包含在这个设备树中。
文件系统过滤驱动并不创建物理或功能设备对象,它们创建控制设备对象和过滤设备对象。
控制设备对象对系统和用户模式应用程序提供过滤驱动的描绘。
过滤设备对象执行对指定文件系统或卷的实际过滤工作。
文件系统过滤驱动通常创建一个控制设备对象和多个过滤设备对象。
(5)、其它不同点:
由于文件系统过滤驱动并不是设备驱动,因此他们将不会执行直接内存访问(DMA)。
与设备过滤驱动不同,设备过滤驱动可以附加到目标设备功能驱动的上层和下层,文件系统过滤驱动仅能附加到目标文件系统驱动的上层。
因此在设备驱动队列中,文件系统仅能进行上层过滤而无法进行下层过滤。
1.3 文件系统过滤驱动的工作原理
1 文件系统驱动
文件系统驱动是存储管理子系统的一个重要组成部分,它向用户提供在磁盘或光盘等非易失性媒介信息的存储、转发,同时和存管理器、高速缓冲管理器紧密结合,不但保证了应用程序可以准确地提取数据文件的内容,而且提高了访问效率。
用户进程对磁盘上文件的创建、打开、读、写等操作由WIN 32子系统调用相应的服务来代表该进程发出请求操作。
I/O管理器接收到上层传来的I/O请求,通过构造输入输出请求包IRP(I/O Request Package)来描述这个请求,然后向下传递给文件系统驱动、存储设备驱动做后续处理,低层驱动处理完毕后把结果依次向上返回,最后经过I/O管理器,由WIN 32子系统把结果返回给发出请求的应用进程,整个对文件的操作请求执行完毕。
Windows 的I/O 管理器是可扩展结构,支持分层驱动模型,这样按照我们的需求开发具有某种功能的驱动程序插入到这个层次结构当中,截获所需处理的IRP进行处理,然后再继续向下传递或直接向上返回结果。
2 文件系统过滤驱动
文件系统过滤驱动是针对文件系统而言,它既可以位于文件系统驱动之上,也可以被插在文件系统驱动和存储设备驱动之间。
I/O管理器在发送文件操作请求到目标设备对象之前,会检查是否有附加的设备对象挂载在目标设备之上,若有,则把该IRP先发送给附加设备,经附加设备所属驱动程序的处理后,再发送给目标设备完成操作请求。
这样通过文件系统过滤驱动程序构造附加设备对象挂载在文件系统的存储设备之上,在过滤驱动程序中对发送到目标设备的操作请求进行预期处理,达到控制文件访问、保护文件安全性等目的。
1.4 文件系统过滤驱动开发过程
和其他应用程序一样,驱动函数也有一个主函数,称为入口函数DriverEntry,格式为:NTSTATUS DriverEntry( I N P D R I V E R _ O B J E C T D r i v e r O b j e c t,I NPUNICODE_STRING RegistryPath)。
DriverObject 是驱动对应的驱动对象,是系统在加载驱动时分配的。
RegistryPath是专用于记录驱动相关参数的注册表路径,也是由系统所分配。
DriverObject驱动对象拥有一组函数指针,称为dispatch functions,在IRP发送给目标设备之前,编写这组函数,在dispatch functions中按照功能需求处理这些IRP,可以让IRP 失败掉,或使其成功返回,或对其进行修改,甚至可以自己构造IRP向下层驱动程序发送。
在DriverEntry中首先调用系统函数IoCreateDevice生成一个控制设备对象CDO,作用是修改整个驱动的内部配置。
接着对所要监控的目标设备对象进行绑定,过程如下:调用ZwCreateFile函数获得设备对象句柄ntFileHandle,再通过ObReferenceObjectByHandle函数生成该ntFileHandle
描述的文件设备对象指针FileObject(Windows NT把每个设备当作一个文件来看待,并用一个FILE_OBJECT 结构描述其属性);调用IoGetRelatedDeviceObject得到该文件对象对应的设备对象fileSysDevice,即我们最后要绑定到目标设备对象上的附加设备对象;最后我们调用AttachTOTargegDeviceObject把刚生成的附加设备对象fileSysDevice绑定到目标设备对象上。
成功绑定后,在过滤驱动中截获所关注的IRP,设置分发例程,对于不关注的IRP调用默认例程直接向下传递。
以上所有工作完成后,清除DeviceObject初始化标记,整个过滤驱动构造完毕,可以加载使用。
上边的绑定是对系统本地卷的绑定,称为静态绑定。
当一个U 盘插入USB 端口,一个名为“J”的卷动态产生时,要求能够生成一个设备来绑定它,称这种绑定为动态绑定。
一个新的存储媒质被系统发现并在文件系统中生成一个Volume的过程
称为Mounting。
过程开始时,文件系统CDO 收到一个MajorFunction Code 为
IRP_MJ_FILE_SYSTEM_CONTROL,MinorFunction Code 为IRP_MN_MOUNT 的IRP。
如果已绑定了文件系统CDO,则可以得到这样的IRP,在其中知道一个新的Volume正在Mounting,这时再按照上边的静态绑定方法来绑定这个新生成的卷设备对象。
微软为我们提供了一个有用的系统调用IoRegisterFsRegistrationChange,用它来注册一个回调函数,当系统中有任何文件系统被激活或撤消时,注册过的回调函数就会被调用,在回调函数中绑定刚激活的文件系统的控制设备对象,在的分发例程中绑定这个新卷设备对象。
2 USB管理系统1:文件系统过滤驱动
USB管理系统是一个对U盘进行读写控制操作的文件系统过滤驱动程序,在系统的过滤层进行监控,对辅存发向内存的数据包IRP进行截获,然后分析IRP包,通过分析对U盘文件进行操作。
并用MFC实现一个界面清晰,操作简单的USB管理系统,可以实现连接驱动、禁止读写、开放读写、只读、安装驱动、卸载驱动等操作。
是一款功能完整的U盘读写控制的管理系统。
2.1 开发目的
现在有很多人需要开发文件系统驱动,windows的PC机上以过滤驱动居多,其目的不外乎以下几种:一是用于防病毒引擎。
希望在系统读写文件的时候,捕获读写的数据内容,然后检测其中是否含有病毒代码。
二是用于文件系统的透明附加功能。
比如希望在文件写过程中对数据进行加密,数据个性化等等过程,针对特殊的过程
进行特殊处理,增加文件系统效率等。
三是一些安全软件使用文件过滤进行数据读写的控制,作为防信息泄漏软件的基础。
四是也有一些数据安全厂家用来进行数据备份与灾难恢复。
为了对U盘进行读写控制等操作,保护pc机上的数据安全保密,编写了一个文件系统过滤驱动程序——USB管理系统。
2.2 开发环境及准备工作
开发平台用的是XP系统,用到的开发工具是VC++ 6.0 和Win2DDK,用VC进行程序的编写,DDK完成对驱动的编译。
开发前要掌握windows编程,熟悉IRP结构,
了解驱动程序的编写及安装。
安装过滤驱动经常会出现蓝屏,系统瘫痪,所以要做好系统备份或者安装双系统。
2.3 安装文件过滤驱动
对于Windows XP和后续操作系统来说,可以通过INF文件或安装应用程序来安装文件系统过滤驱动(对于Windows 2000和更早的操作系统,过滤驱动通常通过服务控制管理器Service Control Manager来进行安装)。
USB管理系统通过INF下面说一说INF的相关内容。
2.3.1 INF简介
INF是Device INFormation File的英文缩写,是Microsoft公司为硬件设备制造商发布其驱动程序推出的一种文件格式,是Winodws操作系统下用来描述设备或文件等数据信息的文件。
INF文件是由标准的ASCII码组成,您可以用任何一款文字编辑器查看修改其中的内容。
一般我们总是认为INF文件是系统设备的驱动程序,其实这是错误的认识,Windows之所以在安装某些硬件的驱动时提示需要INF文件是因为INF文件为该设备提供了一个全面描述硬件参数和相应驱动文件(DLL文件)的信息。
就好比我们看着说明书安装电脑硬件一样,我们就是Windows系统,说明书就是INF 文件。
INF文件功能非常强大,几乎能完成日常操作的所有功能。
您可以把它看成是Windows系统底下的超强批处理。
要熟练掌握和理解甚至是编写INF文件需要对其内部结构有相当的认识。
INF文件中包含硬件设备的信息或脚本以控制硬件操作。
在INF 文件中指明了硬件驱动该如何安装到系统中,源文件在哪里、安装到哪一个文件夹中、怎样在注册表中加入自身相关信息等等。
安装监视器、调制解调器和打印机等设备所需的驱动程序,都是通过INF文件,正是INF的功劳才使得Windows可以找到这些硬件设备的驱动并正确安装。
当我们通过“开始→控制面板→添加删除程序→Windows 安装程序”来添加系统组件的时候,INF文件将会自动调用。
而在其他场合下,则需要在INF文件上点击鼠标右键,然后选择“安装”,你才能顺利安装应用程序。
在C:/Windows/INF文件夹中存放有大量的INF文件。
该文件夹一般处在隐含状态,如果你想查看该文件夹,可选择“查看→文件夹选项→查看”,然后在“文件和文件夹”选项下选择“显示所有文件”。
2.3.2 INF结构
INF文件其实是一种纯文本文件,可以用任意一款文本编辑软件来打开进行编辑,如:记事本、写字板等。
INF文件有一整套的编写规则,每一个INF文件都是严
格按照这些规则来编写的。
*规则一:INF文件是分节的,每一个INF文件有许多的节组成,节名用方括号括起来。
这些节名有些是系统定义好的,有一些是用户自定义的。
每一个节名最长为255个字符(Windows 2000/XP/2003操作系统中)或28个字符(Windows 98操作系统中)。
节与节之间没有先后顺序的区别,另外,同一个INF文件中如果出现两个同样的节名,则系统会自动将这两个节名下面的条目合并到一起。
*规则二:在节与节之间的内容叫条目,每一个节又是由许多的条目组成的,每一个条目都是由形如“signature="$CHICAGO$"”的形式组成的。
如果每一个条目的等号后有多个值,则每一个值之间用“,”号分隔开。
*规则三:INF文件对大小写不敏感。
*规则四:“;”号后面的内容为注释。
*规则五:如果一个条目的内容过多,在一行无法书写完全,则用“\”将一行内容书写为多行。
明白了INF文件的规则后,让我们一起来解剖INF文件的结构。
1.Version节
每一个INF文件都包含一个这样的节,该节中的条目主要是描述此INF文件支持的设备类型和适用的操作系统。
在该节中如果出现“signature="$CHICAGO$"”这样的条目则表示该INF文件适用于Windows 98之后的所有操作系统,如果包含“signature="$Windows NT$"”这样的条目则表示该INF文件适用于Windows 2000/XP/2003操作系统,而且两者必具其一。
另外,该节中“CLASS”条目很重要,它表明了设备的类型,常见的类型有:Display (显示设备,如显卡)、Media(多媒体设备,如声卡)、Net(网络设备,通常是网卡)、Modem(调制解调器)、Printer(打印设备)、Image(图像捕获设备,如摄像头)。
2.Manufacturer节
该节中的条目主要是描述INF文件可以识别的所有硬件设备,其中包含有设备的生产厂家,以便设备的正确安装。
如“%ATi%=ATi”指明设备的生产商为“ATi”,这个大家都不会陌生吧,是显卡的生产商。
3.SourceDisksNames节
该节主要指明安装文件所在的介质。
如:“1="ATi Drivers Release CD"”表明所有驱动程序都在零售版的CD盘上。
4.SourceDiskFiles节
驱动程序文件列表及被安装的位置,该节必须结合[SourceDisksNames]节才能知道具体的位置。
如“atinbtxx.sys=1”,则你必须到[DestinationDirs]节去查看“1”具体代表那个位置。
5.DestinationDirs节
INF文件会指示安装程序在安装的过程中,将一些文件复制到硬盘上,或者将硬盘上的一些文件删除、重命名等。
该节即指定了为实现上述目的的文件所在的目的路径。
6.Defaultinstall节和Install节
在这一节中描述了设备驱动程序与硬件设备的实际属性。
默认情况下,首先执行[DefaultInstall]节,该节指定了要复制或删除的文件,注册表的更新,INF文件的更新等等信息,同时又包含指向其他节的指针。
7.String节
这一节中定义了字符串变量,当某些字符串频繁地出现在INF文件中,为简化输入,可以在该节中定义一个字符串变量,代表该字符串出现在INF文件中。
2.3.3 INF应用实例
下面让我们来看一看USB管理系统的文件过滤驱动程序来对INF有一个具体直观的理解定义。
由于INF文件往往很长,为了说明方便,我们删除了一些大部分的信息,仅保留一个INF文件的结构。
[Version]
signature = "$Windows NT$"
Class = "ActivityMonitor"
ClassGuid = {b86dff51-a31e-4bac-b3cf-e8cfe75c9fc2}
Provider = %Msft%
CatalogFile = sfilter.cat
[DestinationDirs]
DefaultDestDir = 12
FLT.DriverFiles = 12 ;%windir%\system32\drivers
[DefaultInstall]
OptionDesc = %ServiceDesc%
CopyFiles = FLT.DriverFiles
[DefaultInstall.Services]
AddService = %ServiceName%,,FLT.Service
[DefaultUninstall]
DelFiles = FLT.DriverFiles
DelReg = FLT.DelRegistry
[DefaultUninstall.Services]
DelService = %ServiceName%,0x200 ;Ensure service is stopped before deleting
[FLT.Service]
DisplayName = %ServiceName%
Description = %ServiceDesc%
ServiceBinary = %12%\sfilter.sys ;%windir%\system32\drivers\ ServiceType = 2 ;SERVICE_FILE_SYSTEM_DRIVER StartType = 0 ;SERVICE_BOOT_START
ErrorControl = 1 ;SERVICE_ERROR_NORMAL LoadOrderGroup = "FSFilter Activity Monitor"
AddReg = FLT.AddRegistry
[FLT.AddRegistry]
HKR,,"DebugFlags",0x00010001,0
[FLT.DelRegistry]
HKR,,DebugFlags
[FLT.DriverFiles]
sfilter.sys
[SourceDisksFiles]
sfilter.sys = 1,,
[SourceDisksNames]
1 = %DiskId1%,,,
[Strings]
Msft = "Microsoft Corporation"
ServiceDesc = "Sfilter Filter Driver"
ServiceName = "Sfilter"
DiskId1 = "Sfilter Device Installation Disk"
2.4 初始化文件过滤驱动
与设备驱动类似,文件系统过滤驱动也使用DriverEntry例程进行初始化工作。
在驱动程序加载后,加载驱动相同的组件将通过调用驱动程序的 DriverEntry例程来对驱动程序进行初始化工作。
对于文件系统过滤驱动来说,加载和初始化过滤驱动的系统组件为I/O管理器。
DriverEntry例程运行于系统线程上下文中,其IRQL = PASSIVE_LEVEL。
本例程可分页,DriverEntry例程定义如下:
NTSTATUS
DriverEntry (
IN PDRIVER_OBJECT DriverObject,
IN PUNICODE_STRING RegistryPath
)
本例程有两个输入参数。
第一个参数,DriverObject为系统在文件系统过滤驱动加载时所创建的驱动对象;第二个参数,RegistryPath为包含驱动程序注册键路径的Unicode字符串。
文件系统过滤驱动按如下顺序执行DriverEntry例程:
2.4.1 创建控制设备对象
文件系统过滤驱动的DriverEntry例程通常以创建控制设备对象作为该例程的起始。
创建控制设备对象的目的在于允许应用程序即使在过滤驱动加载到文件系统或卷设备对象之前也能够直接与过滤驱动进行通信。
注意:文件系统也会创建控制设备对象。
当文件系统过滤驱动将其自身附加到文件系统之上时(而不是附加到某一特定文件系统卷),过滤驱动同样将其自身附加到文件系统的控制设备对象之上。
在USB管理系统中,控制设备(CDO)对象按如下方式创建:
UNICODE_STRING nameString;
RtlInitUnicodeString( &nameString, L"\\FileSystem\\Filters\\XDFilter" ); status = IoCreateDevice(
DriverObject, //DriverObject
0, //has no device extension,DeviceExtensionSize &nameString, //DeviceName
FILE_DEVICE_DISK_FILE_SYSTEM, //DeviceType
FILE_DEVICE_SECURE_OPEN, //DeviceCharacteristics
FALSE, //Exclusive
&gSFilterControlDeviceObject //DeviceObjectv
);
if (status == STATUS_OBJECT_PATH_NOT_FOUND) {
RtlInitUnicodeString( &nameString, L"\\FileSystem\\XDFilterCDO" );
status = IoCreateDevice(
DriverObject,
0, //has no device extension
&nameString,
FILE_DEVICE_DISK_FILE_SYSTEM,
FILE_DEVICE_SECURE_OPEN,
FALSE,
&gSFilterControlDeviceObject );
if (!NT_SUCCESS( status )) {
KdPrint(( "SFilter!DriverEntry: Error creating control device object \"%wZ\", status=%08x\n", &nameString, status ));
return status;
}
}
else if (!NT_SUCCESS( status )) {
KdPrint(( "SFilter!DriverEntry: Error creating control device object \"%wZ\", status=%08x\n", &nameString, status ));
return status;
}
RtlInitUnicodeString( &linkString, FILESPY_DOSDEVICE_NAME );
status = IoCreateSymbolicLink( &linkString, &nameString );
与文件系统不同,文件系统过滤驱动并不是一定要为其控制设备对象命名。
如果传递给DeviceName参数一个非空(Non-NULL)值,该值将作为控制设备对象的名称。
接下来,在前面的代码范例中DriverEntry可以调用IoCreateSymbolicLink例程来将该对象的核心模式名称与应用程序可见的用户模式名称关联到一起(同样可以通过调用IoRegisterDeviceInterface来使设备对象对应用程序可见)。
注意:由于控制设备对象是唯一不会附加到设备堆栈中的设备对象,因此控制设备对象是唯一的可安全命名的设备对象。
由此,是否为文件系统过滤驱动的控制设备对象是否命名是可选的。
注意:文件系统的控制设备对象必须命名。
过滤设备对象从不命名。
参数DeviceType 代表某种设备类型,其可能的取值均以常量形式定义在ntifs.h中,例如:FILE_DEVICE_DISK_FILE_SYSTEM。
如果向DeviceName传递了一个非空值(Non-NULL),DeviceCharacteristics标识必须包括 FILE_DEVICE_SECURE_OPEN。
该标识指示I/O 管理器对所有发送到控制设备对象的Open请求进行安全检测。
文件系统过滤驱动在分派例程中识别其自身控制设备对象的有效方式为将设备指针与前期存储的全局控制设备对象指针进行比较。
因此上面驱动范例将 IoCreateDevice所返回的设备对象指针存储到了全局变量gSFilterControlDeviceObject中。
需要注意以下几点:
1)习惯使用UNICODE_STRING 字符串。
这些字符串用Rtl…系列的函数来操作。
阅读DDK 帮助,然后熟悉这些字符串的用法。
2)用KdPrint(())来代替printf 输出信息。
这些信息可以在DbgView 中看到。
KdPrint(())自身是一个宏,为了完整传入参数所以使用了两重括弧。
这个比DbgPrint 调用要稍好。
因为在free 版不被编译。
3)查看DDK 帮助了解生成设备对象IoCreateDevice 的用法。
2.4.2注册IRP分派例程
过滤驱动DriverEntry例程中的DriverObject参数提供了一个指向过滤驱动的驱动对象的指针。
为了注册I/O请求包(IRP)的分派例程,必须为主功能码注册分派例程的入口点。
本系统按下列方式设置分派例程入口点:
for (i = 0; i <= IRP_MJ_MAXIMUM_FUNCTION; i++) {
DriverObject->MajorFunction[i] = SfPassThrough;
}
DriverObject->MajorFunction[IRP_MJ_CREATE] = SfCreate;
DriverObject->MajorFunction[IRP_MJ_CREATE_NAMED_PIPE] = SfCreate;
DriverObject->MajorFunction[IRP_MJ_CREATE_MAILSLOT] = SfCreate;
DriverObject->MajorFunction[IRP_MJ_FILE_SYSTEM_CONTROL] = SfFsControl;
DriverObject->MajorFunction[IRP_MJ_CLEANUP] = SfCleanupClose;
DriverObject->MajorFunction[IRP_MJ_CLOSE] = SfCleanupClose;
DriverObject->MajorFunction[IRP_MJ_SET_INFORMATION] = XdDispatch;
DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = XdDeviceCtl;
注意:在上面的For循环为每个IRP主功能码分派例程都分派了默认的分派例程。
这是一个比较好的做法,因为,默认情况下,I/O管理器完成未知IRP并返回STATUS_INVALID_DEVICE_REQUEST。
文件系统过滤驱动在这种方式下不会拒绝未知的IRP,这些请求将发送给低层驱动。
由于这个原因,默认分派例程仅向下层传递IRP。
2.4.3 注册Fast I/O分派例程
过滤驱动DriverEntry例程的DriverObject参数提供了指向过滤驱动驱动对象的指针。
为了注册文件系统过滤驱动的Fast I/O分派例程,必须分配并初始化Fast I/O分派表,向该表中存储Fast I/O分派例程,然后将该分派表的地址存储到驱动对象的FastIoDispatch成员中。
本系统按下述方式为Fast I/O分派例程设置入口点:
RtlZeroMemory( fastIoDispatch, sizeof( FAST_IO_DISPATCH ) );
fastIoDispatch->SizeOfFastIoDispatch = sizeof( FAST_IO_DISPATCH ); fastIoDispatch->FastIoCheckIfPossible = SfFastIoCheckIfPossible;。