
Магистерское исследование CVE-2024-30051 (переполнение кучи в Windows DWM). Отличается высоконадежным эксплойтом с автоматической оптимизацией heap spray, ведением журнала в реальном времени и эмпирическим анализом частоты успеха. Портфолио, демонстрирующее продвинутую эксплуатацию двоичных файлов Windows, манипулирование компоновкой кучи и LPE через Desktop Window Manager.
Heap-based Buffer Overflow в Windows Desktop Window Manager (
dwmcore.dll)
Локальное повышение привилегий → Уровень целостности SYSTEM через процесс DWM
Целевая сборка: Windows 11 22H2 (10.0.22621.3447) · Патч: KB5037771
Этот репозиторий содержит моё исследование магистерской диссертации по CVE-2024-30051,
уязвимости повышения привилегий высокой степени серьезности (CVSS 7.8) в основной библиотеке
диспетчера окон Windows (dwmcore.dll).
Уязвимость возникает из-за ошибки вычисления размера при целочисленном делении в
CCommandBuffer::Initialize. Размер, используемый для new(), и размер, используемый для memcpy(),
расходятся из-за этой ошибки, что приводит к переполнению кучи на 0x8F байт. Успешная
эксплуатация заставляет dwm.exe загрузить управляемую злоумышленником DLL, выполняя
произвольный код под учетной записью window manager\dwm-1 с уровнем целостности SYSTEM.
| Аспект | Описание |
|---|---|
| Patch diffing | Полный анализ BinDiff с идентификацией CCommandBuffer::Initialize как точного локуса уязвимости (оценка схожести 0.32 против глобальной 0.98 по 14 062 сопоставленным функциям) |
| Динамический анализ WinDbg | Пошаговая верификация всех 4 хуков, перезаписи поля размера и конструирования полезной нагрузки |
| Эмпирический анализ heap spray | 50 контролируемых сессий в двух конфигурациях ОЗУ (8 192 МБ и 4 096 МБ) с формальными статистическими тестами |
| Статистические выводы | U-критерий Манна-Уитни (p = 0.031) и t-критерий Уэлча (p = 0.011) подтверждают влияние ОЗУ; наблюдаемые средние значения в 12.9–19 раз лучше теоретического прогноза ~64 попыток |
| Централизация пути DLL полезной нагрузки | Извлечен жестко заданный путь в константу препроцессора #define PAYLOAD_DLL_PATH |
| Журналирование сессий | Полный журнал с метками времени для каждой сессии записывается в %TEMP%\cve_30051_log.txt |
| Академическая документация | Первопричина, анализ heap spray за 50 сессий и временная шкала CVE |
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 # Эксплойт — heap spray + хукинг + переполнение
│ └── payload/
│ ├── payload.vcxproj
│ ├── payload.vcxproj.filters
│ ├── dllmain.cpp # DLL полезной нагрузки — запуск оболочки SYSTEM + очистка
│ ├── framework.h
│ ├── pch.h
│ └── pch.cpp
│
└── docs/
├── screenshots/ # Снимки patch diffing, WinDbg и криминалистические копии
└── analysis/
├── 01-root-cause.md # Ошибка целочисленного деления в CCommandBuffer::Initialize
├── 02-heap-spray.md # Эмпирические данные 50 сессий и статистические выводы
└── 03-timeline.md # Хронология обнаружения, раскрытия и патча
Откройте C21.sln в Visual Studio 2022. Соберите проект payload в конфигурации Release x64.
Запустите setup.bat из корня репозитория. Он копирует s11.dll в
C:\Users\Public\Documents\s11.dll (путь, определенный PAYLOAD_DLL_PATH).
⚠️ DLL обязательно должна находиться по этому точному пути перед запуском
C26f.exe. Размещение рядом с исполняемым файлом не сработает.
Соберите проект C26f в конфигурации Release x64.
x64\Release\C26f.exe
Запускайте из стандартной (не повышенной привилегиями) командной строки. Эксплойт автоматически повторяет попытки до 10 раз.
В случае успеха dwm.exe загружает s11.dll и запускает командную строку с уровнем целостности SYSTEM.
Журнал сессии записывается в %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 // Ожидание в мс после распыления (200 мс)
#define SLEEP_POST_HOLES 0xC8 // Ожидание в мс после освобождения дырок (200 мс)
#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.99 |
| Сопоставленные функции | 14 062 (99.1%) |
Сходство CCommandBuffer::Initialize | 0.32 |
| Базовых блоков — уязвимая версия | 4 |
| Базовых блоков — исправленная версия | 20 (добавлено 16 блоков проверки) |
Аномальная оценка 0.32 на фоне глобального сходства 0.98 является прямой сигнатурой локуса уязвимости.
1. Хук RtlCreateHeap → перехватить дескриптор кучи dwmcore
2. Хук RtlAllocateHeap → перехватить адрес базового блока
3. Хук NtDCompositionCreateChannel → перехватить MappedAddress (разделяемая область памяти)
4. Хук NtDCompositionCommitChannel → перезаписать поле размера (0x120 → 0x23F)
внедрить дополнительные команды пакета
5. Heap spray 0x10000 объектов CHolographicInteropTexture (размер=0x1B0)
6. Освободить дырки через каждые 0x10 индексов → создать промежутки для попадания переполнения
7. Записать полезную нагрузку в буфер переполнения → KCBTable+0x388 + LoadLibraryA + путь DLL
8. Освободить все объекты распыления → вызвать переполнение → LoadLibraryA("s11.dll")
9. dwm.exe загружает DLL полезной нагрузки → запускает командную строку с целостностью SYSTEM
Влияет ли доступный объем ОЗУ на количество попыток, необходимых для успешного heap spray?
Два блока по 25 сессий каждый. Протокол на сессию: восстановление чистого моментального снимка после загрузки → ожидание 100 секунд для стабилизации → запуск эксплойта → запись попытки успеха.