对抗与枚举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

最新文章

  1. TypeScript: Angular 2 的秘密武器(译)
  2. 立即执行函数: (function(){...})() 与 (function(){...}()) 有什么区别?
  3. shell中三种引号的用法
  4. python入门笔记
  5. Delphi面向对象---接口
  6. java 杂物间 (二) Spring Web
  7. How to Write and Publish a Scientific Paper: 7th Edition(科技论文写作与发表教程)(11.04更新)
  8. [MySql]explain用法及实践
  9. Awk 实例
  10. UVaLive 6855 Banks (水题,暴力)
  11. Cppcheck 用法(上篇)
  12. eXtremeDB
  13. hibernate初体验
  14. (未解决)在JSTL中,session 和 sessionScope 有什么区别 ??
  15. 基于visual Studio2013解决面试题之0602全排列
  16. 总结基础OOP(面向对象)
  17. sau交流学习社区第三方登陆github--oauth来实现用户登录
  18. windows 2008下IIS7 安装ASP.NET 遇到500.19
  19. 微信浏览器安卓手机video浮在最上层问题
  20. 一篇文章说清楚mysql索引

热门文章

  1. SVHN数据集 Format1 剪裁版
  2. 【Azure 微服务】PowerShell中,用Connect-ServiceFabricCluster命令无法连接到sf-test.chinaeast2.cloudapp.chinacloudapi.cn:19000 问题分析
  3. where / having / group by / order by / limit 简单查询
  4. C语言之预处理详解
  5. vue-cli2 项目中使用node-sass
  6. .Net Core发布到Linux下验证码失效处理方案详解
  7. 仿VUE创建响应式数据
  8. redis安装、配置、启动
  9. 201871010113-贾荣娟 实验三 结对项目—《D{0-1}KP 实例数据集算法实验平台》项目报告
  10. Dynamics CRM存放选项集记录的表