Win64 驱动内核编程-34.对抗与枚举MiniFilter
对抗与枚举MiniFilter
MiniFilter 是目前杀毒软件用来实现“文件系统自我保护”和“文件实时监控”的方法。
由于 MiniFilter 模型简单,开发快捷,通用性好,以前用 FSD HOOK 或者标准过滤驱动来实现相关功能的杀软纷纷改用 MiniFilter,比如卡巴斯基。不过,枚举 MiniFilter 就跟之前枚举回调的方法不太相同了,因为 MiniFilter 的框架不在 NTOSKRNL 里,自成一套系统,有专用的 API。不过“自成一套系统,有专用 API”的好处就是,无需我们自己通过特征码来定位数组或者链表,直接使用 MiniFilter 提供的 API 就行。
枚举MiniFilter主要使用FltEnumerateFilters这个API,它会返回过滤器对象(FLT_FILTER)的地址,然后根据过滤器对象的地址,加上一个偏移,获得记录过滤器 PreCall、PostCall、IRP 等信息的结构体指针(PFLT_OPERATION_REGISTRATION)。上文之所以说要加上偏移,是因为 FLT_FILTER 的定义在每个系统都不同,比如 WIN7X64 中的定义为:
nt!DbgBreakPointWithStatus:
fffff800`03e74f60 cc int 3
kd> dt fltmgr!_FLT_FILTER
+0x000 Base : _FLT_OBJECT
+0x020 Frame : Ptr64 _FLTP_FRAME
+0x028 Name : _UNICODE_STRING
+0x038 DefaultAltitude : _UNICODE_STRING
+0x048 Flags : _FLT_FILTER_FLAGS
+0x050 DriverObject : Ptr64 _DRIVER_OBJECT
+0x058 InstanceList : _FLT_RESOURCE_LIST_HEAD
+0x0d8 VerifierExtension : Ptr64 _FLT_VERIFIER_EXTENSION
+0x0e0 VerifiedFiltersLink : _LIST_ENTRY
+0x0f0 FilterUnload : Ptr64 long
+0x0f8 InstanceSetup : Ptr64 long
+0x100 InstanceQueryTeardown : Ptr64 long
+0x108 InstanceTeardownStart : Ptr64 void
+0x110 InstanceTeardownComplete : Ptr64 void
+0x118 SupportedContextsListHead : Ptr64 _ALLOCATE_CONTEXT_HEADER
+0x120 SupportedContexts : [6] Ptr64 _ALLOCATE_CONTEXT_HEADER
+0x150 PreVolumeMount : Ptr64 _FLT_PREOP_CALLBACK_STATUS
+0x158 PostVolumeMount : Ptr64 _FLT_POSTOP_CALLBACK_STATUS
+0x160 GenerateFileName : Ptr64 long
+0x168 NormalizeNameComponent : Ptr64 long
+0x170 NormalizeNameComponentEx : Ptr64 long
+0x178 NormalizeContextCleanup : Ptr64 void
+0x180 KtmNotification : Ptr64 long
+0x188 Operations : Ptr64 _FLT_OPERATION_REGISTRATION
+0x190 OldDriverUnload : Ptr64 void
+0x198 ActiveOpens : _FLT_MUTEX_LIST_HEAD
+0x1e8 ConnectionList : _FLT_MUTEX_LIST_HEAD
+0x238 PortList : _FLT_MUTEX_LIST_HEAD
+0x288 PortLock : _EX_PUSH_LOCK
FLT_OPERATION_REGISTRATION 的结构体定义是不变的:
枚举代码如下:
#include <Fltkernel.h>
ULONG FltFilterOperationsOffset=0x188; //WIN7 OFFSET of fltmgr!_FLT_FILTER->PFLT_OPERATION_REGISTRATION
//typedef struct _FLT_OPERATION_REGISTRATION
//{
//UCHARMajorFunction;
//ULONGFlags;
//PVOIDPreOperation;
//PVOIDPostOperation;
//PVOIDReserved1;
//} FLT_OPERATION_REGISTRATION, *PFLT_OPERATION_REGISTRATION;
typedef struct _FLT_FILTER
{
UCHAR buffer[1024];
} FLT_FILTER, *PFLT_FILTER;
//NTSTATUS
//__fastcall
//FltEnumerateFilters
//(
// PFLT_FILTER *FilterList,
// ULONG FilterListSize,
// PULONG NumberFiltersReturned
//);
//
//NTSTATUS
//__fastcall
//FltObjectDereference
//(
// PVOID FltObject
//);
ULONG EnumMiniFilter()
{
long ntStatus;
ULONG uNumber;
PVOID pBuffer = NULL;
ULONG uIndex = 0, DrvCount = 0;
PVOID pCallBacks = NULL, pFilter = NULL;
PFLT_OPERATION_REGISTRATION pNode;
do
{
if(pBuffer != NULL)
{
ExFreePool(pBuffer);
pBuffer = NULL;
}
ntStatus = FltEnumerateFilters(NULL, 0, &uNumber);
if(ntStatus != STATUS_BUFFER_TOO_SMALL)
break;
pBuffer = ExAllocatePoolWithTag(NonPagedPool, sizeof(PFLT_FILTER) * uNumber, 'mnft');
if(pBuffer == NULL)
{
ntStatus = STATUS_INSUFFICIENT_RESOURCES;
break;
}
ntStatus = FltEnumerateFilters(pBuffer, uNumber, &uNumber);
}
while (ntStatus == STATUS_BUFFER_TOO_SMALL);
if(! NT_SUCCESS(ntStatus))
{
if(pBuffer != NULL)
ExFreePool(pBuffer);
return 0;
}
DbgPrint("MiniFilter Count: %ld\n",uNumber);
DbgPrint("------\n");
__try
{
while(DrvCount<uNumber)
{
pFilter = (PVOID)(*(PULONG64)((PUCHAR)pBuffer + DrvCount * 8));
pCallBacks = (PVOID)((PUCHAR)pFilter + FltFilterOperationsOffset);
pNode = (PFLT_OPERATION_REGISTRATION)(*(PULONG64)pCallBacks);
__try
{
while(pNode->MajorFunction != 0x80) //IRP_MJ_OPERATION_END
{
if(pNode->MajorFunction<28) //MajorFunction id is 0~27
{
DbgPrint("Object=%p\tPreFunc=%p\tPostFunc=%p\tIRP=%d\n",
pFilter,
pNode->PreOperation,
pNode->PostOperation,
pNode->MajorFunction);
}
pNode++;
}
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
FltObjectDereference(pFilter);
DbgPrint("[EnumMiniFilter]EXCEPTION_EXECUTE_HANDLER: pNode->MajorFunction\n");
ntStatus = GetExceptionCode();
ExFreePool(pBuffer);
return uIndex;
}
DrvCount++;
FltObjectDereference(pFilter);
DbgPrint("------\n");
}
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
FltObjectDereference(pFilter);
DbgPrint("[EnumMiniFilter]EXCEPTION_EXECUTE_HANDLER\n");
ntStatus = GetExceptionCode();
ExFreePool(pBuffer);
return uIndex;
}
if(pBuffer != NULL)
{
ExFreePool(pBuffer);
ntStatus=STATUS_SUCCESS;
}
return uIndex;}
执行结果:
不过对抗 MiniFilter 似乎就只有两种方法了:
1.把记录的函数地址改为自己设置的空函数;
2.把处理函数头改为 RET 直接返回。 为什么不能把 直接把 MiniFilter 对象 反注册呢?因为MSDN 对 对 FltUnregisterFilter 的 用途 给出了 这样的解释 :A minifilter driver can only callFltUnregisterFilter to unregister itself, not another minifilter driver。据我测试,如果第三方驱动强制使用此函数注销一个 MiniFilter,轻则无效,重则蓝屏。
把 MINIFILTER 的处理函数禁用掉之后,卡巴斯基 2013 在 WIN64 系统上的文件保护就彻底失效了,可以直接使用最简单的方法来删除卡巴斯基文件夹内的文件,国内那些采用同样方法实现文件自我保护的杀毒软件(****)同理。
宋孖健,13
Win64 驱动内核编程-34.对抗与枚举MiniFilter的更多相关文章
- Win64 驱动内核编程-3.内核里使用内存
内核里使用内存 内存使用,无非就是申请.复制.设置.释放.在 C 语言里,它们对应的函数是:malloc.memcpy.memset.free:在内核编程里,他们分别对应 ExAllocatePool ...
- Win64 驱动内核编程-8.内核里的其他常用
内核里的其他常用 1.遍历链表.内核里有很多数据结构,但它们并不是孤立的,内核使用双向链表把它们像糖 葫芦一样给串了起来.所以遍历双向链表能获得很多重要的内核数据.举个简单的例子,驱 动对象 Driv ...
- Win64 驱动内核编程-7.内核里操作进程
在内核里操作进程 在内核里操作进程,相信是很多对 WINDOWS 内核编程感兴趣的朋友第一个学习的知识点.但在这里,我要让大家失望了,在内核里操作进程没什么特别的,就标准方法而言,还是调用那几个和进程 ...
- Win64 驱动内核编程-2.基本框架(安装.通讯.HelloWorld)
驱动安装,通讯,Hello World 开发驱动的简单流程是这样,开发驱动安装程序,开发驱动程序,然后安装程序(或者其他程序)通过通讯给驱动传命令,驱动接到之后进行解析并且执行,然后把执行结果返回. ...
- Win64 驱动内核编程-18.SSDT
SSDT 学习资料:http://blog.csdn.net/zfdyq0/article/details/26515019 学习资料:WIN64内核编程基础 胡文亮 SSDT(系统服务描述表),刚开 ...
- Win64 驱动内核编程-32.枚举与删除注册表回调
枚举与删除注册表回调 注册表回调是一个监控注册表读写的回调,它的效果非常明显,一个回调能实现在SSDT 上 HOOK 十几个 API 的效果.部分游戏保护还会在注册表回调上做功夫,监控 service ...
- Win64 驱动内核编程-25.X64枚举和隐藏内核模块
X64枚举和隐藏内核模块 在 WIN64 上枚举内核模块的人方法:使用 ZwQuerySystemInformation 的第 11 号功能和枚举 KLDR_DATA_TABLE_ENTRY 中的 I ...
- Win64 驱动内核编程-28.枚举消息钩子
枚举消息钩子 简单粘贴点百度的解释,科普下消息钩子: 钩子是WINDOWS中消息处理机制的一个要点,通过安装各种钩子,应用程序能够设置相应的子例程来监视系统里的消息传递以及在这些消息到达目标窗口程序之 ...
- Win64 驱动内核编程-31.枚举与删除映像回调
枚举与删除映像回调 映像回调可以拦截 RING3 和 RING0 的映像加载.某些游戏保护会用此来拦截黑名单中的驱动加载,比如 XUETR.WIN64AST 的驱动.同理,在反游戏保护的过程中,也可以 ...
随机推荐
- 任务队列 与 Celery概述
一.任务队列(Task Queues) 1.1 什么是任务队列? 任务队列用于管理后台工作,通常这些后台工作必须在 HTTP请求-响应循环 之外执行. 1.2 为什么需要任务队列? 对于那些不是由客户 ...
- Apache配置 5.访问日志不记录静态文件
介绍:项目中的CSS.图片.js都是静态文件.一般会将静态文件放到一个单独的目录中,以方便管理. 1. 配置 # vim /usr/local/apache2.4/conf/extra/httpd-v ...
- imagemagick 之 Fred's ImageMagick Scripts 在Ubuntu 下的实践
Fred's ImageMagick Scripts 官网:http://www.fmwconcepts.com/imagemagick/index.php Windows 10 (64-bit) u ...
- springboot系列四:springboot整合mybatis jsp
一.用IDEA 创建maven项目 项目目录结构 1.添加pom jar依赖 <?xml version="1.0" encoding="UTF-8"?& ...
- Python中树的遍历-堆排序
1.二叉树的遍历 遍历:迭代所有元素一遍. 树的遍历:对树中所有的元素不重复的访问一遍,也成扫描 广度优先遍历:层序遍历 深度优先遍历:前序.中序.后续遍历. 遍历序列:将树中所有元素遍历一遍后,得到 ...
- 一款检测代码中TODO的eslint插件
一款检测代码中TODO的eslint插件 前言 看了我标题进来的同学应该也知道我做的是个啥东西 没错是一个eslint插件,前端魔法师们日常所使用的工具之一 什么?你不知道eslint是干嘛的--吃鲸 ...
- 前端 | 使用 ECharts 绘制关系图
0 需求 做的项目需要画一个关系图,主要需求如下: 需要展示6种对象之间的关系:数据机构 数据 合约 模型 计算机构 应用 支持突出显示6种对象中的某一种的所有对象 支持Top x子图功能.top x ...
- 配置redis 4.0.11 集群
配置redis 4.0.11 集群 准备redis 软件和redis配置文件 启动Redis服务 /data/soft/redis/src/redis-check-aof --fix /log/red ...
- 别人 echo 、你也 echo ,是问 echo 知多少?-- Shell十三问<第三问>
别人 echo .你也 echo ,是问 echo 知多少?-- Shell十三问<第三问> 承接上一章所介绍的 command line ,这里我们用 echo 这个命令加以进一步说明. ...
- 各种OJ网站,刷题必备
各种OJ网站 落谷 vijos JoyOI CodeVS Comet OJ 北京大学 浙江大学 杭州电子科技大学 信息学奥赛一本通 以上就是本蒟蒻所知的OJ网站 收集和打字应该值一个赞吧