系统调用完整性层:将EDR从内核迁移到用户态的架构设想

admin 2026-01-22 00:19:42 网络安全文章 来源:ZONE.CI 全球网 0 阅读模式

文章总结: 本文提出了系统调用完整性层架构设想,旨在通过内核子系统将EDR逻辑迁移至用户态。该方案利用AltSyscalls拦截关键系统调用,通过暂停分发并将待处理对象交由用户态EDR检查,以对抗HellsGate等绕过技术。文章阐述了架构设计与同步暂停机制,分析了性能与死锁等技术挑战,并探讨了API支持的可能性,为未来EDR架构演进提供了新的研究方向。 综合评分: 85 文章分类: 安全建设,解决方案,终端安全


cover_image

系统调用完整性层:将 EDR 从内核迁移到用户态的架构设想

fluxsec fluxsec

securitainment

2026年1月21日 10:24 中国香港

| 原文链接 | 作者 | | — | — | | https://fluxsec.red/introducing-system-call-integrity-layer | fluxsec |

让系统调用解释自身行为。

TLDR

我提出了一个内核子系统,名为系统调用完整性层 (SCIL),它允许用户态 EDR 通过 Alt Syscalls 对选定的系统调用进行拦截,暂停调用分发并将待处理系统调用对象(PSO) 交给 EDR 进程进行检查,然后再允许系统调用继续执行。

项目地址:GitHub!

前言

这个小型项目 (尽管在复杂度上并不小) 属于一个思想实验和一系列架构设想,未来可能会被 Microsoft 或安全团队实现,用于对抗恶意行为者在运行时逃避检测的技术手段。

我想要阐述的一些内容,作为第三方开发者是无法完整实现的。对我来说,也无法同时构建这项依赖于 Alt Syscalls 和 secure enclaves 的技术 – 因为 Alt Syscall 技术要求 HVCI 被禁用。

因此我将在 VTL0 中构建这个项目。VTL1 的次优方案是 ELAM 和 Protected Process Light– 为了节省繁琐的工作 (以及便于调试),我打算构建一个标准的用户态应用程序,因为这只是一个概念验证。如果这个项目将来真的被实际团队采纳,那么需要更完善的应用程序设计。

我热爱 Windows Internals,这项工作并非旨在成为具有严密信任边界、精致通信流程或健壮威胁模型的完整解决方案。我只是有了一个我认为很酷的想法,想尝试在操作系统中构建一个子系统,就像我是 Microsoft 那些才华横溢的研究员之一。可以说是 Microsoft 角色扮演!不过,我确实相信,这为安全软件从内核迁移到用户态提供了一个有趣概念的起点,我将其称为系统调用完整性层

大胆尝试。勇于探索。敢于实验。

简介

系统调用是 Windows 的主要支柱,用户应用程序和操作系统必须通过它与计算机硬件交互,或访问系统内部结构,以确保计算机正常运行。

由于系统调用在用户应用程序和内核之间充当中介,而 Microsoft 阻止 EDR 直接挂钩 System Service Dispatch Tables (即 Patch Guard),EDR 厂商决定在用户态应用程序中挂钩 .text段,以帮助判断应用程序中发生的行为 (这是现代 Windows 上使用的众多机制之一)。

遗憾的是,威胁行为者和安全研究员开发了诸如 Hells Gate 等技术,能够绕过 EDR 在 NTDLL中包裹系统调用的挂钩存根。我之前提出了一种名为 Ghost Hunting 的方法,使用 Alt Syscalls和其他信号来判断进程在进行系统调用时是否试图逃避 EDR。

虽然这种方法是成功的,但它依赖于 EDR 使用 Alt Syscalls,而我认为这是一个完全闭源的 Microsoft 专有内部系统。因此,它很可能只是一个 ‘Gedankenexperiment'(思想实验)。

我个人支持 EDR 以驱动程序形式存在于内核中,考虑到它们需要对系统进行的审查级别,这完全说得通。当然,总有关于驱动程序导致半个地球宕机的争论 (咳咳),但我不认同这种论点,因为你可以对任何驱动程序或 Msft 内核发布提出同样的论点。这不是第一个导致宕机的驱动程序,也不太可能是最后一个。

我最近一直在思考如何将 EDR 从内核中移出 (出于探索目的),以及如何击败那些绕过 EDR .text段挂钩的威胁行为者。乍一看,这似乎是两个独立的问题,但我想提出一个单一的解决方案

正如我在前言中所说,这个想法更多是一种 Windows 操作系统的架构设计,必须由 Microsoft 实现,我认为这不是安全厂商现在可以直接采用的 (我不这么认为?)。不过,我想将此作为一个基础概念,社区中的其他人可以借鉴、思考,也许有一天 – 在此基础上继续构建!

系统调用完整性层

系统调用完整性层 (SCIL) 被设计为内核中的一个子系统,允许来自用户态的 EDR 通过 Alt Syscalls 挂钩系统调用。EDR 可以标记哪些进程需要被挂钩,并且只指定特定的 System Service Numbers 进行挂钩。

从架构上看,理想的安全解决方案如下:

System Call Integrity Layer VTL1 Architecture

SCIL 子系统在运行时有两个主要功能:

  1. 记录系统调用和参数 (本质上类似于 Events Tracing for Windows: Threat Intelligence的数据流)。

  2. 对于需要深度检查的进程/系统调用:

  3. 通过同步对象临时暂停系统调用。

  4. 与用户态 EDR 应用程序通信 (EDR 此时不再位于内核中),通知其存在一个待处理系统调用对象(PSO)。我尚未确切设计 PSO 将包含或指向什么内容。

  5. 用户态 EDR 应用程序可以执行它通常在 ntdll等处执行的 EDR 操作,然后再允许系统调用分发。

  6. 如果 EDR 批准,则向 SCIL 子系统发送信号以释放同步对象,允许系统调用继续分发。

实际应用中的子系统还需要在 EDR 用户态处理程序故障或响应时间过长时提供短路机制。这类情况仍然可以通过上述第 1 点的信号发射向 EDR 提供遥测数据接入。实际流程如下 (注意这里我没有使用 VBS):

System Call Integrity Layer Architecture

建议只对系统调用的特定子集通过 SCIL 进行挂钩,以避免因持续等待、上下文切换等消耗系统资源。一些合适的候选调用包括:

  • NtOpenProcess
  • NtAllocateVirtualMemory
  • NtWriteVirtualMemory
  • NtContinue
  • NtCreateThread
  • NtCreateProcess
  • NtProtectVirtualMemory
  • NtMapViewOfSection

针对 EDR 厂商/安全厂商的安全子系统的优势在于,Microsoft 可以提供额外的 API,例如 GetThreadContext,EDR 可以直接以受支持的方式使用它来执行诸如检测 Vectored Exception Handler 滥用等操作。

不建议在需要近实时操作的机器上启用系统调用挂钩 (如 SCADA),但你可以考虑仍然使用 SCIL 子系统的日志记录功能,并从中读取数据,就像使用 Events Tracing for Windows 一样。

暂停系统调用

我认为需要探索的主要部分是系统调用分发暂停。幸运的是,我在篡改 Syscalls 方面已经做了大量研究,正如我在关于 Hells Hollow technique 的文章中所述。我建议阅读一下,以准确理解我们可以在分发序列中的哪个位置注入自己的代码。借用我添加到那篇文章的图像,我们可以在我们的回调处理程序框中实现这一点 (忽略栈相关内容 – 正如 @sixtyvividtails 向我指出的,我们不需要那样做来读取/修改陷阱):

Windows 11 KTRAP_FRAME Alt Syscalls Hells Hollow modify return value

我的思路是,如果满足挂钩条件,我们可以使用 KeWaitForSingleObject,通过将其设置为可警报等待来允许线程执行其他任务,然后,以下哪个先发生:

  1. 等待超时 -> 记录并继续执行
  2. EDR 用户态进程回复,系统调用可以继续执行。我们需要跟踪事件同步对象,以便在准备释放时获取正确的对象。我构建了 wdk-mutexcrate,可以以线程安全的方式跟踪这些结构。

或者:我可以考虑使用不可警报等待,并依赖调度器处理等待事务挂起的线程..我可能也会尝试这种方式。

记住,由于资源耗尽瓶颈和响应性问题,这不会针对每个系统调用和每个进程进行设计。

技术挑战

自然,这个提案并非没有技术问题。主要包括:

  • 需要安全的威胁模型和信任边界,以防止对手从用户态干预系统调用分发 (Rootkit 总会存在),或订阅信号 (需要类似 ETW:TI 的保护)。

  • 在系统调用中途暂停线程感觉..很危险。

  • 性能问题 (客观上,这需要测量。需要在真实工作负载下进行测试)。

  • 线程/系统资源匮乏。

  • 死锁。

  • 关于进程/SSN 标记的 ‘Time of check time of use’ 问题。

  • 快速复制到 PSO(我们不希望通过不必要地复制数据到缓冲区来浪费周期)。

  • PSO

    引发时的高效通信和操作 – EDR 组件是否需要打开进程、检查内存等。这种做法的可接受程度如何?

  • 这些更改会影响遗留应用程序吗?(我的直觉是不会)

  • 将线程置于可警报状态会导致递归问题吗 (考虑到它正处于热系统调用分发路径中),会引入其他奇怪的副作用或未定义行为吗?如果一个被暂停的线程需要服务一个本身会进行挂钩系统调用的 APC,会发生什么..?

  • 威胁行为者能否利用这一点来 DOS 系统?

我认为这些问题并非无法解决,但需要认真的性能分析和测试。我只是在这个 POC 项目的开始阶段,我已经开始了系统的大纲,现在在 GitHub 上。

一旦我确定了一些更具事务性的 API,我将开始开发这个项目,我需要对在系统调用中途暂停线程 (可警报) 进行认真测试。我认为这个层面可以由 Microsoft 通过 API 化,通过他们的内核工程师使其比我所能实现的更加稳定,并提供给安全厂商。我不在安全厂商工作,我不知道他们可以在多大程度上集成到操作系统中 (是否有幕后共享),但我希望未来能看到在不依赖未公开 API 的情况下提供更多操作系统集成的努力。威胁行为者并没有放慢脚步,相反,现在比以往任何时候都多。

下一步计划

我没有低估这件事的复杂性。但分解如下:

  1. 定义威胁模型和信任边界。明确说明系统设计将如何防止恶意软件劫持子系统的意图。
  2. 从日志记录模块开始 – 在系统范围内应用此功能,并通过用户态 EDR 信号接收器将所有系统调用记录到文件中。
  3. 实验:在测试进程中挂钩 NtOpenProcess 并测试同步对象方法,让用户态进程发送信号返回以恢复执行。
  4. 尝试不可警报等待。
  5. 定义 PSO的具体形式。
  6. 正确实现 PSO 分发例程。
  7. 添加可调用 API(必须通过 IOCTL,或者也许我可以创建自己的 SSN 并使用 AltSyscalls 来分发它们,那将非常棒),安全厂商可能对内核扩展感兴趣。

下次再见,ciao xo!


Introducing System Call Integrity Layer

免责声明:本博客文章仅用于教育和研究目的。提供的所有技术和代码示例旨在帮助防御者理解攻击手法并提高安全态势。请勿使用此信息访问或干扰您不拥有或没有明确测试权限的系统。未经授权的使用可能违反法律和道德准则。作者对因应用所讨论概念而导致的任何误用或损害不承担任何责任。


免责声明:

本文所载程序、技术方法仅面向合法合规的安全研究与教学场景,旨在提升网络安全防护能力,具有明确的技术研究属性。

任何单位或个人未经授权,将本文内容用于攻击、破坏等非法用途的,由此引发的全部法律责任、民事赔偿及连带责任,均由行为人独立承担,本站不承担任何连带责任。

本站内容均为技术交流与知识分享目的发布,若存在版权侵权或其他异议,请通过邮件联系处理,具体联系方式可点击页面上方的联系我

本文转载自:securitainment fluxsec fluxsec《系统调用完整性层:将 EDR 从内核迁移到用户态的架构设想》

评论:0   参与:  0