0


你的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

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

typedefstruct_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,//  Version0,//  FlagsNULL,//  Context
    Callbacks,//  Operation callbacks
    PtUnload,//  MiniFilterUnload
    PtInstanceSetup,//  实例绑定回调函数,可以决定绑定哪些卷
    PtInstanceQueryTeardown,//  InstanceQueryTeardown
    PtInstanceTeardownStart,//  InstanceTeardownStart
    PtInstanceTeardownComplete,/** 过滤管理器在发送的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

驱动

A

B

,

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

函数中利用

FltWriteFile

FltReadFile

实现了一个文件拷贝的功能:
FltWrite
并且文件打开时是用的

FltCreateFileEx2

函数, 并且

Instance

参数并不是为

NULL

:
FltCreateFileEx2
这就导致如果使用

wcifs.sys

提供的文件拷贝功能, 那么常规的EDR或者杀软的

MiniFilter

根本就监控不到, 因为

wcifs.sys

的高度更低, 这就导致我们可以绕过EDR或者杀软的自保;
调用驱动需要的结构体:

structWcifsPortMessageCopyFileHandler{/*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

可以阻止第三方文件的写入, 应该做一些额外的验证, 确保自保目录的安全;

标签: 安全

本文转载自: https://blog.csdn.net/qq_40827990/article/details/135883485
版权归原作者 钞sir 所有, 如有侵权,请联系我们删除。

“你的MiniFilter安全吗?”的评论:

还没有评论