你的MiniFilter安全吗?

news2025/3/11 17:05:58

简介

筛选器管理器 (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),			//  Size
	FLT_REGISTRATION_VERSION,           //  Version
	0,                                  //  Flags
	NULL,                               //  Context
	Callbacks,                          //  Operation callbacks
	PtUnload,                           //  MiniFilterUnload
	PtInstanceSetup,                    //  实例绑定回调函数,可以决定绑定哪些卷
	PtInstanceQueryTeardown,            //  InstanceQueryTeardown
	PtInstanceTeardownStart,            //  InstanceTeardownStart
	PtInstanceTeardownComplete,         /** 过滤管理器在发送的I/O请求都被完成的时候,调用这个函数, 在这个函数中,微过滤驱动关闭所有还被打开的文件*/
	NULL,                               //  GenerateFileName
	NULL,                               //  GenerateDestinationFileName
	NULL                                //  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.coloradmin.cn/o/1417226.html

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

相关文章

STM32CubeMX教程31 USB_DEVICE - HID外设_模拟键盘或鼠标

目录 1、准备材料 2、实验目标 3、模拟鼠标实验流程 3.0、前提知识 3.1、CubeMX相关配置 3.1.0、工程基本配置 3.1.1、时钟树配置 3.1.2、外设参数配置 3.1.3、外设中断配置 3.2、生成代码 3.2.0、配置Project Manager页面 3.2.1、设初始化调用流程 3.2.2、外设中…

优选6款前端动画特效分享(附在线演示)

优选6款前端动画特效 其中有CSS动画、canvas动画、js小游戏等等 下方效果图可能不是特别的生动 那么你可以点击在线预览进行查看相应的动画特效 同时也是可以下载该资源的 翻页时钟特效 基于react实现的一款翻页时钟特效 切换时间特效跟比赛切换分数牌相似 以下效果图只能体现…

Gitlab7.14 中文版安装教程

Gitlab7.14 中文版安装教程 注: 本教程由羞涩梦整理同步发布,本人技术分享站点:blog.hukanfa.com转发本文请备注原文链接,本文内容整理日期:2024-01-28csdn 博客名称:五维空间-影子,欢迎关注 …

T05垃圾收集算法与垃圾收集器ParNew CMS

垃圾收集算法与垃圾收集器ParNew & CMS 垃圾收集算法 #### f 分代收集理论 当前虚拟机的垃圾收集都采用分代收集算法。根据对象存活周期不同将内存分为几块,一般将java堆分为新生代和老年代,然后根据各个年代的特点选择不同的垃圾收集算法。 在新…

MySQL-窗口函数 简单易懂

窗口函数 考查知识点: • 如何用窗口函数解决排名问题、Top N问题、前百分之N问题、累计问题、每组内比较问题、连续问题。 什么是窗口函数 窗口函数也叫作OLAP(Online Analytical Processing,联机分析处理)函数,可…

ESP8266 控制之 : 使用 RingBuffer USART1 和 USART3互传

简介 使用Buffer来避免数据的丢失, 或许你自己在使用串口进行收发时会丢失数据, 现在我们就来简单使用一下RingBuffer创建Rx、Tx的Buffer来避免发送接收丢包或数据丢失问题。 扩展知识 RingBuffer的介绍, 看完大概也就知道了,实在不知道就看看下面的代码 线路连接…

微信小程序开发学习笔记《14》上拉触底事件案例

微信小程序开发学习笔记《14》上拉触底事件案例 博主正在学习微信小程序开发,希望记录自己学习过程同时与广大网友共同学习讨论。建议仔细阅读对应官方文档 一、最终实现效果 实现在加载完这一页之后,刷新之后展示 “数据加载中”,加载完后…

超温报警器电路设计方案汇总

超温报警器电路设计方案(一) 该超温报警电路由温度采集电路、继电器控制电路、延时电路、秒脉冲信号发生器、计数译码电路、数显电路、报警电路共同构成。下面来详细介绍一下各部分电路的功能。 温度采集电路 温度采集电路由负温度系数的热敏电阻RW、R…

STM32 自学笔记 学习笔记 一

起源,A7,A9,M3,原来弄了A9的TQ2440,结果还得来重新熟悉下32函数JLINK使用SW方式,本来可以下载,但是一根线掉了重新上去,就出各种跟线无关问题,干脆把32断了重新接,结果就成功了&…

服务攻防-开发组件安全JacksonFastJson各版本XStreamCVE环境复现

知识点 1、J2EE-组件Jackson-本地demo&CVE(数据处理) 2、J2EE-组件FastJson-本地demo&CVE(数据处理) 3、J2EE-组件XStream-本地demo&CVE(数据处理) 章节点: 1、目标判断-端口扫描…

【机器学习入门】18种常见的机器学习算法数学公式及解析

机器学习算法基础原理: https://codeknight.blog.csdn.net/article/details/135632808https://codeknight.blog.csdn.net/article/details/135632808 https://codeknight.blog.csdn.net/article/details/135639843https://codeknight.blog.csdn.net/article/detai…

Android 性能优化总结:包体积优化

前言 随着开发不断迭代,App体积越来越大,包大小的增大也会给我们应用带来其他的影响 比如 下载率影响 过大的包体积会影响下载转化率,根据Google Play Store包体积和转化率分析报告显示,平均每增加1M,转化率下降0.2%左…

【MATLAB第95期】#源码分享 | 基于MATLAB的卷积神经网络CNN图像分类源代码分享(含两个案例)

【MATLAB第95期】#源码分享 | 基于MATLAB的卷积神经网络CNN图像分类源代码分享(含两个案例) 一、案例一 1、背景介绍 目的:训练和测试卷积神经网络,以检测钻头三种类型。 深度学习(DL)是机器学习的一个子…

Element table组件内容\n换行

漂亮的页面总是让人心旷神怡,层次清晰的页面让用户操作起来也是易于上手及展示。 如下的页面展示就是非常low的:用户根本阅读其中的数据。 在这个页面,根据用户填写过程生成多次填写记录,如果不进行层次性的展示,数据…

【C语言】学生管理系统

学生管理系统是一个用于管理学生信息、成绩、课程等数据的软件系统。在本文中,我们将使用C语言来实现一个简易的学生管理系统,包括学生信息的录入、显示、查询等功能。我们将使用文件来存储学生信息,以便实现持久化存储。 该学生管理…

JAVA 学习 面试(十一)常见设计模式

设计模式 ## 1、创建型模式 对象实例化的模式,创建型模式用于解耦对象的实例化过程。 单例模式:某个类智能有一个实例,提供一个全局的访问点。 工厂模式:一个工厂类根据传入的参量决定创建出哪一种产品类的实例。 抽象工厂模式&a…

Android学习之路(25) Theme和Style

1、官方详细解读 样式和主题背景 | Android 开发者 | Android Developers 2、应用场景 类似web设计中css样式。将应用设计的细节与界面的结构和行为分开。 样式style :应用于 单个 View 的外观。样式可以指定字体颜色、字号、背景颜色等属性 主题theme&…

OpenHarmony—不支持解构赋值

规则:arkts-no-destruct-assignment 级别:错误 ArkTS不支持解构赋值。可使用其他替代方法,例如,使用临时变量。 TypeScript let [one, two] [1, 2]; // 此处需要分号 [one, two] [two, one];let head, tail [head, ...tail]…

WordPress如何使用SQL实现一键关闭/开启评论功能(已有评论)

WordPress本人就自带评论功能,不过由于种种原因,有些站长不想开启评论功能,那么应该怎么实现一键关闭评论功能或开启评论功能呢?或者针对已有评论功能的文章进行一键关闭或开启评论功能应该怎么操作? 如果你使用的Wor…

每日一道面试题:Java中序列化与反序列化

写在开头 哈喽大家好,在高铁上码字的感觉是真不爽啊,小桌板又拥挤,旁边的小朋友也比较的吵闹,影响思绪,但这丝毫不影响咱学习的劲头!哈哈哈,在这喧哗的车厢中,思考着这样的一个问题…