在过滤驱动程序创建IRP查询文件信息
文件系统过滤驱动
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请求的进程及线程的相关信息,如:获得发起进程名称,与安全访问规则(进程白名单)中的可信进程相比较,若该进程位于规则中,说明信任其行为是安全的,允许访问受保护文件;否则,拒绝访问。
Windows文件系统过滤驱动开发教程(第二版)
Hale Waihona Puke -1. 改版序大约两年以前我在驱动开发网上发表了一组描述如何开发 Windows 文件系统过滤驱动的文章。非常庆幸这些文章能 给大家带来帮助。
原本的文章中我使用了自己编写的代码。我不打算在这里论述代码风格的优劣并发起一场辩论,无可怀疑的是,读者们 大多喜欢看到类似微软范例的代码。为此我把文章中的代码换成微软标准的文件过滤驱动范例 sfilter 的代码。赠于喜欢此 书的读者和驱动开发的后来者们。
WindowsTDI过滤驱动开发(学习资料)
[版权所有] 本文作者是楚狂人,代码来源于开源工程tdifw与DDK的例子, 有问题欢迎与我联系讨论。
mail:******************* QQ: 16191935 msn:************************----------------------------------------------------------- Windows TDI过滤驱动开发 目 录(0) TDI概要(1) 准备工作(2) TDI设备与驱动入手(3) 绑定设备(4) 简单的处理请求(5) 基础过滤框架(6) 主要过滤的请求类型(7) CREATE的过滤(8) 准备解析ip地址与端口(9) 获取生成的IP地址和端口(10) 连接终端的生成与相关信息的保存(11) TDI_ASSOCIATE_ADDRESS的过滤(12) TDI_CONNECT的过滤(13) TDI_SEND,TDI_RECEIVE,TDI_SEND_DATAGRAM,TDI_RECEIVE_DATAGRAM(14) 设置事件(15) TDI_EVENT_CONNECT类型的设置事件的过滤(16) 一个传说中的问题(17) 收尾与清理的工作(0) TDI概要 最早出现的网络驱动应该是网卡驱动,这是Windows的理所当然的需求,为了进一步分割应用程序的网络数据传输与下层协议直到下层硬件的关系,又出现了协议驱动,后来微软和硬件商联合制定了NDIS标准,作为从硬件到协议的内核驱动程序的调用接口标准,而协议驱动与应用层的API之间,则出现了TDI接口。
最近国内安全软件的开发兴起,网络驱动的开发在其中有不少的应用,如果我们学习TDI接口的话,可能有以下一些目的: 自己要开发协议驱动,向上提供TDI接口,这种可能性存在,但不广泛。
我们想自己调用TDI接口,来进行网络数据传输,意义不大。
我们对TDI进行协议层过滤,开发防火墙或类似安全监控软件,这种应用还是比较多的。
驱动程序打开别的驱动程序创建的Device的几种方法
可以用IoGetDeviceObjectPointer函数通过设别名获得文件对象,而不是设备句柄。调用IoGetDeviceObjectPointer会使文件对象引用计数增加1,用完后可以用ObDerefernceObject减少引用计数值。用这个函数打开的设备得到的是文件对象,所以不能再用ZwReadFile和ZwWriteFile函数去读写设备,这个时候需要自己创建IRP,创建Irp的函数大至有4个,IoBuildSynchronousFsdRequest,IoBuildAsynchronousFsdRequest,IoBuildDeviceIoControlRequest,还有就是IoAllocateIrp!创建后调用IoGetNextIrpStackLocation,和IoCallDriver函数进行发送(这里有个问题,书上说IoCallDriver函数会使Irp堆栈向后移,必须用IoGetNextIrpStackLocation,IoSkipCurrentIrpStackLocation等函数使堆栈向前,我的理解是IoCallDriver函数需要的是下移个堆栈,因此需要这号链接是内核层与应用层的唯一识别路基。应用层想要打开设备,必须通过符号链接,同样内核层打开内核层设别也可以通过符号链接,可以利用ZwOpenSymbolicLinkObject函数得到符号链接句柄,然后使用ZwQuerySymbolicLinkObject得到设备名,有了设备名酒可以通过上面的方法打开设备。这里为什么要这样绕圈子呢,如果你是在应用层去控制一个驱动程序去打开另外一个驱动程序的时候,由于是应用层,是得不到那个驱动程序创建的设备名的,只能得到符号链接,这个时候就必须用这种方法。
驱动程序打开别的驱动程序创建的Device的几种方法
Windows 文件过滤驱动经验总结
P 后什么都不做,直接调用 IoCompleteRequest() 来返回。 (2) 拿到这个 IRP 后什么都不做,直接传递到底层设备,
使用IoSkipCurrentIrpStackLocation() 后调用 IoCallDriver() 传递。 (3) 使用 IoBui
ldSynchronousFsdRequest() 或 IoBuildDeviceIoControlRequest()来建立 IRP 的。
Windows 文件过滤驱动经验总结 1、获得文件全路径以及判断时机 除在所有 IRP_MJ_XXX 之前自己从头创建 IRP
发送到下层设备查询全路径外,不要尝试在 IRP_MJ_CREATE 以外的地方获得全路径,因为只有在 IRP_MJ_CREATE 中才会使
用 ObCreateObject() 来建立一个有效的 FILE_OBJECT。而 在 IRP_READ IRP_WRITE 中它们是直接操作
TION 等 IRP 不要去管它,因为它只是一个过程。最终读 写还是如上所介绍。至于以上这些 IRP 哪个是由 CC MGR 发送的,哪些是由
I/O MGR 发送和在什么时候发送的,这个已经有很多讨论了,相 信可以找到。
7、举例说明关于 IRP 传递与完成注意事项 只
看 Walter Oney 的那本 《Programming the Microsoft Windows driver model》里介绍的
其是你要达到一些特殊目的,这时候更需要注意,如 IRP_MN_QUERY_DIRECTORY,不同的标志结果有很大的不同。 3、从
头建立 IRP 获取全路径注意点 自己从头建立一个 IRP_MJ_QUERY_INFORMATION 的 IRP 获取全路径时需要注意,不
文件系统Minifilter驱动
文件系统Minifilter驱动声明:本系列文章源于WDK,所有权利归原作者所有,翻译的目的只为交流和学习。
除了商用你可以随意地使用这篇译文。
但请不要删除声明。
——by jununfly说明:所有preoperation及postoperation均简写为pre-oper和post-oper所有文件系统过滤驱动均简写为FSFD(文件系统过滤驱动)所有基于IRP的I/O即IRP-based I/O均简写为IRP-I/O版本:20090220Filter管理器和Minifilter驱动架构Filter 管理器是一个内核模式驱动,它遵照legacy文件系统filter模型并具有FSFD必需的功能。
利用这些功能,第三方开发者可以写 minifilter驱动,这样的驱动比legacy(陈旧的) FSFD更易于开发,因此缩短了开发过程同时制造出更高质量、更灵活的驱动。
本章包括:一、Filter管理器概念Filter管理器随Windows一起被安装,但它只在minifilter驱动被加载时才起作用。
Filter管理器被绑定到目标卷的文件系统栈上。
当Minifilter驱动要执行过滤I/O操作时,必须先向filter 管理器注册来间接绑定到文件系统栈上。
Legacy 过滤驱动在文件系统I/O栈中的位置,相对于其他过滤驱动来说是在系统启动时由它的加载顺序组决定的。
例如,一个antivirus过滤驱动在栈中的位置应该高于一个“复制操作”的过滤驱动,因而它能在文件被复制到远程服务器之前探测病毒并消除文件中的病毒。
因此,FSFilter Anti- Virus加载顺序组中的过滤驱动的加载要先于FSFilter Replication组中的过滤驱动。
每一个加载顺序组都有一个相应的系统定义的类和INF文件中要使用的类GUID。
像legacy过滤驱动一样,minifilter驱动的绑定也按照一定的顺序。
不过,绑定顺序是由altitude这个唯一标识符决定。
基于IRP的Windows设备驱动程序文件操作的实现
第23卷第1期2010年2月四川理工学院学报(自然科学版)JournalofSiehuanUniversityofScience&Engineering(NaturalScienceEdition)VoL23No.1Feb.20lO文章编号:1673-1549(2010)01-0041-03基于IRP的Windows设备驱动程序文件操作的实现王兰英,居锦武(四川理工学院计算机学院,四川自贡643000)摘要:文件是数据存储的基础,处于Windows操作系统内核中的设备驱动程序,对文件系统的访问不像应用程序那样方便。
文章介绍了Windows设备驱动程序通过建立自定义I/O请求包(IRP)。
并将IRP发送到文件系统驱动程序的方式。
实现对文件的内核级操作的方法。
该方法可实现文件建立、读、写、删除和改名等功能。
文章给出了基于微软设备驱动程序开发工具实现的IRP包的建立、发送和完成的源码。
关键词:驱动程序开发工具;驱动程序;内核;文件;I/O请求包中图分类号:TP311文献标识码:A引言文件是操作系统的核心,也是数据存储的基础,文件基于磁盘或是半导体闪盘存储,具有非易失性,不会因掉电等原因而导致数据丢失,涉及到硬件的程序经常要将采集的数据或是El志数据存入文件。
微软公司的Windows操作系统工作于CPU的保护模式下,操作系统内核及设备驱动程序工作于0环,称为核心态;应用程序、动态链接库工作于3环,称为用户态。
操作系统通过环级保护来实现对用户态程序的访问权限限制。
工作于核心态的设备驱动程序…是操作系统的信任部件,其访问权限不受任何限制。
Windows操作系统提供了多种多样的API供应用程序实现对文件的操作,如创建、删除、改名、读和写等。
但这些API工作于用户态,只能供应用程序使用,设备驱动程序无法使用。
文章首先简要介绍Windows操作系统的基本结构,然后介绍了在设备驱动程序中通过建立自定义的IRP,并将它发送到文件系统驱动程序,以实现核心态文件操作的方法。
Fiery Command WorkStation 使用手册说明书
Fiery Command WorkStation© 2015 Electronics For Imaging. 此产品的《法律声明》适用于本出版物中的所有信息。
目录概述 (13)Command WorkStation (13)Command WorkStation 工作空间 (13)作业中心 (14)设备中心 (15)添加和连接 Fiery Server (17)访问级别 (17)连接到 Fiery Server (17)添加并连接到 Fiery Server (17)搜索可用的 Fiery Server (18)退出 Fiery Server (18)更改 Fiery Server 的用户 (18)查看其他 Fiery Server (19)服务器列表 (19)自定义 Command WorkStation (22)设置 Command WorkStation 预置 (22)管理作业中心的列 (23)更改列显示 (23)调整列宽度 (23)重新定义窗格和队列大小 (24)重新定义“正在打印”和“正在处理”队列的大小 (24)重新定义“作业摘要”和“服务器列表”窗格的大小 (24)自定义工具栏 (24)默认工具栏图标 (25)配置 Fiery Server 设定 (26)关于 Configure (26)我使用的是哪个版本的 Configure? (26)查找帮助以及有关 Configure 的其他信息 (26)访问基于 Java 的旧版本 Configure 的帮助 (27)访问基于 HTML 的新版本 Configure 的帮助 (27)查看服务器配置设定 (27)将服务器配置保存为文件 (28)打印“服务器配置”页 (28)访问 Configure (28)从 Command WorkStation 访问 Configure (28)从 WebTools 访问 Configure (29)退出 Configure (29)用户与群组 (29)创建新用户 (30)创建群组 (30)将用户添加到现有群组 (31)创建扫描作业的邮箱 (32)从群组中删除用户 (32)更改用户属性 (32)更改群组权限 (33)删除用户或群组 (33)关于备份和恢复 (34)备份或恢复 Fiery Server 设定 (35)管理 Fiery Central 工作流程 (37)关于 Fiery Central (37)连接或断开 Fiery Central 服务器 (37)Fiery Central 服务器工作空间 (38)查看 Fiery Central 作业 (39)自定义 Fiery Central 作业中心 (40)查看或编辑 Fiery Central 许可证 (40)配置 Fiery Central (41)Fiery Central Manager (42)访问 Fiery Central Manager (42)Fiery Central 打印机群组 (42)备份或恢复 Fiery Central (45)使用 Fiery Central Paper Catalog (46)设置 VDP 文件搜索路径 (47)设置 Digital StoreFront 连接 (47)查看作业 (48)Fiery 预览 (48)查看已假脱机、未经处理的作业 (49)页面视图、印张视图和校对视图 (51)“设定”窗格 (52)打开“校对视图” (53)预览中的工具栏图标 (54)预览光栅图 (54)光栅预览中的工具栏图标 (55)在光栅预览中合并页面 (56)VDP 光栅预览 (56)打印 (59)导入要打印的作业 (59)将作业导入打印队列 (59)从外部 Fiery Server存档导入作业 (60)设置打印选项 (60)查看作业属性 (60)“作业属性”窗口中的作业操作 (61)打印选项类别 (62)作业属性中的 Fiery Impose 模板 (62)预设打印设定 (63)服务器预设 (67)从作业移除光栅数据 (70)打印方法 (70)使用纸盘对齐 (70)样本打印 (71)校样打印 (72)按序打印 (73)设置按序打印 (74)在 Configure 中设置按序打印选项 (74)使用 Quick Doc Merge (75)管理作业 (77)搜索作业 (77)使用筛选视图选项卡搜索作业 (77)过滤作业列表 (78)导出作业列表 (78)将作业移至其他队列 (79)将作业发送至另一台 Fiery Server (80)存档作业 (80)拖放文件管理 (81)Fiery JDF 作业 (82)关于 Fiery JDF 和 JMF (82)Fiery JDF 设置 (82)启用 JDF 提交应用程序 (82)Fiery JDF 工作流程 (83)提交 JDF 作业 (83)显示 Command WorkStation 中的 JDF 列标题 (83)Fiery JDF 作业和虚拟打印机 (83)指定作业的 JDF 设定 (84)“作业信息”选项卡 (84)“运行列表”选项卡 (85)“关闭作业”选项卡 (85)将 JDF 作业纸张添加到 Paper Catalog (86)解决 JDF 作业中的纸张冲突问题 (86)Fiery Dashboard (87)创建 EFI 通行证帐户(免费) (87)登录到 Fiery Dashboard (87)Fiery Dashboard 数据收集 (88)授权数据收集 (88)取消数据收集的授权 (88)管理颜色 (89)彩色打印选项 (89)查看或编辑默认颜色设定 (89)特性档 (95)查看特性档属性 (96)比较特性档色域 (96)导入或导出特性档 (96)创建或删除特性档 (98)编辑特性档设定 (99)编辑特性档内容 (99)打印测试页 (101)校准 (pre-System 10) (102)Calibrator 模式 (103)使用 ColorCal 进行校准 (103)使用 ES-1000 进行校准 (105)使用 Eye-One 进行校准 (106)对多个校准集应用测量值 (107)创建或删除自定义校准集 (107)恢复默认测量值 (108)校准(System 10 和更高版本) (108)校准黑白打印 (109)校准工作流程 (109)启动 Calibrator (109)打印校准页 (110)使用分光光度计测量色块 (110)使用 ColorCal 测量色块 (111)从备用测量仪器导入测量数据 (113)查看测量结果 (114)导出测量数据 (115)重设测量数据 (115)Calibrator 预置 (116)校准设定 (117)自定义 Image Enhance 设定 (120)Image Enhance Visual Editor (121)何时使用 IEVE 或 Image Enhance 打印选项 (122)打开大型作业 (122)预设 (122)调整图像 (122)保存对作业的编辑 (122)启动 Image Enhance Visual Editor (123)使用预设 (123)打开大型作业 (124)调整色调 (124)调整颜色 (125)调整清晰度 (126)校正红眼 (127)专色 (127)专色群组和定义 (127)更改专色或颜色组的顺序 (128)查找专色 (129)编辑专色 (129)优化专色 (129)创建、重命名或删除专色或颜色群组 (130)导入和导出自定义颜色群组 (131)查看颜色群组的色域 (131)色版页和色版书 (132)打印专色色板页或色板书 (132)测量和导入专色值 (133)替换颜色 (134)二色打印映射 (135)管理服务器资源 (137)虚拟打印机 (137)创建、编辑或复制虚拟打印机 (137)管理虚拟打印机 (138)从 Windows 打印到虚拟打印机 (139)从 Mac OS 打印到虚拟打印机 (139)Paper Catalog (140)从 Paper Catalog 选择纸张 (141)设置 Paper Catalog (142)管理 Paper Catalog 数据库 (147)纸张属性 (149)常见纸张属性 (149)纸盘关联 (157)纸盘关联显示 (158)将纸张分配给纸盘 (158)智能纸张 (159)监控纸盘中的纸张状态 (161)更改列显示 (161)VDP 资源 (162)管理 FreeForm 主文页 (162)备份 VDP 资源 (163)恢复 VDP 资源 (163)查看并删除全局资源 (164)字体 (164)备份和恢复字体 (165)查看用户和群组权限 (165)访问用户和群组 (166)查看用户和群组权限的详细信息 (166)比较权限 (166)查看或添加群组 (166)访问群组 (167)添加群组 (167)使用作业日志 (167)查看作业日志 (168)打印作业日志 (168)导出作业日志的内容 (168)导出和/或清空作业日志的内容 (169)印刷制版工具 (170)Fiery Graphic Arts 的功能 (170)Fiery Graphic Arts Package (Premium Edition) (170)Fiery Productivity Package (170)控制栏 (171)页面大小和控制栏(FS100/100Pro 或较早版本) (172)默认情况下,在每页打印控制栏 (172)查看和编辑控制栏 (172)创建自定义或重复的控制栏 (173)导出、导入或删除自定义控制栏 (173)恢复出厂默认控制栏设定 (174)陷印 (174)设置所有作业的自动陷印 (174)指定陷印宽度 (175)指定陷印颜色减少 (175)指定陷印形状 (175)指定陷印对象类型 (175)进度 (176)查看或编辑进度设定 (176)校样半色调模拟 (176)查看或编辑自定义半色调网屏 (177)纸色模拟白点编辑 (177)编辑纸色模拟白点值 (178)配置和运行预检 (179)ImageViewer (179)启动 ImageViewer (180)调整图像预览 (180)调整图像的大小 (181)查看图像中的颜色值 (181)显示分色 (181)使用曲线编辑颜色响应或灰度响应 (182)使用颜色轮编辑颜色 (183)通过图像编辑灰度响应曲线 (183)将颜色编辑应用于一个或所有页面 (183)通过本地文件应用颜色编辑 (184)通过服务器预设应用颜色编辑 (184)应用 Curve2/Curve3 文件的颜色曲线 (185)应用灰度响应曲线编辑 (185)打印含编辑内容的作业 (186)将软校样导出为 PDF 格式 (186)比较显示器特性档和输出特性档 (187)在 Fiery Server 上安装当前编辑 (187)在 Fiery Server 上恢复出厂默认响应曲线 (188)设置 ImageViewer 预置 (188)Booklet Maker (189)Booklet Maker 拼版 (189)关于 Booklet Maker 和 Fiery Impose (189)访问 Booklet Maker (189)从打印机驱动程序 访问 Booklet Maker (190)在 Command WorkStation 中访问 Booklet Maker (190)创建小册子 (190)从 Booklet Maker 窗口创建小册子 (190)从 Booklet Maker 向导创建小册子 (191)小册子类型 (192)鞍式装订 (193)套叠式鞍式装订 (194)胶装 (195)一合一 胶装 (196)纸张大小 (197)缩小文档页面大小以适合所选的纸张大小 (198)“缩小至适合”选项 (199)页面对齐 (203)对齐页面 (203)页面对齐和装订线 (206)爬移补偿 (208)采用一合一胶装的混合纸张 (208)在 Booklet Maker 中指定混合纸张设定 (209)在混合纸张中浏览作业 (210)以页面形式查看作业的版面 (210)以印张形式查看作业的版面 (210)Booklet Maker 混合纸张限制 (211)添加 封面 (211)在应用程序中更改文档大小 (212)更改测量单位 (212)预览小册子 (213)小册子工作流程示例 (213)打印胶装小册子 (213)打印鞍式装订小册子 (213)打印套叠式鞍式装订小册子 (214)Booklet Maker 限制 (214)Booklet Maker 词汇表 (215)索引 (219)概述Command WorkStationCommand WorkStation 是 Fiery Server的打印作业管理界面。
文件过滤的一点总结
文件系统驱动文件系统驱动主要生成两类设备:文件系统控制设备,文件系统的卷设备文件系统控制设备:主要任务是修改整个驱动的内部配置文件系统的卷设备:一个卷对应一个逻辑盘发送给控制设备的请求(IRP),一般是文件系统控制IRP(主功能号为IRP_MJ_FILE_SYSTEM_CONTROL);发送给卷设备的IRP一般则是文件操作IRP。
过滤的目标最终是为了得到文件操作的IRP,但是控制设备的IRP,一般用来捕获卷设备的生成信息,所以我们要先绑定文件系统的控制设备,达到绑定文件系统的卷设备的目的~~(1)生成自己的一个控制设备,当然必须给控制设备指定名称(2)设置普通分发函数(3)设置快速IO分发函数(4)编写一个文件系统变动回调函数,在其中绑定刚激活的文件系统控制设备(动态绑定)(5)使用IoRegisterFsRegistrationChange调用注册这个回调函数文件系统控制设备的绑定过滤设备扩展typedef struct _SFILTER_DEVICE_EXTENSION {ULONG TypeFlag;//// 绑定的文件系统设备(真实设备)//PDEVICE_OBJECT AttachedToDeviceObject;//// 与文件系统设备相关的真实设备(磁盘),这个在绑定时使用////PDEVICE_OBJECT StorageStackDeviceObject;////// 如果绑定了一个卷,那么这是物理磁盘卷名;否则这是绑定的控制设备名////UNICODE_STRING DeviceName;//// 用来保存名字字符串的缓冲区//WCHAR DeviceNameBuffer[MAX_DEVNAME_LENGTH];//// The extension used by other user.//UCHAR UserExtension[1];} SFILTER_DEVICE_EXTENSION, *PSFILTER_DEVICE_EXTENSION;绑定文件系统控制设备SfAttachToFileSystemDevice文件系统控制设备已经被绑定,绑定的目的是为了获得发送给文件系统控制设备的文件系统控制请求。
文件过滤驱动
读写过滤
读操作
文件的长度: Length = IrpSp->Parameters.Read.Length;
文件的偏移量: Offser.QuadPart = IrpSp->Parameters.Read.ByteOffset.QuadPart
文件内容: Irp-> MdlAddress不为空,则使用Irp-> MdlAddress,缓冲区位置为MmGetSystemAddressForMdlSafe(Irp-> MdlAddres),否则直接使用Irp-> UserBuffer
重要技术难点
缓存管理
单缓存
合法进程打开存在文件,关闭文档,明文保存在缓存, 此时缓存没有刷 至硬盘,也没有清空内存中的资源。此时非法进程再打开文档,在 IRP_MJ_CREATE例程会刷新缓存操作,所以非法进程打开为乱码 合法进程打开存在文件,明文保存在缓存, 此时缓存没有刷至硬盘,也 没有清空内存中的资源。此时非法进程再打开文档,如果是word这种占着句 柄没有关闭的文档,判断为非法进程,禁止打开;如果是notedpad采用内存 映射文件的方式的,句柄关闭,则非法进程打开正在被合法进程打开的文档 ,在IRP_MJ_CREATE例程会刷新缓存操作,所以非法进程打开为乱码 非法进程打开未打开过的加密文档,密文。合法进程再打开加密文档,会先 刷新缓存。 合法进程打开加密文档,在关闭的时候在IRP_MJ_CLEANUP例程中对新 建的文件才刷新缓存
而且有些程序的文件格式没有定式,甚至可以保存为任意后缀,例如记 事本,这样加密指定的文件后缀就带来了安全漏洞。
2、加密不区分后缀: 加密不区分后缀是指保密程序对生成的所有文件都进行加密。这种加密
Windows下文件过滤驱动技术
Windows下文件过滤驱动技术徐国栋;朱亮【摘要】Windows文件过滤驱动在不改变复杂的文件系统基础上,可方便地扩展FO子系统的功能.在深入研究了文件过滤驱动技术基础上,结合安全加密技术与权限控制技术,实现了一个安全、易用、管理方便的安全文件系统.【期刊名称】《微型电脑应用》【年(卷),期】2016(032)008【总页数】3页(P74-75,80)【关键词】文件过滤驱动;I/O请求包;基于角色的访问控制【作者】徐国栋;朱亮【作者单位】上海其祥电脑系统工程有限公司上海200237;北京科瑞科技发展股份有限公司上海,100097【正文语种】中文【中图分类】TP183随着企事业单位的快速发展,电子文档为企事业单位承载了越来越多的重要信息。
而由于电子文档的容易散播性,导致企事业单位的重要资料很容易被非法获取、篡改、乃至无序传播等,这使得企事业单位所做的大量工作付之东流,严重危害了自身的利益。
特别是棱镜门事件后,文档安全的重要性也日益受到重视。
文件安全管理就是为了提高电子文档数据的安全性和保密性、防止秘密数据被意外、或非法获取所采用的技术手段。
密码学是信息系统安全的核心,它是研究密码系统和通信安全的一门学科[1]。
密码学的基本功能是提供保密性,使非授权者无法获悉消息的内容。
Windows的I/O管理器是一个可扩展的结构,通过开发过滤驱动程序可以扩展I/O子系统的功能。
I/O管理器支持分层驱动程序模型,每个I/O请求包(IRP,I/O request package)的处理分别经过各层驱动程序,直到某层驱动程序完成这个请求[2]。
1.1 过滤驱动程序过滤驱动工作在系统驱动层和应用层之间,透明地截取发往低级驱动程序设备对象的请求,低级驱动程序的用户完全不知道它们的请求被过滤器驱动程序预处理和截取了。
使用过滤器驱动程序可以实现以下几种主要功能:允许修改已有驱动程序在某些方面的行为,而不必重写整个驱动程序。
MiniFilter文件过滤第一讲文件过滤框架以及安装方式
MiniFilter⽂件过滤第⼀讲⽂件过滤框架以及安装⽅式⽬录MiniFilter⽂件过滤第⼀讲⽂件过滤框架以及安装⽅式⼀⼂MiniFilter ⽂件过滤框架1.1 简介MiniFilter是微软为我们开发的⼀个新的驱动,称为过滤管理器.(Filter Manager或者 fltmgr).这个驱动主要作⽤就是如果有⽂件操作可以通知我们. MiniFilter的优点和不⾜如下:优点:1.增加开发速度2.不⽤关⼼IRP处理⼯作,这些交给 Filter Manager处理即可.不⾜:MiniFilter开发的时候虽然简单了但是隐藏了很多细节.⽐如设备对象等等.如果使⽤以前的⽅式进⾏开发那么就如同 C语⾔内嵌汇编对兼容性不好也失去了MiniFilter的意义.1.2 MiniFilter框架框架如下:在IO管理器中我们的 MiniFilter会去进⾏注册. 如上图所⽰. 有 A B C三个.⽽MiniFilter中最重要的是⾼度值(Altitude) 不光有⾼度值还有分组.⽐如A的分组就在FSFilter Activity Monitor B在FSFilter Anti-Virus也就是反病毒层级. ⾼度越⾼越会被先执⾏.假设你拦截了⽂件访问你可以不发送给下⼀层. 这样 B C 就接受不到了. 所以这个⾼度值需要我们找微软申请.(但是不申请好像也能⽤.只要不影响即可)⾼度值是从20000 ~ 429999的.⽽⾼度值⼜有分组. 所以⾼度值不能乱写.⼀般就是每个分组有个⾼度值范围.查询地址如下:⼆⼂MiniFilter 编程框架2.1 简介对应到程序来说 MiniFilter是很简单的. 只需要三个内核API就可以使⽤MiniFilter了.⽽API中所需要的参数就是结构体. 所以我们搞清楚结构体中的参数就可以了. 其实就是往结构体⾥⾯填写东西即可.内核API如下:NTSTATUSFltRegisterFilter(IN PDRIVER_OBJECT Driver,IN CONST FLT_REGISTRATION *Registration,OUT PFLT_FILTER *RetFilter);NTSTATUSFltStartFiltering(IN PFLT_FILTER Filter);VOIDFltUnregisterFilter(IN PFLT_FILTER Filter);API就三个. 分为注册启动卸载其中启动和卸载都是⼀个参数.就是Filter句柄.此句柄是从FltRegisterFilter第三个参数传出的. 所以主要学习的就是第⼀个.此函数有三个参数参数1 Driver 在DDK驱动中的 DriverEntry中的驱动对象.参数2 ⼀个结构体此结构体就是我们要了解的结构体.下⾯说.参数3 传出的句柄. ⽂件管理器的句柄. 注册成功后会传出句柄给启动和卸载函数使⽤.2.2 FLT_REGISTRATION 结构体在我们的注册函数中有次结构体. 此结构体如下:typedef struct _FLT_REGISTRATION {USHORT Size; @1 指向⾃⾝的⼤⼩sizeof(FLT_REGISTRATION).USHORT Version; 版本必须设置为FLT_REGISTRATION_VERSIONFLT_REGISTRATION_FLAGS Flags; 标志 @1CONST FLT_CONTEXT_REGISTRATION *ContextRegistration; 上下⽂@2CONST FLT_OPERATION_REGISTRATION *OperationRegistration;PFLT_FILTER_UNLOAD_CALLBACK FilterUnloadCallback;PFLT_INSTANCE_SETUP_CALLBACK InstanceSetupCallback;PFLT_INSTANCE_QUERY_TEARDOWN_CALLBACK InstanceQueryTeardownCallback;PFLT_INSTANCE_TEARDOWN_CALLBACK InstanceTeardownStartCallback;PFLT_INSTANCE_TEARDOWN_CALLBACK InstanceTeardownCompleteCallback;PFLT_GENERATE_FILE_NAME GenerateFileNameCallback;PFLT_NORMALIZE_NAME_COMPONENT NormalizeNameComponentCallback;PFLT_NORMALIZE_CONTEXT_CLEANUP NormalizeContextCleanupCallback;#if FLT_MGR_LONGHORNPFLT_TRANSACTION_NOTIFICATION_CALLBACK TransactionNotificationCallback;PFLT_NORMALIZE_NAME_COMPONENT_EX NormalizeNameComponentExCallback;#endif // FLT_MGR_LONGHORN} FLT_REGISTRATION, *PFLT_REGISTRATION;含义如下:成员含义说明是否重点⚪了解√号重点 ×极少或不使⽤Size⼤⼩指向⾃⾝的⼤⼩ sizeof(FLT_REGISTRATION)⚪Version版本必须设置为 FLT_REGISTRATION_VERSION⚪Flags标志两种设置,设置为NULL或者 FLTFL_REGISTRATION_DO_NOT_SUPPORT_SERVICE_STOP 设置为STOP的时候 MinniFilter停⽌服务的时候不会进⾏卸载不管你的卸载函数是否设置⚪ContextRegistration上下⽂注册处理上下⽂的函数如果注册了则结构体数组的最后⼀项必须设置为 FLT_CONTEXT_END⚪OperationRegistration回调函数集重点中的重点,主要学习的就是这个域怎么设置. 是⼀个结构体数组可以设置我们感兴趣的回调. 最后⼀项设置为 IRP_MJ_OPERATION_END√FilterUnloadCallback卸载函数卸载MiniFilter回调.如果flags = xx_STOP 那么不管你是否设置都不会卸载√InstanceSetupCallback 卷实例加载回调当⼀个卷加载的时候MiniFilter会为其⽣成⼀个实例并且绑定,⽐如移动硬盘接⼊的时候就会⽣成⼀个实例. 可以设置为NULL.⚪InstanceQueryTeardownCallback 控制实例销毁函数这个实例只会在⼿⼯解除绑定的时候会来.⚪InstanceTeardownStartCallback实例销毁函数当调⽤的时候代表已经解除绑定,可以设置为NULL⚪InstanceTeardownCompleteCallback 实例解绑定完成函数当确定时调⽤解除绑定后的完成函数,可以设置为NULL.⚪GenerateFileNameCallback⽂件名字回调⽣成⽂件名可以设置回调,可以设置为NULL.⚪NormalizeNameComponentCallback查询WDK⚪×NormalizeContextCleanupCallback查询WDK⚪×TransactionNotificationCallback查询WDK⚪×NormalizeNameComponentExCallback查询WDK ⚪×成员含义说明是否重点⚪了解√号重点 ×极少或不使⽤其实本质就是学习回调函数集他是⼀个对象数组.我们看下它的结构吧.typedef struct _FLT_OPERATION_REGISTRATION {UCHAR MajorFunction;FLT_OPERATION_REGISTRATION_FLAGS Flags;PFLT_PRE_OPERATION_CALLBACK PreOperation;PFLT_POST_OPERATION_CALLBACK PostOperation;PVOID Reserved1;} FLT_OPERATION_REGISTRATION, *PFLT_OPERATION_REGISTRATION;参数1 指明的你想监控的IRP操作参数2 是个标志参数3 是你执⾏的监控回调 pre代表的意思是先前回调. ⽐如⽂件创建还未创建之前调⽤你参数4 监控后回调. ⽂件创建完会调⽤的回调参数五保留参数给NULL即可.IRP可以监控很多这个查询WDK⽂档即可.这⾥说⼀下标志标志如下:标志含义FLTFL_OPERATION_REGISTRATION_SKIP_CACHED_IO使⽤此标志代表了不对缓存的IO处理进⾏ pre和post函数操作适⽤于快速IO 因为所有快速IO已经缓存FLTFL_OPERATION_REGISTRATION_SKIP_PAGING_IO指定不应该为分页操作的IO进⾏回调操作.对于不是基于IRP的io操作都会跳过.不会调⽤我们的函数看着⽐较蒙对吧. 那我说⼀下. 其实在我们写⼀个⽂件的时候并不是直接写⼊到磁盘中.⽽是先写到缓存中的. 缓存在写到内存中的.调⽤链⼤概如下:APP->IO->FSD->Cache->MM->IO->FSD->DISk 第⼀种APP->IO->FSD->DISk 第⼆种第⼀种就是先写到缓存中,当满⾜1024个字节的时候再由MM发起IO请求.然后在通知⽂件系统最好写道磁盘中.第⼆种就是直接通过IO到⽂件系统,然后写⼊到磁盘中.如果频繁读写是影响效率的.所以对于第⼀种不是IRP发起的请求我们都可以忽略掉.所以这两个标志的意思就是差不多这个意思.2.3 pre回调和post回调pre回调函数原型如下:typedef FLT_PREOP_CALLBACK_STATUS(*PFLT_PRE_OPERATION_CALLBACK) (__inout PFLT_CALLBACK_DATA Data,__in PCFLT_RELATED_OBJECTS FltObjects,__deref_out_opt PVOID *CompletionContext);post回调函数如下:typedef FLT_POSTOP_CALLBACK_STATUS(FLTAPI *PFLT_POST_OPERATION_CALLBACK) (__inout PFLT_CALLBACK_DATA Data,__in PCFLT_RELATED_OBJECTS FltObjects,__in_opt PVOID CompletionContext,__in FLT_POST_OPERATION_FLAGS Flags);2.3.1 pre返回值和post返回值⾸先说⼀下返回值pre返回值如下返回值含义是否是重点FLT_PREOP_SUCCESS_WITH_CALLBACK完成回调的调⽤并且callbackData往下发,post中可以使⽤CallbackData√FLT_PREOP_SUCCESS_NO_CALLBACK完成回调,不带参数往下发.√FLT_PREOP_PENDING挂起FLT_PREOP_DISALLOW_FASTIO禁⽤FastioFLT_PREOP_COMPLETE完成回调,不会往下发√FLT_PREOP_SYNCHRONIZE同步其实主要就是三个常⽤的就是FLT_PREOP_SUCCESS_WITH_CALLBACK和FLT_PREOP_COMPLETEPOST回调返回值含义是否常⽤FLT_POSTOP_FINISHED_PROCESSING完成,筛选器管理器将继续完成 I/O 操作的处理。
文件系统过滤驱动教程
创建一个简易的文件系统过滤驱动
开始之前
要想编译一个驱动,你需要 WDK 或者 IFS 开发包。 你可以从微软的网站获取它们。另外,你 不得不设置一个环境变量%WINDDK%来指向你安装 WDK/IFS 开发包的路径。 注意:每一个小的错误可能导致蓝屏死机或者系统不稳定。
Main.c
Driver entry
这是如何驱动的入口点。我们要做的第一件事是存储到 DriverObject 一个全局变量中(我 们一会儿就要使用它)。
Collapse code snippet Copy Code
//////////////////////////////////////////////////////// // Global data
{ ...
for (;;) { IoEnumerateDeviceObjectList( DriverObject, devList, sizeof(devList), &numDevices);
if (0 == numDevices) { break; }
numDevices = min(numDevices, RTL_NUMBER_OF(devList));
Collapse Copy Code
////////////////////////////////////////////////////////////////////////// // Global data
FAST_IO_DISPATCH g_fastIoDispatch = { sizeof(FAST_IO_DISPATCH), FsFilterFastIoCheckIfPossible, ... }; ////////////////////////////////////////////////////////////////////////// // DriverEntry - Entry point of the driver
IRP原理以及派遣函数基本工作流程
IRP原理以及派遣函数基本工作流程IRP(I/O Request Packet)原理是指在Windows内核中,用于进行输入输出操作的基本数据结构。
IRP原理的设计目标是将不同类型的I/O 请求抽象为统一的数据结构,从而方便内核进行统一处理。
IRP的基本组成部分包括标志位(Flags)、类型(Type)、大小(Size)、关联设备对象(RelatedDeviceObject)、关联文件对象(AssociatedFileObject)、请求标识(RequestorMode)、当前栈位置(CurrentStackLocation)等。
其中,请求标识用于确定请求是由用户模式代码发起还是由内核模式代码发起;当前栈位置则用于指示当前处理该请求的驱动程序所在的栈位置。
IRP的派遣函数是用于将IRP分派给驱动程序来处理的函数。
派遣函数的基本工作流程如下:1. 当用户模式代码发起一个I/O请求时,Windows内核将根据请求的类型等信息构造一个IRP,并将其插入到相关的驱动程序设备对象的IRP队列中。
2.当IRP到达驱动程序的派遣函数时,派遣函数首先需要检查当前栈位置是否是最后一个栈位置。
如果不是,则将栈位置指向下一个栈位置,然后根据IRP的类型执行相应操作。
3.根据IRP的类型,派遣函数可以执行各种不同的操作,例如打开文件、读写数据、关闭文件等。
如果需要进行物理设备的访问,派遣函数将构造相应的参数,例如建立缓冲区、设置传输模式等。
4.在执行完相应操作后,派遣函数将会更新IRP的各个字段,例如修改IRP的状态、更新已传输的数据长度等。
总结来说,IRP原理是通过定义统一的数据结构,将各种不同类型的I/O请求抽象为一个标准格式,从而方便内核进行统一处理。
IRP的派遣函数则是用于将IRP分派给驱动程序进行处理的函数,它根据IRP的类型执行相应的操作,并根据需要调用完成例程来进行后续处理。
通过IRP原理和派遣函数,Windows内核可以实现统一的I/O管理和处理机制,提高I/O操作的效率和可靠性。
文件过滤驱动加载过程
文件过滤驱动学习笔记(二)1.概述刚学习文件系统过滤时只是做一些简单的应用也没有深究其中的细节;说起来对文件系统过滤也只是一知半解惭愧的很。
后与人讨论发现很多细节自己很模糊;比如其中涉及的驱动对象之间的区别、卷设备加载对文件过滤驱动的影响等。
自己还是需要仔细研究一下,最近查了一些官方及前辈们的资料似乎有些理解在此记录下来做个笔记。
2.相关对象说明在文件过滤驱动学习中会遇到几种设备对象总是混淆。
最近硬着头皮查阅DDK才有些理解。
2.1.存储设备(Storage Device)存储设备可以理解为一个磁盘、一个CD;它可以物理的也可以是逻辑的,它上边可以有一个或多个卷设备对象。
大多数存储设备是一个PnP设备,它们由PnP管理器加载。
存储设备表现为PnP设备树(PnP Device Tree)上的一个节。
注意:文件系统驱动和文件系统过滤驱动都不是PnP设备驱动。
2.2.存储卷(Storage Volume)存储卷是一个存储设备如固定磁盘,软盘,CD盘,格式化后存储的目录与文件。
一个很的大卷可以被分成一个或多个逻辑卷;每一个卷都会被格式化成指定的一种格式,如NTFS,FA T等。
它通常是一个物理设备对像(PDO)。
它与文件系统卷对象是不同的。
2.3.文件系统卷设备对象(File System VDO)一个存储卷被文件系统加载时就会产生一个文件系统卷设备对像(File System VDO);它总是与指定的逻辑或物理设备相联结(这里我理解应该是说它总是代表了一种数据存储及组织格式,也就是我们常说的FA T和NTFS)。
文件系统过滤驱动就是要附加到这种设备对象上过滤读写相关的操作。
DDK上说文件系统卷设备对象是不需要命名的,因为给它命名会带来安全隐患;这点没有太理解还需要再查阅一些资料。
2.4.文件系统控制设备对象(File System CDO )文件系统控制设备对象是一个文件系统的入口,它不是单个的卷并且它是存储在全局文件系统队列里的。
#Windows文件系统过滤器之微过滤器驱动开发指南
微过滤器驱动开发指南0.译者序对我来说,中文永远是最美,最简洁,最精确和最高雅的文字。
本文翻译仅仅用做交流学习。
我不打算保留任何版权或者承担任何责任。
不要引用到赢利出版物中给您带来版权官司。
本文的翻译者是楚狂人,如果有任何问题,,或者是QQ16191935,或者是MSN 。
我翻译此文出于对文件系统技术的兴趣。
这就是新的文件系统过滤接口。
其实也不算什么新的东西,微软开发了另一个“旧模型的”过滤驱动,称之为过滤管理器<Filter Manager)。
从而提供了一系列新的接口来让你开发新的过滤器。
确实这套接口变简单清晰了。
你至少避免了包含无数个信息的IRP,避免了请求在各个部件中循环的发来发去,一个分发例程中处理无数中情况,一不小心系统崩溃。
我不知道花了多少时间才弄明白一个简单的缓冲读请求从用户到过滤到文件系统和缓冲管理器,虚拟内存管理器之间的关系!现在你也许不需要再管他们了,仅仅做好自己的过滤工作就可以。
这套接口强大吗?能实现你想要的功能吗?你很快就发现你没有研究过sfilter就看不懂Minifilter,或者是还得从sfilter开始做起更灵活一点。
微软就是这样,拿僵硬而且也不简单的东西来“简化”强大灵活但是设计上一团糟的东西,对于你来说是两者都必须学习,最后你的脑子被微软塞得满满的,不过没关系,我们已经习惯了.此文的原文是《Filter Driver Development Guide》,出自微软的网站。
我在以下这个地址下载得到此文:我尽量在翻译中使文章保持原貌。
如果您认为此文无法理解,建议您首先阅读旧的文件过滤驱动的相关资料。
我认为必须有文件系统和windows驱动的相关知识,才能阅读此文。
我未必总是使用规范的名词,但我总是使用最容易理解的名词。
一些常用的可能不翻译,比如IRP,MDL,有驱动开发经验的人应该可以理解。
另一些可能采用中文<英文)的方式。
一些解释如下:例程<Routine):我不懂得例程和函数有什么不同。
实现一个具有还原功能的磁盘卷过滤驱动
实现⼀个具有还原功能的磁盘卷过滤驱动磁盘过滤驱动的概念1.设备过滤和类过滤在之前的⽂章⾥,我们已经介绍过滤的概念,所谓过滤技术就是在本来已有的设备栈中加⼊⾃⼰的⼀个设备。
由于Windows向任何⼀个设备发送IRP请求都会⾸先发送给这个设备所在设备栈的最上层设备,然后再依次传递下去,这就使得加⼊的设备在⽬标设备之前获取Irp请求称为可能,这时候就可以加⼊⾃⼰的处理流程。
在这⾥把插⼊设备栈的⽤户设备叫做过滤设备,建⽴这个设备并使其具有特殊功能的驱动叫做过滤驱动。
在前⾯已经展⽰了如何去建⽴⼀个过滤设备并将其绑定在⼀个有名字的设备上,这叫做设备过滤,这是对某个特定设备加以过滤的⽅法。
但是在实际应⽤中,这种⽅法还存在⼀些问题,例如,Windows中有很多即插即⽤设备,如何在这些设备加⼊系统的时候就⾃动对他们进⾏绑定呢?实际上,在Windows的过滤驱动框架中,还有⼀种叫做类过滤驱动的驱动程序,能够在某⼀类特定的设备建⽴时有Pnp Manager调⽤指定的过滤驱动代码,并且允许⽤户对此时这⼀类设备进⾏绑定。
根据⽤户设备在整个设备栈中的位置可以分为上层过滤和下层过滤。
2.磁盘设备和磁盘卷设备过滤驱动在Windows的存储系统中,最底层的是磁盘,⽽在磁盘上⾯⼜有卷,卷虽然只是逻辑上的⼀个概念,但是Windows仍然为其建⽴了设备,所以在Windows的存储系统⾥有磁盘设备和磁盘卷设备两种类型的设备。
如果⼀个磁盘卷位于某个磁盘上,那么对于磁盘卷的访问最终也会体现在相应的磁盘上。
但是这并不意味着他们在⼀个设备栈上,irp不会原封不动从磁盘卷设备栈上⼀直传到磁盘设备栈上,更何况Windows中还存在着跨磁盘的卷,软RAID卷等不能对应到唯⼀磁盘上的卷。
从驱动的⾓度上来讲,这两种设备受到读/写请求都是针对与磁盘⼤⼩或者卷⼤⼩范围之内的请求,都是以扇区⼤⼩对齐,处理起来也没有什么太⼤的区别。
在此我们选⽤磁盘卷设备的上层类过滤驱动。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
在开发Windows下文件系统过滤驱动程序时,我们经常需要先查询一下文件的属性信息,为了实现这个小目标,可以调用Windows Native API函数ZwQueryInformationFile并提供希望查询的文件信息类的名字及结构即可。
不过如果我们在驱动程序当中自己处理信息查询请求,可以避免IRP重入的问题。
1.自己创建文件信息查询IRPNTSTA TUSQueryFileInformation(PDEVICE_OBJECT DeviceObject,PFILE_OBJECT FileObject,FILE_INFORMA TION_CLASS FileInformationClass,PVOID FileInfo,ULONG FileInfoLength){PIRP Irp;KEVENT event;IO_STA TUS_BLOCK IoStatusBlock;PIO_STACK_LOCA TION IoStackLocation;//// Initialize the event//KeInitializeEvent(&event, NotificationEvent, FALSE);//// 分配一个IRP,用目标设备对象的StackSize作为新创建IRP的堆栈大小,这是// 标准的提供堆栈大小的方法。
//Irp = IoAllocateIrp(DeviceObject->StackSize, FALSE);if (!Irp)return FALSE;//// 设置IRP头的相关参数,由于我们采用IoAllocateIrp创建的IRP,因此很多// 域要自己设置,包括安装输入缓冲区,同步事件以及IRP标志字段,这个字段// 对文件信息查询没有太大的用处,对文件读写十分关键。
//Irp->AssociatedIrp.SystemBuffer = FileInfo;Irp->UserEvent = &event;Irp->UserIosb = &IoStatusBlock;Irp->Tail.Overlay.Thread = PsGetCurrentThread();Irp->Tail.Overlay.OriginalFileObject = FileObject;Irp->RequestorMode = KernelMode;Irp->Flags = 0;//// 设置IRP堆栈位置中的相关参数,最重要的是MajorFunction,它决定了这个// IRP的主要功能,另外Parameters.QueryFile.FileInformationClass定义了// 希望查询哪种文件信息。
//IoStackLocation = IoGetNextIrpStackLocation(Irp);IoStackLocation->MajorFunction = IRP_MJ_QUERY_INFORMA TION;IoStackLocation->DeviceObject = DeviceObject;IoStackLocation->FileObject = FileObject;IoStackLocation->Parameters.QueryFile.Length = FileInfoLength;IoStackLocation->Parameters.QueryFile.FileInformationClass = FileInformationClass;//// 安装IRP完成例程//IoSetCompletionRoutine(Irp, QueryFileInformationCompleted, 0, TRUE, TRUE, TRUE);(void) IoCallDriver(DeviceObject, Irp);//// 等待同步时间返回,我们在IRP的完成例程当中将事件置为信号态//KeWaitForSingleObject(&event, Executive, KernelMode, TRUE, 0);return( NT_SUCCESS( IoStatusBlock.Status ));}NTSTA TUSQueryFileInformationCompleted(PDEVICE_OBJECT DeviceObject,PIRP Irp,PVOID Context){//// Copy the status information back into the "user" IOSB.//*Irp->UserIosb = Irp->IoStatus;if( !NT_SUCCESS(Irp->IoStatus.Status) ) {DbgPrint(("QueryFileInformationCompleted ERROR ON IRP: %x\n", Irp->IoStatus.Status ));}//// 在完成例程中设置同步事件为信号态。
//KeSetEvent(Irp->UserEvent, 0, FALSE);//// 在完成例程里需要自己释放刚刚创建的IRP,因为I/O管理器不会为我们做这个工作//IoFreeIrp(Irp);//// 我们返回STA TUS_MORE_PROCESSING_REQUIRED,就是告诉I/O管理器这个IRP 还有其它// 的进程在访问,请不要将其删除,事实上这个IRP应该由我们自己来释放而不是I/O // 管理器,所以在自己创建的IRP的完成例程当中必须返回这个值。
另外,这个我们不// 能为这个IRP调用IoCompleteRequest。
//return STA TUS_MORE_PROCESSING_REQUIRED;}2.文件基本信息类在IFS中的定义如下:typedef struct _FILE_BASIC_INFORMA TION { // ntddk wdm nthal LARGE_INTEGER CreationTime; // ntddk wdm nthal LARGE_INTEGER LastAccessTime; // ntddk wdm nthal LARGE_INTEGER LastWriteTime; // ntddk wdm nthal LARGE_INTEGER ChangeTime; // ntddk wdm nthal ULONG FileAttributes; // ntddk wdm nthal} FILE_BASIC_INFORMA TION, *PFILE_BASIC_INFORMA TION; // ntddk wdm nthal该结构包含了文件的创建时间以及修改时间等等,另外,文件属性域FileAttributes包含了用来记录该文件的属性,包括是否系统文件、隐藏文件等等,这个字段可能是如下标记的组合:#define FILE_A TTRIBUTE_READONLY0x00000001 // 只读#define FILE_A TTRIBUTE_HIDDEN 0x00000002 // 隐藏#define FILE_A TTRIBUTE_SYSTEM 0x00000004 // 系统#define FILE_A TTRIBUTE_DIRECTORY0x00000010 // 目录#define FILE_A TTRIBUTE_ARCHIVE 0x00000020 // 流#define FILE_A TTRIBUTE_DEVICE 0x00000040 // 设备#define FILE_A TTRIBUTE_NORMAL 0x00000080 // 正常#define FILE_A TTRIBUTE_TEMPORARY0x00000100 // 临时#define FILE_A TTRIBUTE_SPARSE_FILE 0x00000200 // 稀疏文件#define FILE_A TTRIBUTE_REPARSE_POINT 0x00000400 //#define FILE_A TTRIBUTE_COMPRESSED 0x00000800 // 压缩#define FILE_A TTRIBUTE_OFFLINE 0x00001000 //#define FILE_A TTRIBUTE_NOT_CONTENT_INDEXED 0x00002000 //#define FILE_A TTRIBUTE_ENCRYPTED 0x00004000 // 加密,仅NTFS5以后有效#define FILE_A TTRIBUTE_V ALID_FLAGS 0x00007fb7#define FILE_A TTRIBUTE_V ALID_SET_FLAGS 0x000031a7所以我们可以通过测试成功打开的文件的基本信息中的属性字段就能够判断该文件的性质。
函数定义如下:NTSTA TUSQueryFileBasicInformation(PDEVICE_OBJECT DeviceObject,PFILE_OBJECT FileObject,PFILE_BASIC_INFORMA TION FileBasicInfo,ULONG FileInfoLength){return QueryFileInformation(DeviceObject,FileObject,FileBasicInformation,FileBasicInfo,FileInfoLength);}调用实例:FileBasicInfo = ExAllocatePoolWithTag(NonPagedPool, sizeof(FILE_BASIC_INFORMA TION), FIL TER_POOL_FLAG);if(!FileBasicInfo)FreeFullPathNameBuffer(AnsiPathName, fullPathName);ExFreePool(FileCtx);return CompleteRequest(Irp, STA TUS_INSUFFICIENT_RESOURCES, 0); }Status = QueryFileBasicInformation(hookExt->FileSystem,FileObject,FileBasicInfo,sizeof(FILE_BASIC_INFORMA TION));if(!NT_SUCCESS(Status)){ExFreePool(FileBasicInfo);Irp->IoStatus.Status = Status;IoCompleteRequest(Irp, IO_NO_INCREMENT);return Status;}if(FileBasicInfo->FileAttributes & FILE_A TTRIBUTE_SYSTEM){ExFreePool(FileBasicInfo);Irp->IoStatus.Status = STA TUS_SUCCESS;IoCompleteRequest(Irp, IO_NO_INCREMENT);return Status;}if(FileBasicInfo->FileAttributes & FILE_A TTRIBUTE_ENCRYPTED){ExFreePool(FileBasicInfo);Irp->IoStatus.Status = STA TUS_SUCCESS;IoCompleteRequest(Irp, IO_NO_INCREMENT);return Status;}if(FileBasicInfo->FileAttributes & FILE_A TTRIBUTE_DIRECTORY){ExFreePool(FileBasicInfo);Irp->IoStatus.Status = STA TUS_SUCCESS;IoCompleteRequest(Irp, IO_NO_INCREMENT);return Status;}ExFreePool(FileBasicInfo);3.标准文件信息定义如下:typedef struct _FILE_STANDARD_INFORMA TION { // ntddk wdm nthal LARGE_INTEGER AllocationSize; // ntddk wdm nthal LARGE_INTEGER EndOfFile; // ntddk wdm nthal ULONG NumberOfLinks; // ntddk wdm nthal BOOLEAN DeletePending; // ntddk wdm nthal BOOLEAN Directory; // ntddk wdm nthal} FILE_STANDARD_INFORMA TION, *PFILE_STANDARD_INFORMA TION; // ntddk wdm nthalAllocationSize是文件创建时或者文件修改以后文件系统为该文件分配的磁盘空间的大小,这个值一般是物理扇区大小的整数倍,并且比文件的实际大小要大,如果文件的实际大小超过这个值,则文件系统会自动将这个值扩大以满足文件增大的需要。