A practical approach to detecting Bring Your Own Vulnerable Driver (BYOVD) activity using KQL and LOLDrivers.

In the recent years, we have observed an increase in attacks using Bring Your Own Vulnerable Drivers (BYOVD). Threat actors deliver legitimate, signed drivers with known vulnerabilities into target systems to gain unauthorized kernel-level access.
When a driver is signed, the system believes it has been verified and allows it to operate with elevated privileges. However, if a signed driver contains vulnerabilities, attackers can bypass traditional security measures and execute malicious activities with elevated privileges.
Many attackers use BYOVD to defeat endpoint protection before detonating a payload. For example, in early 2026, Qilin ransomware used a multi-stage infection chain that began with a malicious msimg32.dll, side-loaded by a legitimate application. The final payload dropped by this loader was an EDR killer capable of disabling over 300 different EDR drivers through BYOVD.
This EDR killer first drops and loads rwdrv.sys, a driver that ships legitimately with GPU-Z and ThrottleStop, carrying a valid digital signature. The driver itself is not an offensive exploit in the traditional sense; it is a hardware diagnostics interface that exposes physical memory access, MSR reads/writes, and PCI configuration operations.

Qilin Ransomware then uses all of these to take down EDR solutions:
NtQuerySystemInformation Superfetch data.rwdrv.sys, bypassing the EDR's virtual address space entirely. The EDR cannot observe its own callbacks being erased.hlpdrv.sys is loaded to terminate the now-blind EDR processes via IOCTL 0x222008, bypassing Protected Process Light (PPL).
We have used other examples in our own Red Team engagements as well, below are three examples:
BdApiUtil.sys (Baidu Antivirus) exposes a process termination IOCTL at 0x800024B4 that accepts a raw PID. Four bytes in, the process is gone.
wsftprm.sys (Topaz Antifraud). The IOCTL uses a deliberately obfuscated calculation (IoControlCode - 0x222000 - 4 - 4 - 16 = 4) that resolves to 0x22201C. The input is a 1036-byte buffer with the PID in the first four bytes and padding to fill the rest.
NSecKrnl.sys (NSEC) with an IOCTL at 0x2248E0 that takes a uint64_t PID.
To avoid hash-based detection, we SigFlip the drivers before dropping them. SigFlip appends arbitrary data to the signature overlay, which is the part Windows does not validate during Authenticode verification.
LOLDrivers (Living Off The Land Drivers) is a community-driven project documenting known vulnerable and malicious Windows kernel drivers. Every entry includes file hashes (SHA256 and SHA1), abuse scenarios and affected operating systems.
The full dataset is available as a JSON feed via API, which makes it directly usable in KQL-based detections without any external tooling.
let LOLDrivers = externaldata(Category: string, KnownVulnerableSamples: dynamic, Verified: string)
[@"https://www.loldrivers.io/api/drivers.json"]
with (format="multijson")
| mv-expand KnownVulnerableSamples
| extend SHA256 = tostring(KnownVulnerableSamples.SHA256), SHA1 = tostring(KnownVulnerableSamples.SHA1)
| where Verified == "TRUE";
DeviceEvents
| where ActionType == "DriverLoad"
| join kind=inner (LOLDrivers | where isnotempty(SHA256)) on SHA256
| union (
DeviceEvents
| where ActionType == "DriverLoad"
| join kind=inner (LOLDrivers | where isnotempty(SHA1)) on SHA1
)
| distinct TimeGenerated, DeviceName, InitiatingProcessAccountName, InitiatingProcessFileName, FileName, SHA256, SHA1, Category
With this query, we can generate awesome detection rules and even evaluate if the tenant uses vulnerable drivers.
