BYOVD: Detección y Prevención en un Endpoint Windows 11 con Hardening
Escrito por 0xM4L · Investigación de Seguridad OFFCEPT
Probamos BYOVD contra un endpoint Windows 11 25H2 totalmente hardened con MDE y ASR en modo Block. Siete de veintiún drivers públicamente conocidos fueron detectados al escribirse en disco. Nueve cargaron limpiamente en el kernel y mataron todos los procesos PPL-protected de Defender. La cobertura de la blocklist va con meses de retraso respecto a la divulgación pública. El allow-listing con WDAC y la detección conductual son los únicos controles que cierran la brecha.
Bring Your Own Vulnerable Driver (BYOVD) sigue siendo una de las formas más fiables de que los atacantes consigan código corriendo en el kernel de Windows en 2026. En vez de encontrar un exploit de kernel fresco, el atacante trae un driver legítimamente firmado pero vulnerable, lo carga y abusa de su funcionalidad expuesta (normalmente vía IOCTLs) para leer y escribir memoria de kernel, terminar procesos protegidos, o cegar y desactivar las propias defensas del endpoint.
Este artículo recorre un lab hands-on donde probamos BYOVD contra una máquina Windows 11 totalmente gestionada y protegida por EDR, y muestra que incluso con los controles "Block Vulnerable Drivers" activados, un número significativo de drivers conocidos como vulnerables sigue cargando y corriendo. Terminamos con un conjunto de mitigaciones y defensas que realmente marcan la diferencia.
Aviso. Esta investigación se realizó en un lab aislado que poseemos y controlamos, con fines defensivos. No corras drivers vulnerables ni tooling que mata EDRs contra sistemas que no estás autorizado a probar.
Metodología
Agrupamos los drivers vulnerables en tres categorías según lo "conocidos" que son para los defensores:
- Categoría 1: en blocklist + PoC público. Drivers ya presentes en blocklists públicas (la Vulnerable Driver Blocklist de Microsoft, LOLDrivers) con un exploit listo para usar publicado.
- Categoría 2: en blocklist, sin PoC público. Drivers listados como vulnerables pero sin exploit turnkey; tienes que escribir el tuyo.
- Categoría 3: no listados / desconocidos. Drivers vulnerables aún sin catalogar en ninguna parte. Zero-days: vulnerabilidad desconocida, driver desconocido, sin entrada en ninguna blocklist.
Para este lab usamos un fork del proyecto BYOVD de BlackSnufkin, un PoC en Rust que abusa de IOCTLs de driver para terminar procesos arbitrarios por PID desde kernel mode, incluyendo ~21 drivers vulnerables (Categoría 1), más un driver adicional de LOLDrivers sin exploit público (Categoría 2), y drivers descubiertos en software de Windows de terceros aún no listados en ninguna parte, para los que desarrollamos un PoC que abusa de un zero-day (Categoría 3). Este artículo se centra en la Categoría 1, porque es el caso que los defensores deberían estar mejor equipados para detener y, como veremos, a menudo no lo están.
Configuración del Lab
| Componente | Detalle |
|---|---|
| SO | Windows 11 25H2 |
| EDR | Microsoft Defender for Endpoint (MDE) |
| Gestión | Inscrito vía Microsoft Intune |
| Políticas | Attack Surface Reduction (ASR), Block Abuse of Exploited Vulnerable Signed Drivers |
El endpoint está incorporado a MDE e inscrito vía Intune → Endpoint security → Attack surface reduction, usando el perfil de Attack Surface Reduction Rules. La regla específica es "Block abuse of exploited vulnerable signed drivers", configurada en Block. Esta es exactamente la configuración que desplegaría una organización consciente de la seguridad: un SO moderno, un EDR de primer nivel, gestión MDM, y el propio control anti-BYOVD del vendor activado.

Parte 1: Detección on-write
Copiamos los 21 drivers de BlackSnufkin a disco bajo C:\drivers\BYOVD-main\. 7 drivers fueron marcados y puestos en cuarentena por MDE en el momento en que tocaron disco, detectados como VulnerableDriver:* (y uno como Trojan:Win64/KillAV):
- Ksapi64-Killer
- NSec-Killer
- PoisonX-Killer
- STProcessMonitor-Killer
- TfSysMon-Killer
- UnknownKiller
- Viragt64-Killer

Los 14 drivers restantes se quedaron en disco; Defender no los marcó al escribirse: AppRemover-Killer, Astra64-RW, BdApiUtil-Killer, CcProtect-Killer, EnPortv-Killer, GameDriverX64-Killer, GoFlyDrv-Killer, HWAudioOs2Ec-Killer, K7Terminator, MonProcessEX-Killer, PCTcore64-Killer, Wsftprm-Killer, Xhunter1-Killer, Xkpsm-Killer.
Conclusión: la detección on-write/on-access solo atrapó a un tercio de un conjunto de drivers de Categoría 1, públicamente conocidos. El resto depende de controles en tiempo de carga, que probamos a continuación.
Parte 2: Registrar e iniciar los drivers
Un driver de kernel solo se vuelve interesante una vez que se registra como servicio y se inicia. Usamos un pequeño wrapper en PowerShell alrededor de sc.exe para registrar cada .sys como servicio de kernel mode con inicio bajo demanda. Todos los servicios se crearon con éxito; registrar el servicio y escribir la clave HKLM\SYSTEM\CurrentControlSet\Services\<nombre> no está bloqueado en sí mismo.
#Requires -RunAsAdministrator
$SC = "$env:SystemRoot\System32\sc.exe"
$DriverRoot = 'C:\drivers\BYOVD-main'
Get-ChildItem -LiteralPath $DriverRoot -Filter *.sys -Recurse -File -Force |
ForEach-Object {
$name = $_.BaseName
$key = "HKLM:\SYSTEM\CurrentControlSet\Services\$name"
if (Test-Path $key) {
& $SC delete $name 2>&1 | Out-Null
Remove-Item $key -Recurse -Force -ErrorAction SilentlyContinue
}
$out = & $SC create $name binPath= $_.FullName type= kernel start= demand
if ($LASTEXITCODE -eq 0) {
Write-Host "[+] $name -> $($_.FullName)" -ForegroundColor Cyan
} else {
Write-Warning "[-] $name : $($out -join ' ')"
}
}
La parte interesante es sc start, que dispara la carga real en el kernel. Aquí las protecciones por capas por fin entran en acción, pero solo para algunos drivers:
| Resultado | Significado | Qué control lo detuvo |
|---|---|---|
RUNNING | Driver cargado en el kernel | Nada lo detuvo |
FAILED 577: Windows no puede verificar la firma digital | Bloqueado por code-integrity / firma | DSE / WHQL |
FAILED 0x800B010C: certificado explícitamente revocado | Certificado de firma revocado | Revocación de certificado |
FAILED 5: Acceso denegado | Bloqueado por la Vulnerable Driver Blocklist / ASR | Blocklist |
FAILED 31 / 183 | Error de init de dispositivo/driver (no es un bloqueo de seguridad) | n/a |
Un driver incluso mostró un mensaje explícito: PCTcore64.sys: A security setting is detecting this as a vulnerable driver and blocking it from loading. You will need to adjust your settings to load this driver.
A pesar de tener todas las protecciones activadas, 9 drivers conocidos como vulnerables alcanzaron el estado RUNNING y quedaron vivos en el kernel: ardrv, ASTRA64, CcProtect, EnPortv, GoFly64, HWAudioOs2Ec_1, MonProcessEX, STProcessMonitor_v114, xkpsm. No son drivers oscuros. La mayoría estaba catalogada en LOLDrivers meses antes de esta prueba. La entrada más antigua se publicó en marzo de 2026; a 8 de agosto de 2026, casi cinco meses después, siguen cargando y corriendo en una máquina totalmente parcheada y con políticas hardened. Ese es el hallazgo central: la cobertura de la blocklist va por detrás de la divulgación pública, y la brecha se mide en meses.
Parte 3: Abusar de un driver cargado para matar Defender
Para demostrar que un driver que "sigue cargando" no es un problema teórico, tomamos uno de los drivers en ejecución (CcProtect.sys) y usamos el PoC de BYOVD para terminar procesos protegidos desde el kernel. El PoC abre el device object del driver (\\.\CcProtect) y envía el IOCTL 0x222024 con el nombre de un proceso objetivo; el driver, corriendo en kernel mode, termina el PID correspondiente, saltándose la protección de user mode (PPL) que normalmente blinda estos procesos.
Lo apuntamos directamente a todo el stack de Defender / MDE:
MsMpEng.exe- Motor del antivirus DefenderMpDefenderCoreService.exe- Servicio core de DefenderSecurityHealthService.exeNisSrv.exe- Servicio de inspección de redMsSense.exe,SenseIR.exe,SenseTVM.exe,SenseNdr.exe- Componentes del sensor MDE

Todos corren como Protected Processes (PsProtectedSignerAntimalware-Light / PsProtectedSignerWindows-Light). Los kills tienen éxito. Una herramienta de user mode nunca podría hacer esto a un proceso antimalware protegido con PPL, pero un driver de kernel sí.
Una salvedad sobre persistencia: Defender tiene self-healing. Los servicios antimalware dirigidos por MpDefenderCoreService acaban relanzándose. Para mantener el endpoint ciego, un atacante tiene que re-matar los procesos continuamente o encadenar una persistencia completa de SYSTEM/kernel para detener y eliminar los servicios directamente. En cualquier caso, el punto se mantiene: BYOVD es una amenaza real y actual para la seguridad del endpoint, incluso con antimalware y EDR instalados y configurados.
Reglas de detección custom en Microsoft Defender XDR
Dado que la blocklist integrada no ve drivers desconocidos o aún firmados, podemos cerrar parte de la brecha con una regla de detección custom en Microsoft Defender XDR que alerte sobre cualquier registro nuevo de driver de kernel, vulnerable o no. Un enfoque ingenuo vigilaría sc.exe create ... type= kernel, pero eso se salta de forma trivial: un atacante puede registrar el driver directamente vía la API del Service Control Manager, vía NtLoadDriver, o con syscalls indirectas, y ninguna de esas toca sc.exe. Filtrar por paths sospechosos de ficheros es igual de débil.
El chokepoint robusto es el registro. Todas esas técnicas (incluida NtLoadDriver) siguen exigiendo una clave de servicio bajo ...\CurrentControlSet\Services\<nombre> con un ImagePath apuntando al .sys. Detectamos esa escritura en cualquier path y aplicamos un modelo default-deny: alertar sobre cada registro de driver de kernel excepto los que estén en una baseline known-good mantenida.
// Alerta sobre CUALQUIER registro nuevo de servicio de driver de kernel,
// independientemente de la herramienta o el path.
// La escritura en Services\<name>\ImagePath es el invariante por el que sc.exe,
// la API del SCM y NtLoadDriver pasan todos.
DeviceRegistryEvents
| where ActionType in ("RegistryValueSet", "RegistryKeyCreated")
| where RegistryKey has @"\CurrentControlSet\Services\"
| where RegistryValueName == "ImagePath" and RegistryValueData endswith ".sys"
// default-deny: conserva solo lo que NO está en tu baseline aprobada.
// Mantén KnownGoodDrivers como watchlist, idealmente indexada por hash/firmante y no por path.
| where RegistryValueData !in~ (KnownGoodDrivers)
| project Timestamp, DeviceName, RegistryKey, RegistryValueData,
InitiatingProcessFileName, InitiatingProcessCommandLine,
InitiatingProcessAccountNameGuárdala como regla de detección custom en Advanced Hunting; configura la frecuencia, la severidad y las entidades de máquina/fichero a mapear para que un evento que coincida levante una alerta y, opcionalmente, dispare una respuesta automatizada. Un registro que apunte fuera de \Windows\System32\drivers\ merece una severidad más alta.
Mitigaciones y defensas
Ningún control único detiene BYOVD; hace falta defence-in-depth. Aproximadamente por orden de impacto:
- 1. Aplica la Microsoft Vulnerable Driver Blocklist, y no confíes solo en ella. Actívala (viene activada con HVCI/SAC en Windows moderno), pero trátala como necesaria-pero-insuficiente. Como se muestra arriba, la blocklist va con meses de retraso respecto a la divulgación pública y aquí dejó pasar 9 de 21 drivers bien conocidos.
- 2. Activa VBS, HVCI/Memory Integrity y Device Guard. Hypervisor-Enforced Code Integrity (HVCI) corre la code integrity de kernel mode dentro de un entorno aislado por VBS y fuerza la validación de firma y las comprobaciones de revocación de certificado en tiempo de carga. Este es el paso de hardening de plataforma más valioso de todos. Despliégalo primero en un anillo de pruebas; drivers incompatibles pueden causar fallos de arranque.
- 3. Pasa a una allow-list con App Control for Business (WDAC). En vez de bloquear lo conocido como malo, permite solo lo conocido como bueno: whiteliste publishers, firmantes y hashes específicos de drivers. Es el único enfoque que también aborda los drivers de Categoría 3 (desconocidos/zero-day), porque un driver no listado se deniega por defecto.
- 4. Exige requisitos modernos de firma de drivers (EV / WHQL) y bloquea los drivers heredados. Muchos drivers abusados son binarios antiguos con cross-signing. Exigir firma moderna cierra un gran trozo del catálogo de Categoría 1/2.
- 5. Restringe quién puede registrar y cargar drivers. Cargar un driver exige admin local /
SeLoadDriverPrivilege. Aplica least privilege y JIT/JEA para el personal de IT. - 6. Audita y elimina drivers de terceros arriesgados. Los anti-cheat de gaming, las utilidades de overclocking de GPU/CPU y las viejas herramientas de información de sistema de vendors son reincidentes en endpoints de producción. Parchea o prohíbe el software que incluye versiones de driver conocidas como vulnerables.
- 7. Mantén al día firmas, motor y blocklist. Asegúrate de que la protección cloud de MDE y la blocklist de drivers se auto-actualizan. Una blocklist obsoleta es exactamente el modo de fallo ilustrado arriba.
- 8. Mantén ASR en modo Block. Usa primero
Auditpara construir la baseline, luego pasa aBlockpara "Block abuse of exploited vulnerable signed drivers" y combínalo con el conjunto amplio de reglas ASR. - 9. Vigila el comportamiento, no solo el binario. Sysmon Event ID 6 (carga de driver) correlacionando hash, estado de firma y path; Event ID 7045 (nuevo servicio instalado); escrituras de registro de nuevos servicios de kernel; eventos de bloqueo WDAC (3023 / 3033). Alerta sobre cargas desde paths escribibles por el usuario (
\AppData\,\Temp\,\ProgramData\) y cruza los hashes contra loldrivers.io. - 10. Vigila el impacto. Peticiones IOCTL anómalas a un device object recién cargado, eliminación de callbacks de kernel y terminación de procesos PPL/antimalware iniciada desde el kernel son señales de alta fidelidad de que un kill ya está en curso. Configura alertamiento inmediato sobre terminación de procesos de seguridad y huecos de heartbeat del sensor en el portal de MDE.
- 11. Valida continuamente y planifica el fallo. Asume que algún driver conseguirá pasar. Corre simulaciones de BYOVD y ejercicios de red team, aísla hosts con actividad de kernel sospechosa y asegúrate de que los planes de backup y recuperación contemplan un escenario donde la prevención falló.
Dónde fallan las blocklists
El tema consistente es que bloquear por reputación es siempre reactivo. Un driver tiene que ser descubierto, analizado, catalogado y empujado a la blocklist antes de ser detenido, y cada día de esa ventana carga limpiamente. Los drivers de Categoría 2 y 3 nunca entran en esa ventana. Así se comportan los controles ante el caso más difícil: un driver vulnerable firmado válidamente pero desconocido (Categoría 3 / zero-day):
| Control | ¿Detiene un driver vulnerable firmado y desconocido? | Por qué |
|---|---|---|
| Vulnerable Driver Blocklist | No | El driver desconocido no está en ninguna lista |
| HVCI / Memory Integrity | No | Está firmado válidamente, así que carga; los ataques de lectura/escritura de kernel data-only nunca introducen código ejecutable nuevo que HVCI pueda atrapar |
| WDAC / App Control allow-list | Sí | Default-deny: un driver no aprobado explícitamente nunca carga, sea conocido como malo o no |
| Detección conductual de carga de drivers | Detecta | Marca la carga de cualquier driver fuera de la baseline, más la actividad IOCTL anómala / eliminación de callbacks tras la carga |
Los controles de firma y reputación son estructuralmente ciegos ante un driver desconocido-pero-firmado. Solo la autorización de carga (allow-listing) y la detección conductual lo abordan, e incluso el allow-listing falla si el driver vulnerable es uno que aprobaste legítimamente, dejando la detección conductual del impacto (kills PPL inesperados, eliminación de callbacks, IOCTLs sospechosos) como última línea.
Por eso la respuesta más duradera es detectar y controlar el acto de cargar un driver, vulnerable o no, en vez de comparar contra una lista de malos. En la próxima parte de esta serie profundizamos exactamente en eso: customizar la lógica de detección de EDR/XDR (Defender Advanced Hunting KQL y queries análogas de Elastic) más el allow-listing con WDAC, para sacar a la superficie cualquier evento de carga de driver y decidir sobre él por política, cerrando la brecha que las defensas BYOVD basadas en firmas y blocklists dejan abierta.
Referencias
- Microsoft: Enable memory integrity (HVCI / VBS)
- Microsoft: Strategies to monitor and prevent vulnerable driver attacks
- BlackSnufkin: BYOVD project
- LOLDrivers
- Check Point Research: Breaking Boundaries: Investigating Vulnerable Drivers and Mitigating Risks
- Cisco Talos: Exploring vulnerable Windows drivers
- CrowdStrike: Falcon Prevents Vulnerable Driver Attacks in a Real-World Intrusion