
Investigación de tesis de maestría sobre CVE-2024-30051 (desbordamiento de montón de DWM en Windows). Incluye un exploit de alta fiabilidad con optimización automatizada de heap spray, registro en tiempo real y análisis empírico de la tasa de éxito. Pieza de portafolio que demuestra explotación avanzada de binarios de Windows, manipulación del diseño del montón y LPE a través del Administrador de ventanas de escritorio.
Desbordamiento de búfer basado en heap en el Administrador de ventanas de escritorio de Windows (
dwmcore.dll)
Escalada de privilegios local → nivel de integridad SYSTEM a través del proceso DWM
Objetivo de compilación: Windows 11 22H2 (10.0.22621.3447) · Parche: KB5037771
Este repositorio contiene mi investigación de Tesis de Máster sobre CVE-2024-30051, una vulnerabilidad de elevación de privilegios de severidad alta (CVSS 7.8) en la librería principal del Administrador de ventanas de escritorio de Windows (dwmcore.dll).
La vulnerabilidad se origina en un error de cálculo de tamaño por división entera en CCommandBuffer::Initialize. El tamaño usado para new() y el usado para memcpy() divergen debido a este error de cálculo, produciendo un desbordamiento de heap de 0x8F bytes. Un exploit exitoso provoca que dwm.exe cargue una DLL controlada por el atacante, ejecutando código arbitrario bajo la cuenta window manager\dwm-1 con nivel de integridad SYSTEM.
| Aspecto | Descripción |
|---|---|
| Diffing de parches | Análisis BinDiff completo que identifica CCommandBuffer::Initialize como el lugar exacto de la vulnerabilidad (puntuación de similitud de 0.32 frente a 0.98 global en 14,062 funciones coincidentes) |
| Análisis dinámico con WinDbg | Verificación paso a paso de los 4 hooks, de la sobrescritura del campo de tamaño y de la construcción del payload |
| Análisis empírico del heap spray | 50 sesiones controladas en dos configuraciones de RAM (8,192 MB y 4,096 MB) con pruebas estadísticas formales |
| Hallazgos estadísticos | Mann-Whitney U (p = 0.031) y prueba t de Welch (p = 0.011) confirman el efecto de la RAM; medias observadas 12.9–19× mejores que la predicción teórica de ~64 intentos |
| Ruta de la DLL del payload centralizada | Ruta hardcodeada extraída a la constante de preprocesador #define PAYLOAD_DLL_PATH |
| Registro de sesiones | Registro completo con marcas de tiempo por sesión escrito en %TEMP%\cve_30051_log.txt |
| Documentación académica | Causa raíz, análisis de heap spray de 50 sesiones y cronología del CVE |
CVE-2024-30051-Masters-Thesis/
├── README.md
├── LICENSE
├── setup.bat # Copies s11.dll to required location
│
├── exploit/
│ ├── C21.sln # Visual Studio 2022 solution
│ ├── exploit_src/
│ │ ├── c26f.vcxproj
│ │ ├── c26f.filters
│ │ └── main.cpp # Exploit — heap spray + hooking + overflow
│ └── payload/
│ ├── payload.vcxproj
│ ├── payload.vcxproj.filters
│ ├── dllmain.cpp # Payload DLL — spawns SYSTEM shell + cleanup
│ ├── framework.h
│ ├── pch.h
│ └── pch.cpp
│
└── docs/
├── screenshots/ # Patch diffing, WinDbg, and forensic captures
└── analysis/
├── 01-root-cause.md # Integer division bug in CCommandBuffer::Initialize
├── 02-heap-spray.md # 50-session empirical data and statistical findings
└── 03-timeline.md # Discovery, disclosure, and patch chronology
Abre C21.sln en Visual Studio 2022. Compila el proyecto payload en Release x64.
Ejecuta setup.bat desde la raíz del repositorio. Copia s11.dll a C:\Users\Public\Documents\s11.dll (la ruta definida por PAYLOAD_DLL_PATH).
⚠️ La DLL debe estar en esta ruta exacta antes de ejecutar
C26f.exe. Colocarla junto al ejecutable no funcionará.
Compila el proyecto C26f en Release x64.
x64\Release\C26f.exe
Ejecuta desde un CMD estándar (sin elevación). El exploit reintenta automáticamente hasta 10 veces. En caso de éxito, dwm.exe carga s11.dll y abre un CMD con nivel de integridad SYSTEM. Se escribe un registro de sesión en %TEMP%\cve_30051_log.txt.
#define MAX_ATTEMPTS 10 // Max auto-retry attempts per session
#define SPRAY_STEP 0x10 // Hole spacing index (1024 holes)
#define SPRAY_RANGE_START 0x3000 // Spray range start index
#define SPRAY_RANGE_END 0x7000 // Spray range end index
#define SLEEP_POST_SPRAY 0xC8 // ms wait after spray (200ms)
#define SLEEP_POST_HOLES 0xC8 // ms wait after freeing holes (200ms)
#define PAYLOAD_DLL_PATH "C:\\Users\\Public\\Documents\\s11.dll"
En CCommandBuffer::Initialize (dwmcore.dll 10.0.22621.3447), CD2DSharedBuffer::GetBufferSize se llama dos veces. El tamaño pasado a new() se somete a una división entera por 0x90 antes de la multiplicación, mientras que memcpy() usa el valor bruto:
buffer_size = GetBufferSize() → e.g. 0x23F
size_new = (0x23F / 0x90) * 0x90 = 0x1B0 ← allocated
size_memcpy = 0x23F ← copied
overflow = 0x23F - 0x1B0 = 0x8F bytes
Comparación BinDiff entre la compilación 10.0.22621.3447 (vulnerable) y la 10.0.22621.3593 (parcheada):
| Métrica | Valor |
|---|---|
| Similitud global | 0.98 |
| Confianza | 0.99 |
| Funciones coincidentes | 14,062 (99.1 %) |
Similitud de CCommandBuffer::Initialize | 0.32 |
| Bloques básicos — versión vulnerable | 4 |
| Bloques básicos — versión parcheada | 20 (16 bloques de validación añadidos) |
La puntuación anómala de 0.32 frente a una similitud global de 0.98 es la firma directa del lugar de la vulnerabilidad.
1. Hook RtlCreateHeap → capture dwmcore heap handle
2. Hook RtlAllocateHeap → capture base chunk address
3. Hook NtDCompositionCreateChannel → capture MappedAddress (shared memory region)
4. Hook NtDCompositionCommitChannel → overwrite size field (0x120 → 0x23F)
inject additional batch commands
5. Heap spray 0x10000 CHolographicInteropTexture objects (size=0x1B0)
6. Free holes every 0x10 indices → create gaps for overflow landing
7. Write payload into overflow buffer → KCBTable+0x388 + LoadLibraryA + DLL path
8. Release all spray objects → trigger overflow → LoadLibraryA("s11.dll")
9. dwm.exe loads payload DLL → spawns CMD as SYSTEM integrity
¿Influye la RAM disponible en el número de intentos necesarios para lograr un heap spray exitoso?
Dos bloques de 25 sesiones cada uno. Protocolo por sesión: restaurar un snapshot limpio posterior al arranque → esperar 100 segundos de estabilización → lanzar el exploit → registrar el intento de éxito.
| Bloque | RAM | Sesiones | Éxitos | Fallos |
|---|---|---|---|---|
| A | 8,192 MB | 25 | 24 | 1 |
| B | 4,096 MB | 25 | 24 | 1 |