为什么做电影网站没有流量,饮食网站建设策划书,网约车后台平台网站建设,c 网站开发流程简介
筛选器管理器 (FltMgr.sys)是Windows系统提供的内核模式驱动程序, 用于实现和公开文件系统筛选器驱动程序中通常所需的功能; 第三方文件系统筛选器开发人员可以使用FltMgr的功能可以更加简单的编写文件过滤驱动, 这种驱动我们通常称为MiniFilter, 下面是MiniFilter的基本…简介
筛选器管理器 (FltMgr.sys)是Windows系统提供的内核模式驱动程序, 用于实现和公开文件系统筛选器驱动程序中通常所需的功能; 第三方文件系统筛选器开发人员可以使用FltMgr的功能可以更加简单的编写文件过滤驱动, 这种驱动我们通常称为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 attachmentsFltCreateCommunicationPort
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产品等也会通过这种方式来对自己的安装目录进行保护, 禁止第三方软件等往自己的目录写入文件, 例如我们往一个受保护的目录中创建一个新文件, 会被阻止: 如果我们在自己的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等函数中, 也有这种机制: 如果有这样的MiniFilter驱动, 满足了这两个条件:
Altitude比杀软或者EDR的Altitude低;存在文件读写的接口;
那我们是不是就可以绕过杀毒软件或者EDR的自保了呢:
Wcifs.sys
在Windows中有一个驱动, 是处理容器相关的, 叫做wcifs.sys: 这个驱动注册了MiniFilter, 并且Altitude也比较低, 远远小于常规EDR注册的MiniFilter的高度: 在这个驱动中还注册了与应用层之间的通信接口: 在WcPortMessage函数中, MessageCode 4时, 有一个WcCopyFileHandler函数 在WcCopyFileHandler函数中利用FltWriteFile和FltReadFile实现了一个文件拷贝的功能: 并且文件打开时是用的FltCreateFileEx2函数, 并且Instance参数并不是为NULL: 这就导致如果使用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可以阻止第三方文件的写入, 应该做一些额外的验证, 确保自保目录的安全;