当前位置: 首页 > 内核 > 正文

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/ | 安全技术研究

avatar
该日志由 Socarates 于2024年02月22日发表在 内核 分类下, 你可以发表评论,并在保留原文地址及作者的情况下引用到你的网站或博客。
原创文章转载请注明: MiniFilter | 安全技术研究
关键字: , , ,
【上一篇】
【下一篇】

MiniFilter:等您坐沙发呢!

发表评论


快捷键:Ctrl+Enter