一、永恒的猫鼠游戏
EDR 部署在终端上,攻击者也活跃在终端上。这意味着两者共享同一套操作系统、同一份内存空间、同一组内核 API------攻击者有充足的动机和手段去研究 EDR 的检测逻辑并尝试绕过。
理解 EDR 的攻防对抗,不是为了教攻击者如何突破防线,而是为了让防御者清楚:每一种检测机制都有其盲区,每一层防护都可能被针对性对抗。一个成熟的 EDR 产品不会宣称"无法被绕过",而是通过多层检测叠加和自身防护机制,将绕过的成本提高到攻击者难以承受的程度。
本文从攻击者视角梳理常见的 EDR 绕过技术,再从防御视角解析 EDR 的自我保护体系和反制手段。

二、用户态绕过技术
EDR 的用户态检测主要依赖对 ntdll.dll 中系统调用包装函数的 Hook。攻击者的绕过思路也围绕这一点展开。
2.1 直接系统调用(Direct Syscall)
Windows 中,用户态程序要进入内核执行操作,必须通过 ntdll.dll 中的包装函数(如 NtOpenProcess、NtAllocateVirtualMemory)。这些函数的本质是:将系统调用号(SSN,System Service Number)放入 eax 寄存器,然后执行 syscall 指令进入内核。
EDR 通常在这些 Nt* 函数的开头插入跳转指令(Inline Hook),将执行流重定向到 EDR 的检测回调。如果攻击者不调用 ntdll.dll 的函数,而是自己在代码中直接设置 SSN 并执行 syscall 指令,就能完全绕过用户态 Hook。
工具链(如 SysWhispers)可以自动生成直接系统调用的汇编桩代码,使这一技术的使用门槛大幅降低。
2.2 间接系统调用(Indirect Syscall)
直接系统调用有一个明显特征:syscall 指令来自 ntdll.dll 以外的内存区域。现代 EDR 在内核回调中会检查系统调用的返回地址(RIP),如果发现 syscall 指令不在 ntdll.dll 的 .text 段内,就会标记为可疑。
间接系统调用解决了这个问题:攻击者仍然在自己的代码中设置寄存器参数,但不直接执行 syscall,而是跳转到 ntdll.dll 内部已有的 syscall; ret 指令片段(gadget)。这样内核看到的返回地址位于 ntdll.dll 内部,与正常调用无法区分。
同时,跳转目标越过了 Nt* 函数开头被 Hook 的字节,因此 EDR 的用户态 Hook 仍然不会被触发。
2.3 ntdll Unhooking
另一种思路是直接移除 EDR 放置的 Hook:
- 从磁盘重新加载 ntdll:攻击者将 C:\Windows\System32\ntdll.dll 的干净副本映射到内存,用其中的原始字节覆盖当前被 Hook 的 dll 代码段。
- KnownDlls 重映射:利用Windows 的 KnownDlls 机制获取干净的 ntdll 映像。
- Halo's Gate / Tartarus Gate:当某个Nt* 函数被 Hook 时,通过扫描相邻未被 Hook 的函数来推断 SSN(系统调用号在 ntdll 中通常是连续分配的),从而恢复被 Hook 函数的调用能力。
Unhooking 的风险在于:修改 ntdll.dll 代码段本身就是一个高可疑行为,EDR 可以通过内存完整性校验检测到这一操作。
2.4 AMSI 绕过
AMSI 为 EDR 提供了脚本明文内容,但攻击者可以通过以下方式禁用或绕过:
- AMSI Patch:在内存中修改dll 的 AmsiScanBuffer 函数,将其开头改为直接返回 AMSI_RESULT_CLEAN(即"内容安全"),使后续所有脚本扫描都被跳过。
- AMSI 上下文损坏:通过传入畸形参数使AMSI 上下文初始化失败,后续扫描静默失效。
- 完全内存执行:在.NET 运行时中直接发射 IL 代码,绕过脚本宿主的 AMSI 集成点。
2.5 ETW 绕过
ETW 是 EDR 的重要遥测来源,攻击者可以:
- ETW Patch:修改dll 中的 EtwEventWrite 函数,使其直接返回而不上报事件。
- 关闭 Trace 会话:通过 EventUnregister 或直接操作 ETW 会话句柄,停止 EDR 订阅的事件追踪。
- 日志提供者屏蔽:利用Windows 事件追踪的机制,阻止特定 Provider 的事件发送到消费者。
三、内核态对抗
当用户态绕过不够时,高级攻击者会尝试在内核层面削弱 EDR 的采集能力。
3.1 回调摘除
EDR 在内核中注册了多种回调(进程回调、注册表回调、对象回调等)。这些回调注册后存储在内核的回调链表中。攻击者如果获得内核代码执行权限(通常通过漏洞利用),可以:
- 直接从回调链表中移除EDR 的回调条目,使 EDR 不再收到事件通知。
- 修改回调函数指针,将其指向一个"什么都不做"的空函数。
这种技术的前提是获得内核执行权限,通常需要配合内核漏洞利用(BYOVD,Bring Your Own Vulnerable Driver------加载一个有已知漏洞的合法签名驱动,利用其漏洞获得内核读写原语)。
3.2 Minifilter 对抗
EDR 的文件系统监控依赖 Minifilter 驱动。攻击者可以:
- Altitude 竞争:加载一个Altitude 更高的 Minifilter,在 EDR 之上拦截文件操作并修改或丢弃事件,使 EDR 看到的文件操作是被篡改过的。
- 驱动卸载:通过FltUnregisterFilter 或直接操作驱动对象,尝试卸载 EDR 的 Minifilter。
- 绕过文件系统:直接操作磁盘原始扇区,绕过整个文件系统栈(包括Minifilter)。这种手法在 bootkit 和勒索软件中较为常见。
3.3 驱动签名与加载对抗
Windows 要求内核驱动必须有微软签名。攻击者的常见路径是 BYOVD:寻找存在漏洞的合法签名驱动(如某些硬件厂商的过时驱动),加载后利用漏洞获得内核任意读写能力,进而关闭 EDR 的内核保护。
四、EDR 的自我保护体系
面对上述对抗,EDR 产品构建了多层自我保护机制,目标是:即使攻击者获得管理员权限,也难以禁用或篡改 EDR。
4.1 受保护进程轻量版(PPL)
Windows 提供 PPL(Protected Process Light)机制,允许安全软件将自身进程注册为受保护进程。PPL 进程具有以下特性:
- 普通进程(即使以管理员权限运行)无法打开PPL 进程的句柄用于写入、注入或终止。
- 无法将DLL 注入到 PPL 进程的地址空间。
- 无法调试PPL 进程。
PPL 的保护级别由签名策略决定。EDR 进程通常使用 PsProtectedSignerAntimalware 保护级别,需要对应的微软签名证书才能生效。
4.2 早期启动反恶意软件(ELAM)
ELAM(Early Launch Anti-Malware)是微软在 Windows 8 引入的机制,允许安全软件的驱动在所有其他第三方驱动之前加载。ELAM 驱动可以:
- 在系统启动早期就开始监控,防止恶意驱动在EDR 加载前先行植入。
- 通过回调检查后续加载的驱动签名,阻止未签名或恶意签名的驱动加载。
- 为EDR 的主驱动提供一个安全的加载环境。
ELAM 驱动必须经过微软的特殊签名(ELAM EKU),且必须满足严格的行为规范(不能在 ELAM 阶段执行复杂逻辑,只能做驱动签名验证)。
4.3 防篡改保护(Tamper Protection)
Tamper Protection 是一组综合性的配置保护机制,防止攻击者通过修改注册表、停止服务、卸载程序等方式禁用 EDR:
- 注册表保护:EDR的配置注册表键被 Minifilter 或注册表回调锁定,禁止删除或修改。
- 服务保护:EDR的 Windows 服务被标记为不可停止、不可禁用,服务控制管理器(SCM)的操作被拦截。
- 文件保护:EDR的安装目录和关键文件被 Minifilter 锁定,禁止删除、替换或重命名。
- 卸载保护:卸载流程需要防篡改密码或云端授权,防止攻击者通过脚本静默卸载。
微软 Defender for Endpoint 的 Tamper Protection 还会与 Windows 安全中心集成,确保即使攻击者修改了组策略或注册表,实时保护也不会被关闭。
4.4 看门狗与心跳机制
EDR 通常在内部实现多进程/多线程的互相监控:
- 主服务与看门狗进程:主服务负责核心功能,独立的看门狗进程监控主服务的存活状态。如果主服务被终止,看门狗立即重启它。
- 内核态与用户态心跳:内核驱动定期向用户态服务发送心跳,如果用户态服务长时间无响应,驱动可以触发系统恢复或上报告警。
- 云端失联检测:管理平台监控终端的心跳上报,如果某台终端突然停止上报,会标记为"可能被篡改"并触发告警。
4.5 配置与文件完整性保护
- 内存驻留配置:关键策略不再仅依赖磁盘文件,而是在内存中维护一份权威副本,防止攻击者通过修改磁盘配置文件来降级保护。
- 数字签名校验:EDR的可执行文件、驱动、规则库都带有数字签名,加载时进行完整性校验,防止被替换为恶意版本。
- 目录占位防护(Directory Squatting):防止攻击者在 EDR 安装路径之前创建同名目录,导致 EDR 安装或更新失败。
五、对抗性检测:EDR 如何反制绕过
自我保护解决的是"EDR 不被关掉"的问题,而对抗性检测解决的是"即使攻击者尝试绕过,EDR 仍能发现"的问题。
5.1 调用栈异常检测
即使攻击者使用间接系统调用绕过了用户态 Hook,内核回调仍然可以捕获系统调用事件。EDR 在内核回调中检查调用栈:
- 正常调用的栈帧应该是dll → ntdll.dll → syscall → 内核。
- 如果栈中出现异常的返回地址(如来自堆内存、来自未签名模块、或栈帧被刻意伪造),则标记为可疑。
- 间接系统调用虽然syscall 指令在 ntdll 内,但调用栈中 ntdll 之前的帧可能来自攻击者的代码,这仍然是异常信号。
5.2 内存页属性与 VAD 扫描
EDR 可以扫描进程的虚拟地址空间,寻找异常的内存区域:
- RWX 内存页:同时具有可读、可写、可执行属性的内存页是进程注入的典型特征。正常程序很少使用RWX 页。
- VAD(Virtual Address Descriptor)异常:Windows 内核用 VAD 树描述进程的虚拟内存布局。EDR 可以检查 VAD 条目,发现被隐藏的内存区域(如通过 NtAllocateVirtualMemory 分配但未在 VAD 中正确标记的区域)。
- 私有可执行内存:不属于任何已加载模块的可执行内存页,可能是反射型DLL 注入或 shellcode。
5.3 系统调用号解析异常检测
Halo's Gate 等技术通过扫描相邻函数来推断 SSN。EDR 可以检测:
- 进程对dll 代码段的异常读取模式(如顺序扫描多个 Nt* 函数的前导字节)。
- 进程内存中出现与ntdll 系统调用桩相似的代码模式。
- 系统调用号与调用函数不匹配(如调用NtOpenProcess 但使用了 NtWriteVirtualMemory 的 SSN)。
5.4 内核回调完整性校验
EDR 的内核驱动可以定期校验内核回调链表的完整性:
- 检查进程回调、注册表回调、对象回调链表中是否存在异常条目(如被移除、被替换)。
- 校验Minifilter 驱动对象的函数指针表是否被篡改。
- 监控内核中对回调注册/注销函数的调用,发现异常的回调操作。
5.5 行为关联兜底
即使单点检测被绕过,EDR 的行为关联引擎仍然可以从整体行为模式中发现异常:
- 一个进程虽然绕过了内存操作的Hook,但它后续创建了远程线程、建立了可疑网络连接、修改了注册表持久化键------这些行为组合起来仍然会触发告警。
- 攻击者绕过AMSI 执行了恶意脚本,但脚本执行后派生的进程、访问的文件、连接的 C2 服务器仍然在 EDR 的监控范围内。
这就是多层检测的价值:绕过每一层的技术都存在,但同时绕过所有层且不留下任何行为痕迹的难度极高。
六、客观认识:没有不可绕过的 EDR
需要坦诚地说明:
- 任何用户态检测都可以被内核权限绕过。如果攻击者获得了内核执行权限,理论上可以禁用所有EDR 的内核回调和驱动。EDR 能做的是通过 ELAM、驱动签名策略、内核回调完整性校验等手段提高获得内核权限的难度。
- BYOVD 是当前最难防御的攻击路径之一。合法签名的有漏洞驱动数量众多,且微软无法在不影响兼容性的情况下全部吊销。EDR通常通过驱动行为监控(如检测驱动的异常内核读写操作)来缓解,而非完全阻止。
- 自我保护不是绝对的。PPL、Tamper Protection 等机制依赖操作系统提供的安全原语,如果操作系统本身存在漏洞,这些保护也可能被突破。2026年已有安全研究展示了利用 EDR 自身管理工具(如 unprotect 命令)将 EDR 变为"特洛伊木马"的攻击手法。
- 对抗是持续的。攻击者和防御者在不断进化,今天有效的绕过技术可能在下次EDR 规则更新后失效,反之亦然。
因此,评估 EDR 产品时不应问"它能不能被绕过",而应问:绕过它需要多少成本?攻击者需要多少前置条件?绕过之后是否还有其他检测层可以兜底?
七、总结
EDR 的攻防对抗是一场围绕操作系统内部机制的技术博弈:
- 攻击者的路径:从用户态Hook 绕过(Direct/Indirect Syscall、Unhooking),到 AMSI/ETW 禁用,再到内核态回调摘除和 BYOVD,逐步深入。
- 防御者的体系:PPL保护进程、ELAM 抢占启动时机、Tamper Protection 锁定配置、看门狗维持存活、内核完整性校验防止回调被篡改。
- 最终的兜底:多层行为关联检测,确保即使单点被绕过,整体攻击行为仍然可见。
一个成熟的 EDR 产品不会宣称"无法被绕过",而是通过纵深防御将绕过成本推高到攻击者难以承受的水平。对于企业安全团队而言,理解这些对抗技术的价值在于:合理设定对 EDR 的预期,不将其视为万能屏障,而是将其作为终端可见性和快速响应的基础设施,与身份认证、网络分段、漏洞管理等其他安全控制协同运作。