Skip to content
KitploitKITPLOIT
工具博客
提交
工具博客
提交

黑客、渗透测试和网络安全工具,武装您的安全武器库!

Kitploit 是一个黑客、网络安全和渗透测试工具的目录。发现最新的项目更新,查找漏洞、分析系统、自动化测试并加强你的安全。

··订阅源·联系·隐私·© 2026 Kitploit

工具目录

分类

查看所有分类
Loading categories
CVE-2024-30051 — 针对 CVE-2024-30051 的详细技术分析与概念验证(PoC)漏洞利用代码。该漏洞是 Windows DWM 核心库中的堆缓冲区溢出漏洞,可导致本地权限提升至系统完整性级别。 | Kitploit
工具/GitHubGitHub/fortra/cve-2024-30051
权限提升漏洞分析漏洞利用逆向工程学习与教育二进制利用
GitHubfortra/cve-2024-30051

CVE-2024-30051

针对 CVE-2024-30051 的详细技术分析与概念验证(PoC)漏洞利用代码。该漏洞是 Windows DWM 核心库中的堆缓冲区溢出漏洞,可导致本地权限提升至系统完整性级别。

查看仓库
12636122年前Kitploit 审核通过

最受欢迎

查看全部 →

发现我们社区最常用的工具。

探索所有工具

浏览我们的工具集合

查看所有工具 →
分享

Windows DWM Core Library 特权提升漏洞 (CVE-2024-30051)(发布于 2024 年 8 月 15 日)

在本博客文章中,我将解释 Microsoft Windows DWM Core 库中的一个漏洞,该漏洞是在为 Core Impact 开发利用程序时分析的。该漏洞允许无特权的攻击者以具有 Integrity System 权限的 DWM 用户身份执行代码 (CVE-2024-30051)。

由于当时没有足够的公开信息来开发利用程序,我不得不进行大量逆向工作,因此这里我将展示如何使用 IDA PRO 逆向 Windows 23H2 的 KB5037771 补丁,将使用 BINDIFF 对 dwmcore.dll 版本 10.0.22621.3447 和版本 10.0.22621.3593 进行二进制差异分析,展示堆溢出是如何产生的,然后通过提升权限来利用它,最后创建一个可用的 PoC。

索引:

[Windows DWM Core Library 特权提升漏洞 (CVE-2024-30051) 1](#windows-dwm-core-library-elevation-of-privilege-vulnerability-cve-2024-30051)

[漏洞详情: 2](#vulnerability-details)

[差异分析查找漏洞: 3](#diffing-to-find-the-bug)

[利用 CVE-2024-30051 的 PoC 分析: 8](#analysis-of-the-poc-exploiting-cve-2024-30051)

[1) 初始化 8](#initialization)

[2) 挂钩 8](#hooking)

[3) 创建窗口 16](#creating-the-window)

[4) 创建设备 16](#create-device)

[5) 创建工厂 22](#create-factory)

[6) 创建设备上下文 28](#create-a-device-context)

[7) 创建组合设备 29](#create-a-composition-device)

[8) 调用 hook3 函数 31](#calling-dcompositioncreatedevice-function)

[9) 为 HWND 创建目标 32](#creating-a-target-for-handle-hwnd)

[10) 创建表面 33](#creating-surface)

[11) 调用 BeginDraw、EndDraw 和 CreateVisual 34](#calling-begindraw-enddraw-and-createvisual)

[11) 调用 Visual SetContent 36](#calling-visual-setcontent)

[12) 释放对象 38](#release-objects)

[13) 提交组合设备 38](#commit-composition-device)

[14) 调用 hook2 39](#calling-hook2)

[15) 调用 hook 39](#remember-that-the-vulnerable-function-can-be-reached-using-some-methods-of-the-cprimitivegroup-class.-at-this-point-it-creates-a-heap-then-hook2-captures-and-saves-the-corresponding-heaphandle.)

[16) 调用 hook4 41](#calling-the-function-hook4)

[17) 执行堆喷射 49](#performing-heap-spray)

[18) 发送前修改基础块 51](#modifying-the-base-chunk-before-send)

[19) 调试 DWM 进程 52](#debugging-the-dwm-process)

[20) 提升权限至 Integrity System 级别 62](#elevating-privileges-to-integrity-system-level)

漏洞详情:

Windows DWM Core Library 特权提升漏洞 CVE-2024-30051

发布时间:2024 年 5 月 14 日

分配 CNA:Microsoft CVE-2024-30051

影响:特权提升

最高严重性:重要

弱点:

CWE-122:基于堆的 缓冲区溢出

CVSS:3.1 7.8 / 7.2

漏洞存在于 Windows 主 DWM 库 dwmcore.dll 中整数除法的尺寸计算错误。本地用户可以在 dwmcore.dll 的 CCommandBuffer::Initialize 方法中导致堆缓冲区溢出,并可以以具有 Integrity System Privileges 的 DWM 用户身份执行任意代码。利用程序将在 DWM 进程中执行堆喷射来准备内存,最终在 dwmcore.dll 中产生堆溢出,该溢出通过释放堆喷射的某些部分来触发。

一旦利用成功,DWM 进程将加载我们精心制作的 DLL,该 DLL 以具有 Integrity System Privileges 的 DWM 用户身份执行我们的代码或可执行文件(在我们的例子中是 CMD)。

让我们逐步分析这个漏洞,看看它如何允许我们以 Integrity Level SYSTEM 的 DWM 用户身份运行。请注意,由于这不是属于 Administrators 组的用户,它有一些权限限制。

差异分析查找漏洞:

Windows 11 23H2 的补丁可以从以下地址下载:

https://www.catalog.update.microsoft.com/Search.aspx?q=KB5037771

windows11.0-kb5037771-x64_19a3f100fb8437d059d7ee2b879fe8e48a1bae42.msu

dwmcore.dll 的易受攻击版本是:10.0.22621.3447

dwmcore.dll 的修补版本是:10.0.22621.3593

分析更改的函数后,很明显修补版本的 CCommandBuffer::Initialize 添加了大量块,使其看起来与未修补版本大不相同。

静态逆向该函数后,有两个对 CD2DSharedBuffer::GetBufferSize 的调用。

第一次调用获取要分配给 new 的 size,第二次调用获取相同的 memcpy 的大小。

一切最初看起来都是正确的。然而,在分配之前,它对大小执行了一些操作。

它通过调用相同的 CD2DSharedBuffer::GetBufferSize 函数获取 buffer_size 和 buffer_size2,两者返回相同的值。但在 new 中,它执行了一个前操作,将 buffer_size 除以 0x90 再乘以 0x90,而在 memcpy 中,它直接使用返回的 buffer_size2 而不对其进行操作。

通过这些操作,我发现最终用于 new 和 memcpy 的大小可能不同。

buffer_size = buffer_size2(返回的大小)

size_new = buffer_size/0x90 x 0x90

size_memcpy = buffer_size2

例如,如果 buffer_size 是 0x91

buffer_size = buffer_size2 = 0x91

size_new = buffer_size/0x90 x 0x90 = 0x90

size_memcpy = buffer_size2 = 0x91

这个例子证明存在 堆溢出。它复制了比分配更多的字节,并且大小是可控的。

例如,如果 buffer_size 是 0x23f,就像他们在 POC 中使用的那样。

buffer_size = buffer_size2 = 0x23F

size_new = buffer_size/0x90 x 0x90 = 0x1b0

size_memcpy = buffer_size2 = 0x23f

分析了易受攻击的函数后,我想了解如何到达易受攻击的函数 CCommandBuffer::Initialize。事情从这里开始变得复杂。

回过头来查看对该函数的引用,它似乎是通过 CPrimitiveGroup 类的方法到达的:

这些方法可以从 CPrimitiveGroup 对象的 vftable 访问:

它有它的 构造函数:

并且是这样到达的:

最初我经历这个过程时,花时间阅读了 PDF “The Lost World of DirectComposition: Hunting Windows Desktop Window Manager Bugs” 并深入研究了 Direct Composition 的世界。这帮助我创建了第一个 PoC。

另外,我需要逆向 win32ksys 并尝试通过以下函数发送数据包:

  • NtDCompositionCreateChannel

  • NtDCompositionProcessChannelBatchBuffer

  • NtDCompositionCommitChannel

我的第一个 PoC 到达了 CPrimitiveGroup 的构造函数。然而,经过大量逆向后,我未能找到一种方法,通过这些函数的 ALPC 调用直接处理对 vftable 方法的调用来到达易受攻击的函数。

我花了很多时间进行一些复杂的逆向工作。在这个过程中,我找到了利用此漏洞的恶意代码样本,这非常有帮助,因为利用方法比我最初想象的要复杂得多。它还包含多个系统 API 的挂钩,并使用了一些可能有点可疑的方法。但在战争和漏洞利用中一切都是有效的,因此我开始分析恶意代码,并根据分析创建了我的最终 PoC,最终成功利用了该漏洞,我将在下面解释这一点。

首先,我想澄清的是,恶意代码不仅利用了 CVE-2024-30051 漏洞将我们的进程提升到 Integrity System 级别,而且还执行了第二部分,最终提升到一个具有所有权限的 SYSTEM 用户,这已经超出了所解释的 CVE 范围。

此外,需要注意的是,恶意代码比我的 PoC 复杂得多,我的 PoC 试图最小化代码。恶意代码执行了更多检查以确保可靠性,因此它在第一次尝试时就成功了。我丢弃了所有那些检查以简化代码,并专注于纯粹的利用,甚至可能需要运行 PoC 两到三次才能成功利用。

利用 CVE-2024-30051 的 PoC 分析:

1) 初始化

可执行的 PoC 链接是 https://github.com/fortra/CVE-2024-30051

首先,PoC 调用 GetVersion 获取其运行的操作系统版本,并根据版本对某些全局变量执行不同的初始化。我的 PoC 在 Windows 11 23H2 和 Windows 11 22H2 上进行了测试。其他系统也存在漏洞,并添加了利用它们所需的值。

2) 挂钩

它挂钩了四个系统函数,如果不挂钩这些函数,就无法成功利用。这些系统函数是:RtlAllocateHeap、RtlCreateHeap、NtDCompositionCreateChannel 和 NtDCompositionCommitChannel。

在这些函数中,它将修补前 5 个字节,使其跳转到自己的代码。当然,代码不能离得太远,因为 5 字节跳转不能覆盖整个内存,并且必须在附近。

为此,恶意代码使用了一段非常长的代码,分析内存映射以决定在哪里可以分配自己的代码。由于代码很复杂,我专注于将其简化为两行简单的代码:

base_ntdll = GetModuleHandleW(L"ntdll.dll");

global4_ = (char *)VirtualAlloc((LPVOID)(base_ntdll-0x2000), 0x1000uLL, 0x3000u, 0x40u);

我从 ntdll 基址 减去了 0x2000,并将该地址传递给 VirtualAlloc 进行分配。
64 位 DLL 在内存中映射得相当独立,彼此之间存在空白空间。
让我们看看 hooks 是如何工作的:

它调用一个 hook 函数,该函数将执行对 RtlAllocateHeap API 的挂钩,该 API 有三个参数,第一个是要修补的 API 的地址,称为 sym_RtlAllocateHeap。
在修补之前,它指向 API 的起始位置:

这里是 RtlAllocateHeap 函数:

第二个参数是称为 hook 的例程,当 API 被完全修补后将执行该例程:

hook 函数调用 my_RtlAllocateHeap。

hook 函数将修补 API 的前 5 个字节,使其跳转到 hook。

它将在分配的区域中调用代码,该区域将执行被 5 个字节覆盖的第一个 API 指令,然后跳转到修补字节之后的 RtlAllocateHeap+5:

这是 API 在挂钩后的样子。前 5 个字节被更改,使其跳转到 hook。它将调用 my_RtlAllocateHeap,该代码就在上面,并将返回到紫色标记的区域以继续执行 API:

当 API 执行完毕后,它将返回到 hook。在那里,它将比较全局变量 heap_base(最初为 零)与传递给 RtlAllocateHeap 的第一个参数:

之后,代码等待某个特定的分配,该分配具有特定的 HeapHandle。最初这个变量为零,只要它为零,就会跳过并像正常的 RtlAllocateheap 一样工作:

参数 HeapHandle 是在 RtlCreateHeap 内部获得的,巧合的是,这是第二个挂钩的 API。

查找对全局变量 heap_base 的引用,它只在 hook2 函数中更改其值,该函数是在挂钩 RtlCreateHeap 后执行的:

所以,想法是捕获某个 HeapHandle 并将其保存在 heap_base 中。由于现在它不为零,函数 hook 将开始比较每个分配。因此,PoC 将保存与先前存储的 HeapHandle 相同的内存地址。

当这种情况发生时,它将把分配的地址保存到名为 base 的变量中:

现在这两个挂钩是链式的。当 hook2 保存预期的 HeapHandle 值时,它会激活 hook 函数,该函数将保存使用相同 HeapHandle 的分配地址。

第三个挂钩是对 NtDCompositionCreateChannel 的挂钩。第一次调用时,它将保存 MappedAddress,即第三个参数的内容。从那里,它将把 hooked_flag 更改为 1,这样之后就不会再保存,而是正常工作。

保存在变量 base 中的地址稍后将被读取三次。其中两次将发生在最后一个挂钩中,称为 hook4:

对 NtDCompositionCommitChannel 的 hook4 函数将在稍后进行分析,因为它相当复杂且非常重要。

3) 创建窗口

完成四个挂钩后,它返回到主函数开始创建一个窗口。这是通过调用 RegisterClassExW 完成的。但是,为了稍后使用而注册窗口类,应该通过 CreateWindowExW 函数 调用它。

它通过调用 CoInitializeEx 初始化 COM 库,供调用线程使用:

它根据所需大小计算窗口矩形所需的大小:

调用 CreateWindowExW 函数来创建一个将绘制的窗口:

4) 创建设备

从那里,调用 D3D11CreateDevice 来创建一个设备或代表显示适配器的 DirectX 设备:

在我的 PoC 中,ppDevice 被命名为 d3dDevice,ppInmediateContext 被命名为 d3dContext:

参数 flags 需要设置为 0x20:

然后调用 AddRef:

这将增加 COM 对象接口指针的引用计数器:

值 0x10 被从 THIS 中减去:

在 ID3D11Device-0x10 的偏移量 0xf8 处,有一个指向 TComObject 的指针:

这将作为新的 THIS,并最终跳转到 TComObject::AddRef:

并且最终将 TComObject 偏移量 8 处的 对象计数器 加一:

然后,AddRef 将增加在 D3D11CreateDevice 中创建的其他对象类型的计数器,即 ID3D11DeviceContext 类型:

在这种情况下,要找到新的 THIS,它减去 0x108:

它跳转到这里,在偏移量 0x98 处是新的 THIS:

这是计数器。在这个例子中,它是一个 QWORD:

5) 创建工厂

PoC 调用 D2D1CreateFactory 来使用 Direct2D,并创建 ID2D1Factory 接口,该接口用于创建其他可用于绘制或描述形状的 Direct2D 资源:

riid 参数是 Microsoft 页面建议的:

https://learn.microsoft.com/en-us/windows/win32/api/d2d1/nf-d2d1-d2d1createfactory

这是恶意代码使用的:

适用于 ID2D1Factory 的正确值可以在这里找到**:**

https://github.com/apitrace/dxsdk/blob/master/Include/d2d1_1.h

由于我不是 Direct Composition 的专家,我随后使用了与恶意代码相同的步骤:

返回的新工厂没有提供任何详细的类型。它说 void *,这意味着它没有正式文档记录:

由于在这种情况下我不知道对象类型,我开发了一个使用它的可执行文件,以便在内存中轻松查看它:

在四个 hook 函数中添加断点。在这种情况下,hook2 中的断点将显示何时捕获了 HeapHandle:

当捕获到所需的 块 时,应该停止 hook:

在其他两个 hooks 中设置断点:

然后它继续调用 QueryInterface:

https://help.solidworks.com/2020/english/api/sldworksapi/queryinterface_example_cplusplus_com.htm

https://github.com/tpn/winsdk-10/blob/master/Include/10.0.16299.0/shared/dxgi.idl

它尝试执行一种动态转换。如果类型为 ID3D11Device 的对象可以接受 IDXGIDevice 的接口(使用方法等),它将创建原始对象的副本,该副本接受新类型,之后返回指向它的指针。在这种情况下,变量 d3dContext1 将是 IDXGIDevice 类型:

两个对象都继承自 CLayeredObject<Cdevice>

原始的 ID3D11Device 是**:**

就像返回指针的那个一样。

然后它使用函数 CreateDevice 创建一个 ID2D1Device 对象:

在 value2 中,它返回一个 ID2D1Device 类型的对象。

6) 创建设备上下文此时,PoC 从 Direct2d 设备创建一个新的设备上下文。使用函数 CreateDeviceContext

https://learn.microsoft.com/en-us/windows/win32/api/d2d1_1/nf-d2d1_1-id2d1device-createdevicecontext

在 PoC 中是这样实现的:

7) 创建一个组合设备

然后调用 DCompositionCreateDevice

https://learn.microsoft.com/en-us/windows/win32/api/dcomp/nf-dcomp-dcompositioncreatedevice

IID 属于 _IDCompositionDevice

8) 调用 DCompositionCreateDevice 函数

在追踪 DCompositionCreateDevice 函数的同时,它会在调用 NtDCompositionCreateChannel 时停在 hook3:

这样它就能捕获系统在调用 DCompositionCreateDevice 时内部使用的 MappedAddress:

这是到目前为止的调用栈:

这是 dcomp 模块调用函数 NtDCompositionCreateChannel 的位置:

9) 为句柄 HWND 创建目标

从上一步返回后,保存 MappedAddress。使用 ALPC 连接到 DWM 进程,然后调用 CreateTargetForHwnd

https://learn.microsoft.com/en-us/windows/win32/api/dcomp/nf-dcomp-idcompositiondevice-createtargetforhwnd

它使用已创建窗口的句柄 HWND。它与刚创建的设备相关,该设备是此方法的 THIS 指针:

10) 创建表面

然后调用 CreateSurface

https://learn.microsoft.com/en-us/windows/win32/api/dcomp/nf-dcomp-idcompositiondevice-createsurface

11) 调用 BeginDraw、EndDraw 和 CreateVisual

然后调用 BeginDraw、EndDraw,然后到达 CreateVisual。

它调用 BeginDraw

https://learn.microsoft.com/en-us/windows/win32/api/dcomp/nf-dcomp-idcompositionsurface-begindraw

这使用了 IID _IDXGISurface:

然后使用 EndDraw:

https://learn.microsoft.com/en-us/windows/win32/api/dcomp/nf-dcomp-idcompositionsurface-enddraw

最后,它调用 CreateVisual:

https://learn.microsoft.com/en-us/windows/win32/api/dcomp/nf-dcomp-idcompositiondevice-createvisual

12) 调用 Visual SetContent

接下来,它调用 IDCompositionVisual::SetContent:

https://learn.microsoft.com/en-us/windows/win32/api/dcomp/nf-dcomp-idcompositionvisual-setcontent

并调用 SetRoot:

在 BeginDraw 中接收到的 updateObject 在文档中没有指定其类型。

13) 释放对象

接下来,它释放之前创建的对象:

14) 提交组合设备

现在,使用相同的 dcompDevice 对象(类型为 IDCompositionDevice)调用 Commit 方法:

15) 调用 hook2

调用该 Commit 方法会停在 hook2 处,该钩子捕获所需的 HeapHandle:

现在的调用栈如下:

请记住,可以使用 CPrimitiveGroup 类的某些方法到达易受攻击的函数。此时它会创建一个 Heap,然后 hook2 捕获并保存相应的 HeapHandle。

16) 调用函数钩子

在返回主函数之前,它还使用 RtlAllocateHeap 创建一个块。该块随后被捕获并存储在 hook 函数内部的 base 变量中:

Create 和 Allocate 调用是依次进行的:

两者(Allocate 和 Create)都是从 DirectComposition::Cdevice::Commit 调用的:

17) 调用函数 hook4

之后,当调用 NtDCompositionCommitChannel 时,它会停在 hook4:

NtDCompositionCommitChannel 从这里调用:

它也从 DirectComposition::Cdevice::Commit 调用

值得一提的是,系统已经将命令批处理,准备通过 ALPC 发送到 DWM。之后,它使用 NtDCompositionCommitChannel 发送命令。
函数 hook4 拦截 NtDCompositionCommitChannel 调用,此时会将更多命令添加到批处理中。

让我们看看 hook4 做了什么:

遍历由 base 指向的块。

当在块中找到值 0x120 时退出循环:

它存储了 0x120 值所在的位置和偏移量:

它将 0x120 值覆盖为 value4,该值等于 0x1b0 + 0x8f = 0x23f。这是它在溢出时用于 memcpy 的大小:

它将 0xbc + 0x90 添加到存储 0x120 的地址指针上:

请记住,在距 base 偏移 0x48 处的大小为 0x120。它被覆盖为 0x23f,因此原始块的大小必须是 0x120:

源是 0x23f + 0x2c 的指针地址:

它最初添加了 0x90,但现在又减去了 0x90。
目标将是 指向 0x120 的指针 + 0xbc 的地址:

它将写入以下内容:

所有写入操作都在块内部:

它将重复循环 3 次,这是 0x1b0/0x90 的整数除法结果:

之后,由于 ArgChannelHandle 通道与捕获 MappedAddress 时使用的通道相同。PoC 将使用 NtDCompositionProcessChannelBatchBuffer 向 batch 添加命令。这些命令将与系统已添加的命令一起被处理。batch 收集它们,然后使用 NtDCompositionCommitChannel 一次性发送所有命令:

发送的命令值为 8,对应 SetResourceIntegerProperty,用于 4 个不同的跟踪器(1、2、3 和 4)。

18) 执行堆喷射

当 PoC 返回到主函数时,它会创建一个不同的通道来执行堆喷射。

它批处理 0x10000 条命令,这些命令通过 _NtDCompositionCommitChannel 发送:

这使用了值 CreateResource=1 和类型 CHolographicInteropTextureMarshaler = 0x50:

下面的代码执行分配。用于喷射的对象大小为 0x1b0:

然后它执行一个循环来释放上一步创建的对象,并在内存分布中制造空洞。
变量 counter2 从 0x3000 开始,以步长 0x20 增加,直到小于 0x7000:

19) 在发送前修改基础块

它从 base + 0x48 + 44 + 0x1b0 的方向写入 0x41
也就是说,它写入的值将在之后被使用——当它溢出相邻的块时:

这个 pvalue7 位于距 base 地址 0x224 处:

然后进入函数 “escribe”:

它写入 pKernelCallbacktable 加上 0x388、LoadLibraryA 地址 以及将要加载的 DLL 的路径。在此示例中,我将其命名为 s11.dll。

20) 调试 DWM 进程

现在,需要一个内核调试器来停在易受攻击的函数处,因为堆溢出发生的地方。这是因为 DWM 进程无法使用 用户模式 调试器进行调试。

使用 IDA PRO 远程调试目标,设置一个条件断点,使其在大小等于 0x1b0 时停止:

print ("VALUE1 %x" % ((cpu.rax)))
return cpu.rax==0x1b0.

由于正在内核中调试用户模式程序,需要切换到 DWM 进程上下文以放置断点。用以下命令重新加载用户符号:

. reload /user

用以下命令重新加载内核符号:

. reload /f

当 ShowWindow 被单步执行时会停止:

它以大小 0x1b0 分配,并以大小 0x23f 复制,从而产生堆溢出:

此时调用栈如下所示:

为了创建溢出,DWM 在下面的代码中接收值:

从我的 PoC 发送的 base 中的精心构造的值使用 MapViewofFile 在 DWM 进程 的 dwmcore.dll 模块中读取:

上一个函数从以下位置调用:

当使用 ALPC 从 hook4 通过 destination_copy (NtDCompositionCommitChannel) 发送时,它会停止:

请记住,在 hook4 命令中,向批处理添加了命令。然而,系统也已经向批处理添加了一些命令,包括 base 和精心构造的数据:

在这种情况下,它共享一个内存区域,起始地址为 000001cd'178d0000。当将其用作 memcpy 的源时,它将位于同一内存区域中偏移 0x794 字节之后。

共享内存区域的大小为 0x4000:

当要分配的大小为 0x1b0 时,它会停止,并执行 memcpy 复制 0x23f 字节:

超出 0x1b0 的内存中是将覆盖相邻块的溢出代码:

当 PoC 释放这些块时,最终会跳转到 LoadLibraryA,加载精心构造的库:

该跳转来自这里:

堆喷射使用大小为 0x1b0 的 CHolographicInteropTexture 对象进行。

由于我在内存分布中制造了空洞,这会释放一些对象。由于将要溢出的块的大小也是 0x1b0,它有很大的概率位于堆喷射的空洞中。

在 memcpy 的目标处,块每 0x1b0 字节排列一次:

指向 vftable 的指针被指向 LoadLibrary 的指针覆盖:

覆盖前:

覆盖后:

请记住,它最终跳转到 [R11+50],这是指向 LoadLibraryA 的指针。

21) 将权限提升到系统完整性级别

执行 PoC,将 DLL 复制到 PoC 中指定的相同路径:

执行 PoC 后,会以 DWM 用户系统完整性级别权限执行一个 CMD 进程:

参考资料:

Fortra GitHub 上的 PoC: https://github.com/fortra/CVE-2024-30051

https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2024-30051

https://msrc.microsoft.com/update-guide/en-US/advisory/CVE-2024-30051

PoC 到此结束。请记住,如果多次执行,堆可能会处于不稳定状态,因此可能需要重新启动机器才能再次工作。此外,虽然它不一定第一次就能成功,但通常第二次或第三次尝试就能正常工作。如您所见,逆向工程可能很困难,因此如果您有任何问题,可以咨询我。

邮件:[email protected]

X: @ricnar456

下载工具