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的回调:
关键回调类型及其在内核中的位置:
-
进程通知回调
- API: PsSetCreateProcessNotifyRoutine(Ex)
- 内部结构: PspCreateProcessNotifyRoutine[]
- 触发时机: 进程创建/退出时
- 脱钩方法: 遍历数组,将EDR的回调条目清零 -
线程通知回调
- API: PsSetCreateThreadNotifyRoutine(Ex)
- 内部结构: PspCreateThreadNotifyRoutine[]
- 触发时机: 线程创建/退出时 -
模块加载回调
- API: PsSetLoadImageNotifyRoutine(Ex)
- 内部结构: PspLoadImageNotifyRoutine[]
- 触发时机: DLL/EXE加载到内存时 -
注册表回调
- API: CmRegisterCallback(Ex)
- 内部结构: CallbackListHead(双向链表)
- 触发时机: 任何注册表操作时 -
对象管理器回调
- API: ObRegisterCallbacks
- 内部结构: ObpCallbackListHead
- 触发时机: 进程/线程句柄的创建和复制时
- 脱钩难度: 最高——回调结构在受保护的内核内存中
5.2 实战脱钩流程
回调脱钩的基本流程(需要驱动级权限执行):
-
获取内核基址:通过NtQuerySystemInformation(SystemModuleInformation)枚举内核模块
-
定位回调数组:通过特征码扫描或PDB符号解析,定位PspCreateProcessNotifyRoutine等全局变量
-
枚举回调条目:遍历数组中的每个回调结构,检查回调地址所属的驱动模块
-
识别EDR回调:判断回调函数地址是否属于EDR的驱动模块(如CsAgent.sys for CrowdStrike)
-
脱钩操作:将目标回调条目的函数指针清零,或标记为Inactive
-
清理痕迹:恢复被修改的内核结构的原始保护属性
防御要点: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规避技术来验证检测能力的有效性,是保持安全态势的必需手段。
版权声明
本站仅做备份收录,仅供研究与教学参考之用。
读者将信息用于其他用途的,全部法律及连带责任由读者自行承担,本站不承担任何责任。










评论