文章总结: 本文系统解析EDR事件采集与遥测机制,涵盖用户态hook、内核ETW/ETW-TI、内核回调及AMSI等传感器通道,强调EDR不感知进程内部数据修改,并讨论用户态hook的绕过方法如直接系统调用,指出内核遥测更可靠,建议结合多层传感器提升检测能力。
综合评分: 85
文章分类: 安全工具,安全运营
EDR事件采集与遥测机制
原创
pandazhengzheng
pandazhengzheng
安全分析与研究
2026年9月17日 22:00
广东
在小说阅读器读本章
去阅读
在公众号小说中沉浸阅读
目录
- 事件接收总览
- 用户态 Hook
- 内核遥测:ETW
- 内核遥测:ETW-TI
- 内核回调
- AMSI 机制
- 传感器注入时序与 KAPC
- 遥测的不可绕过性与信任梯度
- 小结
1. 事件接收总览
1.1 从执行到遥测
一旦 .exe 二进制通过 AV 签名扫描和 AV 模拟(-内存)扫描,它被允许执行。
┌─────────────────┐ ┌──────────────────┐ ┌──────────────────────┐ ┌───────────┐
│ File Write / │ │ Antivirus Scan │ │ Antivirus Emulation │ │ Execution │
│ File Read ├──►│ File ├───►│ Memory ├───►│ Make │
│ │ │ Signature │ │ Signature │ │ Process │
│ │ │ Scanning │ │ Scanning │ │ │
└─────────────────┘ └──────────────────┘ └──────────────────────┘ └───────────┘
进程要做任何有用的事(打开文件、创建网络连接、显示窗口),都需要与 Windows 内核交互。没有绕过内核的方法。Microsoft 使 Windows 内核能够生成关于其操作的数据,并允许软件消费这些数据(事件)。EDR 就是这样的消费者。
1.2 事件管道
Process
┌────────────────┐ ┌─────────────┐
│ │ │ │
│ │ │ Windows │
│ │ │ kernel │
├────────────────┤ Syscalls │ │
│ (Hooked) ├───────────────────►│ │
│ │ │ │
│ ntdll.dll ├─────────────────┐ │ │
│ NtApi │ Usermode │ └──────┬──────┘
├────────────────┤ Hooks │ │
│ │ │ │ kernel
│ │ │ │ ETW
│ │ ▼ ▼
│ │ ┌────────────────────────┐
│ │ │ EDR │
│ │ └────────────────────────┘
└────────────────┘
1.3 两个主要通道
EDR 通过两个主要通道接收数据:
- 用户态(hooked API):EDR 注入的 DLL hook 了
ntdll.dll的关键函数; - 内核回调(ETW、ETW-TI、内核回调):内核驱动注册的回调。
这些传感器在系统中的某些东西被添加/删除/改变时产生事件:
- 文件
- 注册表键
- 进程、线程
- 内存区域
1.4 规则匹配
EDR 包含规则以匹配事件的恶意行为。规则可以是:
- 精确/脆弱:很好地检测一个特定事物(低误报 FP),易于绕过;
- 稳健:更通用的检测,更难绕过,更高 FP,更多异常。
1.5 进程内部数据修改的不可见性
关键认知:EDR 不感知进程内部的数据修改本身。进程调用
ntdll!RtlCopyMemory可能产生遥测(ntdll 可被 hook),但用 for 循环逐字节拷贝不产生任何遥测。
这是”data-only 操作”的核心优势——在进程内部用非 API 方式操作数据,不产生遥测。
1.6 扩展的传感器视图
┌──────────────┐
┌─────────────┐ EtwWrite() ┌──────────┐ Kernel callbacks │ │
│ Process ├───────────►│ ├─────────────────────►│ │
│ │ │ │ │ │
├─────────────┤ │ OS │ ETW │ │
┌───────┤ ntdll.dll │ │ ├─────────────────────►│ EDR │
│ ┌───►│ │ syscall │ │ ETW-TI │ │
│ │ ├─────────────┤ │ ├─────────────────────►│ │
│ │ │ amsi.dll │ pipe │ │ │ │
│ └────┤ ├───────────────────────────► AMSI │ │
└──────►│ │ │ │
└─────────────┘ └──────────────┘
EDR 输入源:
- 用户态 hook / AMSI
- 内核回调
- ETW
- ETW-TI
2. 用户态 Hook
2.1 ntdll.dll 的角色
Windows 的官方内核接口是 ntdll.dll(它为我们发出 syscall)。这称为原生 API(NtAPI)。ntdll.dll 为我们调用正确的 syscall。WinAPI(kernel32.dll 等其他 DLL)最终都调用 NtAPI。
WinAPI NtApi Kernel
┌────────────────┐ ┌────────────────┐ ┌─────────────────────────┐ ┌───────────────────────┐
│ kernel32.dll ├──►│ kernelbase.dll ├──►│ ntdll.dll │syscall│ │Kernel │
│ OpenProcess │ │ OpenProcess │ │ NtOpenProcess ├───────┤►│NtOpenProcess │
└────────────────┘ └────────────────┘ └─────────────────────────┘ └───────────────────────┘
注意:syscall 编号可能随 Windows 版本变化,因此硬编码不可靠。
2.2 NtAPI 函数的汇编形式
ntdll.dll 中 NtAPI 函数的典型形式,用 syscall 汇编指令执行系统调用:
SysNtCreateFile proc
mov r10, rcx
mov eax, 55h ; SSN (System Service Number)
syscall
ret
SysNtCreateFile endp
2.3 Hook 的安装
用户态 hook 是 ntdll.dll 导出函数中的补丁,在实际函数执行前调用另一个 DLL 函数。Windows 提供直接 hook 函数/IAT 的功能。
原始函数(磁盘): EDR Hook 后(内存):
---------------------- -----------------------
mov r10, rcx mov r10, rcx
>mov eax, 50h jmp 0x7ffaeadea621 ← hook 跳转
test byte ptr [0x7FFE0h], 1 test byte ptr [0x7FFE0h], 1
jne 0x17e76540ea5 jne 0x17e76540ea5
syscall syscall
ret ret
2.4 常被 hook 的 ntdll 函数
| 函数名 | 相关攻击者技术 |
| — | — |
| NtOpenProcess | 进程注入 |
| NtAllocateVirtualMemory | 进程注入 |
| NtWriteVirtualMemory | 进程注入 |
| NtCreateThreadEx | 进程注入 |
| NtSuspendThread | APC shellcode 注入 |
| NtResumeThread | APC shellcode 注入 |
| NtQueueApcThread | APC shellcode 注入 |
EDR 接收函数调用名及其参数作为遥测。
2.5 KAPC 注入安装 hook
hook 安装通过内核回调(PsSetCreateProcessNotifyRoutine)在新进程创建早期获通知,然后向进程注入 DLL(如 amsi.dll),创建 APC 调用 DLL 中修补原始 ntdll.dll 函数的函数(或通常修补 DLL 导入地址表),使调用绕道进入 amsi.dll。
ntdll.dll 被修补后,每次函数调用都被 amsi.dll 拦截。
EDR 的 KAPC hook 安装:创建执行 hooking 的 APC。”Early Bird APC injection”技术使用相同的 APC 机制,因此可在 KAPC hooking 执行之前运行。
2.6 用户态 hook 的绕过
用户态 hook 可通过以下方式绕过:
- Direct syscalls:避免调用
ntdll.dll; - Indirect syscalls:调用
ntdll.dll函数,但在 hook 之后; - **Patching/restoring
ntdll.dll**:完全移除 hook。
用户态 hook 易于绕过,因为它们完全位于”我们自己的”内存空间,可自由修改。但恢复 ntdll.dll 本身会产生遥测,需使用 direct syscalls 等。
2.7 用户态 hook 的定位与局限
EDR 不应仅依赖用户态 hook,而仅用于辅助遥测。它们提供比内核遥测(如 ETW)更多的信息。内核只”看到” syscall/ntdll.dll 函数,而非最初发起的原始函数。这很有用,因为它生成更通用的检测,无需 hook 所有的 DLL 函数。但可能产生更多误报,因为仅凭 syscall 更难识别”非恶意”行为(可用信息更少)。
例如,CreateFileA()、CreateFileW()、OpenFile() 和 CreateFileTransacted() 最终都调用 NtCreateFile()。
注意:调用栈可显示链中最初调用了哪个函数。
2.8 各 EDR 的 hook 使用情况
免责声明:
本文所载程序、技术方法仅面向合法合规的安全研究与教学场景,旨在提升网络安全防护能力,具有明确的技术研究属性。
任何单位或个人未经授权,将本文内容用于攻击、破坏等非法用途的,由此引发的全部法律责任、民事赔偿及连带责任,均由行为人独立承担,本站不承担任何连带责任。
本站内容均为技术交流与知识分享目的发布,若存在版权侵权或其他异议,请通过邮件联系处理,具体联系方式可点击页面上方的联系我。
本文转载自:安全分析与研究 pandazhengzheng
pandazhengzheng《EDR事件采集与遥测机制》