2015年5月29日星期五

一种minifilter驱动保护的方案

/*
通常的保护驱动的思路是在驱动入口不设置驱动对象的卸载函数的成员。

minifilter框架也类似。

开始的思路也是这样的,
可是经测试不行,因为通常minifilter不设置驱动对象的卸载函数,而是设置FLT_REGISTRATION的卸载函数。
经分析FltRegisterFilter是把自己的_FLT_REGISTRATION复制/修改到_FLT_FILTER。
最后经分析和原始的想法是一样的。
不罗嗦了,直接见要点.

具体的做法是:
1.FLT_REGISTRATION的Flags包含FLTFL_REGISTRATION_DO_NOT_SUPPORT_SERVICE_STOP。
  这是通过逆向分析出的。
  MSDN是这样说的:
  If this flag is set, the minifilter is not unloaded in response to service stop requests, even if the FilterUnloadCallback member is not NULL.
  也就是说,如果这样了即使设置了FilterUnloadCallback成员,FilterUnloadCallback成员也是无效的。
  具体的键反汇编。
  还有一个值是:FLTFL_REGISTRATION_SUPPORT_NPFS_MSFS,这个早就研究了。
2.驱动不能停止咋办?(不同于卸载,禁止卸载可以通过注册表回调来实现,更不是隐藏等别的功能)
  此时驱动还在运行,我们可以和他通讯呀!
  所以可选的思路有:
  1)设置驱动对象的卸载函数为FLT_REGISTRATION的FilterUnloadCallback应该设置的函数。
  2)设置驱动对象的卸载函数为fltmgr!FltpMiniFilterDriverUnload。
  3)设置驱动对象的卸载函数为nt!IopInvalidDeviceRequest。
  经测试:
  方法三是不可行的,这个会蓝屏,蓝屏原因就不说了,你分析吧!
  方法二是不可取的,因为那个函数是未公开的,函数的地址不好获取。
  方法以是可行的,建议的。

made by correy
made at 2015.05.29

下面附下IDA分析的FltRegisterFilter函数:
*/

NTSTATUS __stdcall FltRegisterFilter(PDRIVER_OBJECT Driver, _FLT_REGISTRATION *Registration, _FLT_FILTER **RetFilter)
    /*
    略有改动,改为自己的编码风格。
    里面还有一些数字的含义,请自己修改。
    */
{
    NTSTATUS result; // eax@2
    _FLT_REGISTRATION *P_FLT_REGISTRATION; // esi@3
    int n; // eax@10
    _FLT_OPERATION_REGISTRATION *OperationRegistration; // ecx@10
    _FLT_FILTER *Ret_Filter; // ebx@14
    _FLT_MUTEX_LIST_HEAD *ActiveOpens; // ST28_4@16
    _FLT_MUTEX_LIST_HEAD *PortList; // ST20_4@16
    _FLT_OPERATION_REGISTRATION *i; // eax@19
    char MajorFunction; // cl@20
    int temp; // ST44_4@28
    unsigned int OperationRegistration_length; // [sp+30h] [bp-24h]@14
    _FLT_OPERATION_REGISTRATION *P_FLT_OPERATION_REGISTRATION; // [sp+34h] [bp-20h]@16
    NTSTATUS result_2; // [sp+38h] [bp-1Ch]@17
    BOOL B = FALSE;

    *RetFilter = 0;

    if ( !(g_dword_BIT & 1) )
        return 0xC01C0007;                          // 见ntstatus.h的定义。

    P_FLT_REGISTRATION = Registration;

    if ( (Registration->Version & 0xFF00) != 512 )
        return 0xC000000D;  // 见ntstatus.h的定义。

    result = FltpRestoreFltMgrsPageableState();
    if ( result < 0 )
        return result;

    B = (Registration->GenerateFileNameCallback || !Registration->NormalizeNameComponentCallback) && (Registration->NormalizeNameComponentCallback || !Registration->NormalizeContextCleanupCallback);
    if ( !B )
    {
        return 0xC000000D;  // 见ntstatus.h的定义。
    }

    n = 0;
    OperationRegistration = Registration->OperationRegistration;
    if ( OperationRegistration )
    {
        while ( 1 )
        {
            ++n;
            if ( OperationRegistration->MajorFunction == -128 )
                break;
            ++OperationRegistration;
        }
    }

    OperationRegistration_length = 20 * n;

    Ret_Filter = (_FLT_FILTER *)ExAllocatePoolWithTag(0, 20 * n + Driver->DriverExtension->ServiceKeyName.Length + 288, 0x6C664D46u);
    if ( !Ret_Filter )
    {
        return 0xC000009A;
    }

    memset(Ret_Filter, 0, 0x120u);
    Ret_Filter->FilterUnload = Registration->FilterUnloadCallback;
    Ret_Filter->InstanceSetup = Registration->InstanceSetupCallback;
    Ret_Filter->InstanceQueryTeardown = Registration->InstanceQueryTeardownCallback;
    Ret_Filter->InstanceTeardownStart = Registration->InstanceTeardownStartCallback;
    Ret_Filter->InstanceTeardownComplete = Registration->InstanceTeardownCompleteCallback;
    Ret_Filter->GenerateFileName = Registration->GenerateFileNameCallback;
    Ret_Filter->NormalizeNameComponent = Registration->NormalizeNameComponentCallback;
    Ret_Filter->NormalizeContextCleanup = Registration->NormalizeContextCleanupCallback;
    P_FLT_OPERATION_REGISTRATION = (_FLT_OPERATION_REGISTRATION *)&Ret_Filter[1];
    Ret_Filter->Base.Flags = 0x2000000;
    Ret_Filter->Base.PointerCount = 1;
    FltpExInitializeRundownProtection(&Ret_Filter->Base.RundownRef);
    Ret_Filter->Base.PrimaryLink.Flink = 0;
    FltObjectReference((int)Ret_Filter);
    Ret_Filter->DriverObject = Driver;
    Ret_Filter->InstanceList.rCount = 0;
    ExInitializeResourceLite(&Ret_Filter->InstanceList.rLock);
    InitializeListHead(&Ret_Filter->InstanceList.rList);
    ActiveOpens = &Ret_Filter->ActiveOpens;
    ActiveOpens->mCount = 0;
    ActiveOpens->mLock.Count = 1;
    ActiveOpens->mLock.Owner = 0;
    ActiveOpens->mLock.Contention = 0;
    KeInitializeEvent(&Ret_Filter->ActiveOpens.mLock.Event, SynchronizationEvent, 0);
    InitializeListHead(&Ret_Filter->ActiveOpens.mList);
    PortList = &Ret_Filter->PortList;
    PortList->mCount = 0;
    PortList->mLock.Count = 1;
    PortList->mLock.Owner = 0;
    PortList->mLock.Contention = 0;
    KeInitializeEvent(&Ret_Filter->PortList.mLock.Event, SynchronizationEvent, 0);
    InitializeListHead(&Ret_Filter->PortList.mList);
    Ret_Filter->PortLock.Value = 0;

    if ( !Registration->ContextRegistration || (result_2 = FltpProcessContextRegistration((int)Ret_Filter, &Registration->ContextRegistration->ContextType), result_2 >= 0) )
    {
        if ( Registration->OperationRegistration )//各个操作的前后操作。
        {
            Ret_Filter->Operations = P_FLT_OPERATION_REGISTRATION;
            P_FLT_OPERATION_REGISTRATION = (_FLT_OPERATION_REGISTRATION *)((char *)P_FLT_OPERATION_REGISTRATION + OperationRegistration_length);
            qmemcpy(&Ret_Filter[1], Registration->OperationRegistration, OperationRegistration_length);
            for ( i = Ret_Filter->Operations; ; ++i )
            {
                MajorFunction = i->MajorFunction;
                if ( i->MajorFunction == -128 )
                    break;

                if ( MajorFunction == -19 )
                {
                    Ret_Filter->PreVolumeMount = i->PreOperation;
                    Ret_Filter->PostVolumeMount = i->PostOperation;
                }
                else if ( MajorFunction != -20 && MajorFunction == 16 )//#define IRP_MJ_SHUTDOWN                 0x10.关机是没有后操作的,有了,按思想是笑话。你设置了,这里也会给抹掉。
                {
                    i->PostOperation = 0;
                }
            }

            P_FLT_REGISTRATION = Registration;
        }

        Ret_Filter->Name.Buffer = (unsigned __int16 *)P_FLT_OPERATION_REGISTRATION;
        Ret_Filter->Name.Length = 0;
        Ret_Filter->Name.MaximumLength = Driver->DriverExtension->ServiceKeyName.Length;
        temp = (int)(&P_FLT_OPERATION_REGISTRATION->MajorFunction + Driver->DriverExtension->ServiceKeyName.Length);
        RtlCopyUnicodeString((PUNICODE_STRING)&Ret_Filter->Name, (PCUNICODE_STRING)&Driver->DriverExtension->ServiceKeyName);
        result_2 = FltpInitializeFilterVerifier(Ret_Filter);
        if ( result_2 >= 0 )
        {
            result_2 = FltpGetInstanceAltitude(Ret_Filter, 0, 0, (PUNICODE_STRING)&Ret_Filter->DefaultAltitude);
            if ( result_2 >= 0 )
            {
                result_2 = FltpFindFrameForFilter(Ret_Filter, &Ret_Filter->DefaultAltitude);
                if ( result_2 >= 0 )
                {
                    result_2 = FltpLinkFilterIntoFrame(Ret_Filter);
                    if ( result_2 >= 0 )
                    {
                        Ret_Filter->OldDriverUnload = Driver->DriverUnload;
                        if ( !P_FLT_REGISTRATION->FilterUnloadCallback || P_FLT_REGISTRATION->Flags & 1 )//#define FLTFL_REGISTRATION_DO_NOT_SUPPORT_SERVICE_STOP  0x00000001
                        {//If this flag is set, the minifilter is not unloaded in response to service stop requests, even if the FilterUnloadCallback member is not NULL.
                            Driver->DriverUnload = 0;
                            DriverObject->DriverUnload = 0;
                        }
                        else
                        {
                            Driver->DriverUnload = (void (__stdcall *)(_DRIVER_OBJECT *))FltpMiniFilterDriverUnload;
                        }
                        if ( !(g_dword_BIT & 0x20) )
                            g_dword_BIT |= 0x20u;

                        *RetFilter = Ret_Filter;
                    }
                }
            }
        }
    }

    if ( result_2 < 0 )
    {
        ExDeleteResourceLite(&Ret_Filter->InstanceList.rLock);
        FltpCleanupContextRegistration(Ret_Filter);
        FltpCleanupFilterVerifier(Ret_Filter);
        FltpFreeUnicodeString(&Ret_Filter->DefaultAltitude);
        ExFreePoolWithTag(Ret_Filter, 0);
    }

    result = result_2;

    return result;
}


/*
3.注意:
  文件微过滤驱动的卸载函数的原型是:
  typedef NTSTATUS (*PFLT_FILTER_UNLOAD_CALLBACK) ( FLT_FILTER_UNLOAD_FLAGS Flags );
  这个不同于常规驱动的的卸载函数。
  VOID DRIVER_UNLOAD ( _In_ struct _DRIVER_OBJECT *DriverObject );
  区别是返回值和参数。

  这里有一个值:FLTFL_FILTER_UNLOAD_MANDATORY。

  这个函数的说明是:
  Minifilter drivers are not required to register a FilterUnloadCallback routine.
  However, registering an unload routine is strongly recommended.
  If a minifilter driver does not register a FilterUnloadCallback routine, it cannot be unloaded.
  卸载函数不是必须的,但是强烈建议加上,如果没有就不能卸载。

  注意:FLTFL_FILTER_UNLOAD_MANDATORY和STATUS_FLT_DO_NOT_DETACH的关系。
  如果:是FLTFL_FILTER_UNLOAD_MANDATORY必须返回成功,如果返回STATUS_FLT_DO_NOT_DETACH会蓝屏。
        可是用net stop每次都是FLTFL_FILTER_UNLOAD_MANDATORY,sc stop没有试验,但是fltmc unload 却不是。
        所以此思路无效不可行。
*/

没有评论:

发表评论