Windows 桌面窗口管理器(
dwmcore.dll)中的堆缓冲区溢出 本地权限提升 → 通过 DWM 进程获得 SYSTEM 完整性级别 构建目标:Windows 11 22H2 (10.0.22621.3447) · 补丁:KB5037771
本仓库包含我针对 CVE-2024-30051 的 硕士论文研究,这是 Windows 桌面窗口管理器核心库(dwmcore.dll)中的一个高严重性(CVSS 7.8)权限提升漏洞。
该漏洞源于 CCommandBuffer::Initialize 中的整数除法尺寸计算错误。由于该计算错误,用于 new() 的尺寸与用于 memcpy() 的尺寸出现偏差,导致产生 0x8F 字节的堆溢出。成功利用后,dwm.exe 会加载攻击者控制的 DLL,在 window manager\dwm-1 账户下以 完整性级别 SYSTEM 执行任意代码。
CVE-2024-30051-Masters-Thesis/
├── README.md
├── LICENSE
├── setup.bat # 将 s11.dll 复制到所需位置
│
├── exploit/
│ ├── C21.sln # Visual Studio 2022 解决方案
│ ├── exploit_src/
│ │ ├── c26f.vcxproj
│ │ ├── c26f.filters
│ │ └── main.cpp # 漏洞利用 — 堆喷射 + 钩子 + 溢出
│ └── payload/
│ ├── payload.vcxproj
│ ├── payload.vcxproj.filters
│ ├── dllmain.cpp # 载荷 DLL — 生成 SYSTEM shell + 清理
│ ├── framework.h
│ ├── pch.h
│ └── pch.cpp
│
└── docs/
├── screenshots/ # 补丁对比、WinDbg 和取证截图
└── analysis/
├── 01-root-cause.md # CCommandBuffer::Initialize 中的整数除法错误
├── 02-heap-spray.md # 50 次会话实证数据与统计发现
└── 03-timeline.md # 发现、披露和补丁时间线
在 Visual Studio 2022 中打开 C21.sln。以 Release x64 构建 payload 项目。
从仓库根目录运行 setup.bat。它将 s11.dll 复制到 C:\Users\Public\Documents\s11.dll(PAYLOAD_DLL_PATH 定义的路径)。
⚠️ 在运行
C26f.exe之前,DLL 必须位于此确切路径。 将其放在可执行文件旁边无效。
以 Release x64 构建 C26f 项目。
x64\Release\C26f.exe
从标准(非提升)CMD 运行。漏洞利用程序会自动重试最多 10 次。成功后,dwm.exe 加载 s11.dll 并生成一个具有 SYSTEM 完整性级别 的 CMD。会话日志写入 %TEMP%\cve_30051_log.txt。
#define MAX_ATTEMPTS 10 // 每次会话的最大自动重试次数
#define SPRAY_STEP 0x10 // 孔间距索引(1024 个孔)
#define SPRAY_RANGE_START 0x3000 // 喷射范围起始索引
#define SPRAY_RANGE_END 0x7000 // 喷射范围结束索引
#define SLEEP_POST_SPRAY 0xC8 // 喷射后等待毫秒数(200ms)
#define SLEEP_POST_HOLES 0xC8 // 释放孔后等待毫秒数(200ms)
#define PAYLOAD_DLL_PATH "C:\\Users\\Public\\Documents\\s11.dll"
在 CCommandBuffer::Initialize(dwmcore.dll 10.0.22621.3447)中,CD2DSharedBuffer::GetBufferSize 被调用两次。传递给 new() 的尺寸先被整数除以 0x90 再乘法,而 memcpy() 使用原始值:
buffer_size = GetBufferSize() → 例如 0x23F
size_new = (0x23F / 0x90) * 0x90 = 0x1B0 ← 已分配
size_memcpy = 0x23F ← 已复制
overflow = 0x23F - 0x1B0 = 0x8F 字节
BinDiff 比较版本 10.0.22621.3447(易受攻击)与 10.0.22621.3593(已修补):
全局相似度为 0.98 时,异常得分 0.32 是漏洞位置的直接特征。
1. 钩子 RtlCreateHeap → 捕获 dwmcore 堆句柄
2. 钩子 RtlAllocateHeap → 捕获基块地址
3. 钩子 NtDCompositionCreateChannel → 捕获 MappedAddress(共享内存区域)
4. 钩子 NtDCompositionCommitChannel → 覆盖 size 字段(0x120 → 0x23F)
注入额外的批处理命令
5. 堆喷射 0x10000 个 CHolographicInteropTexture 对象(大小=0x1B0)
6. 每隔 0x10 个索引释放孔 → 为溢出着陆创建间隙
7. 将载荷写入溢出缓冲区 → KCBTable+0x388 + LoadLibraryA + DLL 路径
8. 释放所有喷射对象 → 触发溢出 → LoadLibraryA("s11.dll")
9. dwm.exe 加载载荷 DLL → 生成 SYSTEM 完整性级别的 CMD
可用 RAM 是否影响成功堆喷射所需的尝试次数?
两组,每组 25 次会话。每个会话的协议:恢复干净启动后快照 → 等待 100 秒稳定 → 启动漏洞利用 → 记录成功尝试。
| 组 | RAM | 会话数 | 成功 | 失败 |
|---|---|---|---|---|
| A | 8,192 MB | 25 | 24 | 1 |
| 检验 | 统计量 | p 值 | 结论 |
|---|---|---|---|
| Mann-Whitney U | U = 184.0 | p = 0.031 | 拒绝 H₀ |
| Welch t 检验 | t(23) = −2.695 | p = 0.011 | 拒绝 H₀ |
base = heap_base + 0x720 证实了可重现的启动后堆布局是确定性的主要驱动力,而非孔密度。完整原始数据、会话日志格式和确定性堆观测记录在 docs/analysis/02-heap-spray.md 中。
成功后,一个 CMD 窗口在 window manager\dwm-1 下打开:
=====================================================
CVE-2024-30051 - Windows DWM 堆溢出 EoP
CWE-122 | CVSS 7.8 | 权限提升
=====================================================
研究与复现者 : devianntsec
原始 PoC 作者 : Ricardo Narvaja (Fortra)
目标 : Windows 11 22H2 (22621.3447)
=====================================================
[*] 当前用户:
window manager\dwm-1
[*] 强制性完整性级别:
Mandatory Label\System Mandatory Level S-1-16-16384
[*] 已启用特权:
SeImpersonatePrivilege 已启用
=====================================================
Shell 在 DWM 进程下运行 - SYSTEM 级别
=====================================================
项目(s11.dll 和 .bat 脚本)在 5 秒后通过延迟清理过程自动删除。
| 文档 | 描述 |
|---|---|
| 根本原因分析 | CCommandBuffer::Initialize 中的整数除法错误、补丁对比方法 |
本研究是我网络安全硕士论文(UCAM — Campus Internacional de Ciberseguridad)的一部分,分析了跨多个环境的 N-Day 漏洞。
此 CVE 代表了论文中的 Windows 桌面应用程序 向量,展示了:
关键词: EoP · 堆溢出 · DirectComposition · DWM · 补丁对比 ·
BinDiff · WinDbg · 堆喷射 · 实证分析 · CVE-2024-30051
Annais Molina (devianntsec) — 网络安全硕士生
MIT 许可证 — 参见 LICENSE
本仓库 仅供教育和安全研究目的,作为学术硕士论文的一部分。所有测试均在隔离的虚拟机上进行,无网络暴露。仅在你拥有或已获得明确书面授权进行测试的系统上使用。未经授权对系统进行使用是非法的,并可能导致刑事起诉。
| 方面 | 描述 |
|---|
| 补丁对比 | 完整的 BinDiff 分析,确定 CCommandBuffer::Initialize 为确切的漏洞位置(相似度得分 0.32,而在 14,062 个匹配函数中全局相似度为 0.98) |
| WinDbg 动态分析 | 逐步验证所有 4 个钩子、size 字段覆盖和载荷构建 |
| 实证堆喷射分析 | 跨两种 RAM 配置(8,192 MB 和 4,096 MB)的 50 次受控会话,并进行了正式统计测试 |
| 统计发现 | Mann-Whitney U (p = 0.031) 和 Welch t 检验 (p = 0.011) 确认 RAM 影响;观察到的均值比理论预测约 64 次尝试好 12.9–19 倍 |
| 载荷 DLL 路径集中化 | 将硬编码路径提取为 #define PAYLOAD_DLL_PATH 预处理器常量 |
| 会话日志记录 | 每次会话的完整时间戳日志写入 %TEMP%\cve_30051_log.txt |
| 学术文档 | 根本原因、50 次会话堆喷射分析以及 CVE 时间线 |
| 指标 | 值 |
|---|
| 全局相似度 | 0.98 |
| 置信度 | 0.99 |
| 匹配函数数 | 14,062(99.1%) |
CCommandBuffer::Initialize 相似度 | 0.32 |
| 基本块 — 易受攻击版本 | 4 |
| 基本块 — 已修补版本 | 20(添加了 16 个验证块) |
| B |
| 4,096 MB |
| 25 |
| 24 |
| 1 |
| 组 | RAM | 平均尝试次数 | 标准差 | 95% CI | 与理论值(64)的倍数 |
|---|
| A | 8,192 MB | 3.375 | 1.135 | [2.896; 3.854] | ≈ 19 倍更快 |
| B | 4,096 MB | 4.958 | 2.645 | [3.841; 6.076] | ≈ 12.9 倍更快 |
| 痕迹 | 位置 | 持久性 | 检测工具 |
|---|
dwm.exe 的子进程 cmd.exe | 安全事件日志 | 是(如果进程审核已启用) | 事件 ID 4688 |
外部进程访问 dwm.exe | Sysmon | 是 | Sysmon 事件 ID 10 |
尝试失败时 dwm.exe 崩溃 | 应用程序事件日志 | 是 | 事件 ID 1000 |
磁盘上的载荷 DLL s11.dll | C:\Users\Public\Documents\ | 仅前约 5 秒 | SHA-256 监控 |
| 50 次会话实证数据、原始会话数据、统计检验 |
| CVE 时间线 | 发现、披露和补丁时间线 |