MiniFilter
一、前言
由于sFilter过于复杂,微软于是对其进行了简化封装,并提供了接口进行驱动的编写。MiniFilter是由过滤管理器与过滤驱动组成的,其中过滤驱动还有着altitude(inf文件中定义),也就是高度,高度值越大,其位于设备栈中的位置越靠前,并且其决定了过滤驱动在设备栈中的位置,所以如下图,驱动a比驱动b更早地接收到来自过滤管理器的请求。

二、代码细节
1.DriverEntry
在DriverEntry中,可以使用FltRegisterFilter向过滤管理器进行对过滤驱动的注册。
NTSTATUS
FLTAPI
FltRegisterFilter (
_In_ PDRIVER_OBJECT Driver,
_In_ CONST FLT_REGISTRATION *Registration,
_Outptr_ PFLT_FILTER *RetFilter
);
其中,Driver就是我们驱动入口函数所提供的参数。而Registeration的类型为FLT_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;
#if FLT_MGR_LONGHORN
PFLT_TRANSACTION_NOTIFICATION_CALLBACK TransactionNotificationCallback;
PFLT_NORMALIZE_NAME_COMPONENT_EX NormalizeNameComponentExCallback;
#endif // FLT_MGR_LONGHORN
#if FLT_MGR_WIN8
PFLT_SECTION_CONFLICT_NOTIFICATION_CALLBACK SectionNotificationCallback;
#endif // FLT_MGR_WIN8
} FLT_REGISTRATION, *PFLT_REGISTRATION;
其中最属OperationRegistration这个成员最重要。我们稍后再讲。
至于第三个参数,其是一个类似于句柄的东西,在之后的启用过滤函数FltStartFiltering作为唯一的参数,以及注销过滤函数FltUnregisterFilter的唯一参数。
上面的结构体中:
1、ContextRegistration是一个数组,内部的每一个值都代表了驱动程序可能用到的上下文。不需要的话可以置NULL
2、OperationRegistration是最重要的字段,决定了过滤驱动能够所作的操作。这也是一个数组。
typedef struct _FLT_OPERATION_REGISTRATION {
UCHAR MajorFunction;
FLT_OPERATION_REGISTRATION_FLAGS Flags;
PFLT_PRE_OPERATION_CALLBACK PreOperation;
PFLT_POST_OPERATION_CALLBACK PostOperation;
PVOID Reserved1;
} FLT_OPERATION_REGISTRATION, *PFLT_OPERATION_REGISTRATION;
1)MajorFunction代表的是IRP的类型
2)Flags置0
3)PreOperation是个函数,表示IRP操作前回调,注:过滤驱动中没有IRP,IRP在设备栈中是过滤管理器所操作的。通常可以在其中做拦截等等的操作。操作前回调可能的返回值如下:

函数的原型如下:
typedef FLT_PREOP_CALLBACK_STATUS
(FLTAPI *PFLT_PRE_OPERATION_CALLBACK) (
_Inout_ PFLT_CALLBACK_DATA Data,
_In_ PCFLT_RELATED_OBJECTS FltObjects,
_Outptr_result_maybenull_ PVOID *CompletionContext
);
data的类型如下:

其中能用到的属IoStatus和Iopb。IoStatus为此请求的状态,而Iopb内部的Parameters则包含了读写IRP的一些详细信息。如果是创建文件irp,则可以使用如下方式获得文件名称。

注意,使用IoStatus.Status=STATUS_ACCESS_DENIED表示拒绝操作。即文件创建失败。
4)PostOperation后函数,表示操作已经完成,这里其实也无关紧要了,但可以做一些查看的操作,通常返回FLT_POSTOP_FINISHED_PROCESSING表示过滤驱动已经完成对IO的所有处理,返回控制给过滤管理器。
2、_FLT_REGISTRATION其余的字段函数如下:

三、应用程序与过滤驱动通信
NTSTATUS
DriverEntry (
__in PDRIVER_OBJECT DriverObject,
__in PUNICODE_STRING RegistryPath
)
{
NTSTATUS status;
PSECURITY_DESCRIPTOR sd;
OBJECT_ATTRIBUTES oa;
UNICODE_STRING uniString; //for communication port name
UNREFERENCED_PARAMETER( RegistryPath );
PT_DBG_PRINT( PTDBG_TRACE_ROUTINES,
("NPminifilter!DriverEntry: Entered\n") );
//
// Register with FltMgr to tell it our callback routines
//
status = FltRegisterFilter( DriverObject,
&FilterRegistration,
&gFilterHandle );
ASSERT( NT_SUCCESS( status ) );
if (NT_SUCCESS( status )) {
//
// Start filtering i/o
//
status = FltStartFiltering( gFilterHandle );
if (!NT_SUCCESS( status )) {
FltUnregisterFilter( gFilterHandle );
}
}
//Communication Port
status = FltBuildDefaultSecurityDescriptor( &sd, FLT_PORT_ALL_ACCESS );
if (!NT_SUCCESS( status )) {
goto final;
}
status = FltBuildDefaultSecurityDescriptor( &sd, FLT_PORT_ALL_ACCESS );
if (!NT_SUCCESS( status )) {
goto final;
}
RtlInitUnicodeString( &uniString, MINISPY_PORT_NAME );
InitializeObjectAttributes( &oa,
&uniString,
OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE,
NULL,
sd );
status = FltCreateCommunicationPort( gFilterHandle,
&gServerPort,
&oa,
NULL,
NPMiniConnect,
NPMiniDisconnect,
NPMiniMessage,
1 );
FltFreeSecurityDescriptor( sd );
if (!NT_SUCCESS( status )) {
goto final;
}
final :
if (!NT_SUCCESS( status ) ) {
if (NULL != gServerPort) {
FltCloseCommunicationPort( gServerPort );
}
if (NULL != gFilterHandle) {
FltUnregisterFilter( gFilterHandle );
}
}
return status;
}
使用FltCreateCommunicationPort进行通信端口相关函数的注册,涉及到通讯的连接、断开、通信三个函数。上例中,通过通信端口名称MINISPY_PORT_NAME将内核与用户进行连接。
而应用程序使用FilterConnectCommunicationPort进行通信连接。使用FilterSendMessage进行通信,其像DeviceIoControl同样具备着输入与输出参数。
参考:《Windows内核编程》 –谭文
《Windows内核编程》–Pavel Yosifovich
本文固定链接: https://www.socarates.online/index.php/2024/02/22/minifilter/ | 安全技术研究
MiniFilter:等您坐沙发呢!
发表评论
