一. 概述
Windows操作系统中,文件系统过滤驱动的过滤设备绑定在文件系统(FSD)设备之上,监视和过滤我们的文件访问。当应用层发起文件操作调用时内核层都会转换为IRP发送到设备栈中位于栈顶的设备,然后通过IO栈单元(IO_STACK_LOCATION)保存一些参数把IRP请求继续向下层设备发送,最后至FSD,由FSD完成实际的文件操作。卷参数块(VPB)保存了文件系统中在一个卷设备创建(卷的挂载)成功时的一些卷参数信息。wdm.h中对其结构定义如下:
文件系统过滤驱动对文件操作的过滤,实际上就是把过滤设备绑定在文件系统卷设备: Vpb->DeviceObject上来实现过滤的。
这里要总结的是:如何在内核层自己创建并填写IRP及下层栈单元,把请求直接送往FSD的卷设备上。常用的文件操作包括:
文件的生成/打开(IRP_MJ_CREATE),
文件的关闭(IRP_MJ_CLEANUP: 表示句柄数为0,IRP_MJ_CLOSE: 表示文件对象引用计数为0,即将销毁),
文件读/写(IRP_MJ_READ/IRP_MJ_WRITE),
文件设置(IRP_MJ_SET_INFORMATION)
文件查询(IRP_MJ_QUERY_INFORMATION)
目录下项查询(MajorFuncton: IRP_MJ_DIRECTORY_CONTROL, MinorFunction: IRP_MN_QUERY_DIRECTORY)
每类操作对应的内核函数如下表所示:
二. 自己发送IRP请求操作文件的封装:
1. 实现MDL链解锁及释放,完成例程的功能, 后续的各IRP完成时统一使用
(1)解锁并释放MDL链
(2)文件操作完成例程:
2. 文件的打开/生成: 与其它IRP不同,在发送IRP_MJ_CREATE请求前就需要创建并填写好文件对象,FSD的卷设备可以从根目录pRootFileObject->Vpb->DeviceObject得到,对应的卷管理器生成的卷设备可以从: pRootFileObject->Vpb->RealDevice得到
(1)创建文件对象可以用已导出但未公开的nt!ObCreateObject, 该函数原型如下:
(2) 设置安全状态可以用已导出但未公开的nt!SeCreateAccessState,该函数原型如下:
(3)自己创建并发送IRP进行文件打开/生成的实现:
3. 文件关闭的实现: 分两步:1)发送主功能号为IRP_MJ_CLEANUP的IRP向FSD表明: 文件对象句柄数已为0 =>发送主功能号为IRP_MJ_CLOSE的IRP向FSD表明: 文件对象引用计数已为0, 由FSD负责销毁文件对象
(1)文件关闭1: IRP_MJ_CLEANUP
(2) 文件关闭2:IRP_MJ_CLOSE
4. 文件读/写的实现:
5. 文件设置的实现:
6. 文件查询的实现:
7. 目录下项查询项查询的实现: IRP主功能号为: IRP_MJ_DIRECTORY_CONTROL, 次功能号为: IRP_MN_QUERY_DIRECTORY
三. 文件IRP操作测试: 这里实现常用的几个功能就可以把前面的文件操作涵盖
文件删除
2. 文件更名:
(1) 如果仅仅是当前路径下的文件更名, 可以把下层的栈单元参数: pIrpSp->Parameters.SetFile.FileObject = NULL
(2) 这里着重要说明的是第2种情况, 把文件移动到同一卷的不同目录下,这方面的例子比较少,经过逆向分析nt!NtSetInformationFile=>nt!IopOpenLinkOrRenameTarget,可以得出: 需要新创建移动后的目标文件对象pTargetFileObject,并填写: pIrpSp->Parameters.SetFile.FileObject=pTargetFileObject
Win10 X64(1809)分析过程如下(由于函数体过长,一些无关紧要的就不贴出来了, 有兴趣的可以自己慢慢分析,这里只贴出关键处的分析):
1)nt!NtSetInformationFile分析关键处:
在这个内核函数中对于类型为:FileRenameInformation,FileLinkInformation的文件设置会检查:
pFileLinkOrRenameInfo->FileName及FileLinkOrRenameInfo->RootDirectory,当: pFileLinkOrRenameInfo->FileName[0]==L'\\'或pFileLinkOrRenameInfo->RootDirectory!=NULL时会执行调用nt!IopOpenLinkOrRenameTarget创建移动后的目标文件, 根据返回的文件句柄就可以很容易得到目标文件对象指针pTargetFileObject了。
2)nt!IopOpenLinkOrRenameTarget分析
根据对nt!NtSetInformationFile进行的分析,不难推出:nt!IopOpenLinkOrRenameTarget函数原型如下:
当pFileLinkOrRenameInfo->FileName[0]==L'\\'或pFileLinkOrRenameInfo->RootDirectory!=NULL时都会nt!NtSetInformationFile调用nt!IopOpenLinkOrRenameTarget, 这里考虑: pFileLinkOrRenameInfo->FileName包含完整路径的情况就可以实现后面的功能了。
分析关键处:
(3)根据前面的分析,得出文件更名IRP操作的实现:
3. 文件的拷贝/移动: 打开源文件及目标文件,从源文件读取再写入目标文件就可以了,如果需要移动,拷贝成功后再删除源文件。
#define FILE_TRANS_BUF_MAXLEN (4*1024*1024)
[培训]科锐逆向工程师培训第53期2025年7月8日开班!
最后于 2020-12-8 11:42
被低调putchar编辑
,原因: