The Windows kernel driver is an interesting space that falls between persistence and privilege escalation. The origins of a vulnerable driver being used to elevate privileges may have begun in the gaming community as a way to hack or cheat in games, but also has potential beginnings with Stuxnet. Despite efforts from Microsoft to provide stable drivers and implement checks to prevent malicious or vulnerable drivers from loading, these controls are not yet widely implemented by organizations, leaving them vulnerable to driver-based attacks. For adversaries, drivers provide a layer of persistence not monitored by many tools, or prevented by antivirus products, without the risk of prevention controls causing an operating system error. As noted by Rapid7 in their 2021 research, other examples use a driver to unhook EDR callbacks or hide exploitation/rootkit artifacts. The adversary can write themselves a UEFI rootkit,overwrite all data (resulting in BSoD),or inject code into other processes. Drivers can be hard to determine as malicious or benign. As defenders, drivers can be a bit of a gray area as most organizations trust but do not verify what drivers are loaded, let alone monitor for new driver installation.
This blog post explores the nuances of drivers and what distinguishes them, examines the known knowns of vulnerable drivers, provides guidance on simulating adversary tradecraft with the Atomic Red Team, shares strategies for mitigating driver-related threats, and discusses Splunk Security Content available to defend against these types of attacks.
At a high level, what makes up a driver?
Two important components make up a Windows driver: a kernel service and a file on disk. However, monitoring for just .sys files on disk is not sufficient as third-party applications may load their own drivers from non-standard paths. Typically, drivers will be located under c:\windows\system32\drivers or C:\Windows\System32\DriverStore with the .sys file extension. During creation, the service part is usually installed as a KernelDriver type, although there are four types to be aware of: KernelDriver, FileSystemDriver, Win32OwnProcess, and Win32ShareProcess. For the purposes of this blog, we will focus only on kernel drivers. Additionally, it's important to note that Windows does not require drivers to have the .sys file extension; some third-party applications may use a different extension, such as .dll. These are all important factors to keep in mind.
Digital certificates are integral to Windows drivers. According to Microsoft, drivers must be signed in order to function properly. However, there are exceptions to this rule, such as the use of the test signing certificate or the Windows Driver Kit WDKTestCert. Unfortunately, some adversaries have exploited these vulnerabilities, as recently reported by CrowdStrike. Because drivers operate at the intersection of user and kernel mode, it is crucial that they are signed. In fact, the majority of vulnerable drivers are signed. Digital certificates can have a variety of states, including Signed, Unsigned, Expired, Bad Signature, Invalid Signature, Invalid Chain, Untrusted Root, or Explicit Distrust.
Digital certificates are used to verify the authenticity and integrity of a Windows driver. When a driver is signed with a digital certificate, it means that the certificate's private key has been used to create a digital signature for the driver's code. This signature can then be verified by Windows to ensure that the driver has not been tampered with by a malicious actor. If the signature is invalid, Windows will refuse to load the driver. By requiring drivers to be signed, Windows provides an additional layer of protection against malware and other security threats.
On the certificate state, a certificate that is "signed" means that it has been verified by a trusted authority and is considered to be legitimate. An "unsigned" certificate has not been verified by a trusted authority and is often associated with malicious or suspicious software. An "expired" certificate means that it is no longer valid and should not be trusted. A "bad signature" or "invalid signature" means that the certificate's digital signature does not match the expected value, indicating that the certificate may have been tampered with. An "invalid chain" means that the certificate was not issued by a trusted root authority, while an "untrusted root" means that the root authority is not trusted by the operating system. These different states can have significant implications for the security of a driver, and it is important to monitor and address any certificates with problematic states.
Not every instance of a driver is considered a vulnerable driver. As summed up by Microsoft, vulnerable or malicious drivers may fall into the following categories:
- Known security vulnerabilities that can be exploited by attackers to elevate privileges in the Windows kernel
- Malicious behaviors (malware) or certificates used to sign malware
- Behaviors that aren't malicious but circumvent the Windows Security Model and can be exploited by attackers to elevate privileges in the Windows kernel
Over time, adversaries have abused certificate authorities by signing their custom drivers to deliver malware. In 2022, Symantec uncovered an extreme case of this with the Daxin malware, which was described as “... without doubt the most advanced piece of malware Symantec researchers have seen used by a China-linked actor.” What made Daxin so special? To analyze the samples used by Daxin, the Splunk Threat Research Team (STRT) ran them through Sigcheck, and the resulting output provides valuable insights into the tactics, techniques, and procedures used by the attackers.
In some cases, unsigned drivers may still be loaded, particularly in organizations with older system setups that do not have the latest Windows operating system or sufficient prevention and granular control measures in place. While this may be less common today, it is still a possibility to keep in mind. It is important for organizations to take steps to prevent the loading of unsigned drivers and ensure that their systems are secure against this type of attack.
Where Do Digital Signatures Fit?
MITRE ATT&CK describes T1553.002, Subvert Trust Controls: Code Signing, as “Adversaries may create, acquire, or steal code signing materials to sign their malware or tools. Code signing provides a level of authenticity on a binary from the developer and a guarantee that the binary has not been tampered with.” In the industry, we have seen certificates stolen and abused time and time again. In March 2022, the ransomware group LAPSUS was reported to have stolen two code signing certificates from NVIDIA, and within the same timeframe it was reported by BleepingCompter that the certificates were now being used by malware to sign Quasar remote access trojan and to sign a Windows driver. This bought adversaries time to utilize the certificate to sign malicious software and get it past many controls.
Another approach adversaries take is to self sign the driver (or malicious software) and install a new certificate on the compromised endpoint. This approach is fairly noisy and not commonly performed as the adversary needs to add the certificate to the certificate store before installing the driver. This was recently seen in a CrowdStrike report, as mentioned before, related to SCATTERED SPIDER using stolen certificates and self-signed certificates.
Staying ahead of attacks involving signed malware and drivers is a complex challenge, and there is no simple solution. The intent of signed malware and drivers can be difficult to determine, making it even more challenging to detect and prevent them. However, having a comprehensive inventory of drivers in your environment can be helpful in understanding the potential risks. By monitoring and controlling the use of drivers, organizations can take steps to reduce the attack surface and protect against malicious actors.
The next section delves into the details of these drivers and explores some effective strategies for preventing them.
The focus of this blog is on known LOLDrivers, or Living Off The Land Drivers, or sometimes called BYOVD (bring your own vulnerable driver). While there is no centralized list of all known LOLDrivers, there are several lists available online that provide useful information. In total, there are 200+ known vulnerable drivers, some of which have been abused, many of which have been reported on, and some of which are unknown. To help teams review these drivers in one place, the Splunk Threat Research Team created a lookup that is related to the following analytic. Note that, based on the telemetry source, this lookup will need to be expanded to the specific vulnerable driver version as our example is based on file name only.
In addition to the lookup, LOLDrivers is a project recently introduced that provides an up-to-date list of vulnerable and malicious drivers in the wild. Within the project is a CSV, JSON, hash lists and Sigma rules that contain everything the project offers.
Microsoft Windows Mitigations
As previously mentioned, Microsoft has taken many steps to prevent drivers from loading. One of these is the Microsoft Recommended Driver Block List. This list is frequently updated by Microsoft. Beginning with the Windows 11 2022 update, the driver block list is enforced by default. In addition to Windows 11 prevent by default, Microsoft also recommends other Windows versions to use and enable HVCI (hypervisor-protected code integrity) and WDAC (Windows Defender Application Control). The full list of drivers on Microsoft’s block list may be found here. However, it's worth noting that not every malicious driver is included on Microsoft’s list.
In 2021, Rapid7 conducted research on the Dell dbutil_2_3.sys driver and identified it as vulnerable to CVE-2021-21551. Subsequent drivers, including dbutildrv2.sys versions 2.5 and 2.7 were found to have the same write-what-where condition. Dell has since released three unique signed drivers, but these drivers are still at risk of being abused. This poses a challenge for default deny or adding drivers to the Microsoft Driver Block List, especially since Dell systems are widely used and many endpoints may still be using the vulnerable versions unless the drivers are automatically updated. We'll discuss the importance of driver inventory in more detail later.
What drivers exist across your fleet of endpoints? What data sources will help you the most? Hunting for drivers can be extremely complex being that they are signed binaries in potentially legitimate locations. Typically, the metadata is filled in for legitimate ones and, as seen with Daxin malware, even malicious ones have metadata. As a defender, understanding the complexities of good and bad for a driver is complex. It’s not an easy answer each time. The questions that need to be asked are:
- Where did this driver come from?
- Does the metadata (signer, publisher, company name) all seem normal for the environment?
- When was it signed? In contrast, are really old drivers normal for the environment (due to third party applications)?
- What path does the driver reside in?
Understanding the metadata is extremely important in creating a baseline for organizations of any size. Having the proper metadata can provide better visibility into the signing state, path and potentially where a driver came from.
There are a few ways to gather the list of drivers across the fleet.
- Windows Registry - HKLM\SYSTEM\CurrentControlSet\Services Registry Tree
- PowerShell Cmdlet - Get-WindowsDriver -Online -All
- Sysmon EventID 6
Let’s check out what these three options provide us.
When a new driver is installed, a registry modification will occur under this path:
A few values will be created when a driver gets installed, and that is shown in the screenshot above. In theory, whenever a new driver gets installed, a new key and multiple values will be written to the registry.
We can loop through the registry using the following PowerShell command to determine drivers installed.
It’s not perfect, but it is one step closer to a simple inventory.
PowerShell natively provides a cmdlet - Get-WindowsDriver - that allows you to view all drivers installed. This cmdlet at first seems great, but it may be slow to run on systems with many drivers. During STRT testing, outputting to a CSV is not perfect, however some utilities may provide a better visual using this cmdlet.
Driverquery.exe is native on the Windows operating system and provides a very thorough listing and csv output of drivers installed.
driverquery /FO csv /v
The Splunk Threat Research Team found this output to be the most complete and easiest to import into Splunk and do something with. Utilizing the PowerShell script inputs, the STRT was able to easily run this command daily (or at any time frequency) to generate the output and import into Splunk. With some simple props and transforms, it allows for easy monitoring of drivers across an entire fleet, critical systems or targeted servers based on importance.
### # Modify cron schedule as you like. Default is once daily. # Modify index as needed. # We recommend this method over the other options provided. ### [powershell://DriverInventory] script = driverquery /FO csv /v schedule = 0 0 * * * #schedule = */5 * * * * sourcetype = PwSh:DriverInventory index=win
[PwSh:DriverInventory] REPORT-DriverQuery = REPORT-DriverQuery
[REPORT-DriverQuery] DELIMS = "," FIELDS = "ModuleName","DisplayName","Description","DriverType","StartMode","State","Status","AcceptStop","AcceptPause","PagedPool","Code","BSS","LinkDate","Path","Init"
This particular method is used in the STRT driver inventory analytic.
Sysmon EventID 6
Sysmon for Windows provides an EventID 6 that shares information about a driver being loaded on the endpoint. There is potential for this event to be voluminous if you have a large fleet that is moving drivers around a lot.
Below are two example configurations for Sysmon:
<!--SYSMON EVENT ID 6 : DRIVER LOADED INTO KERNEL [DriverLoad]--> <!--COMMENT: Because drivers with bugs can be used to escalate to kernel permissions, be extremely selective about what you exclude from monitoring. Low event volume, little incentive to exclude. [ https://attack.mitre.org/wiki/Technique/T1014 ] --> <!--TECHNICAL: Sysmon will check the signing certificate revocation status of any driver you don't exclude.--> <!--DATA: UtcTime, ImageLoaded, Hashes, Signed, Signature, SignatureStatus--> <RuleGroup name="" groupRelation="or"> <DriverLoad onmatch="exclude"> <Signature condition="contains">microsoft</Signature> <!--Exclude signed Microsoft drivers--> <Signature condition="contains">windows</Signature> <!--Exclude signed Microsoft drivers--> <Signature condition="begin with">Intel </Signature> <!--Exclude signed Intel drivers--> </DriverLoad> </RuleGroup>
Olaf Hartong’s Sysmon Modular provides a few options, one for additional MDE visibility and another with excludes:
<!-- Event ID 6 == Driver Loaded - Sysmon will not provide notable additional visibility over MDE. --> <RuleGroup groupRelation="or"> <DriverLoad onmatch="include" /> </RuleGroup>
<!-- Event ID 6 == Driver Loaded - Excludes --> <RuleGroup groupRelation="or"> <!--Default to log all and exclude only valid signed Microsoft or Intel drivers--> <DriverLoad onmatch="exclude"> <Rule groupRelation="and"> <Signature condition="begin with">Intel </Signature> <SignatureStatus condition="is">Valid</SignatureStatus> </Rule> <Rule groupRelation="and"> <Signature condition="contains">Microsoft</Signature> <SignatureStatus condition="is">Valid</SignatureStatus> </Rule> </DriverLoad> </RuleGroup>
Below is a screenshot highlighting what a lot of data looks like from EventID 6:
While it may seem beneficial to have all Microsoft or Intel drivers collected, doing so can generate a significant amount of noise. Fortunately, filtering can help to streamline the process. Collecting drivers on endpoint devices using Sysmon EventID 6 can be a great complementary approach to driver collection, providing additional visibility and reducing noise.
EDR / Application Control Products
Most EDR products will collect a set of binaries on disk to either be analyzed remotely or hash checked by third party service providers; this will definitely help with validating known knowns and having a central collection.
Below are a few hunting queries that the STRT has found to be popular, which include looking for drivers by path and signing information.
Queries for Carbon Black Response
observed_filename:c:\windows\system32\drivers\ observed_filename:c:\windows\system32\drivers\ digsig_result:"Explicit Distrust" (observed_filename:"c:\windows\system32\" OR observed_filename:"c:\windows\syswow64\") .sys (observed_filename:"c:\windows\syswow64\drivers") .sys (observed_filename:"c:\windows\system32\drivers\") .sys digsig_sign_time:[* TO 2015-10-01T23:59:59] process_name:ntoskrnl.exe (digsig_result_modload:"Unsigned" OR digsig_result_modload:"Explicit\ Distrust")
Depending on the product, binary data may be in a separate index. Another great place to focus on is where kernel drivers load - NTOSkrnl.exe. If you focus your query on the module loads (image loads) into NTOSKrnl.exe, you will see drivers being loaded. An example query may look like:
process_name=ntoskrnl.exe | stats count by ImageLoaded
That is if all image loads are being collected (high volume / low reward). With an EDR product, it should be simple enough to drill down by ntoskrnl.exe and view by endpoint. If the product allows, it may be possible to drill down by signature status of the module itself, which can yield great results of suspicious drivers being loaded.
In addition, products that perform application control (default deny for example) do perform an inventory of all system files on disk before moving to a high enforcement. These products are great source of truth when diving into drivers or modules on endpoints.
Now that we've covered LOLDrivers, methods for blocking them, and explored ways to perform driver inventory, it's time to turn our attention to atomic testing. One valuable resource for defenders is the Atomic Red Team project, which offers a range of testing scenarios for various security controls. By leveraging this project, defenders can assess the effectiveness of their controls and identify potential areas for improvement.
Atomic Red Team
There is one Atomic test (test number 2) that showcases how to create a new service. Under MITRE ATT&CK technique T1543.003, we can simulate the addition of a service with sc.exe.
The following Atomic test will create a new service with service control, sc.exe, and attempt to start the service.
The STRT modified the Atomic to allow for the service type to be added and committed back to Atomic Red Team. There are 4 main service types - Own (default), Kernel, FileSystem and Share.
STRT test example using -promptforinputargs
Now our driver, mimidrv.sys, is running!
Want to take your detection development further? Check out AtomicTestHarnesses ServiceInstaller here.
Testing with the Atomic Red Team project is designed to address critical questions specific to your environment. For example, testing can help to determine whether you would be able to detect a new driver that lands in your fleet, what drivers are considered normal, and where a new driver came from. By validating these questions, defenders can gain a better understanding of the efficacy of their controls and develop strategies for improving their security posture.
- Windows security event log: Windows provides great visibility into a new service being created or whenever a new kernel driver is installed. Windows EventID 6 and EventID 7045.
- DriverQuery inputs: With our new inputs, this will allow for inventorying drivers across the fleet that have the Splunk Universal Forwarder installed.
- Sysmon EventID 6 - Driver Load: EventID 6 from Sysmon generates any time a new driver is installed.
This search looks for arguments to sc.exe indicating the creation or modification of a Windows service.
This search identifies drivers being loaded across the fleet. This query relies upon a PowerShell script input to be deployed to critical systems and beyond. If capturing all via the input, this will provide retrospection into drivers persisting. Note that this is not perfect across a large fleet. Modify the query as needed to view the data differently.
This analytic uses Windows EventCode 7045 to identify new Kernel Mode Drivers being loaded in Windows from a non-standard path. Note that adversaries may move malicious or vulnerable drivers into these paths and load up. The idea is that this analytic provides visibility into drivers loading in non-standard file paths.
This analytic assists with viewing all drivers being loaded by using Sysmon EventCode 6 (Driver Load). Sysmon provides some simple fields to assist with identifying suspicious drivers. Use this analytic to look at prevalence of driver (count), path of driver, signature status and hash. Review these fields with scrutiny until the ability to prove the driver is legitimate and has a purpose in the environment.
This analytic identifies installation of a root CA certificate by monitoring the registry. The base paths may be found here. In short, there are specific certificate registry paths that will be written to (SetValue) when a new certificate is added. The high-fidelity events to pay attention to are SetValue events where the TargetObject property ends with "<THUMBPRINT_VALUE>\Blob" as this indicates the direct installation or modification of a root certificate binary blob. The other high fidelity reference will be which process is making the registry modifications. There are very few processes that modify these day-to-day. Therefore, monitoring for all provides a great beginning.
This analytic identifies a new kernel driver being added to Windows using sc.exe. Adding a kernel driver is not common day-to-day and should be investigated to further understand the source.
This hunting analytic will assist with identifying new .sys files introduced in the environment. This query is meant to identify .sys files created on disk. There will be noise, but reducing common process names or applications should help to limit any volume. The idea is to identify new .sys files written to disk and identify them before they're added as a new kernel mode driver.
This analytic utilizes a known list of vulnerable Windows drivers to help defenders find potential persistence or privilege escalation via a vulnerable driver. This analytic uses Sysmon EventCode 6, driver loading. A known gap with this lookup is that it does not use the hash or known signer of the vulnerable driver. Therefore, it is up to the defender to identify version and signing info and confirm it is a vulnerable driver.
Check out the Windows Driver Analytic Story created to help you get started.
Why does this matter?
In today's threat landscape, malicious actors are increasingly leveraging signed drivers and other legitimate tools to evade detection and carry out attacks. This presents a significant challenge for defenders who must navigate the complexities of distinguishing between good and bad drivers. By identifying and blocking known vulnerable drivers, implementing effective driver inventory practices, and testing security controls with tools like the Atomic Red Team project, defenders can improve their ability to detect and prevent attacks involving malicious drivers. These strategies are essential for maintaining a strong security posture and protecting against evolving threats.
Any feedback or requests? Feel free to put in an issue on GitHub and we’ll follow up. Alternatively, join us on the Slack channel #security-research. Follow these instructions if you need an invitation to our Splunk user groups on Slack.
We would like to thank the following for their contributions to this post: Teoderick Contrera, Michael Haag, Mauricio Velazco, Rod Soto, Jose Hernandez, Patrick Barreiss, Lou Stella, Bhavin Patel and Eric McGinnis.