当前位置: 首页 > 科技观察

MINIFILTER实现从分析到实现的文件重定向

时间:2023-03-18 15:46:35 科技观察

本次实验的测试环境为WindowsServer2008R2X64。为了解决例如放置在系统关键目录或业务敏感目录下的恶意可执行程序或网页文件,一些安全软件会使用文件过滤驱动技术结合一定的检测规则来达到保护系统和业务安全的目的。简单看一下Minifilter技术的介绍:Filtermanager是随Windows安装的,但是只有在加载了minifilter驱动的情况下才会起作用。FilterManager绑定到目标卷的文件系统堆栈。Minifilter驱动程序通过向过滤器管理器注册它过滤的I/O操作,间接绑定到文件系统堆栈。FilterManager随Windows安装,但它仅在加载minifilter驱动程序时起作用。FilterManager绑定到目标卷的文件系统堆栈。Minifilter驱动程序通过向过滤器管理器注册它过滤的I/O操作,间接绑定到文件系统堆栈。在微软的WDK实例中,有使用REPARSE重定向的跨盘重定向,也有通过Minifilter使用IoCreateFileSpecifyDeviceObjectHint的非跨盘重定向。因此,我们的目标是先利用部分Windows内核代码看看为什么Reparse可以完成文件重定向功能,然后实现一个可以方便地配置监控路径和重定向路径的驱动程序和应用程序控制程序。虽然通过源码查看文件创建源码的关键部分是WindowsServer2008x64系统,但为了避免过多的逆向分析,直接针对WRK(因为不能过多引用,尽量用文字描述),看看你是否能得到Reparse重定向的结论。当创建文件的入口是IoCreateFile时,它的主要工作是由IopCreateFile的ObOpenObjectByName完成的,这是一个对象管理的内核函数。ObOpenObjectByName函数中的两个主要任务是调用ObpLookupObjectName函数,该函数对应我们真实的文件内核对象,通过ObpCreateHandle完成内核对象插入到指定的句柄表中。其实最好的答案就在这个ObpLookupObjectName函数中,因为这个函数有一个可选的入参RootDirectoryHandle作为要搜索的目录对象,但是同样我们分析在不提供这个参数的过程中的工作。第一步,它会以ObpRootDirectoryObject为根目录对象进行查找,处理以“\??\”开头的对象名,以当前进程的ProcessMap为父目录进行查找。然后进入循环依次分析objectname中的每一段。在访问之前,非KernelMode访问必须通过安全检查。输入ObpLookupDirectoryEntry,计算当前图层对象名称的Hash值,取Hash数组大小37的余数。当获取到的对象的OBJECT_HEADER_NAME_INFO与提供的名称一致时,后继链表将返回此地址目的。直接调用其对象类型的ParseProcedure(进入IopParseFile->IopParseDevice向对应的volume对象发送请求)。阅读后发现,STATUS_REPARSE返回后,会转入ParseFromRoot完成从上述DeviceMap的重新解析。这说明STATUS_REPARSE确实可以帮助我们完成从一个文件位置到另一个文件位置的重定向(比如某类目录总是STATUS_REPARSE,而STATUS_REPARSE对ObpLookupObjectName的个数有限制),其次,它会返回给对象管理器时就完成了整个地方的重新解析,所以这样确实可以完成跨盘操作。实现可配置文件的跨盘重定向我们的目标是实现一个应用程序将监控配置发送给驱动程序,驱动程序将文件重定向的结果报告给应用程序。驱动完成将监控文件夹中新建的所有文件转移到目标文件夹的操作。首先,我们主要关注如何拦截特定路径下的文件创建操作。让我们先完成绑定卷实例。此回调例程在安装新卷后以及在注册后安装卷后调用。在该回调中主要通过FltGetVolumeName完成获取卷的设备名和卷标名,通过FltAllocateContext从内存池或后备表中获取存储上下文的内存,并在实例中完成设置通过FltSetInstanceContext。磁盘被重定向后,以DOS风格的名称发送给应用程序,因此被添加到双链表中以获取其他磁盘的信息。对于绑定后InstanceQueryTeardownCallback、InstanceTeardownStartCallback、InstanceTeardownCompleteCallback3个回调的处理,值得注意的是InstanceQueryTeardownCallback,因为对应的是手动解绑,我们直接返回STATUS_FLT_DO_NOT_DETACH即可拒绝。下面我们看IRP_MJ_CREATE主函数号对应的处理,主函数号(在Minifilter中)为IRP_MJ_NETWORK_QUERY_OPEN。我们也要求在这里处理。由于它是一个快速I/O操作,它返回FLT_PREOP_DISALLOW_FASTIO以拒绝它。我们使用FltGetFileNameInformation和FltParseFileNameInformation来获取它的文件名信息,后者是为了方便将卷设备名转换为DOS风格的名称。在这个过程中,我们根据实例上下文列表和配置生成两个名字,一个是DOS风格的文件名和完整的文件名,前者发送给应用程序,后者设置为FileObject(使用IoReplaceFileObjectName),并在I/OReturn请求包中的STATUS_REPARSE完成第一部分的解析,这样创建操作就会根据新的名字重新从对象管理开始处理。回调函数返回FLT_PREOP_COMPLETE完成I/O请求,不向下发送请求。IRP_MJ_CREATE操作IRP_MJ_SET_INFORMATION的FileInformationClass是FileRenameInformation处理,因为非跨盘移动会通过这个请求完成操作,所以使用和IRP_MJ_CREATE一样的操作。***提及Minifilter中应用程序发送给驱动程序的信息以及驱动程序主动发送给应用程序的处理。应用程序可以通过FilterConnectCommunicationPort请求连接到指定的通信端口。驱动内部通过PFLT_MESSAGE_NOTIFYMessageNotifyCallback回调监听目录和重定向目录。***,重定向完成后,驱动使用FltSendMessage发送消息,应用使用FilterGetMessage获取。测试资源可以通过链接下载:http://pan.baidu.com/s/1o766JtK密码:jnsk。