Minfilter说白了就是基于一个结构 FLT_REGISTRATION 的东西。
我们在驱动中把这个结构定义成全局的。在通过三个函数就可以简单操作Minfilter了
他们分别是
FltRegisterFilter();注册minifilter 函数
FltStartFiltering();开启minifilter 函数
FltUnregisterFilter();停止卸载 minifilter 函数
下面介绍 FLT_REGISTRATION 这个重要的结构体
typedef struct _FLT_REGISTRATION {
USHORT Size; //FLT_REGISTRATION结构的大小(以字节为单位)必须将此成员设置为
sizeof(FLT_REGISTRATION)。
USHORT Version; //FLT_REGISTRATION结构的版本。必须将此成员设置为FLT_REGISTRATION_VERSION。
FLT_REGISTRATION_FLAGS Flags; //这里是个标志位一般填写为0即可
CONST FLT_CONTEXT_REGISTRATION *ContextRegistration; //(标红)这里是minifilter的一个上下文。什么意思呢。也就是这里是一段缓存空间,可以用FltAllocateContext()进行分配之后存一些额外数据 (可以为null)
CONST FLT_OPERATION_REGISTRATION *OperationRegistration; //(标红)这里是minfilter的灵魂 这里是一组回调函数,一个回调对应一个Irp
PFLT_FILTER_UNLOAD_CALLBACK FilterUnloadCallback; //这里是minfilter的卸载函数,可以做一些收尾工作。可以为null,填写null 则这个minfilter就不能卸载。
PFLT_INSTANCE_SETUP_CALLBACK InstanceSetupCallback; //这里也是一个回调,minfilter在首个create操作上调用它,来通知说有一个可用卷
PFLT_INSTANCE_QUERY_TEARDOWN_CALLBACK InstanceQueryTeardownCallback; //这里也是一个回调,手工解除绑定,在实例被销毁时被调用。可以设置成NULL
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; //可空
}
(标红)然而 _FLT_REGISTRATION 中最重要的成员 是 OperationRegistration 是一个结构体,为什么说他重要呢,因为我们可以设置他 在开启minfilter之后,从而拦截处理我们所关心的irp,所以一般这里需要写成数组。
也就是结构体数组。
我们来看一下这个结构
typedef struct _FLT_OPERATION_REGISTRATION {
UCHAR MajorFunction; //需要捕捉irp的类型
FLT_OPERATION_REGISTRATION_FLAGS Flags; //标志位,可以设置 忽略掉一些io操作。
PFLT_PRE_OPERATION_CALLBACK PreOperation; //当此irp请求准备做事情之前会被我们拦截到,用此回调来通知我们,我们在此处理这个irp,可以为null
PFLT_POST_OPERATION_CALLBACK PostOperation; //当此irp请求做完事情之后,会被我们拦截到,用此回调来通知我们,我们在这个时间在进行处理,可以为null
PVOID Reserved1; //系统保留值,必须为null
} FLT_OPERATION_REGISTRATION, *PFLT_OPERATION_REGISTRATION;
观此结构,我们可以发现。只要我们把这个结构体数组 填上我们需要关心的irp 并且提供相应的回调,我们就能处理此次irp 请求。达到我们的需要,比如加解密,查毒等
注意这个结构体数组的最后一个元素必须为 { IRP_MJ_OPERATION_END } ,不然minfilter 分不清这个数组有多大。
我们以下称 当此irp请求准备做事情之前的回调 称为Pre操作。 当此irp请求做完事情之后的回调 称为Post操作。
他们的总体结构如图所示:
他们的定义分别如下
Pre操作 回调
FLT_PREOP_CALLBACK_STATUS
Pre (
_Inout_ PFLT_CALLBACK_DATA Data, //这是我们的irp 已经被重组称CallBackData包了。本质上还是irp
_In_ PCFLT_RELATED_OBJECTS FltObjects, //这里是和我们minfilter相关的一些对象 ,有哪些呢(1)卷设备对象(2)我们的实例对象(3)目标文件的内核对象(4)目标文件所在的设备对象
_Flt_CompletionContext_Outptr_ PVOID *CompletionContext
)
{
//业务逻辑
return 下面讲解;
}
FLT_POSTOP_CALLBACK_STATUS
FsFilter1PostOperation (
_Inout_ PFLT_CALLBACK_DATA Data, //这是我们的irp 已经被重组称CallBackData包了。本质上还是irp
_In_ PCFLT_RELATED_OBJECTS FltObjects, //这里是和我们minfilter相关的一些对象 ,有哪些呢(1)卷设备对象(2)我们的实例对象(3)目标文件的内核对象(4)目标文件所在的设备对象
_In_opt_ PVOID CompletionContext,
_In_ FLT_POST_OPERATION_FLAGS Flags
)
{
//业务逻辑
return 下面讲解;
}
他们的不同 (1)他们的返回类值不一样。(2)他们的参数不一样,这点上面有说明
他们的返回值都是返回给minfilter管理器看的
[培训]科锐逆向工程师培训第53期2025年7月8日开班!
最后于 2019-8-1 18:35
被骄阳a编辑
,原因: