首页
论坛
课程
招聘
[原创]win10 1909逆向(MiniFilter原理剖析1---FltMgr的初始化)
2021-4-16 20:46 3781

[原创]win10 1909逆向(MiniFilter原理剖析1---FltMgr的初始化)

2021-4-16 20:46
3781

0x0 前言


          为了应付面试,学习MiniFilter,顺道将MiniFilter的内部实现基本逆了一道,逆了三个晚上感冒了,先放出一部分,后续会放出MiniFilter通信的内部实现,希望对于像我这种初学MiniFilter,又没有了解sfilter过的同学会有所帮助,大佬请略过。



0x1 原理剖析

        Minifilter开发的驱动程序都依赖于驱动程序 Fltmgr.sys,也就是我们所说的File System Filter Manager(文件过滤系统管理器)。

       本质:我们编写的minifilter过滤驱动则是通过向过滤管理器(Filter Manager)驱动进行注册自己需要过滤的一些操作,提供指定格式的回调函数让过滤管理器来进行调用即可。


FltMgr!GsDriverEntry:入口点

注:编译器默认开启/GS编译选项,用来保护内核栈的完整性。编译器会在程序开始的地方,保存一个cookie值到栈上;在程序退出时再检查这个cookie值是否被破坏,如果被破坏,说明栈溢出,表明系统遭到了破坏从而需要蓝屏保护。

GS是一种被普遍运用的保护机制。开启了GS选项后,编译器会链接一个GS相关的库文件来实现GS功能,当目标系统为Win7时库文件是BufferOverflowK.lib,当目标系统为Win8+时库文件是BufferOverflowFastFailK.lib。链接器是如何实现栈保护的呢?它先在驱动加载的时候,也就是GsDriverEntry函数内初始化cookie。然后在每个驱动函数的开始和结束的地方,添加cookie检查的代码。

链接器为了对cookie进行初始化,会为驱动程序重新生成一个名为GsDriverEntry的入口函数,初始化Cookie后再调用驱动程序自己的DriverEntry入口函数。

----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

NTSTATUS DriverEntry(PDRIVER_OBJECT pDriverObject,PUNICODE_STRING pReg)(参数如下)

//注册MiniFsFilter的通知回调例程必须分配并初始化FS_FILTER_CALLBACKS结构体,后续会向该结构体中写入MiniFs回调例程,并将存储有Callbacks parameter到FsRtlRegisterFileSystemFilterCallbacks中。


FS_FILTER_CALLBACKS Callbacks;

RtlZeroMemory(&Callbacks,Sizeof(FS_FILTER_CALLBACKS));


//FTLMGR初始化全局变量结构,过滤管理器的关链数据结构都写在这个里面

GLOBALS FltGlobals;

RtlZeroMemory(&FltGlobals,Sizeof(GLOBALS))


//设置初始化标志, 1代表FltMgr驱动启动. Gflags第8位,是代表是否DisableFrameMonitoring

FltGlobals.Gflags=1;

//动态加载,将FsrtlFltMgrCallbacks的地址放进FltMgrCallbacks全局变量里

FsRtlRegisterFltMgrCalls(FsrtlFltMgrCallbacks);

//

FltGlobals.Gflags |= 0x102;

FltGlobals.FastManualAttachTimerPeriod=5;

FltGlobals.ManualAttachTimerPeriod=0xF;

//通过注册表里的参数给FltGlobals的结构赋值

FltpReadDriverParameters(RegPath);   RegPath=\Registry\Machine\System\CurrentControlSet\Services\FltMgr

//初始化驱动程序分配的资源结构

ExInitializeResourceLite(&FltDynamicRegistrySettingsResource);

//注册表监控,监控Registry\\Machine\\System\\CurrentControlSet\\Control\\FileSystem\下所有子键

REG_NOTIFY_CHANGE_NAME | REG_NOTIFY_CHANGE_LAST_SET的改变,例程立即返回

实际上就是调用ZwNotifyChangeKey

//判断是否对OCX磁盘阵列的支持,写进FltGlobals.FilterSupportedFeaturesMode   0为允许,1为禁止

//并且更新FltGlobals.FilterSupportedFeaturesMode

FltpUpdateDynamicRegistrySettings();

//给FltMgr全局变量赋值

FltGlobals.DriverObject = DriverObject;

FltGlobals.ActiveProcessorCount = KeQueryActiveProcessorCountEx(0xFFFFi64); //得到当前活动CPU数量

FltGlobals.CacheLineSize = KeGetRecommendedSharedDataAlignment();//Cache缓存的基本单位

FltGlobals.AlignedInstanceTrackingListSize = ~(FltGlobals.CacheLineSize - 1) & (FltGlobals.CacheLineSize - 1 + 0x30);

FltGlobals.RegistryPath.MaximumLength=0x140

FltGlobals.RegistryPath.Buffer = &FltGlobals.RegistryPathBuffer;

RtlCopyUnicodeString(&FltGlobals.RegistryPath, RegPath); //注册表路径Registry\Machine\System\CurrentControlSet\Services\FltMgr复制进去

//创建CDO(控制设备对象)

Status = IoCreateDevice(  DriverObject,

NULL,

&FltMgrDeviceName,   //"\FileSystem\Filters\FltMgr"

FILE_DEVICE_DISK_FILE_SYSTEM, //磁盘文件系统

FILE_DEVICE_SECURE_OPEN,   //标识指示I/O管理器对所有发送到控制设备对象的Open请求进行安全检测

FALSE,

&FltGlobals.ControlDeviceObject);

//创建符号链接

RtlInitUnicodeString(&SymbolicLinkName, L"\\DosDevices\\FltMgr");

Status=IoCreateSymbolicLink(&SymbolicLinkName, &FltMgrDeviceName)

//CDO设备扩展结构指针

(FltGlobals.ControlDeviceObject)->DeviceExtension=0;

//初始化事件跟踪

FltpInitializeTelemetry();

//设置派遣函数

for (i = 0; i <= IRP_MJ_MAXIMUM_FUNCTION; i++){

DriverObject->MajorFunction[i] = FltpDispatch;

}

DriverObject->MajorFunction[IRP_MJ_CREATE] = FltpCreate;

DriverObject->MajorFunction[IRP_MJ_CREATE_NAMED_PIPE] = FltpCreate;

DriverObject->MajorFunction[IRP_MJ_CREATE_MAILSLOT] = FltpCreate;

DriverObject->MajorFunction[IRP_MJ_FILE_SYSTEM_CONTROL] = FltpFsControl; //卷设备绑定

//初始化文件快速IO

PFAST_IO_DISPATCH fastIoDispatch;

fastIoDispatch = ExAllocatePoolWithTag( NonPagedPoolNx,sizeof( FAST_IO_DISPATCH ),'ifMF' );

if ( fastIoDispatch )

{

 /*

      当请求直接传递到基本文件系统时,有6个FastIO例程绕过了文件系统过滤器。

      这6个例程是AcquireFileForNtCreateSection、ReleaseFileForNtCreateSection、

       AcquireForModWrite、ReleaseForModWrite、AcquireForCcFlush和ReleaseForCcFlush。

                                                                                                                                */

RtlZeroMemory(fastIoDispatch,SizeOf(FAST_IO_DISPATCH));

FastIoDipatch->SizeOfFastIoDispatch = Sizeof(FAST_IO_DISPATCH);

FastIoDipatch->FastIoCheckIfPossible = FltpFastIoCheckIfPossible;

FastIoDipatch->FastIoRead = FltpFastIoRead;

FastIoDipatch->FastIoWrite = FltpFastIoWrite;

FastIoDipatch->FastIoQueryBasicInfo = FltpFastIoQueryBasicInfo;

FastIoDipatch->FastIoQueryStandardInfo = FltpFastIoQueryStandardInfo;

FastIoDipatch->FastIoLock = FltpFastIoLock;

FastIoDipatch->FastIoUnlockSingle = FltpFastIoUnlockSingle;

FastIoDipatch->FastIoUnlockAll = FltpFastIoUnlockAll;

FastIoDipatch->FastIoUnlockAllByKey = FltpFastIoUnlockAllByKey;

FastIoDipatch->FastIoDeviceControl = FltpFastIoDeviceControl;

FastIoDipatch->FastIoDetachDevice = FltpFastIoDetachDevice;

FastIoDipatch->FastIoQueryNetworkOpenInfo = FltpFastIoQueryNetworkOpenInfo;

FastIoDipatch->FastIoQueryOpen = FltpFastIoQueryOpen;

FastIoDipatch->MdlRead = FltpFastIoMdlRead;

FastIoDipatch->MdlReadComplete = FltpFastIoMdlReadComplete;

FastIoDipatch->PrepareMdlWrite = FltpFastIoPrepareMdlWrite;

FastIoDipatch->MdlWriteComplete = FltpFastIoMdlWriteComplete;

FastIoDipatch->FastIoReadCompressed = FltpFastIoReadCompressed;

FastIoDipatch->FastIoWriteCompressed = FltpFastIoWriteCompressed;

FastIoDipatch->MdlReadCompleteCompressed = FltpFastIoMdlReadCompleteCompressed;

FastIoDipatch->MdlWriteCompleteCompressed = FltpFastIoMdlWriteCompleteCompressed;

DriverObject->FastIoDispatch = FastIoDipatch;

//初始化FsFilter回调

FS_FILTER_CALLBACKS fsFilterCallbacks;

fsFilterCallbacks.SizeOfFsFilterCallbacks = sizeof( FS_FILTER_CALLBACKS );

fsFilterCallbacks.PreAcquireForSectionSynchronization = FltpPreFsFilterOperation;

fsFilterCallbacks.PostAcquireForSectionSynchronization = FltpPostFsFilterOperation;

fsFilterCallbacks.PreReleaseForSectionSynchronization = FltpPreFsFilterOperation;

fsFilterCallbacks.PostReleaseForSectionSynchronization = FltpPostFsFilterOperation;

fsFilterCallbacks.PreAcquireForCcFlush = FltpPreFsFilterOperation;

fsFilterCallbacks.PostAcquireForCcFlush = FltpPostFsFilterOperation;

fsFilterCallbacks.PreReleaseForCcFlush = FltpPreFsFilterOperation;

fsFilterCallbacks.PostReleaseForCcFlush = FltpPostFsFilterOperation;

fsFilterCallbacks.PreAcquireForModifiedPageWriter = FltpPreFsFilterOperation;

fsFilterCallbacks.PostAcquireForModifiedPageWriter = FltpPostFsFilterOperation;

fsFilterCallbacks.PreReleaseForModifiedPageWriter = FltpPreFsFilterOperation;

fsFilterCallbacks.PostReleaseForModifiedPageWriter = FltpPostFsFilterOperation;

fsFilterCallbacks.PreQueryOpen = FltpPreFsFilterOperation;

fsFilterCallbacks.PostQueryOpen=FltpPostFsFilterOperation;

//注册文件过滤系统回调,其实就是将上面初始化的回调函数复制到新申请的内存,并将地址写进DriverObject->DriverExtension->FsFilterCallBacks里

 status = FsRtlRegisterFileSystemFilterCallbacks( DriverObject, &fsFilterCallbacks );


//初始化MiniFilter通信端口(用来三环和0环通信),

status = FltpInitializeMessagingSupport(DriverObject);

1.创建二个对象类型(FilterConnectionPort)

(FilterCommunicationPort)

2.创建设备对象

3.创建符号



FltpInitializeMessagingSupport主要就是实现了这三个功能,并将结果放入FltGlobals结构体里



//初始化参数偏移表

FltpBuildParameterOffsetTable();

//初始化

FltpInitThrottledWorkItemCtrl();



//初始化

FltGlobals.Phase2InitLock = 1;

FltGlobals.Phase2InitLock_Owner = 0;

FltGlobals.Phase2InitLock_Contention = 0;

//

KeInitializeEvent(&Event, SynchronizationEvent, 0);

//第二阶段初始化完成

//主要是初始化FltGloblas上的各个链表。

status = FltpCompletePhase2Init();

//上面的FltpInitLokkasideList,也是完成各个链表的初始化:


/这个函数实现比较复杂

status = FltpAttachFrame(&FrameZeroAltitude, &v41);

主要实现过程:

1.申请一段空间用来存放FRAME

PFLTP_FRAME NewFrame = ExAllocatePoolWithTag(NonPagedPoolNx, Sizeof(FLTP_FRAME), 'rfMF');

NewFrame->Type.Signature=0xF103

NewFrame->Type.Size=0x780

if(FltGlobals->FrameList.rCount) //如果FrameList里存在Frame

{

preFrame = (FltGlobals->FrameList->Fink - 8);

NewFrame->FrameID = *(FltGlobals->FrameList->Fink - 8 + 0x18) + 1;  //NewFrame->FrameID=(preFrame->FrameId+1)

   //NewFrame->AltitudeIntervalLow存放的是前面那一个层高

status = FltpCopyUnicodeString(&NewFrame->AltitudeIntervalLow, & preFrame->AltitudeIntervalHigh);

}else

{

//将前一个层高置为“0”

RtlInitUnicodeString(&DestinationString, L"0");

status = FltpCopyUnicodeString(&NewFrame->AltitudeIntervalLow, &DestinationString);

FltpStartManualDeviceAttachChecks();

}

//将“49999”这个层高复制到FRAME里

status = FltpCopyUnicodeString(&NewFrame->AltitudeIntervalHigh, FrameZeroAltitude);

//将Frame里的其他部分初始化

status = FltpInitializeFrame(NewFrame);

//将Frame添加到全局变量里

FltGlobals.FrameList.rCount++;

NewFrame->Link.Fink= FltGlobals.FrameList.Fink;

FltGlobals.FrameList.Fink=NewFrame->Link.Blink;

NewFrame->Link.Bink= &FltGlobals.FrameList;

FltGlobals.FrameList.Bink=&NewFrame->Link;

2.注册一个文件系统变动回调函数,用来被通知文件系统的激活和注销

status = IoRegisterFsRegistrationChangeMountAware(FltGlobals.DriverObject, FltpFsNotification, TRUE);

1.确认文件过滤能接受的范围。

2.将结构填充到IopFsNotifyChangeQueueHead队列尾部。

nPacket->DriverObject = DriverObject;

nPacket->NotificationRoutine = DriverNotificationRoutine;

InsertTailList( &IopFsNotifyChangeQueueHead, &nPacket->ListEntry );

//挂靠

RtlInitUnicodeString(&ObjectName, L"\\Device\\RawDisk");

IoGetDeviceObjectPointer(&ObjectName, 0x80u, &FileObject, &DeviceObject)

FltpFsNotificationActual(DeviceObject, 1);

里面实现最关键的函数:

FltpAttachToFileSystemDevice(DeviceObject, &ObjectName)

1.FltpCreateControlDeviceObject    FltMgr创建一个CDO设备。

2.FltpAttachDeviceObject    将FltMgr创建的CDO设备挂靠到RawDisk设备上

ObfDereferenceObject(FileObject);

RtlInitUnicodeString(&ObjectName, L"\\Device\\RawCdRom");

IoGetDeviceObjectPointer(&ObjectName, 0x80u, &FileObject, &DeviceObject)

FltpFsNotificationActual(DeviceObject, 1);

里面实现最关键的函数:

FltpAttachToFileSystemDevice(DeviceObject, &ObjectName)

1.FltpCreateControlDeviceObject    FltMgr创建一个CDO设备。

2.FltpAttachDeviceObject    将FltMgr创建的CDO设备挂靠到RawCdRom设备上

ObfDereferenceObject(FileObject);

//创建一个回调,加载完start=1,2,3的所有驱动程序以后,调用回调,里面设置了一个标志位,代表加载完成。

IoRegisterDriverReinitialization(DriverObject, FltpDriverReinitialization, 0);


完。



第五届安全开发者峰会(SDC 2021)10月23日上海召开!限时2.5折门票(含自助午餐1份)

收藏
点赞4
打赏
分享
最新回复 (4)
雪    币: 3793
活跃值: 活跃值 (3951)
能力值: ( LV4,RANK:55 )
在线值:
发帖
回帖
粉丝
下咯 活跃值 2021-4-17 09:26
2
0

。。。。有点乱

最后于 2021-5-3 15:20 被下咯编辑 ,原因:
雪    币: 6802
活跃值: 活跃值 (696)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
Ally Switch 活跃值 2021-4-17 09:32
3
0
豆总牛逼
雪    币: 7309
活跃值: 活跃值 (8548)
能力值: ( LV12,RANK:340 )
在线值:
发帖
回帖
粉丝
SSH山水画 活跃值 4 2021-4-19 17:33
4
0
豆总带带弟弟啊
雪    币: 249
活跃值: 活跃值 (112)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
Anowhere 活跃值 2021-4-30 20:12
5
0
豆总牛逼
游客
登录 | 注册 方可回帖
返回