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 的驱动.同理,在反游戏保护的过程中,也可以 ...
随机推荐
- 如何在 ASP.NET Core 中写出更干净的 Controller
你可以遵循一些最佳实践来写出更干净的 Controller,一般我们称这种方法写出来的 Controller 为瘦Controller,瘦 Controller 的好处在于拥有更少的代码,更加单一的职 ...
- 手把手教你集成华为机器学习服务(ML Kit)人脸检测功能
当给自己拍一张美美的自拍照时,却发现照片中自己的脸不够瘦.眼睛不够大.表情不够丰富可爱-如果此时能够一键美颜瘦脸并且添加可爱的贴纸的话,是不是很棒? 当家里的小孩观看iPad屏幕时间过长或者眼睛离屏幕 ...
- Android - Handler原理
Handler的主要作用是收发消息和切线程 功能一:收发消息 简单流程介绍 希望你看完这篇文章后也可以把流程自己讲出来,并且每个环节还可以讲出很多细节 他的消息机制离不开Looper.MessageQ ...
- 叫练手把手教你读JVM之GC信息
案例 众所周知,GC主要回收的是堆内存,堆内存中包含年轻代和老年代,年轻代分为Eden和Surivor,如下图所示.我们用案例分析下堆的GC信息[版本:HotSpot JDK1.8]. /** * @ ...
- Centos7安装Nacos单机模式以及集群模式(包含nignx安装以及实现集群)的相关配置
Nacos 致力于帮助您发现.配置和管理微服务.Nacos 提供了一组简单易用的特性集,帮助您快速实现动态服务发现.服务配置.服务元数据及流量管理. Nacos支持三种部署模式 单机模式 - 用于测试 ...
- vue全局错误捕获
1.errorHandler Vue全局配置 errorHandler可以进行全局错误收集,捕获全局错误抛出,避免前端页面挂掉 export default function errorHandl ...
- 洛谷P1290欧几里德游戏
题目地址 题目大意: 两个人st和ol博弈 有两个整数n,m 每次轮到一个人时候,需要选择用大的那个数减去小的那个数的倍数(不能减为负数) 最后得到0的为胜利者 思路: (以下讨论均在n<m的条 ...
- [树形DP]电子眼
电 子 眼 电子眼 电子眼 题目描述 中山市石一个环境优美.气候宜人的小城市.因为城市的交通并不繁忙,市内的道路网很稀疏.准确地说,中山市有N-1条马路和N个路口,每条马路连接两个路口,每两个路口之间 ...
- 深入Spring Security魔幻山谷-获取认证机制核心原理讲解(新版)
文/朱季谦 本文基于Springboot+Vue+Spring Security框架而写的原创学习笔记,demo代码参考<Spring Boot+Spring Cloud+Vue+Element ...
- [Fundamental of Power Electronics]-PART I-5.不连续导电模式-5.3 Boost变换器实例
5.3 Boost变换器实例 作为第二个示例,考虑图5.12的Boost变换器.让我们来确定不同模式的边界并且求解DCM下的电压变换比.此前在2.3节中分析了在CCM工作的Boost变换器的特性,并确 ...