Windows EDR内核回调通知机制致盲攻击

admin 2024年6月19日21:58:53评论16 views字数 7721阅读25分44秒阅读模式

介绍

本文将讨论干扰EDR本身的内部工作方式以及它们如何连接到系统。由于能力有限,本文将仅关注 Windows 系统上EDR的攻防技术。本文主要讲述了EDR的工作原理,及如何利用内核回调通知机制来使EDR无效

什么是 EDR?

EDR 代表终端端点检测和响应,EDR 是下一代防病毒和检测主机系统上可疑活动的技术,它们提供持续监控和高级威胁所需的工具。

EDR 不仅可以查找恶意文件,还可以监视端点和网络事件并将其记录在数据库中以供进一步分析、检测和调查。在许多 EDR 控制台中,您可以看到进程树、执行流程、进程注入等。

以下是您可能知道的一些常见 EDR 供应商。

Windows EDR内核回调通知机制致盲攻击    

Windows EDR内核回调通知机制致盲攻击    

背景知识

Windows 内核

在了解 EDR 的工作原理之前,我们需要对 Windows 内核有一个基本的了解。在 Windows 架构中,有不同的访问模式。其中两种模式是用户模式(非正式地称为用户空间)和内核模式(内核空间)。

您可以将用户空间视为您与之交互的 Windows 部分。这包括用户可用的应用程序,例如 Microsoft Office、Internet 浏览器(Chrome、Firefox 等)等。一般来说,您在日常工作或家庭使用中使用的任何应用程序。

内核空间是系统服务运行的地方。这些包括操作系统代码、设备驱动程序、系统服务等等。内核模式拥有访问所有系统内存和 CPU 指令的权限。您可以将内核视为操作系统的核心,它弥合了应用程序与底层硬件之间的鸿沟。

拆分的原因是为了保护关键的 Windows 功能不被用户或用户空间应用程序修改。如果用户能够直接修改内核代码,那么不仅存在巨大的安全隐患,还存在功能隐患。如果关键功能被篡改,导致未处理的异常,则可能导致严重错误并导致系统崩溃。

Windows EDR内核回调通知机制致盲攻击

补丁保护

在过去(x86 Windows XP 时代及之前),用户空间和内核空间之间并没有明确的权限划分。应用程序能够为了自己的目的修补内核函数(尽管微软不鼓励这种做法)。例如,应用程序可能会将内核系统调用表修补到自己的内存空间。因此,当应用程序调用某个内核函数时,杀毒软件或恶意应用程序可以将执行引导到自己的内存空间。

下面是一个潜在系统调用表的示例,以及修改方法。在 PatchGuard 之前,应用程序可以更改系统调用表地址。因此,当另一个应用程序尝试调用该函数时,它实际上是在调用“恶意”函数。

Windows EDR内核回调通知机制致盲攻击

当然,这并不总是出于恶意,因为许多防病毒引擎使用此功能来提高其可见性(如果恶意应用程序调用某个函数,则该函数将被重定向并由 AV 函数进行分析)。但同样,这为名为“rootkit”的恶意软件家族铺平了道路,这些恶意软件家族可以在内核的最深层运行,完全控制操作系统功能,甚至在系统恢复后仍能持续存在。不仅如此,任何对内核进行错误修补并导致未处理异常的应用程序(无论是好是坏)都会导致主机蓝屏并崩溃。

Windows 的解决方案是 内核补丁保护 (KPP) ,通常称为 PatchGuard 。此功能首先在 Windows XP 和 Server 2003 SP1 的 x64 版本中实现。此功能强制限制内核中可以修改和不可以修改的内容(例如修改系统调用地址)。如果进行了任何未经授权的修补,PatchGuard 将执行错误检查并通过蓝屏/重启关闭系统并显示 CRITICAL_STRUCTURE_CORRUPTION 错误。可能触发错误检查的修改示例包括:

  • 修改系统服务表

  • 修改描述符表

  • 修改或修补内核库

  • 内核未分配的内核堆栈

**需要注意的是,PatchGuard 并非万能药。由于 Windows 系统的运行方式,PatchGuard 存在绕过漏洞,并且恶意补丁和 rootkit 仍然存在(尽管很少见)。**

最大的问题是由于这些保护措施,继续使用内核补丁进行操作不符合 EDR 供应商的最佳实现方式。因为:

  1. 如果 EDR 服务使用 PatchGuard 绕过漏洞来修改内核空间,则 Microsoft 可以随时对其进行修补,并破坏其功能和运营模型    

  2. 如果软件中存在漏洞,他们就有可能让整个操作系统崩溃

因此,如果EDR应用程序想要重定向执行流,则必须在 用户空间 内进行。它们确实通过驱动程序等与内核进行交互

进程如何与内核交互

当应用程序调用 Windows API 来执行其代码时,流程如下所示:

Windows EDR内核回调通知机制致盲攻击

在这个例子中,由于 Mimikatz 想要从 LSASS 读取内存,它必须调用 Kernel32 库中的 ReadProcessMemory 函数(由 Kernel32.dll 调用)。该函数调用最终将转发到 Ntdll.dll 中的NtReadVirtualMemory 调用。(内部工作原理稍微复杂一些,但对于本示例而言,了解这些 Windows API 调用的工作原理并不是完全必要的)。    

由于应用程序不能直接与内核交互,它们使用所谓的“ Syscall”。Syscall充当内核空间的代理调用。

Windows EDR内核回调通知机制致盲攻击

基本上,NTDLL 创建对内核的系统调用,内核将执行 NtReadVirtualMemory 的系统调用。内核运行必要的函数,该函数的结果从系统调用返回给应用程序。这样,应用程序就可以利用内核功能,而无需实际修改或在内核内存空间中运行

Windows 驱动程序

在某些情况下,应用程序需要访问内核中的受保护数据。为此,需要使用相应的驱动程序。驱动程序有多种类型,例如硬件驱动程序和软件驱动程序。本文将重点介绍软件驱动程序,因为我们不会与打印机等硬件进行交互。

根据 Microsoft 文档 ,当工具需要访问核心操作系统数据结构时,将使用软件驱动程序。此类数据结构只能由在内核模式下运行的代码访问。通常,需要此功能的工具分为两部分:

1用户模式组件(应用程序)

1此组件在用户模式下运行,并提供用户界面。在 EDR 的范围内,可以将其视为分析事件的 GUI 控制台    

1内核模式组件(驱动程序)

1该组件以内核模式运行,并将信息传回相应的应用程序。

下面是来自同一 Microsoft 文档的图表:

Windows EDR内核回调通知机制致盲攻击

在许多 EDR 实现中,都有一个软件驱动程序,允许应用程序访问内核并利用它来提高进程的可见性。

需要注意的是,虽然驱动程序可以在内核模式下运行,但它们仍然受到 PatchGuard 的限制。它们无法修补受保护的内存,否则会导致系统崩溃。

内核回调

当微软实施 PatchGuard 时,人们知道这将删除某些程序(例如 AV)的功能。实施的妥协是使用所谓的内核回调。

内核回调的工作方式是,驱动程序可以在其代码中为任何支持的操作注册一个“回调”,并在执行特定操作时收到 事前 或 事后 通知。回调不会对底层 Windows 内核执行任何修改。

这些回调的一个常见实现是 PsSetCreateProcessNotifyRoutine(Ex) 。当驱动程序实现此回调函数时,每当创建新进程时,都会调用此回调例程并向请求该进程的驱动程序发送通知。然后,驱动程序可以相应地执行其自己的函数。

请记住,这可以是事前或事后通知。如果安全设备收到正在创建进程的预先通知,它可以检查这是否是已知的坏文件,并向 EDR 驱动程序发出通知以防止该进程发生。同样,如果风险未知,它可以采取事后通知并记录进程操作以供以后进一步分析和关联。

当发生某个操作时,回调会向指定的内核驱动程序发送通知,然后该驱动程序将指令发送回用户空间应用程序。

Windows EDR内核回调通知机制致盲攻击

EDR工作原理

你可能会问为什么你需要了解 Windows 内核才能理解 EDR。这是理解 EDR 的基础,因为它们涉及上述所有知识点。

EDR 通常会执行以下操作:

  • 内核回调

  • DLL hooking/patching

  • 程序执行流 重定向

接下来在将 EDR 添加到组合中时,我们将详细分析MImikatz程序的进程树。    

Windows EDR内核回调通知机制致盲攻击

内核回调

如前所述,许多 EDR 应用程序都有一个实现内核回调的相应驱动程序。此示例将以“进程创建”回调为例。当执行应用程序(例如 Mimikatz.exe)时,需要通过诸如“ CreateProcessW ”之类的函数创建进程。通过调用此函数,将触发相应的回调函数,并且任何实现该回调的驱动程序都会收到通知。因此,在下图中:

  1. 恶意用户或程序想要生成“malware.exe”。为此,将调用 CreateProcessW 来创建新进程及其主线程。如果将其与我们的 Mimikatz 进程图进行比较,就会发现这是在 Kernel32 步骤中。    

  2. 执行“进程创建”回调函数,并向 EDR 驱动程序发送预通知,表明将创建一个新进程

  3. EDR 驱动程序指示 EDR 应用程序 (EDR_Process.exe) 在应用程序 (malware.exe) 的内存空间中注入并挂接 NTDLL,以将程序执行流 重定向到自身。在 Mimikatz 图上,这是 NTDLL 部分,就在进行系统调用之前

Windows EDR内核回调通知机制致盲攻击

DLLhook

现在让我们讨论一下 NTDLLhook 涉及哪些内容。

查看下面的 Mimikatz 图,这是我们当前执行的位置。NTDLL 已被 EDR 应用程序挂接,这是驱动程序在收到回调通知后的指示。通过挂接 NTDLL,执行流被重定向到 EDR 内存空间和函数(例如 DLL)。由于它是在 用户空间 修补内存空间,因此不存在内核崩溃的风险,并且符合 PatchGuard。    

Windows EDR内核回调通知机制致盲攻击

现在你可能想知道hook是什么意思。进一步分解,下面是 EDR 如何hook DLL 的示例。

在原始 NTDLL 内存空间中(红色顶部框),可以看到 syscall 指令将执行权交给了内核。这是未hook函数的正常流程。

在hook/patch的函数(底部)中,可以看到无条件跳转(或其他指令)到达 EDR 内存空间,在该图中为 ctiuser (在我们图的范围内为 EDR.dll)。

一旦执行流被重定向,EDR 引擎就会分析请求并确定可以运行的执行。如果确定执行足够安全,它会将函数重定向回原始 NtWriteVirtualMemory 地址,并执行内核的系统调用,并将响应返回给请求应用程序。(左流程)

如果确定该调用是恶意的,则不会进行系统调用,并终止该进程。(正确流程)

Windows EDR内核回调通知机制致盲攻击

回到我们的 Mimikatz 图,这是我们的流程,包括回调和hook。

Windows EDR内核回调通知机制致盲攻击

EDR绕过方式

至此我们对 EDR 的基本原理及执行流程有了基本的了解,我们可以开始了解它们的弱点了。从我们目前所知道的情况来看,有两个主要的地方可以阻碍执行流程

  • 删除 DLL hook

  • 删除内核回调    

虽然删除 DLL hook是可行的,但可能需要从我们运行的每个可执行文件中解除hook。这并非不可能,但我们会偷懒,选择阻力最小的路径。如果我们完全删除内核回调,理论上,我们运行的任何可执行文件都不会受到 EDR 的判断

查看我们的图表,这里是我们要使EDR 无效的地方(蓝色)。

Windows EDR内核回调通知机制致盲攻击

如果没有回调,EDR 驱动程序将不知道发送到内核的函数调用,并且执行流程中不会发生重定向。因此,可以返回一个干净的、不受监控的流程:    

Windows EDR内核回调通知机制致盲攻击

阻止回调

要删除回调,我们可以从三个选项中选择一个(当然可能也有其他更多的方式),具体取决于我们想要的破坏程度。

  • 将整个回调数组清零

  • 将特定进程通知回调清零 (仅删除回调数组中的 EDR 驱动程序)

  • Patch EDR 进程通知回调

清零回调数组

回调数组包含很多内容,但为了简单起见,您可以将其视为“一个数组,其中包含指向每个从回调函数请求通知的驱动程序的指针” 。为了说明这一点,我将进入 Windows 内核调试器。我们不会详细介绍调试的工作原理;这更多是为了表明回调数组确实存在。

首先,我们将反汇编(“u”) PspSetCreateProcessNotifyRoutine ,我们现在需要知道的是,这是在创建新进程时运行的回调routine 。我们将继续反汇编,直到到达“lea”指令。这个地址将保存包含请求回调的驱动程序列表的回调数组。

Windows EDR内核回调通知机制致盲攻击

查看此内存地址,我们会看到以下数组。红色突出显示的所有内容都是指向驱动程序的不同指针。    

Windows EDR内核回调通知机制致盲攻击

现在,我要稍微作弊一下,使用一个我们稍后会讨论的工具,但为了证明这些是驱动程序回调,让我们将它们与名称一起列出。

Windows EDR内核回调通知机制致盲攻击

我们可以将这个数组中的每个地址清零,但这可能会导致其他驱动程序出现不当行为,而作为攻击方成员,你可能不想这样做。

如上所示,数组中第 6 个元素的值是我们的 EDR 驱动程序。如果我们将数组中第 6 个元素的回调地址清零(第 7 个值,因为数组以 0 开头),理论上我们应该能够将 EDR 隐藏在进程创建事件中。

为了演示,我们运行 Mimikatz(GitHub 上最新版本,未做任何修改),不修改任何回调。通过运行它,我们调用“进程创建”函数并触发一个回调,该回调将通知 EDR,因为它的驱动程序位于回调数组中。    

Windows EDR内核回调通知机制致盲攻击

我们看到驱动程序看到了正在创建的恶意进程并指示终止该进程。

现在,让我们将 EDR 回调清零,从数组中删除 EDR 驱动程序,看看是否可以阻止向 EDR 应用程序发送通知。    

Windows EDR内核回调通知机制致盲攻击

运行 Mimikatz。由于不再有回调通知,EDR 不知道该进程已创建,因此不会执行任何分析/终止。

Windows EDR内核回调通知机制致盲攻击

如果我们将驱动程序地址返回到我们的回调数组,我们就可以看到在运行程序时 EDR 按预期运行。    

Windows EDR内核回调通知机制致盲攻击

Windows EDR内核回调通知机制致盲攻击

Patch EDR 进程通知回调

此方法涉及将 EDR 驱动程序回调保留在数组中(不清零),但将函数中的第一个指令更改为“ret”函数。在汇编指令中,这基本上意味着返回。

进一步反汇编EDR驱动程序函数,我们可以看到任何更改之前的起始指令。    

Windows EDR内核回调通知机制致盲攻击

再次使用我们的秘密工具,我们将使用“ret”命令修补第一条指令。

Windows EDR内核回调通知机制致盲攻击

Windows EDR内核回调通知机制致盲攻击

现在,当我们运行 Mimikatz 时,回调函数仍会被调用,但它会立即“返回”到正常执行流程:

Windows EDR内核回调通知机制致盲攻击

为了证明这是有效的,让我们将原始指令返回到函数中:

Windows EDR内核回调通知机制致盲攻击

我们可以看到,EDR 再次能够终止执行流程。

Windows EDR内核回调通知机制致盲攻击

优化攻击方式

虽然我们可以演示如何使用 Windows 内核调试器来欺骗 EDR,但显然,这对于隐蔽攻击行动来说并不理想。在每个想要篡改 EDR 的主机上跳转到调试器既不隐蔽也不有效,这就是我们的秘密工具发挥作用的地方。

要通过恶意应用程序自动执行此操作,我们需要创建自己的恶意驱动程序/恶意应用程序组合,就像 EDR 驱动程序和应用程序协同工作一样。基本上就是用内核对抗内核。

我们将使用来自 fdiskyou 的 GitHub 项目的evil客户端/驱动程序:    

https://github.com/fdiskyou/windows-ps-callbacks-experiments

相关研究的附带资料库(http://deniable.org/windows/windows-callbacks)。

编译源代码,你会得到两个文件:

evil.sys (驱动程序)

evilcli.exe(应用程序)—它可以将回调数组清零,以及使用“ret”命令修补函数指令。它还可以将任何更改恢复到修补之前的状态。

Windows EDR内核回调通知机制致盲攻击

应用程序与驱动程序协同工作。驱动程序具有读取和修改回调数组所需的权限,因为它在内核空间内运行。应用程序是指示驱动程序执行哪些命令的用户面板。

在 Windows 上加载驱动程序

要在 Windows 系统上加载驱动程序,您需要设置一定的权限,并遵守一定的安全规则:

  1. 要加载驱动程序,您需要在主机上至少以管理员权限运行

  2. Windows 不允许加载未签名的内核驱动程序

例外情况是如果你启用“ 测试签名模式 ”(在开发人员环境之外可能看不到)

否则,您有两个选择:

利用现有的驱动程序

获取driver签名

2015 年 7 月 29 日之后颁发的任何证书将不允许在运行某些版本的 Windows 10 的安全启动计算机上加载

如下所示,我们无法在“测试签名模式”(此处未涉及)之外加载我们的驱动程序。

Windows EDR内核回调通知机制致盲攻击

经过一番摸索,通过浏览一些论坛,我很快找到了可能可以解决我的问题的人。

Windows EDR内核回调通知机制致盲攻击

查看证书,它甚至是在我们 2015 年 7 月 29 日截止日期之前创建的!关于驱动程序证书的另一个有趣的事实是,微软通常不关心证书是否过期。只要它在某个时间点有效。这可能会在未来发生变化,但目前这是允许的。    

Windows EDR内核回调通知机制致盲攻击

Microsoft 允许使用其 SignTool 和适当的 交叉证书 对驱动程序进行签名。交叉证书是“由一个证书颁发机构 (CA) 颁发的数字证书,用于为另一个证书颁发机构的根证书签署公钥。交叉证书提供了一种从单个受信任的根 CA 到多个其他 CA 创建信任链的方法”

交叉证书:

  • 允许操作系统内核拥有单一受信任的 Microsoft 根权限

  • 将信任链扩展到颁发软件发布者证书 (SPC) 的多个商业 CA,这些证书用于对在 Windows 上分发、安装和加载的软件进行代码签名

微软的官方文档页面提供了每个 CA 交叉证书的下载。    

Windows EDR内核回调通知机制致盲攻击

由于我们的证书是由“VeriSign Class 3 Public Primary Certification Authority”颁发的,因此我们将下载相应的证书。结合使用证书和交叉证书,我们可以对我们的恶意驱动程序进行签名。

为了签署证书,我们将使用前面提到的SignTool。

Windows EDR内核回调通知机制致盲攻击

如我们所见,我们遇到了一个小问题。它说我们没有符合标准的证书。请记住,证书已于 2014 年 11 月过期。事实证明,我们可以对系统时间进行一些欺骗。

Windows EDR内核回调通知机制致盲攻击

Windows EDR内核回调通知机制致盲攻击

Windows EDR内核回调通知机制致盲攻击

有了“有效”证书,我们现在应该能够毫无问题地加载驱动程序

Windows EDR内核回调通知机制致盲攻击

当我们运行相应的 evilcli.exe 应用程序时,我们现在可以利用新驱动程序的功能。    

Windows EDR内核回调通知机制致盲攻击

为了显示应用程序和驱动程序之间的关联,下面是在不启动驱动程序的情况下运行应用程序时发生的情况。

Windows EDR内核回调通知机制致盲攻击

总结

最后,让我们使用新的evil程序来隐藏 EDR 驱动程序中的进程、线程和 loadimage 回调,并执行 Mimikatz 来获取完整的密码转储。

首先,我们可以看到我们的 EDR 服务正在运行(你必须再次相信我的话)。    

Windows EDR内核回调通知机制致盲攻击

Windows EDR内核回调通知机制致盲攻击

Windows EDR内核回调通知机制致盲攻击

Windows EDR内核回调通知机制致盲攻击

并显示恢复 EDR 回调:

Windows EDR内核回调通知机制致盲攻击

Windows EDR内核回调通知机制致盲攻击

潜在检测方式

一般来说,防病毒软件和其他安全设备通常不会对驱动程序进行严格审查。它们通常比典型的用户应用程序受到更多的信任。因此,病毒签名可能不是检测恶意驱动程序最可靠的方法。(EDR 未对我的文件进行 AV 检测)。

此外,许多 EDR 未实施防篡改措施来检查其回调是否被清零或更改。原因可能是因为它们在内核中运行,因此它们不希望因持续检查而产生额外的 CPU 周期开销。随着新研究的出现,这种情况可能会在未来有所改变,但目前,我们也不能依赖 EDR 来为我们进行检查。

我发现,Windows 事件日志实际上会记录驱动程序在系统日志中加载的时间。以下是合法戴尔驱动程序的正常 EventID 7045(已安装新服务)。当在计算机上安装新服务/驱动程序时,会发生这些事件。当您安装打印机/wifi/usb 或其他驱动程序时,您可能会看到此事件。

除了一种特殊情况外(至少在我的计算机上),加载内核模式驱动程序时,安全标识符(SID)始终为“S-1-5-18”(本地系统帐户)。    

Windows EDR内核回调通知机制致盲攻击

正如你在加载我们的恶意驱动程序时所看到的,它是由用户 SID 安装的:

Windows EDR内核回调通知机制致盲攻击

诚然,该驱动程序是“evil.sys”并且安装在用户的桌面上,但在实际的活动中,它可能有一个合法的名称并安装在 System32/Drivers/ 目录中。    

我确信如果您创建具有 SYSTEM 权限的服务,它看起来会有所不同,但通常这需要 PSEXEC 或漏洞之类的工具,这些工具可能会更嘈杂并且更有可能被 AV/EDR 标记。

这可能不是一个完美的检测,因为存在极端情况。下面是 Wireshark 安装附带的 Npcap 数据包驱动程序的安装。但我想,在非技术性商业环境中,像这样的驱动程序可能不会安装在普通工作站上。

Windows EDR内核回调通知机制致盲攻击

原文始发于微信公众号(暴暴的皮卡丘):Windows EDR内核回调通知机制致盲攻击

  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2024年6月19日21:58:53
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   Windows EDR内核回调通知机制致盲攻击https://cn-sec.com/archives/2858827.html

发表评论

匿名网友 填写信息