EDR规避深度剖析:系统调用间接执行、ETW绕过与内核回调脱钩"

admin 2026-10-18 13:57:17 网络安全文章 来源:ZONE.CI 全球网 0 阅读模式

cover_image

EDR规避深度剖析:系统调用间接执行、ETW绕过与内核回调脱钩

原创

Pik安全实验室
Pik安全实验室

Pik安全实验室

2026年7月13日 15:54
广东

在小说阅读器读本章

去阅读

从Userland到Kernel:2025年终端安全对抗的最前线  |  前沿攻防技术系列

————————————————————————————————————————

一、终端对抗的新格局

EDR(Endpoint Detection and Response)已经成为企业安全的基础设施。CrowdStrike、Microsoft Defender for Endpoint、SentinelOne三巨头占据了全球90%以上的市场份额。但与此同时,EDR规避技术也进入了高度工程化的阶段——从简单的进程注入发展到了内核回调脱钩、硬件断点利用等底层对抗。

2025年,攻击者已经不再讨论\"能不能绕过EDR\",而是讨论\"绕过EDR需要多少毫秒\"。MITRE ATT&CK评估数据显示,顶级攻击团队能够在500ms内完成从初始执行到EDR供应商遥测盲区的转移。

本文将从攻防双视角,深入终端安全对抗的最前沿技术。注意:所有内容均基于公开研究和防御视角,旨在帮助安全团队理解攻击面,而非提供攻击工具。

二、EDR的检测架构——要绕过先要理解

2.1 EDR的传感器布局

现代EDR不是单一模块,而是一个多层传感器网络。理解每个传感器的能力和盲区是规避的基础:

传感器层 实现方式 可见范围 规避难度
用户态API Hook ntdll.dll的IAT/EAT Hook Ring3 API调用 中等——已有成熟绕过方案
内核回调(Kernel Callback) PsSetCreateProcessNotifyRoutine等 进程/线程/模块/注册表事件 高——需要内核级操作
ETW(Event Tracing for Windows) 系统级事件追踪框架 网络连接、DNS查询、进程创建等 中高——可被patch
Minifilter驱动 文件系统过滤驱动 所有文件读写操作 高——触及底层文件IO
AMSI(Antimalware Scan Interface) 脚本引擎集成的扫描接口 PowerShell/VBS/JS/.NET加载 低——极易被patch
硬件虚拟化(VBS/HVCI) 基于Hypervisor的隔离监控 内核内存完整性 极高——需要Hypervisor级对抗

2.2 为什么ETW是攻击者的首选目标

ETW是Windows上最强大但最不被理解的安全基础设施。几乎每个攻击行为都会产生ETW事件:

·进程创建 → Microsoft-Windows-Kernel-Process Provider → Event ID 1

·网络连接 → Microsoft-Windows-Kernel-Network Provider → Event ID 3

·DNS查询 → Microsoft-Windows-DNS-Client Provider → Event ID 3008

·PowerShell执行 → Microsoft-Windows-PowerShell Provider → Event ID 4103/4104

·.NET程序集加载 → Microsoft-Windows-DotNETRuntime Provider

攻击者的核心逻辑是:如果我能控制ETW,我就能控制EDR看到什么。以下是三种核心绕过手法。

三、系统调用间接执行(Indirect Syscall)

3.1 为什么直接Syscall已经不够了

早期EDR规避方案使用直接的syscall指令来绕过ntdll.dll的用户态Hook。但现代EDR已经进化——它们在内核层面通过ETW栈跟踪或内核回调监控syscall的返回地址。如果syscall指令来自ntdll.dll以外的内存区域(如手动分配的可执行内存),立即触发告警。

这就是间接系统调用(Indirect Syscall)诞生的背景——在ntdll.dll模块内部找一个合法的syscall指令地址,将控制流\"伪装\"成来自合法模块。

3.2 间接Syscall的核心实现

// 间接系统调用的核心逻辑(C伪代码)
typedef NTSTATUS (NTAPI\ pNtAllocateVirtualMemory)(
    HANDLE, PVOID\
, ULONG\_PTR, PSIZE\_T, ULONG, ULONG
);

// 步骤1:从ntdll.dll中定位syscall gadget
PVOID FindSyscallGadget() {
    HMODULE ntdll = GetModuleHandle(L\"ntdll.dll\");
    PUCHAR base = (PUCHAR)ntdll;

// NtAllocateVirtualMemory在ntdll中的偏移
    PUCHAR func = base + GetNtFunctionOffset(\"NtAllocateVirtualMemory\");

// 在函数体内搜索 syscall; ret 序列(0x0F 0x05 0xC3)
    for (int i = 0; i < 32; i++) {
        if (func[i] == 0x0F && func[i+1] == 0x05 && func[i+2] == 0xC3) {
            return &func[i];  // 返回合法syscall gadget的地址
        }
    }
    return NULL;
}

// 步骤2:设置SSN(System Service Number)和参数
NTSTATUS IndirectNtAllocateVirtualMemory(
    HANDLE hProcess, PVOID\* baseAddr, ULONG\_PTR zeroBits,
    PSIZE\_T size, ULONG allocType, ULONG protect)
{
    PVOID gadget = FindSyscallGadget();
    DWORD ssn = GetSyscallNumber(\"NtAllocateVirtualMemory\");

// 设置寄存器:RAX=SSN, R10=第一个参数
    // 然后跳转到ntdll.dll中的合法syscall gadget
    // 此时内核看到的返回地址在ntdll.dll内,EDR不会触发告警
    \_\_asm {
        mov r10, rcx           // 第一个参数放入R10
        mov eax, ssn           // 系统调用号
        jmp gadget             // 跳转到合法gadget(不是call,所以返回
                               // 地址保持在调用者的合法堆栈中)
    }
}

3.3 EDR的反制:调用栈验证

面对间接syscall,EDR厂商升级了检测策略——通过内核回调(PsSetCreateProcessNotifyRoutine等)获取用户态调用栈,验证调用来源:

EDR内核回调中的调用栈验证逻辑:
1. 捕获syscall发生时的用户态RSP
2. 遍历调用栈帧
3. 验证关键函数的返回地址是否落在对应模块的合法地址范围内
4. 如果发现返回地址指向未知内存区域或
   栈帧结构异常 → 判定为间接调用,触发高级告警

攻击者的进一步对抗:
- Stack Spoofing:伪造调用栈帧使得栈回溯结果
  看起来完全合法
- 使用ROP链在合法模块内部跳转(如ntdll中
  的其他gadget),使栈回溯指向合法地址

Stack Spoofing示例(简化):
\_\_asm {
    // 推送伪造的返回地址,都是合法模块内的地址
    push fake\_ret\_addr\_3   // ntdll!LdrpDoDebuggerBreak+0x1c
    push fake\_ret\_addr\_2   // kernel32!BaseThreadInitThunk+0x14
    push fake\_ret\_addr\_1   // ntdll!RtlUserThreadStart+0x21
    jmp indirect\_syscall\_gadget
    // 当EDR回溯这个栈时,看到的是一个完全正常的调用链
}

四、ETW的完整攻防

4.1 ETW的内部架构与攻击面

ETW由三个核心组件构成,每个都是潜在的攻击面:

·Providers(提供程序):产生事件的组件,如内核和用户态应用程序

·Controllers(控制器):管理ETW会话的组件,负责启动/停止追踪

·Consumers(消费者):接收和处理事件的组件,如EDR的遥测收集器

攻击者主要针对Provider和Consumer之间的数据路径。核心技术是patch EtwEventWrite(ntdll中的ETW写入函数),使其在关键事件发生时不写入数据。

4.2 ETW Patch的三种技术路线

技术1:直接Patch EtwEventWrite
// 最粗暴但有效的方法——让ETW写入直接返回成功
// 找到EtvEventWrite函数,将函数开头改为 ret 0x14
PUCHAR etwFunc = GetProcAddress(ntdll, \"EtwEventWrite\");
DWORD oldProtect;
VirtualProtect(etwFunc, 1, PAGE\_EXECUTE\_READWRITE, &oldProtect);
\*etwFunc = 0xC3;  // 0xC3 = RET指令
VirtualProtect(etwFunc, 1, oldProtect, &oldProtect);

技术2:Hook NtTraceEvent
// EtwEventWrite最终会调用NtTraceEvent进行实际的系统调用
// 在NtTraceEvent入口处设置inline hook
// 检测到特定GUID(如PowerShell的ETW Provider GUID)时直接返回

技术3:内存补丁 EtwEventWriteFull
// Patch EtwEventWriteFull中的关键逻辑分支
// 使其在任何过滤条件下都跳过事件写入
// 更隐蔽但需要定位正确的偏移量

防御检测:
- 检查ntdll.dll的.text段完整性(内存 vs 磁盘对比)
- 监控VirtualProtect调用中涉及ntdll地址的情况
- ETW本身可以监控其他ETW Provider的健康状态

五、内核回调脱钩(Kernel Callback Unhooking)

5.1 回调的工作原理

EDR在内核注册多种回调来接收系统事件。Windows内核维护着多个回调数组——每个数组是一个链表或数组结构,EDR将自己的回调函数地址插入其中。攻击者可以遍历这些数组,删除或无效化EDR的回调:

关键回调类型及其在内核中的位置:

  1. 进程通知回调
       - API: PsSetCreateProcessNotifyRoutine(Ex)
       - 内部结构: PspCreateProcessNotifyRoutine[]
       - 触发时机: 进程创建/退出时
       - 脱钩方法: 遍历数组,将EDR的回调条目清零

  2. 线程通知回调
       - API: PsSetCreateThreadNotifyRoutine(Ex)
       - 内部结构: PspCreateThreadNotifyRoutine[]
       - 触发时机: 线程创建/退出时

  3. 模块加载回调
       - API: PsSetLoadImageNotifyRoutine(Ex)
       - 内部结构: PspLoadImageNotifyRoutine[]
       - 触发时机: DLL/EXE加载到内存时

  4. 注册表回调
       - API: CmRegisterCallback(Ex)
       - 内部结构: CallbackListHead(双向链表)
       - 触发时机: 任何注册表操作时

  5. 对象管理器回调
       - API: ObRegisterCallbacks
       - 内部结构: ObpCallbackListHead
       - 触发时机: 进程/线程句柄的创建和复制时
       - 脱钩难度: 最高——回调结构在受保护的内核内存中

5.2 实战脱钩流程

回调脱钩的基本流程(需要驱动级权限执行):

  1. 获取内核基址:通过NtQuerySystemInformation(SystemModuleInformation)枚举内核模块

  2. 定位回调数组:通过特征码扫描或PDB符号解析,定位PspCreateProcessNotifyRoutine等全局变量

  3. 枚举回调条目:遍历数组中的每个回调结构,检查回调地址所属的驱动模块

  4. 识别EDR回调:判断回调函数地址是否属于EDR的驱动模块(如CsAgent.sys for CrowdStrike)

  5. 脱钩操作:将目标回调条目的函数指针清零,或标记为Inactive

  6. 清理痕迹:恢复被修改的内核结构的原始保护属性

防御要点:PatchGuard(内核补丁保护)会在随机间隔检查关键内核结构的完整性,包括回调数组。检测到篡改后会触发Bug Check 0x109(CRITICAL\_STRUCTURE\_CORRUPTION)导致蓝屏。高级攻击者通过禁用PatchGuard(需要Bootkit级别攻击)或利用Hypervisor虚拟化在更深层拦截来绕过。

六、EDR厂商的反制演进

防御方并非停滞不前。以下是2024-2025年EDR厂商的核心反制手段:

·从内核回调向硬件虚拟化迁移:Microsoft的VBS(Virtualization-Based Security)将关键安全组件移至Hypervisor层,即使攻击者控制了内核也难以触及

·用户态行为分析:不再单纯依赖API监控,而是分析进程整体的行为图(父子进程关系、网络连接模式、内存分配模式)

·机器学习异常检测:在传感器端部署轻量级ML模型,检测异常的系统调用模式(如短时间高密度syscall = 可疑)

·内存完整性扫描:定期对比关键DLL(ntdll/kernel32)的磁盘版本和内存版本,检测Inline Hook和Patch

·内核回调的\"看门狗\"机制:定期验证所有注册回调都在正常运行,被脱钩立即告警

七、总结

终端安全对抗的本质是一场永无止境的军备竞赛。攻击者向底层迁移(Ring3→Ring0→Hypervisor→固件),防御方也向底层迁移。但有一个不变的原则:纵深防御。

对于防御者来说,不要指望单一的EDR能阻止所有攻击。结合应用白名单、网络分段、最小权限和运行时行为分析的多层防御体系,才能显著提高攻击成本。同时,定期进行红队演练,模拟最新的EDR规避技术来验证检测能力的有效性,是保持安全态势的必需手段。


EDR规避深度剖析:系统调用间接执行、ETW绕过与内核回调脱钩" 网络安全文章

EDR规避深度剖析:系统调用间接执行、ETW绕过与内核回调脱钩"

本文深入剖析了2025年终端安全对抗中EDR规避的三大前沿技术:间接系统调用通过从ntdll.dll内合法地址执行syscall来绕过用户态hook;ETW绕过通过patchEtwEventWrite等函数使EDR无法接收关键事件;内核回调脱钩通过遍历并清零EDR注册的回调函数指针来隐藏进程创建等行为。文章指出攻击者已能在500ms内完成规避,防御方则向硬件虚拟化、行为分析和内存完整性扫描演进。建议防御者采用纵深防御策略,结合应用白名单、网络分段和最小权限原则。
珠海高新区某半导体企业IT岗火热招募中" 网络安全文章

珠海高新区某半导体企业IT岗火热招募中"

本文为珠海某半导体企业的IT工程师招聘广告,月薪八千至一万二。岗位核心要求包括企业信息化建设、网络运维以及代码保密与数据防泄漏方案落地,需三年以上经验。文末附带招聘中介天唯科技的业务与资质简介,整体属于安全IT领域的典型招聘推广软文,对相关求职者有一定参考价值。
http.sys—UlpParseNextRequest中连接数组容量整数溢出(CWE-190)导致内核池溢出" 网络安全文章

http.sys—UlpParseNextRequest中连接数组容量整数溢出(CWE-190)导致内核池溢出"

该漏洞是http.sys驱动中UlpParseNextRequest函数的整数溢出问题(CWE-190),导致内核池缓冲区溢出(CWE-122)。根因是16位加法无溢出检查,当capacity接近0xFFFF时加5会回绕,导致后续分配过小,引发溢出。补丁通过RtlUShortAdd函数添加溢出检查,并由KIR特性标志控制。攻击者可通过HTTP监听器远程触发,影响IIS、WinRM等服务。建议系统管理员确保KIR标志启用以防范此漏洞。
奇安信联合共建“可信决策人工智能技术北京市重点实验室”正式获批" 网络安全文章

奇安信联合共建“可信决策人工智能技术北京市重点实验室”正式获批"

奇安信联合共建的‘可信决策人工智能技术北京市重点实验室’正式获批。该实验室聚焦解决大模型幻觉、数据投毒等AI安全痛点,旨在推动AI决策的可信可控。奇安信将提供网络安全底座与实战攻防检验机制,开放政企场景加速技术成果转化,以此深化其在人工智能与网络安全交叉领域的产学研协同布局。
评论:0   参与:  0