文章总结: CVE-2024-21338是WindowsAppLocker驱动appid.sys中的权限提升漏洞,被Lazarus组织利用。攻击者通过IOCTL0x22A018调用AipSmartHashImageFile函数,破坏KTHREAD结构的PreviousMode字段,结合令牌模拟和绕过SMEP/kCFG防护,实现从管理员到内核的访问。补丁添加了ExGetPreviousMode检查来修复。 综合评分: 85 文章分类: 漏洞分析,渗透测试,红队,内网渗透,恶意软件
Windows 管理员到内核的权限提升(CVE-2024-21338)
Rafael Rafael
securitainment
2026年7月17日 13:50 中国香港
在小说阅读器读本章
去阅读
| 原文链接 | 作者 | | — | — | | https://hakaisecurity.io/cve-2024-21338-from-admin-to-kernel-through-token-manipulation-and-windows-kernel-exploitation/research-blog/ | Escrito por |
摘要
2024 年 2 月 13 日,在补丁星期二期间,Microsoft基于 Avast 的 Jan Vojtěšek 提交的安全报告披露了 CVE-2024-21338。这是一个全新的 Windows “管理员到内核”权限提升漏洞,允许恶意行为者——在此案例中主要是与朝鲜合作的 Lazarus 组织——通过其 FudModule.dllrootkit 获取内核访问权限。我们都知道 BYOVD(”Bring Your Own Vulnerable Driver”,自带漏洞驱动)理念被全球威胁行为者和恶意软件开发者广泛利用,他们利用自带已签名漏洞驱动的能力来获取内核访问权限,但这已经超越了 BYOVD。此技术适用于系统中已安装的 Windows 驱动:登场的是 appid.sys,它原本由 Windows AppLocker 使用,正如 Microsoft 网站所述,”AppLocker 帮助你控制用户可以运行哪些应用和文件“。
CVE-2024-21338 漏洞利用通过 IOCTL(”输入输出控制“)通信调用 appid.sys驱动内部的特定函数,具体来说是 AipSmartHashImageFile函数,该函数可以通过易受攻击的 IOCTL 控制代码0x22A018来调用。通过使用精心构造的输入缓冲区调用该控制代码,我们能够破坏_KTHREAD线程上下文中的 PreviousMode字段。PreviousMode字段决定了直接系统调用(Nt、Zw)是由内核还是用户发起的。考虑到这一点,我们现在能够调用直接系统调用并使其影响操作系统的内核,从而给予恶意威胁行为者对受害者的内核访问权限。
分析
Lazarus 制作的 FudModule.dll rootkit 的主要焦点是通过篡改 EDR/杀毒产品或使其自身功能对后者隐藏来规避检测,正如 Avast 在”Lazarus and the FudModule Rootkit: Beyond BYOVD with an Admin-to-Kernel Zero-Day”一文所述。然而,本文不会聚焦于 rootkit 本身的工作原理。我们将探索 appid.sys漏洞的工作原理、如何利用它,以及 MSRC 补丁在最新版本 Windows 上做了什么来修复它。
2024 年 2 月 13 日,在补丁星期二期间,Microsoft 安全响应中心(MSRC)披露了一个名为”CVE-2024-21338″的全新漏洞,该漏洞允许攻击者通过向暴露的允许 IOCTL(输入输出控制)通信的函数发送精心构造的 gadget 来读取和写入内核内存。
首先,与 Windows 上任何 IOCTL 通信一样,需要打开与目标驱动通信的句柄。在此案例中,通过在 IDA Pro中分析 appid.sys(AppLocker)驱动,我们可以在 DriverEntry函数中看到,我们需要打开句柄的对象是”\Device\AppID“,如下方截图所示。
DriverEntry 函数
然而,当我们尝试通过 NtCreateFile从 Administrator打开”\Device\AppID“的句柄时,我们遇到了 NTSTATUS代码 0xC0000022(STATUS_ACCESS_DENIED),这意味着 Administrator 用户没有正确的访问权限来打开 AppID 设备的句柄。这让我们开始思考需要什么权限才能成功打开它的句柄。通过调查易受攻击的函数”AipSmartHashImageFile“来试图发现为什么我们无法打开”\Device\AppID“的设备句柄,我们发现通过”AipSmartHashImageFile”函数的交叉引用,可以找到”AipDeviceIoControlDispatch“函数,它与通过设备句柄处理所有对该驱动的 IOCTL 调用的函数相关。
“AipDeviceIoControlDispatch” 函数,与通过设备句柄处理所有对该驱动的 IOCTL 调用的函数相关
打开此调用,我们可以看到”AipSmartHashImageFile“函数通过 IOCTL 代码”0x22A018“被调用,如下方截图所示。
“AipSmartHashImageFile” 函数通过 IOCTL 代码 “0x22A018” 被调用
好了,现在我们有了 IOCTL 代码,能用它做什么?除了通过”NtDeviceIoControl“向此特定函数发送控制请求外,IOCTL 代码还有自己的结构。根据 IOCTL Microsoft 文档,通过分解”AipSmartHashImageFile”函数的 IOCTL 代码,我们可以看到此 IOCTL 代码需要 0x0002(FILE_WRITE_ACCESS)权限才能被调用,这意味着——很可能——要打开驱动的句柄我们需要相同的权限,但你可能会问,哪个用户在 AppID 设备上给予我们这个权限?通过使用 SysInternals Suite中的”WinObj“工具,我们可以列出当前安装中存在的所有系统对象,包括所有驱动的所有设备。通过在”WinObj“应用程序中检查”AppID“设备的权限,我们可以看到”Administrators“组在 AppID的 ACL(访问控制列表)中没有所需的”写入“访问权限,如下方截图所示。
“Administrators” 组在 AppID 的 ACL 中没有所需的”写入”访问权限
我们还可以看到”LOCAL SERVICE“用户名确实拥有所需的”写入“权限,可以成功访问并通过 IOCTL 代码调用我们需要的函数。
“LOCAL SERVICE” 用户名拥有所需的”写入”权限
考虑到这一点,我们现在进入利用阶段,我们将通过”令牌模拟“利用”Windows 访问令牌“,并将精心构造的 gadget 发送到”AipSmartHashImageFile”函数。
利用
利用阶段从获取”\Device\AppID“句柄的访问权开始,为此,我们需要进程中拥有”LOCAL SERVICE“访问权限。要获得此访问权限,我们需要应用一些访问令牌模拟技术,以在进程中实现”LOCAL SERVICE“权限。
什么是 Windows 访问令牌?根据 Microsoft 文档,访问令牌是”一个描述进程或线程的安全上下文的对象。令牌中的信息包括与进程或线程关联的用户账户的身份和权限。当用户登录时,系统通过将用户密码与存储在安全数据库中的信息进行比较来验证。如果密码被认证,系统会生成一个访问令牌。代表该用户执行的每个进程都有此访问令牌的副本”。
这些令牌可以被操纵,使得我们能够通过检查进程是否具有特定权限来从 Windows 中的远程进程窃取它们。在此案例中,从提权(Administrator)到”NT AUTHORITY\SYSTEM“(S-1-5-18),需要两个权限:”SeDebugPrivilege“和”SeAssignPrimaryTokenPrivilege“。
“winlogon.exe”进程暴露了一个同时拥有这两个权限的令牌,因为按照设计,由于该进程需要操纵 Windows 的登录状态,它以 SYSTEM 身份运行,且用户可以轻松与之交互,从而允许用户从 winlogon复制”NT AUTHORITY\SYSTEM”访问令牌。
在使用”DuplicateTokenEx“成功复制 SYSTEM 令牌后,我们现在可以通过查找具有上述权限的任何令牌来获取”NT AUTHORITY\LOCAL SERVICE“(S-1-5-19)访问令牌:”SeDebugPrivilege“和”SeImpersonatePrivilege“。通常,大多数”svchost.exe”进程以”NT AUTHORITY\LOCAL SERVICE“身份运行,因此找到一个应该非常容易和快速。
现在我们拥有了”NT AUTHORITY\LOCAL SERVICE“访问权限,这意味着我们对”AppID“设备句柄(”\Device\AppID“)和 0x22A018控制代码都拥有”写入“访问权限,我们现在可以成功打开上述设备句柄。拥有正确的句柄和对”AipSmartHashImageFile“函数的访问权限后,我们现在可以构造有效载荷来触发”PreviousMode“字节的内存”破坏”。
PreviousMode是每个 _KTHREAD结构中都存在的一个字段,指示系统调用是从 KernelMode还是从 UserMode发起。考虑到这一点,一些 Nt或 Zw(直接)系统调用通过检查当前线程的”PreviousMode“字段来检查”PreviousMode“值,以下是从”ntoskrnl.exe“反汇编中提取的”NtWriteVirtualMemory“系统调用代码片段示例:
“NtWriteVirtualMemory” 系统调用代码片段,取自 “ntoskrnl.exe” 反汇编
“PreviousMode“字段是一个简单的枚举,有两个成员:”UserMode“和”KernelMode“,即 KernelMode为 0,UserMode为 1。知道我们可能可以修改内存中当前 _KTHREAD结构中的此值后,我们深入探讨对此字段的内存破坏实际上是如何工作的。
使”PreviousMode“利用真正起作用的主要罪魁祸首是”AppHashComputeImageHashInternal“,它在”AipSmartHashImageFile“函数内部被”AppHashComputeFileHashesInternal“函数调用,如下方截图所示。
“AppHashComputeFileHashesInternal” 在 “AipSmartHashImageFile” 函数内部
如下方截图所示,两个参数通过这一系列函数链传递,最后是”AppHashComputeImageHashInternal“执行一个由用户控制的函数指针,该函数指针基于用户控制的缓冲区,在此案例中,由我们对 0x22A018控制代码的调用控制。
“AppHashComputeImageHashInternal” 执行由用户控制的函数指针
现在,我们能不能直接构造一个用户模式 shellcode 发送到控制代码,告诉当前线程的”PreviousMode“减为 0?遗憾的是,我们不能。登场的是 kCFG(内核控制流防护)和 SMEP(管理模式执行防护)。
-
SMEP
(管理模式执行防护)不允许我们在更高特权级别时执行用户模式中的代码,这将不允许我们执行用户模式 shellcode 来实现我们想要的目标。
-
kCFG
(内核控制流防护)不允许我们调用任意或未验证的函数指针,特别是那些指向用户模式地址或位于已建立的 CFG 有效内核函数位图之外的位置的指针。此机制确保所有间接函数调用都根据控制流完整性策略进行检查,防止将执行流转移到恶意或意外代码段的利用。
考虑到这两种保护,我们现在需要找到一个存在于有效内核函数的 CFG 位图中的函数,使其可以用作间接函数调用的合法目标。此函数理想情况下应提供可用于进一步利用的能力,在此案例中是内存操纵,同时遵守 kCFG和 SMEP设置的约束。
感谢此前在此问题上的研究,”Windows AppLocker Driver Elevation of Privilege (CVE-2024-21338)”一文详细介绍了如何在 CFG 位图中找到有效的 CFG函数。我们的 PoC中选择的是”ExpProfileDelete“,它是一个有效的 CFG函数,其功能几乎完美适合我们的需求。查看”ExpProfileDelete“函数的反汇编:
“ExpProfileDelete” 函数的反汇编
我们可以看到该函数接收一个参数,该参数将传递给”ObfDereferenceObject“函数,后者随后导致作为”ExpProfileDelete“函数参数传递的地址递减,使”PreviousMode“地址数据从 1变为 0,导致”NtWriteVirtualMemory“和”NtReadVirtualMemory“系统调用将其调用解释为来自内核模式。允许恶意用户控制使用此漏洞利用的系统的内核空间内存。
补丁
Microsoft 安全响应中心(MSRC)在 2 月制作的补丁在”AipSmartHashImageFile“调用之前添加了”ExGetPreviousMode“检查,这防止了用户模式发起的调用触发上述回调函数。下图显示了较新版本 Windows 上相同控制代码的反汇编。
较新版本 Windows 上相同控制代码的反汇编
图片来源:https://decoded.avast.io/janvojtesek/lazarus-and-the-fudmodule-rootkit-beyond-byovd-with-an-admin-to-kernel-zero-day/
通过使用 BinDiff 工具(显示两个二进制文件之间的差异),我们还可以看到补丁中应用的更改,即仅添加了”ExGetPreviousMode“检查。
补丁中应用的更改,即仅添加了 “ExGetPreviousMode” 检查
图片来源:https://nero22k.github.io/posts/windows-applocker-driver-elevation-of-privilege-cve-2024-21338/#patch-diffing
概念验证
基于所示的所有概念,制作了一个概念验证(PoC)来展示此漏洞的严重性。下方是显示 PoC 执行调用栈的图像,遵循上文所示的相同原则。
显示 PoC 执行调用栈的图像
PoC 的链接可在 GitHub 上获取:https://github.com/hakaioffsec/CVE-2024-21338。
结论
总而言之,CVE-2024-21338 漏洞在 Windows 系统中构成了重大的权限提升威胁,值得注意的是,Lazarus 组织利用它绕过了 EDR 和杀毒软件等传统安全措施。此漏洞展示了一种超越已经令人担忧的 BYOVD 方法的高级技术,通过操纵内核中的”PreviousMode“字段来实现未授权访问,同时配合广泛的令牌模拟技术,分别实现从管理员到内核的执行。Microsoft的响应——在其 2 月更新中纳入了关键补丁——突显了网络安全专业人员与威胁行为者之间持续的猫鼠游戏。CVE-2024-21338 的研究帮助我们进一步理解此类特定漏洞如何在野外发生。
参考文献
- https://decoded.avast.io/janvojtesek/lazarus-and-the-fudmodule-rootkit-beyond-byovd-with-an-admin-to-kernel-zero-day/
- https://nero22k.github.io/posts/windows-applocker-driver-elevation-of-privilege-cve-2024-21338/
- https://research.nccgroup.com/2020/05/25/cve-2018-8611-exploiting-windows-ktm-part-5-5-vulnerability-detection-and-a-better-read-write-primitive/
- https://msrc.microsoft.com/update-guide/vulnerability/CVE-2024-21338
- https://malpedia.caad.fkie.fraunhofer.de/details/win.fudmodule
免责声明:本博客文章仅用于教育和研究目的。提供的所有技术和代码示例旨在帮助防御者理解攻击手法并提高安全态势。请勿使用此信息访问或干扰您不拥有或没有明确测试权限的系统。未经授权的使用可能违反法律和道德准则。作者对因应用所讨论概念而导致的任何误用或损害不承担任何责任。
免责声明:
本文所载程序、技术方法仅面向合法合规的安全研究与教学场景,旨在提升网络安全防护能力,具有明确的技术研究属性。
任何单位或个人未经授权,将本文内容用于攻击、破坏等非法用途的,由此引发的全部法律责任、民事赔偿及连带责任,均由行为人独立承担,本站不承担任何连带责任。
本站内容均为技术交流与知识分享目的发布,若存在版权侵权或其他异议,请通过邮件联系处理,具体联系方式可点击页面上方的联系我。
本文转载自:securitainment Rafael Rafael《Windows 管理员到内核的权限提升(CVE-2024-21338)》
版权声明
本站仅做备份收录,仅供研究与教学参考之用。
读者将信息用于其他用途的,全部法律及连带责任由读者自行承担,本站不承担任何责任。









评论