EDR事件采集与遥测机制

· 2026-09-17 22:00 · 0 阅读

原创 pandazhengzheng 2026-09-17 22:00 广东

目录

  1. 事件接收总览

  2. 用户态 Hook

  3. 内核遥测:ETW

  4. 内核遥测:ETW-TI

  5. 内核回调

  6. AMSI 机制

  7. 传感器注入时序与 KAPC

  8. 遥测的不可绕过性与信任梯度

  9. 小结


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 使用情况

跳转微信打开