Minifilter 是一种文件过滤驱动,该驱动简称为微过滤驱动,相对于传统的sfilter文件过滤驱动来说,微过滤驱动编写时更简单,其不需要考虑底层RIP如何派发且无需要考虑兼容性问题,微过滤驱动使用过滤管理器FilterManager提供接口,由于提供了管理结构以及一系列管理API函数,所以枚举过滤驱动将变得十分容易。

通常文件驱动过滤是ARK重要功能之一,如下是一款闭源ARK工具的输出效果图。

由于MiniFilter提供了FltEnumerateFilters函数,所以只需要调用这些函数即可获取到所有的过滤器地址,我们看下微软公开的信息。

NTSTATUS FLTAPI FltEnumerateFilters(
[out] PFLT_FILTER *FilterList,
[in] ULONG FilterListSize,
[out] PULONG NumberFiltersReturned
);

此函数需要注意,如果用户将FilterList设置为NULL则默认是输出当前系统中存在的过滤器数量,而如果传入的是一个内存地址,则将会枚举系统中所有的过滤器信息。

使用FltEnumerateFilters这个API,它会返回过滤器对象FLT_FILTER的地址,然后根据过滤器对象的地址,加上一个偏移,获得记录过滤器PreCall、PostCall、IRP等信息的PFLT_OPERATION_REGISTRATION结构体指针。

上文之所以说要加上偏移,是因为FLT_FILTER的定义在每个系统都不同,比如WIN10 X64中的定义以下样子,这里我们需要记下+0x1a8 Operations因为他指向的就是_FLT_OPERATION_REGISTRATION结构的偏移地址。

lyshark.com: kd> dt fltmgr!_FLT_FILTER
+0x000 Base : _FLT_OBJECT
+0x030 Frame : Ptr64 _FLTP_FRAME
+0x038 Name : _UNICODE_STRING
+0x048 DefaultAltitude : _UNICODE_STRING
+0x058 Flags : _FLT_FILTER_FLAGS
+0x060 DriverObject : Ptr64 _DRIVER_OBJECT
+0x068 InstanceList : _FLT_RESOURCE_LIST_HEAD
+0x0e8 VerifierExtension : Ptr64 _FLT_VERIFIER_EXTENSION
+0x0f0 VerifiedFiltersLink : _LIST_ENTRY
+0x100 FilterUnload : Ptr64 long
+0x108 InstanceSetup : Ptr64 long
+0x110 InstanceQueryTeardown : Ptr64 long
+0x118 InstanceTeardownStart : Ptr64 void
+0x120 InstanceTeardownComplete : Ptr64 void
+0x128 SupportedContextsListHead : Ptr64 _ALLOCATE_CONTEXT_HEADER
+0x130 SupportedContexts : [7] Ptr64 _ALLOCATE_CONTEXT_HEADER
+0x168 PreVolumeMount : Ptr64 _FLT_PREOP_CALLBACK_STATUS
+0x170 PostVolumeMount : Ptr64 _FLT_POSTOP_CALLBACK_STATUS
+0x178 GenerateFileName : Ptr64 long
+0x180 NormalizeNameComponent : Ptr64 long
+0x188 NormalizeNameComponentEx : Ptr64 long
+0x190 NormalizeContextCleanup : Ptr64 void
+0x198 KtmNotification : Ptr64 long
+0x1a0 SectionNotification : Ptr64 long
+0x1a8 Operations : Ptr64 _FLT_OPERATION_REGISTRATION
+0x1b0 OldDriverUnload : Ptr64 void
+0x1b8 ActiveOpens : _FLT_MUTEX_LIST_HEAD
+0x208 ConnectionList : _FLT_MUTEX_LIST_HEAD
+0x258 PortList : _FLT_MUTEX_LIST_HEAD
+0x2a8 PortLock : _EX_PUSH_LOCK

解析FLT_OPERATION_REGISTRATION结构体,可以看到这就是我们需要枚举的过滤器,只要拿到它输出即可:

lyshark.com: kd> dt fltmgr!_FLT_OPERATION_REGISTRATION
+0x000 MajorFunction : UChar
+0x004 Flags : Uint4B
+0x008 PreOperation : Ptr64 _FLT_PREOP_CALLBACK_STATUS
+0x010 PostOperation : Ptr64 _FLT_POSTOP_CALLBACK_STATUS
+0x018 Reserved1 : Ptr64 Void

枚举过滤器代码如下所示。

// 配置属性 -> 连接器 -> 输入-> 附加依赖 -> fltMgr.lib
// 配置属性 -> C/C++ -> 常规 -> 设置 警告等级2级 (警告视为错误关闭) #include <fltKernel.h>
#include <dontuse.h>
#include <suppress.h> // 设置默认回调
NTSTATUS DriverDefaultHandle(PDEVICE_OBJECT pDevObj, PIRP pIrp)
{
NTSTATUS status = STATUS_SUCCESS;
pIrp->IoStatus.Status = status;
pIrp->IoStatus.Information = 0;
IoCompleteRequest(pIrp, IO_NO_INCREMENT); return status;
} VOID DriverUnload(PDRIVER_OBJECT pDriverObject)
{
} NTSTATUS DriverEntry(PDRIVER_OBJECT pDriverObject, PUNICODE_STRING pRegPath)
{
DbgPrint("hello lyshark.com \n"); NTSTATUS status = STATUS_SUCCESS;
pDriverObject->DriverUnload = DriverUnload;
for (ULONG i = 0; i < IRP_MJ_MAXIMUM_FUNCTION; i++)
{
pDriverObject->MajorFunction[i] = DriverDefaultHandle;
} ULONG ulFilterListSize = 0;
PFLT_FILTER *ppFilterList = NULL;
ULONG i = 0;
LONG lOperationsOffset = 0;
PFLT_OPERATION_REGISTRATION pFltOperationRegistration = NULL; // 获取 Minifilter 过滤器Filter 的数量
FltEnumerateFilters(NULL, 0, &ulFilterListSize); // 申请内存
ppFilterList = (PFLT_FILTER *)ExAllocatePool(NonPagedPool, ulFilterListSize *sizeof(PFLT_FILTER));
if (NULL == ppFilterList)
{
return FALSE;
} // 获取 Minifilter 中所有过滤器Filter 的信息
status = FltEnumerateFilters(ppFilterList, ulFilterListSize, &ulFilterListSize);
if (!NT_SUCCESS(status))
{
return FALSE;
} DbgPrint("过滤器数量: %d \n", ulFilterListSize); // 获取 PFLT_FILTER 中 Operations 偏移
lOperationsOffset = 0x1A8; // 开始遍历 Minifilter
__try
{
for (i = 0; i < ulFilterListSize; i++)
{
// 获取 PFLT_FILTER 中 Operations 成员地址
pFltOperationRegistration = (PFLT_OPERATION_REGISTRATION)(*(PVOID *)((PUCHAR)ppFilterList[i] + lOperationsOffset)); __try
{
// 同一过滤器下的回调信息
while (IRP_MJ_OPERATION_END != pFltOperationRegistration->MajorFunction)
{
if (IRP_MJ_MAXIMUM_FUNCTION > pFltOperationRegistration->MajorFunction)
{
// 显示
DbgPrint("Filter: %p | IRP: %d | PreFunc: 0x%p | PostFunc=0x%p \n", ppFilterList[i], pFltOperationRegistration->MajorFunction,
pFltOperationRegistration->PreOperation, pFltOperationRegistration->PostOperation);
} // 获取下一个消息回调信息
pFltOperationRegistration = (PFLT_OPERATION_REGISTRATION)((PUCHAR)pFltOperationRegistration + sizeof(FLT_OPERATION_REGISTRATION));
}
}
__except (EXCEPTION_EXECUTE_HANDLER)
{
}
}
}
__except (EXCEPTION_EXECUTE_HANDLER)
{
} // 释放内存
ExFreePool(ppFilterList);
ppFilterList = NULL; return status;
}

运行代码输出枚举效果如下:

驱动开发:内核枚举Minifilter微过滤驱动的更多相关文章

  1. Minifilter微过滤框架:框架介绍以及驱动层和应用层的通讯

    minifilter是sfilter后微软推出的过滤驱动框架.相比于sfilter,他更容易使用,需要程序员做的编码更简洁. 系统为minifilter专门制作了一个过滤管理器,这个管理器本身其实是一 ...

  2. [Windows驱动开发](三)基础知识——驱动例程

    一.NT式驱动的基本例程 1. 驱动入口函数——DriverEntry // 驱动程序的一般性定义 NTSTATUS DriverEntry(IN PDRIVER_OBJECT pDriverObje ...

  3. 嵌入式linux驱动开发之点亮led(驱动编程思想之初体验)

    这节我们就开始开始进行实战啦!这里顺便说一下啊,出来做开发的基础很重要啊,基础不好,迟早是要恶补的.个人深刻觉得像这种嵌入式的开发对C语言和微机接口与原理是非常依赖的,必须要有深厚的基础才能hold的 ...

  4. linux驱动开发—基于Device tree机制的驱动编写

    前言Device Tree是一种用来描述硬件的数据结构,类似板级描述语言,起源于OpenFirmware(OF).在目前广泛使用的Linux kernel 2.6.x版本中,对于不同平台.不同硬件,往 ...

  5. C++第四十篇 -- 研究一下Windows驱动开发(三)-- NT式驱动的基本结构

    对于NT式驱动来说,主要的函数是DriverEntry例程.卸载例程及各个IRP的派遣例程. 一.驱动加载过程与驱动入口函数(DriverEntry) 和编写普通应用程序一样,驱动程序有个入口函数,也 ...

  6. C++第三十八篇 -- 研究一下Windows驱动开发(二)--WDM式驱动的加载

    基于Windows驱动开发技术详解这本书 一.简单的INF文件剖析 INF文件是一个文本文件,由若干个节(Section)组成.每个节的名称用一个方括号指示,紧接着方括号后面的就是节内容.每一行就是一 ...

  7. Linux驱动开发学习笔记(1):LINUX驱动版本的hello world

    1.关于目录    /lib/modules/2.6.9-42.ELsmp/build/   这个是内核源码所在的目录    一般使用这样的命令进入这个目录:cd /lib/modules/$(una ...

  8. linux驱动开发之九鼎板载蜂鸣器驱动测试【转】

    本文转载自:http://whylinux.blog.51cto.com/10900429/1932491 字符设备驱动用的fileopretion结构体. 1.板载蜂鸣器的驱动测试 我手里有一个BS ...

  9. Windows驱动开发-内核常用内存函数

    搞内存常用函数 C语言 内核 malloc ExAllocatePool memset RtlFillMemory memcpy RtlMoveMemory free ExFreePool

随机推荐

  1. Nginx 目录结构、Nginx服务控制命令

    # Nginx目录结构 # 首先推荐一个查看目录结构的工具 tree # yum install -y tree # sudo apt-get install -y tree ubuntu # 查看n ...

  2. 5. MGR管理维护 | 深入浅出MGR

    GreatSQL社区原创内容未经授权不得随意使用,转载请联系小编并注明来源. 目录 1. 切换主节点 2. 切换单主/多主模式 3. 添加新节点 4. 删除节点 5. 异常退出的节点重新加回 6. 重 ...

  3. Docker 容器虚拟化

    Docker 容器虚拟化 1.虚拟化网络 Network Namespace 是 Linux 内核提供的功能,是实现网络虚拟化的重要功能,它能创建多个隔离的网络空间,它们有独自网络栈信息.不管是虚拟机 ...

  4. Express 使用 Cookie

    在使用 Cookie 之前,需要给 Express 加载中间件,cookie-parser: npm i cookie-parser Express 使用中间件: import express fro ...

  5. ModelBox开发体验:使用YOLOv3做口罩检测

    摘要:本案例将在ModelBox中使用YOLO v3模型,实现一个简单的口罩检测应用 本文分享自华为云社区<ModelBox开发体验Day05开发案例-使用YOLOv3做口罩检测>,作者: ...

  6. Python 工匠:一个关于模块的小故事

    前言 模块(Module)是我们用来组织 Python 代码的基本单位.很多功能强大的复杂站点,都由成百上千个独立模块共同组成. 虽然模块有着不可替代的用处,但它有时也会给我们带来麻烦.比如,当你接手 ...

  7. 【问题解决】npm ERR! code EINTEGRITY

    问题说明 Jenkins构建前端安装依赖报错: npm ERR! code EINTEGRITY 11:05:42 npm ERR! sha512-IJy2B5Ot9wIAGwjSKF94+8yhVC ...

  8. UVA1306 The K-League(最大流)

    题面 有 n n n 支队伍进行比赛,每支队伍需要打的比赛数目相同. 每场比赛恰好一支队伍胜,另一支败. 给出每支队伍目前胜的场数 w i w_i wi​ 和败的场数(没用),以及每两个队伍还剩下的比 ...

  9. c语言_二叉树的建立以及3种递归

    二叉树c语言的实现 二叉树的建立 二叉树的数据结构 typedef struct node{    int data;    struct node* left;    struct node* ri ...

  10. .Net下的Http请求调用(Post与Get)

    http请求调用是开发中经常会用到的功能.在内,调用自有项目的Web Api等形式接口时会用到:在外,调用一些第三方功能接口时,也会用到,因为,这些第三方功能往往是通过http地址的形式提供的,比如: ...