windows11 24H2 NT 内核提权分析(译)

admin 2024年5月24日23:09:15评论6 views字数 5341阅读17分48秒阅读模式

利用 NT 内核在 24H2 中:旧代码中的新漏洞和针对 KASLR 的侧信道

源代码:https://github.com/exploits-forsale/24h2-nt-exploit

背景

即将到来的 Windows 11 版本,24H2,目前正在通过 Windows Insider 计划公开预览。本文介绍了在 24H2 中发现多个内核漏洞并编写漏洞利用程序的过程,包括绕过针对内核 ASLR (KASLR) 的新硬化措施。

这里描述的所有漏洞都存在于 NT 内核本身 (ntoskrnl.exe) 中,在任何进程都可以调用的系统调用中,无论其权限级别或沙箱如何。

旧代码中的新漏洞

在对 24H2 中的 NT 内核的不同部分进行逆向工程时,我发现了两个漏洞,这两个都是用户模式内存的双重获取(归功于:j00ru)。这些漏洞特别有趣,因为它们出现在长期存在的代码中,以前被认为是安全的。

关于用户模式内存易失性的变化

我想以一个免责声明开始本节:以下大部分是最佳猜测。如果没有访问源代码和确切的编译器,就无法完全确定 Microsoft 那边引入观察到的二进制文件变化的确切变化。

在 24H2 中,似乎已经进行了广泛的更改,以在内核内将用户模式内存视为易失性的。这方面的一个证据是新增了一个名为 RtlCopyVolatileMemory 的内存复制函数,顾名思义,它的行为与 RtlCopyMemory 完全相同,但明确用于访问易失性内存。内核以前使用内联读写指令将用户模式内存复制到内核模式的许多实例已被替换为对这个新函数的调用。下面可以看到几个实例:

案例 1:在 NtCreateTimer2 中从用户模式内存进行的 4 个字节读取

windows11 24H2 NT 内核提权分析(译)
案例 1:在 NtCreateTimer2 中从用户模式内存进行的 4 个字节读取

案例 2:在 ObpCaptureBoundaryDescriptor 中从用户模式内存进行的 16 个字节读取

windows11 24H2 NT 内核提权分析(译)
案例 2:在 ObpCaptureBoundaryDescriptor 中从用户模式内存进行的 16 个字节读取

在 24H2 中将用户模式内存视为易失性的变化也可以在 Microsoft GitHub 上的公共拉取请求 中看到,在我看来,这增加了这一变化是广泛变化的理论的可信度。

这些变化也解释了在以前可能被编译器优化隐藏的区域出现的双重获取。在源代码中,对用户模式内存的同一位置进行双重解引用的传统双重获取,可能已优化为二进制文件中的单一解引用。然而,如果内存位置被视为易失性的,那么源代码中的每个解引用应该对应二进制文件中的唯一解引用。下面我将详细介绍我发现的两个漏洞,我怀疑这是这种模式的结果。

CVE-2024-26218:PspBuildCreateProcessContext 中的双重获取导致栈缓冲区溢出

创建进程时,关于正在创建的进程的各种属性是通过 NtCreateUserProcess 系统调用来提供的,在一个 PS_ATTRIBUTE_LIST 结构中。正如名字所示,PS_ATTRIBUTE_LIST 是一个 PS_ATTRIBUTE 结构数组。PspBuildCreateProcessContext 函数处理这些位于用户模式内存中的属性列表。

PspBuildCreateProcessContext 包含了许多用于处理 每种属性类型 的情况。在处理类型为 PsAttributeMitigationOptionsPsAttributeMitigationAuditOptions 的属性时,PS_ATTRIBUTE 中的 Size 字段出现了双重获取。通过在获取之间更改 Size 的值,可以触发栈缓冲区溢出。

下面我提供了伪代码和 23H2 版本相关代码的二进制文件的相应反汇编,该版本不包含双重获取,然后是 24H2 中易受攻击版本的伪代码和反汇编。

23H2

windows11 24H2 NT 内核提权分析(译)
23H2

24H2

windows11 24H2 NT 内核提权分析(译)
24H2

如上所述,将属性视为易失性的变化导致以前的单一解引用被两个单独的解引用所取代。

这个漏洞的概念验证已经在 GitHub 上提供。

CVE-2024-21345: NtQueryInformationThread 中的双重获取导致任意写入

这个漏洞与前一个类似,因为它再次在以前的代码中只包含单一获取的地方双重获取了一个长度字段。与前一个漏洞不同的是,这个漏洞不会导致缓冲区溢出,而是绕过了对用户提供的地址的探测。绕过探测允许用户指定一个完全任意的地址,包括内核地址,进行写入。

NtQueryInformationThread 像其他 NtQueryInformation* 系统调用一样,包含一个巨大的 switch 语句,用于处理可以传入的不同信息类,以便从用户模式查询有关内核对象的信息。这个特定漏洞在处理 ThreadTebInformation 信息类时出现,它允许读取线程的 TEB 的部分内容。这个特定情况的输入是一个位于用户模式内存中的 THREAD_TEB_INFORMATION 结构体。这个结构体包含一个目标指针,用于指定存储 TEB 数据的位置,以及指定从 TEB 读取多少数据的大小。

这个漏洞的代码比前一个更复杂。在这个漏洞中,用户提供的结构体被完全复制到内核模式,然而,在执行调用 ProbeForWrite 时,用户模式内存中的结构体再次被解引用以传递大小。对于调用 ProbeForWrite 后用户输入的所有使用,内核模式复制的结构体被使用。ProbeForWrite 包含一个鲜为人知的怪癖:如果传递的大小为零,函数将立即返回,而不会检查传递的地址。这意味着,如果将内核地址和大小零传递给 ProbeForWrite,将不会引发异常,从而基本上绕过了探测。

与前一个案例一样,我提供了我的伪代码,表示源代码可能的样子,以及 23H2 二进制文件的汇编,其中不包含漏洞,以及 24H2 中漏洞代码的汇编。

23H2

windows11 24H2 NT 内核提权分析(译)
23H2

24H2

windows11 24H2 NT 内核提权分析(译)

24H2

正如上面的代码所示,通过在第一次解引用时让用户模式的 BytesToRead 是一个非零值,然后在第二次解引用之前将其更改为零,代码将向 ProbeForWrite 传递大小零,绕过了实际地址的检查,并允许指定内核地址。稍后,当调用 memmove 时,大小将是第一次解引用时 BytesToRead 的原始值。这允许将 TEB 的内容复制到任意控制的地址和大小。

由于 TEB 位于用户模式内存中,其内容也是可以控制的。通过写入 TEB,然后触发这个漏洞从 TEB 读取,可以可能在内核模式内存中的任何地方写入完全控制的数据。

这个漏洞的概念验证已经在 GitHub 上提供。

24H2 中的 KASLR

在以前的 Windows 版本中,由于许多系统调用在其输出中包含内核指针,击败 KASLR 是微不足道的。然而,在 24H2 中,正如 Yarden Shafir 在一篇 分析这一变化的博客文章 中所记录的,这些内核地址泄漏不再对无特权调用者可用。

在没有经典的 KASLR 绕过的情况下,为了确定内核的布局,需要一种新技术。我听说了一种在 Linux 上使用的技术,称为 EntryBleed,它使用了一个时序侧信道来确定内核的地址,我决定调查是否可以在 Windows 上使用类似的技术。

EntryBleed & Prefetch 简介

EntryBleed 的非常简短的总结如下:KPTI(内核页表隔离)是 Linux 中引入的一个功能,通过从用户模式页表中移除所有内核内存,来分离用户和内核页表,以缓解 Spectre 类攻击。然而,这的一个缺陷是,当用户模式应用程序执行系统调用时,包含系统调用处理程序代码的内存必须在页表中。这意味着内核内存的一个小区域,即系统调用处理程序,仍然存在于用户模式页表中。

由于系统调用处理程序的内存在用户模式页表中,如果可以确定给定地址是否在页表中,就可以找到内存的地址。这就是 prefetch 指令的用武之地。Prefetch 接受一个地址,并尝试将内容加载到 CPU 缓存中,以便将来的访问更快。与读取或写入给定地址的指令不同,prefetch 不关心提供的地址是否是内核地址。事实证明,通过测量 prefetch 指令执行给定目标地址所需的时间,可以确定目标地址是否在当前页表中。

这是 EntryBleed 的非常简短的总结。有关更详细的描述,我强烈推荐 阅读原始文章。

Windows 上的 Prefetch

在了解了 Linux 上的 EntryBleed 后,我开始将这种技术移植到 Windows 上。我最初假设我将不得不应对 KVA 阴影(Windows 等价于 KPTI),但很快意识到现代 Windows 11 机器上不再启用 KVA 阴影。这意味着由于用户和内核页表之间不再有任何隔离,不仅系统调用处理程序的内存存在于用户模式页表中,而且整个内核地址空间也是如此。

此外,我发现了 Daniel Gruss、Clémentine Maurice 和 Anders Fogh 在 2016 年发表的一篇 论文,描述了我希望能够实现的完全针对 Windows 的 prefetch 攻击。在这些资源的帮助下,我开始测量我可以使用的所有机器上的 prefetch 时间,并制作了一个(相当)可靠的工具来确定 Windows 内核的基地址。

这个工具非常是一个概念验证,有很大的改进空间,但我发现它在现代 Intel CPU 上是可靠的。AMD CPU 在 prefetch 映射地址时的行为似乎不太一致。我能够使我测试的 VM 中的 AMD 支持可靠,但在其他硬件上运行时遇到了问题。任何对侧信道更有经验人士的改进都将不胜感激!这个工具的源代码可以在 GitHub 上找到。

prefetch 工具在行动!

windows11 24H2 NT 内核提权分析(译)
prefetch 工具在行动!

利用

现在我们有足够的东西开始构建一个真正的漏洞利用程序。我们已经绕过了 KASLR,确定了内核在内存中的基地址,我们有一个漏洞,允许我们在内核中的任何地方写入任意数据。在以前的 Windows 版本中,可以通过其句柄获取特定对象的内核地址,然后可以作为腐败的目标。现在我们有的唯一的内核地址是内核的基地址,所以我们需要从内核中腐败全局对象开始。

构建内核读取

我们的第一项任务将是构建一个读取原语。有了已经牢固掌握的写入原语,拥有读取将完全为我们打开内核,让我们做任何我们想做的事情。为了完成这个任务,我们需要找到一个内核中的全局变量,我们可以将其作为腐败的目标,以创建一个读取原语。为了寻找这个的候选,我求助于一直乐于助人的 NtQuerySystemInformation 系统调用(长期以来一直是 KASLR 泄漏的来源)。理想的情况是找到一个案例,其中系统调用使用一个全局变量存储指针,读取全局指向的数据,并返回读取的数据到用户模式。

我在处理 SystemManufacturingInformation 信息类的案例中找到了完美的案例。在处理这个信息类时,内核会将一个名为 ExpManufacturingInformation 的全局 UNICODE_STRING 结构体复制到用户模式。UNICODE_STRING 结构体包含一个指针和长度,通过覆盖全局结构体中的这些,可以读取任意地址和大小的数据,并将数据返回到用户模式。

提权前的清单

现在我们已经想出了一个内核读取原语,让我们快速回顾一下我们武器库中的所有东西:

  • ✅内核 ASLR 绕过
    • 使用时序侧信道。
  • ✅任意内核写入
    • 使用 NtQueryInformationThread 中的双重获取。
  • ✅任意内核读取
    • 依赖于 KASLR 绕过和内核写入。
    • 通过腐败 ExpManufacturingInformation 全局和 NtQuerySystemInformation

有了这些可靠的原语,是时候将它们全部整合起来,提升我们的权限了。

实际的漏洞利用:令牌交换

我在最终漏洞利用中使用的技巧是经典的进程令牌交换(在 hasherezade 的这篇文章中描述)。我通过读取内核中的 PsActiveProcessHead 全局来遍历系统上运行的进程列表。一旦我在列表中找到了一个特权进程,我就记录了它的令牌对象的地址。然后我再次遍历进程列表以找到我的漏洞利用进程,并用特权进程的令牌替换了它的令牌。完成后,我调用 CreateProcess 弹出一个闪亮的新 以 NT AUTHORITYSYSTEM 身份运行的命令提示符窗口!

我们的漏洞利用完成了 windows11 24H2 NT 内核提权分析(译)

windows11 24H2 NT 内核提权分析(译)
我们的漏洞利用完成了 windows11 24H2 NT 内核提权分析(译)

完成的漏洞利用的源代码在 GitHub 上可用。

最后的思考

二进制文件以神秘的方式改变

正如我在开始时提到的,我还想再次强调,没有访问源代码和编译器,几乎不可能确切知道是什么导致了这里描述的两个漏洞被引入。作为一个安全研究员,这些突然出现的漏洞是一个惊喜,但对于供应商来说,我相信这些可以凸显对现有代码进行看似无关紧要的更改的风险。

KASLR:还有很长的路要走

KASLR 在 Windows 上长期以来都是微不足道的,任何变化都将是一种改进。微软对 KASLR 的态度也表明,他们不认为它是一种有意义的缓解措施,因为他们 既不服务也不奖励 KASLR 绕过。在 Windows 11 中禁用 KVA 阴影的决定也削弱了内核内存与用户模式之间的隔离。虽然消除许多经典的 KASLR 泄漏肯定会为漏洞开发者创造一些额外的工作,但我不认为它构成了真正的挑战。我相信在未来,我们将看到更多的 KASLR 绕过,这些绕过不需要任何侧信道技巧 windows11 24H2 NT 内核提权分析(译)

- END -

原文始发于微信公众号(3072):windows11 24H2 NT 内核提权分析(译)

  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2024年5月24日23:09:15
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   windows11 24H2 NT 内核提权分析(译)https://cn-sec.com/archives/2772641.html

发表评论

匿名网友 填写信息