首页
社区
课程
招聘
[分享]一个MiniFilter的遍历
发表于: 2024-7-15 00:11 2868

[分享]一个MiniFilter的遍历

2024-7-15 00:11
2868

MiniFilter是一种文件过滤驱动(虽然我喜欢叫他微过滤驱动或者小驱动)
MiniFilter微过滤驱动使用
过滤管理器 FilterManager 提供接口
因为提供了管理结构以及一系列管理API函数,所以枚举MiniFilter十分容易
有一位大佬写的ARK工具里面就有此功能

好了回归正题

对于遍历 MiniFilter
微软也是不负众望

1
2
3
4
5
NTSTATUS FLTAPI FltEnumerateFilters(
  [out] PFLT_FILTER *FilterList,
  [in]  ULONG       FilterListSize,
  [out] PULONG      NumberFiltersReturned
);

https://learn.microsoft.com/zh-cn/windows-hardware/drivers/ddi/fltkernel/nf-fltkernel-fltenumeratefilters
提供了直接遍历的函数
我们只需要微微处理一下就好了

思路大概如下: 获取MiniFilter的数量 -> 获取所有MiniFilter中Filter的信息 -> 遍历MiniFilter数组
前面两个都蛮简单 MiniFilter数组在哪呢?
查看C:\Windows\System32\drivers\fltMgr.sys中的
_FLT_FILTER结构就一目了然了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
struct _FLT_FILTER
{
    /*+0x000*/    struct _FLT_OBJECT Base;
    /*+0x030*/    struct _FLTP_FRAME* Frame;
    /*+0x038*/    struct _UNICODE_STRING Name;
    /*+0x048*/    struct _UNICODE_STRING DefaultAltitude;
    /*+0x058*/    enum _FLT_FILTER_FLAGS Flags;
    /*+0x060*/    struct _DRIVER_OBJECT* DriverObject;
    /*+0x068*/    struct _FLT_RESOURCE_LIST_HEAD InstanceList;
    /*+0x0e8*/    struct _FLT_VERIFIER_EXTENSION* VerifierExtension;
    /*+0x0f0*/    struct _LIST_ENTRY VerifiedFiltersLink;
    /*+0x100*/    PPROC FilterUnload;
    /*+0x108*/    PPROC InstanceSetup;
    /*+0x110*/    PPROC InstanceQueryTeardown;
    /*+0x118*/    PPROC InstanceTeardownStart;
    /*+0x120*/    PPROC InstanceTeardownComplete;
    /*+0x128*/    struct _ALLOCATE_CONTEXT_HEADER* SupportedContextsListHead;
    /*+0x130*/    struct _ALLOCATE_CONTEXT_HEADER* SupportedContexts[7];
    /*+0x168*/    PPROC PreVolumeMount;
    /*+0x170*/    PPROC PostVolumeMount;
    /*+0x178*/    PPROC GenerateFileName;
    /*+0x180*/    PPROC NormalizeNameComponent;
    /*+0x188*/    PPROC NormalizeNameComponentEx;
    /*+0x190*/    PPROC NormalizeContextCleanup;
    /*+0x198*/    PPROC KtmNotification;
    /*+0x1a0*/    PPROC SectionNotification;
    /*+0x1a8*/    struct _FLT_OPERATION_REGISTRATION* Operations;
    /*+0x1b0*/    PPROC OldDriverUnload;
    /*+0x1b8*/    struct _FLT_MUTEX_LIST_HEAD ActiveOpens;
    /*+0x208*/    struct _FLT_MUTEX_LIST_HEAD ConnectionList;
    /*+0x258*/    struct _FLT_MUTEX_LIST_HEAD PortList;
    /*+0x2a8*/    struct _EX_PUSH_LOCK PortLock;
};

很显然

/+0x1a8/ struct _FLT_OPERATION_REGISTRATION* Operations;

就是我们想要的东西
这个东西在我的系统上的偏移是0x1a8
那么剩下的事情还蛮简单的
就直接贴代码和成果了
头文件:

1
2
3
4
5
6
7
#include <ntifs.h>
#include <fltKernel.h>
#include <dontuse.h>
#include <suppress.h>
#include <intrin.h>
 
#include <vector>//Nuget包->ucxxrt库

主代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
struct MiniFilterVec
{
    ULONG64 Index;
    ULONG64 Addr;
    ULONG64 PreFuncAddr;
    ULONG64 PostFuncAddr;
};
 
class MiniFilter
{
public:
    std::vector <MiniFilterVec> _MiniFilterVec;
 
    //0x1A8 Win10 X64
    void ToOperationsOffset(ULONG64 lOperationsOffset_);
    ULONG GetMiniFilterList();
};
ULONG64 lOperationsOffset;
 
void MiniFilter::ToOperationsOffset(ULONG64 lOperationsOffset_) {
    lOperationsOffset = lOperationsOffset_;
}
// 遍历 MiniFilter
ULONG  MiniFilter::GetMiniFilterList() {
    _MiniFilterVec.clear();
    std::vector<MiniFilterVec> _temp_vector;
    // 定义返回值
    NTSTATUS status;
 
    // 获取 Minifilter 数量
    ULONG ul_fliterList_size = 0;
    FltEnumerateFilters(NULL, 0, &ul_fliterList_size);
 
    // 申请内存
    PFLT_FILTER* pp_fliterList = NULL;
    pp_fliterList = (PFLT_FILTER*)ExAllocatePoolWithTag(NonPagedPool,ul_fliterList_size * sizeof(PFLT_FILTER),'FT1');
//高版本可以用ExAllocatePool2    
    if (pp_fliterList == NULL) {
        return STATUS_INSUFFICIENT_RESOURCES;
    }
 
    // 获取 Minifilter 中所有 Filter 的信息
    status = FltEnumerateFilters(pp_fliterList,ul_fliterList_size,&ul_fliterList_size );
    if (!NT_SUCCESS(status)) {
        DbgPrint("FltEnumerateFilters error:%X", status);
        return status;
    }
  //  DbgPrint("ul_fliterList_size = %d", ul_fliterList_size);
 
    // 遍历 Minifilter
    PFLT_OPERATION_REGISTRATION p_FOR = NULL;
    for (ULONG i = 0; i < ul_fliterList_size; i++) {
        // 获取 PFLT_FILTER 中 Operations 成员地址
        p_FOR = (PFLT_OPERATION_REGISTRATION)(*(PVOID*)((UCHAR*)pp_fliterList[i] + lOperationsOffset));
 
        // 遍历回调函数
        while (p_FOR->MajorFunction != IRP_MJ_OPERATION_END) {
            MiniFilterVec _AMiniFilter;
 
            RtlZeroMemory(&_AMiniFilter, sizeof(MiniFilterVec));
            _AMiniFilter.Index = (UINT64)p_FOR->MajorFunction;
            _AMiniFilter.Addr = (UINT64)pp_fliterList[i];
            _AMiniFilter.PreFuncAddr = (UINT64)p_FOR->PreOperation;
            _AMiniFilter.PostFuncAddr = (UINT64)p_FOR->PostOperation;
            _temp_vector.push_back(_AMiniFilter);
 
            // 获取下一个消息回调信息
            p_FOR = (PFLT_OPERATION_REGISTRATION)((UCHAR*)p_FOR + sizeof(FLT_OPERATION_REGISTRATION));
        }
     FltObjectDereference(pp_fliterList[i]);
    }
 
    // 释放内存
    ExFreePool(pp_fliterList);
    _MiniFilterVec = _temp_vector;
    return STATUS_SUCCESS;
}

另外附上一个函数 是IRP类型的

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
std::string MiniFilter::Get_IOTCL_FunctionName(ULONG64 Index)
{
    std::string funciton_name;
    switch (Index)
    {
    case 0:
        funciton_name = "IRP_MJ_CREATE";
        break;
    case 1:
        funciton_name = "IRP_MJ_CREATE_NAMED_PIPE";
        break;
    case 2:
        funciton_name = "IRP_MJ_CLOSE";
        break;
    case 3:
        funciton_name = "IRP_MJ_READ";
        break;
    case 4:
        funciton_name = "IRP_MJ_WRITE";
        break;
    case 5:
        funciton_name = "IRP_MJ_QUERY_INFORMATION";
        break;
    case 6:
        funciton_name = "IRP_MJ_SET_INFORMATION";
        break;
    case 7:
        funciton_name = "IRP_MJ_QUERY_EA";
        break;
    case 8:
        funciton_name = "IRP_MJ_SET_EA";
        break;
    case 9:
        funciton_name = "IRP_MJ_FLUSH_BUFFERS";
        break;
    case 10:
        funciton_name = "IRP_MJ_QUERY_VOLUME_INFORMATION";
        break;
    case 11:
        funciton_name = "IRP_MJ_SET_VOLUME_INFORMATION";
        break;
    case 12:
        funciton_name = "IRP_MJ_DIRECTORY_CONTROL";
        break;
    case 13:
        funciton_name = "IRP_MJ_FILE_SYSTEM_CONTROL";
        break;
    case 14:
        funciton_name = "IRP_MJ_DEVICE_CONTROL";
        break;
    case 15:
        funciton_name = "IRP_MJ_INTERNAL_DEVICE_CONTROL";
        break;
    case 16:
        funciton_name = "IRP_MJ_SHUTDOWN";
        break;
    case 17:
        funciton_name = "IRP_MJ_LOCK_CONTROL";
        break;
    case 18:
        funciton_name = "IRP_MJ_CLEANUP";
        break;
    case 19:
        funciton_name = "IRP_MJ_CREATE_MAILSLOT";
        break;
    case 20:
        funciton_name = "IRP_MJ_QUERY_SECURITY";
        break;
    case 21:
        funciton_name = "IRP_MJ_SET_SECURITY";
        break;
    case 22:
        funciton_name = "IRP_MJ_POWER";
        break;
    case 23:
        funciton_name = "IRP_MJ_SYSTEM_CONTROL";
        break;
    case 24:
        funciton_name = "IRP_MJ_DEVICE_CHANGE";
        break;
    case 25:
        funciton_name = "IRP_MJ_QUERY_QUOTA";
        break;
    case 26:
        funciton_name = "IRP_MJ_SET_QUOTA";
        break;
    case 27:
        funciton_name = "IRP_MJ_PNP";
        break;
    case 28:
        funciton_name = "IRP_MJ_PNP_POWER";
        break;
    case 255:
        funciton_name = "IRP_MJ_ACQUIRE_FOR_SECTION_SYNCHRONIZATION";
        break;
    case 254:
        funciton_name = "IRP_MJ_RELEASE_FOR_SECTION_SYNCHRONIZATION";
        break;
    case 253:
        funciton_name = "IRP_MJ_ACQUIRE_FOR_MOD_WRITE";
        break;
    case 252:
        funciton_name = "IRP_MJ_RELEASE_FOR_MOD_WRITE";
        break;
    case 251:
        funciton_name = "IRP_MJ_ACQUIRE_FOR_CC_FLUSH";
        break;
    case 250:
        funciton_name = "IRP_MJ_RELEASE_FOR_CC_FLUSH";
        break;
    case 249:
        funciton_name = "IRP_MJ_QUERY_OPEN";
        break;
    case 243:
        funciton_name = "IRP_MJ_FAST_IO_CHECK_IF_POSSIBLE";
        break;
    case 242:
        funciton_name = "IRP_MJ_NETWORK_QUERY_OPEN";
        break;
    case 241:
        funciton_name = "IRP_MJ_MDL_READ";
        break;
    case 240:
        funciton_name = "IRP_MJ_MDL_READ_COMPLETE";
        break;
    case 239:
        funciton_name = "IRP_MJ_PREPARE_MDL_WRITE";
        break;
    case 238:
        funciton_name = "IRP_MJ_MDL_WRITE_COMPLETE";
        break;
    case 237:
        funciton_name = "IRP_MJ_VOLUME_MOUNT";
        break;
    case 236:
        funciton_name = "IRP_MJ_VOLUME_DISMOUN";
        break;
    case 128:
        funciton_name = "IRP_MJ_OPERATION_END";
        break;
    }
    if (funciton_name.size() > 0) {
        return funciton_name;
    }
    else {
        return "<N/I> : "+std::to_string(Index);
    }
}

特殊的IRP在fltKernel.h

最终效果


[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

最后于 2024-7-16 15:27 被ShaShen4404编辑 ,原因: 忘记取消引用了
收藏
免费 1
支持
分享
最新回复 (1)
雪    币: 1712
活跃值: (3745)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
感谢分享
2024-8-9 15:05
0
游客
登录 | 注册 方可回帖
返回
//