你的MiniFilter安全吗?

简介

筛选器管理器 (FltMgr.sys)是Windows系统提供的内核模式驱动程序, 用于实现和公开文件系统筛选器驱动程序中通常所需的功能; 第三方文件系统筛选器开发人员可以使用FltMgr的功能可以更加简单的编写文件过滤驱动, 这种驱动我们通常称为MiniFilter, 下面是MiniFilter的基本框架:
MiniFilter
简单的说就是我们可以通过微软提供的一些接口, 可以使我们方便的在内核层监控文件的操作(创建, 删除, 读写等), 例如杀毒软件利用MiniFilter监控文件的创建, 在文件创建时对文件进行病毒查杀; 又例如安全产品利用MiniFilter, 阻止第三方程序在自己的目录下面写文件等…

MiniFilter

由于在MiniFilter中我们不用关心IRP的处理工作, 这些都可以交给 Filter Manager处理, 所以我们要编写一个MiniFilter是很简单的, 只有调用几个API函数, 并在参数中填写我们关心的或者需要处理的结构就可以了;

FltRegisterFilter

我们使用FltRegisterFilter来注册一个过滤器:

NTSTATUS FLTAPI FltRegisterFilter([in]  PDRIVER_OBJECT         Driver,[in]  const FLT_REGISTRATION *Registration,[out] PFLT_FILTER            *RetFilter
);

第一个参数和DriverEntry的第一个参数一样, 第三参数RetFilter作为输出, 主要用于后续调用FltUnregisterFilter时注销MiniFilter:

NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING reg_path)
{NTSTATUS status;	DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "DriverEntry Entry!\n");ExInitializeResourceLite(&GlobalResource);status = FltRegisterFilter(DriverObject, &FilterRegistration, &gFilterHandle);if (NT_SUCCESS(status)) {status = FltStartFiltering(gFilterHandle);if (!NT_SUCCESS(status)) {DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "FltUnregisterFilter status: %lx\n", status);FltUnregisterFilter(gFilterHandle);}else {DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "FltRegisterFilter Start!\n");}}else {DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "status: %lx\n", status);}DriverObject->DriverUnload = UnDriver;return STATUS_SUCCESS;
}

最重要的是第两个参数Registration, 这个参数中定义了一系列的结构, 用于注册监控文件操作的回调等;

typedef struct _FLT_REGISTRATION {USHORT                                      Size;USHORT                                      Version;FLT_REGISTRATION_FLAGS                      Flags;const FLT_CONTEXT_REGISTRATION              *ContextRegistration;const 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;PFLT_TRANSACTION_NOTIFICATION_CALLBACK      TransactionNotificationCallback;PFLT_NORMALIZE_NAME_COMPONENT_EX            NormalizeNameComponentExCallback;PFLT_SECTION_CONFLICT_NOTIFICATION_CALLBACK SectionNotificationCallback;
} FLT_REGISTRATION, *PFLT_REGISTRATION;

可以看到FLT_REGISTRATION有很多字段, 但是我们用到的通常是:

CONST FLT_REGISTRATION FilterRegistration = {sizeof(FLT_REGISTRATION),			//  SizeFLT_REGISTRATION_VERSION,           //  Version0,                                  //  FlagsNULL,                               //  ContextCallbacks,                          //  Operation callbacksPtUnload,                           //  MiniFilterUnloadPtInstanceSetup,                    //  实例绑定回调函数,可以决定绑定哪些卷PtInstanceQueryTeardown,            //  InstanceQueryTeardownPtInstanceTeardownStart,            //  InstanceTeardownStartPtInstanceTeardownComplete,         /** 过滤管理器在发送的I/O请求都被完成的时候,调用这个函数, 在这个函数中,微过滤驱动关闭所有还被打开的文件*/NULL,                               //  GenerateFileNameNULL,                               //  GenerateDestinationFileNameNULL                                //  NormalizeNameComponent
};

FLT_OPERATION_REGISTRATION这个结构中我们定义我们关心的文件操作:

const FLT_OPERATION_REGISTRATION Callbacks[] = {{IRP_MJ_CREATE,0,NPPreCreate,   	// 生成预操作回调函数NPPostCreate	// 生成后操作回调函数},{ IRP_MJ_OPERATION_END }
};

IRP_MJ_CREATE, IRP_MJ_SET_INFORMATION等是IPR请求信息, 操作系统发送 IRP_MJ_CREATE 请求,以打开文件对象或设备对象的句柄。 例如,当驱动程序调用 ZwCreateFile 时,操作系统会发送 IRP_MJ_CREATE 请求以执行实际打开操作; 每个FLT_OPERATION_REGISTRATION都必须以IRP_MJ_OPERATION_END结尾;
所以我们这里注册了有关IRP_MJ_CREATE的回调, 当有IRP_MJ_CREATE请求时, 就会触发我们的回调, 会进入我们的NPPreCreate回调函数, 我们可以在这个函数中处理文件, 例如阻止test1.exe的操作:

FLT_PREOP_CALLBACK_STATUS NPPreCreate(PFLT_CALLBACK_DATA Data,PCFLT_RELATED_OBJECTS FltObjects,PVOID *ComletionContext
) {char Filename[256] = { "X:" };NTSTATUS status;PFLT_FILE_NAME_INFORMATION nameinfo;UNREFERENCED_PARAMETER(FltObjects);UNREFERENCED_PARAMETER(ComletionContext);PAGED_CODE();__try {status = FltGetFileNameInformation(Data,FLT_FILE_NAME_NORMALIZED | FLT_FILE_NAME_QUERY_DEFAULT,&nameinfo);if (NT_SUCCESS(status)) {FltParseFileNameInformation(nameinfo);if (NPUnicodeStringToChar(&nameinfo->Name, Filename)) {if (strstr(Filename, "test1.exe") > 0) {DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "[NPPreCreate] Filename :%s\n", Filename);Data->IoStatus.Status = STATUS_ACCESS_DENIED;Data->IoStatus.Information = 0;FltReleaseFileNameInformation(nameinfo);return FLT_PREOP_COMPLETE;}}FltReleaseFileNameInformation(nameinfo);}}__except (EXCEPTION_EXECUTE_HANDLER) {DbgPrint("NPPreCreate EXCEPTION_EXECUTE_HANDLER");}return FLT_PREOP_SUCCESS_WITH_CALLBACK;
}

.inf文件

MiniFilter驱动加载到系统时, 和常规的驱动加载不太一样, 需要写注册表项, 定义一些字段, 例如Altitude, 这是最重要的一个字段之一;
因为不同的高度意味在不同的加载顺序和分组, 高度越高越会被先执行, 具体的高度以及分组可以参考微软的文档:
在这里插入图片描述
inf驱动安装文件:

;;;
;;; MiniFile
;;;
;;;
;;; Copyright (c) 1999 - 2002, Microsoft Corporation
;;;[Version]
Signature   = "$Windows NT$"
Class       = "ActivityMonitor"             ;This is determined by the work this filter driver does
ClassGuid   = {b86dff51-a31e-4bac-b3cf-e8cfe75c9fc2}    ;This value is determined by the Class
Provider    = %ProviderString%
DriverVer   = 06/16/2007,1.0.0.0
CatalogFile = MiniFile.cat[DestinationDirs]
DefaultDestDir          = 12
MiniFile.DriverFiles  = 12;;
;; Default install sections
;;[DefaultInstall]
OptionDesc  = %ServiceDescription%
CopyFiles   = MiniFile.DriverFiles[DefaultInstall.Services]
AddService  = %ServiceName%,,MiniFile.Service;;
;; Default uninstall sections
;;[DefaultUninstall]
DelFiles   = MiniFile.DriverFiles[DefaultUninstall.Services]
DelService = %ServiceName%,0x200      ;Ensure service is stopped before deleting;
; Services Section
;[MiniFile.Service]
DisplayName      = %ServiceName%
Description      = %ServiceDescription%
ServiceBinary    = %12%\%DriverName%.sys
Dependencies     = "FltMgr"
ServiceType      = 2                        ;SERVICE_FILE_SYSTEM_DRIVER
StartType        = 3                        ;SERVICE_DEMAND_START
ErrorControl     = 1                        ;SERVICE_ERROR_NORMAL
LoadOrderGroup   = "FSFilter Activity Monitor"
AddReg           = MiniFile.AddRegistry;
; Registry Modifications
;[MiniFile.AddRegistry]
HKR,,"SupportedFeatures",0x00010001,0x3
HKR,"Instances","DefaultInstance",0x00000000,%DefaultInstance%
HKR,"Instances\"%Instance1.Name%,"Altitude",0x00000000,%Instance1.Altitude%
HKR,"Instances\"%Instance1.Name%,"Flags",0x00010001,%Instance1.Flags%;
; Copy Files
;[MiniFile.DriverFiles]
%DriverName%.sys[SourceDisksFiles]
MiniFile.sys = 1,,[SourceDisksNames]
1 = %DiskId1%,,,;;
;; String Section
;;[Strings]
ProviderString          = "TODO-Set-Provider"
ServiceDescription      = "MiniFile mini-filter driver"
ServiceName             = "MiniFile"
DriverName              = "MiniFile"
DiskId1                 = "MiniFile Device Installation Disk";Instances specific information.
DefaultInstance         = "Null Instance"
Instance1.Name          = "Null Instance"
Instance1.Altitude      = "370030"
Instance1.Flags         = 0          ; Suppress automatic attachments

FltCreateCommunicationPort

FltCreateCommunicationPort函数可以创建一个通信服务器端口,微筛选器驱动程序可在该端口上接收来自用户模式应用程序的连接请求; 也通过这个函数注册就是可以让ring3的程序直接和MiniFilter驱动进行通信, FltCreateCommunicationPort函数原型如下:

NTSTATUS FLTAPI FltCreateCommunicationPort([in]           PFLT_FILTER            Filter,[out]          PFLT_PORT              *ServerPort,[in]           POBJECT_ATTRIBUTES     ObjectAttributes,[in, optional] PVOID                  ServerPortCookie,[in]           PFLT_CONNECT_NOTIFY    ConnectNotifyCallback,[in]           PFLT_DISCONNECT_NOTIFY DisconnectNotifyCallback,[in, optional] PFLT_MESSAGE_NOTIFY    MessageNotifyCallback,[in]           LONG                   MaxConnections
);

处理与应用层程序通信的逻辑主要就是就在MessageNotifyCallback回调当中;

Flt函数

通过以上的基础知识, 我们知道了在实际的应用当中我们可以通过MiniFilter来监控文件操作, 并且杀毒软件也是通过这种机制来监控文件的创建等事件, 对我们落盘的文件进行查杀的; 同时安全软件软件EDR产品等也会通过这种方式来对自己的安装目录进行保护, 禁止第三方软件等往自己的目录写入文件, 例如我们往一个受保护的目录中创建一个新文件, 会被阻止:
Can't
如果我们在自己的MiniFilter驱动中调用FltCreateFileEx, FltWriteFile, FltReadFile等函数去操作文件, 会不会被其他MiniFilter拦截呢?
我们来看看微软的文档中对FltCreateFileEx的描述, 原型是这样的:

NTSTATUS FLTAPI FltCreateFileEx([in]           PFLT_FILTER        Filter,[in, optional] PFLT_INSTANCE      Instance,[out]          PHANDLE            FileHandle,[out]          PFILE_OBJECT       *FileObject,[in]           ACCESS_MASK        DesiredAccess,[in]           POBJECT_ATTRIBUTES ObjectAttributes,[out]          PIO_STATUS_BLOCK   IoStatusBlock,[in, optional] PLARGE_INTEGER     AllocationSize,[in]           ULONG              FileAttributes,[in]           ULONG              ShareAccess,[in]           ULONG              CreateDisposition,[in]           ULONG              CreateOptions,[in, optional] PVOID              EaBuffer,[in]           ULONG              EaLength,[in]           ULONG              Flags
);

在这这些参数中, 微软对第二个参数Instance有这样的描述:

[in, optional] Instance
创建请求要发送到的微筛选器驱动程序实例的不透明实例指针。
实例必须附加到文件或目录所在的卷。
此参数是可选的,可以为 NULL。 
如果此参数为 NULL,则请求将发送到卷的文件系统驱动程序堆栈顶部的设备对象。 
如果为非 NULL,则请求仅发送到附加到指定实例下方的微型筛选器驱动程序实例。

这里有一个问题, 假如我们有两个MiniFilter驱动AB, A的高度也就是Altitude是370030, B的高度是180000; 如果在B中调用FltCreateFileEx函数并且第二个参数设置为非 NULL, 这个时候对文件的操作在驱动A中就收不到相关的回调, 因为A的高度比B的高, 所以文件操作的请求发不到A去;
同样的, 在FltWriteFile, FltReadFile等函数中, 也有这种机制:
FltWriteFile
FltReadFile
如果有这样的MiniFilter驱动, 满足了这两个条件:

  1. Altitude比杀软或者EDR的Altitude低;
  2. 存在文件读写的接口;

那我们是不是就可以绕过杀毒软件或者EDR的自保了呢:

Wcifs.sys

在Windows中有一个驱动, 是处理容器相关的, 叫做wcifs.sys:
wcifs
这个驱动注册了MiniFilter, 并且Altitude也比较低, 远远小于常规EDR注册的MiniFilter的高度:
Altitude
在这个驱动中还注册了与应用层之间的通信接口:
FltCreateCommunicationPort
WcPortMessage函数中, MessageCode == 4时, 有一个WcCopyFileHandler函数
WcPortMessage
WcCopyFileHandler函数中利用FltWriteFileFltReadFile实现了一个文件拷贝的功能:
FltWrite
并且文件打开时是用的FltCreateFileEx2函数, 并且Instance参数并不是为NULL:
FltCreateFileEx2
这就导致如果使用wcifs.sys提供的文件拷贝功能, 那么常规的EDR或者杀软的MiniFilter根本就监控不到, 因为wcifs.sys的高度更低, 这就导致我们可以绕过EDR或者杀软的自保;
调用驱动需要的结构体:

struct WcifsPortMessageCopyFileHandler
{/*0*/   DWORD MessageVersionOrCode;/*4*/   DWORD MessageSize;/*8*/   wchar_t InstanceName[50];/*108*/ DWORD InstanceNameLength;/*112*/ DWORD ReparseTag;/*116*/ DWORD OffsetToSourceContainerRootId;/*120*/ DWORD SizeOfSourceContainerRootId;/*124*/ DWORD OffsetToTargetContainerRootId;/*128*/ DWORD SizeOfTargetContainerRootId;/*132*/ DWORD OffsetToSourceFileRelativePath;/*136*/ DWORD SizeOfSourceFileRelativePath;/*140*/ DWORD OffsetToTargetFileRelativePath;/*144*/ DWORD SizeOfTargetFileRelativePath;/*148*/ char UnionData[]; // 2*ContainerRootId + source & target relative paths
};

总结

wcifs.sys是系统自带的, 并且默认就会加载, 所以利用该驱动的接口来拷贝文件对于绕过一些文件过滤驱动是很方便的, 同时作为EDR或者杀软产品也不能绝对的相信自己的MiniFilter可以阻止第三方文件的写入, 应该做一些额外的验证, 确保自保目录的安全;

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/660359.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

python21-Python的字符串查找、替换相关方法

str还提供了如下常用的执行查找、替换等操作的方法。 startswith():判断字符串是否以指定子串开头。 endswith():判断字符串是否以指定子串结尾 find():查找指定子串在字符串中出现的位置,如果没有找到指定子串,则返回-1。 index():查找指定子串在字…

Java多线程--解决单例模式中的懒汉式的线程安全问题

文章目录 一、单例设计模式的线程安全问题(1)饿汉式没有线程安全问题(2)懒汉式线程安全问题1、案例2、方式1-同步方法3、方式2-同步代码块4、优化 二、代码(1)实现线程安全的懒汉式(2&#xff0…

猫什么时候发腮?公认发腮效果好的生骨肉冻干推荐

猫什么时候发腮是许多猫主人非常关心的问题。在猫咪的成长过程中,发腮是一项重要的体征,也是猫咪成熟的标志。想要让猫咪拥有可爱的肉嘟嘟脸型,主人需要在适龄的年龄段加强营养补给,不要错失最佳发腮期。那么,猫咪的最…

pytorch交换数组元素坑

写 PermutePatch 时遇到一个 bug:在试图交换 PyTorch 数组的两个元素时,两个位置都变成同一个元素!具体见测试代码。本文兼测几种交换情况: 两个 python 变量list 两个元素numpy 数组两个元素pytorch 数组两个元素 import numpy…

api接口1688商品详情接口采集商品详情数据商品价格详情页数据可支持高并发调用演示示例

接入1688商品详情API接口的步骤如下: 注册账号:首先,你需要在1688开放平台注册一个账号。 创建应用:登录后,在控制台中找到“我的应用”,点击“创建应用”。 获取API密钥:创建应用后&#xff…

【Linux】VMware Workstation16安装银河麒麟高级服务器操作系统V10 SP3 AMD64

目录 一、麒麟服务器概述 二、安装步骤 设置硬盘大小 完成配置 修改内存 处理器等设备配置 选择直接安装 配置磁盘 网络配置 设置root账号密码 开始安装 启动完成 一、麒麟服务器概述 银河麒麟高级服务器操作系统V10是针对企业级关键业务,适应虚拟化、云…

Android开发之动画

逐帧动画 通过在连续的帧之间快速切换来创建动画效果 var anim animationView.background as AnimationDrawable获取动画的Drawable资源anim.start()启动动画anim.stop()停止动画 private lateinit var animationView: ImageView private var flag: Boolean trueanimation…

C语言KR圣经笔记 6.8联合体 6.9位域

6.8 联合体(union) 联合体是一个可以(在不同时间)保存不同类型和大小的对象的变量,由编译器来跟踪大小和对齐要求。联合体提供了一种不用在程序中嵌入任何与机器相关的信息,而能够在单个存储区域内操作不同…

时间序列预测——GRU模型

时间序列预测——GRU模型 在深度学习领域,循环神经网络(RNN)是处理时间序列数据的一种常见选择。上期已介绍了LSTM的单步和多步预测。本文将深入介绍一种LSTM变体——门控循环单元(GRU)模型,包括其理论基础…

Flutter canvas 画一条会动的波浪线 进度条

之前用 Flutter Canvas 画过一个三角三角形,html 的 Canvas 也画过一次类似的, 今天用 Flutter Canvas 试了下 感觉差不多: html 版本 大致效果如下: 思路和 html 实现的类似: 也就是找出点的位置,使用二阶…

DAY37:贪心算法738

今天写了一道题目,顺便看了一个很好的总结,这篇博客可以跳过。 Leetcode:738 单调递增的数字 因为最大的数字是9,当出现后面位数的数字比前面位数的数字小的时候,就把后面的数字都变成9,前面那个数字--。…

网安面试指南——(渗透,攻击,防御)

网安面试 目录 1.什么是 WebShell? 2.什么是网络钓鱼? 3.你获取网络安全知识途径有哪些? 4.什么是 CC 攻击? 5.Web 服务器被入侵后,怎样进行排查? 6.dll 文件是什么意思,有什么用?…

Cannot assign to read only property ‘exports‘ of object ‘#<Object>‘

看下多语言js文件中,是否同级出现相同名称。

3D 转换

1,3D的特点: 近小远大 物体后面遮挡不可见 2,3D移动 translate3d 3D移动在2D移动的基础上多加了一个可以移动的方向,就是z轴方向 transform:translateX(100px):仅仅是在x轴上移动…

mysql8.0主从搭建

一、架构说明 MySQL 主从架构是一种常见的数据库部署方案,用于实现数据的自动同步和冗余备份。在该架构中,主服务器负责处理事务的写入操作,从服务器则负责复制主服务器上的数据,并可以用于读取操作,以减轻主服务器的…

寒假刷题第19天

PTA甲级 1134 Vertex Cover #include<iostream> #include<vector> #include<set>using namespace std;typedef pair<int , int> PII; vector<PII>v; int n , m;bool check(set<int>&se) {for(auto i : v)if(!se.count(i.first) &…

【C/C++ 07】词频统计

一、题目 读入一篇英文短文&#xff0c;去除介词、连词、冠词、副词、代词等非关键性单词后&#xff0c;统计每个单词出现的次数&#xff0c;并将单词按出现次数的降序和单词字符的升序进行显示5个单词。 二、算法 1. 通过<fstream>库创建fstream流对象&#xff0c;并从…

uniapp【组件封装】时间戳格式化为星期

组件 components/dos-week.vue <template><text>{{week}}</text> </template> <script>export default {props: {time: String},mounted(e) {this.week this.getWeek(Number(this.time))},data() {return {week: }},methods: {// 通过时间戳计…

美区或其他外区Appstore账号AppleID注册教程,简单快速,苹果必备!

▍前言 现在越来越多的APP在国区APPstore下架&#xff0c;如果想有更好的使用体验&#xff0c;不得不去外区下载APP&#xff0c;那就需要一个外区的apple id&#xff0c;注册也很简单&#xff0c;今天大鹏通过电脑ipad给大家注册一个&#xff0c;建议大家直接使用iPhone或者iPa…

python魔法函数[全面]

1、init 用于初始化对象的属性和状态 当创建一个对象时&#xff0c;Python会自动调用该对象的__init__方法。 这个方法用于初始化对象的属性和状态&#xff0c;是对象创建过程中的一个重要环节 2、new # 通常我们不需要重写__new__方法&#xff0c;除非我们正在进行一些非常…