
Cadena de explotación completa para CVE-2025-7771 en ThrottleStop.sys, abusando de IOCTLs de lectura/escritura de memoria física no validadas para escalar de administrador a SYSTEM en Windows.
Prueba de concepto completa para el controlador ThrottleStop.sys de TechPowerUp (CVE-2025-7771).
Un controlador de kernel firmado y aún cargable expone lectura y escritura de memoria física
sin validación a través de dos IOCTLs. Este repositorio convierte esa primitiva en una
escalada de privilegios local funcional de administrador a SYSTEM y documenta una peculiaridad
en el nombrado de dispositivos que rompe la mayoría de las detecciones basadas en rutas y nombres de archivo.
Ya existía una PoC para los mismos IOCTLs (ver Créditos). Esta es una cadena de explotación completa e independiente, en lugar de una demostración de primitiva.
| Campo | Valor |
|---|---|
| SHA256 | 16F83F056177C4EC24C7E99D01CA9D9D6713BD0497EEEDB777A3FFEFA99C97F0 |
| SHA1 | 82ED942A52CDCF120A8919730E00BA37619661A3 |
| MD5 | 6BC8E3505D9F51368DDF323ACB6ABC49 |
| Versión | 3.0.0.0 ("Low-Level Driver", 2004-2020) |
| Firmante | TechPowerUp LLC, DigiCert EV Code Signing |
| Huella del certificado | 524EDA9C819321C66E22C7BABEB23DAEAFFB2182 |
| Validez del certificado | 2019-08-10 a 2022-06-15 |
El certificado expiró en 2022, pero la firma lleva una marca de tiempo de contrafirma de confianza, por lo que Windows todavía lo carga. La revocación solo ayuda si su fecha precede al momento de la firma, lo cual rara vez es el caso para controladores antiguos como este.
El recurso de versión no tiene CompanyName, OriginalFilename ni InternalName, por lo que
el archivo no puede atribuirse a un proveedor a partir de sus propios metadatos.
Dos IOCTLs leen y escriben memoria física sin validación de límites ni de direcciones:
| IOCTL | Operación |
|---|---|
0x80006498 | Lectura física |
0x8000649C | Escritura física |
Ambos son METHOD_BUFFERED, por lo que no hay desreferencia de punteros de usuario; el defecto
es la falta de validación de la dirección física proporcionada por el llamador, no un puntero
no verificado.
Merece la pena señalar: el manejador de escritura 0x8000649C está declarado como
FILE_READ_ACCESS. Un handle abierto en modo solo lectura puede seguir emitiendo escrituras
físicas, por lo que la máscara de acceso declarada no coincide con lo que el manejador hace
realmente.
Abrir el dispositivo requiere derechos de administrador, por lo que esto no es un cruce de límite de privilegios por sí mismo. Lo que le proporciona a un atacante que ya es admin es lectura/escritura arbitraria del kernel desde modo usuario, lo que derrota las protecciones que se supone deben mantenerse por encima de admin: integridad de código HVCI, PPL y autoprotección de EDR/AV. El clásico trae-tu-propio-controlador-vulnerable.
Como demostración concreta, la PoC utiliza la primitiva de R/W para robar el token de SYSTEM y lanzar un shell de SYSTEM.
CVSS 4.0: AV:L/AC:H/AT:N/PR:H/UI:N/VC:H/VI:H/VA:H/SC:H/SI:H/SA:H (8.7, Alta).
Todo se ejecuta desde modo usuario contra los IOCTLs de R/W física del controlador. No hay recorrido de tablas de páginas ni CR3 involucrado; ambos procesos se localizan escaneando la memoria física directamente:
ImageFileName sea System y UniqueProcessId sea 4. El escaneo está acotado a los
rangos de RAM poblados leídos de la clave de registro
HARDWARE\RESOURCEMAP\...\Physical Memory del firmware, no una ventana adivinada, por lo
que nunca se tocan los huecos de MMIO y no se pierde nada por encima de la RAM instalada.Token (EPROC_TOKEN) del EPROCESS localizado.Token. El token es un _EX_FAST_REF, por lo que los bits bajos del contador de
referencias se enmascaran por defecto (--mask selecciona el comportamiento).cmd.exe; whoami devuelve NT AUTHORITY\SYSTEM.Los offsets (EPROC_TOKEN, EPROC_PID, EPROC_IMG_NAME, etc.) son para una compilación
específica y deben confirmarse contra dt nt!_EPROCESS en la versión de Windows objetivo.
El nombre del ejecutable importa. El paso 3 localiza nuestro propio proceso haciendo coincidir
su ImageFileName en la memoria física, y ese campo está limitado a 15 caracteres con el
escaneo coincidiendo los primeros 8. Mantén el nombre compilado corto y distintivo; si
renombras el binario, permanece dentro de ese límite o el auto-escaneo no encontrará el proceso.
El controlador no utiliza un nombre de dispositivo fijo. Deriva el nombre del objeto de
dispositivo del nombre del servicio bajo el que está registrado; el nombre de archivo en
disco es irrelevante. Registrar el binario bajo el servicio TRIXX produce \\.\TRIXX sin
importar cómo se llame el archivo en disco.
Por lo tanto, cualquier detección basada en \Device\ThrottleStop o ThrottleStop.sys se
elude trivialmente. La detección tiene que basarse en el hash del archivo o en el certificado
de firma:
SHA256: 16F83F056177C4EC24C7E99D01CA9D9D6713BD0497EEEDB777A3FFEFA99C97F0
Thumbprint: 524EDA9C819321C66E22C7BABEB23DAEAFFB2182
Subject: CN=TechPowerUp LLC, O=TechPowerUp LLC, L=Spokane, S=Washington, C=US
La lista DEVICE_NAMES en el código fuente es solo una sonda para instalaciones conocidas del
producto. Pasa un nombre de dispositivo como argumento para apuntar a un servicio que hayas
registrado tú mismo.
| CVE | Controlador |
|---|---|
| CVE-2019-7245 | GPU-Z.sys |
| CVE-2025-5324 | GPU-Z.sys |
| CVE-2025-7771 | ThrottleStop.sys (este repositorio) |
El binario no se distribuye aquí. Verifica cualquier copia contra el SHA256 anterior. La muestra está catalogada en LOLDrivers.
cl /nologo /EHsc /W4 /O2 src\ThrottleStop.cpp /Fe:myLittleLpe.exe /link advapi32.lib
Solo para uso en laboratorio. Ejecutar dentro de una VM aislada con una instantánea a la que poder revertir.
sc.exe create <name> type= kernel binPath= C:\path\to\ThrottleStop.sys
sc.exe start <name>
myLittleLpe.exe
sc.exe stop <name>
sc.exe delete <name>
El binario no acepta argumentos. Imprime el mapa de memoria física, escanea en busca del
EPROCESS de SYSTEM y el local, intercambia el token y lanza cmd.exe ejecutándose como
NT AUTHORITY\SYSTEM.

Otros trabajos públicos sobre el mismo controlador, para comparación: