Did you know that a completely legitimate driver can give an attacker the opportunity to register in your system for a long time, remaining inside even after reinstalling it? Or turn your computer into a brick? For example, some seemingly harmless trusted (signed) drivers are incidentally tools for overwriting the BIOS. After such an attack, only the programmer will save.
In Windows, there are trusted applications / scripts / libraries with additional
interesting dangerous functionality like executing arbitrary code, downloading files, bypassing UAC, etc. If such additional functionality is found in a kernel component, it becomes even more interesting.
Starting with Windows Vista x64, the Driver Signature Enforcement (DSE) policy applies – all kernel-level drivers must be signed. If an attacker (with user / administrator rights) after penetrating the system wants to get the maximum level of access (install kernel rootkit / bootkit / SMM-rootkit / BIOS-rootkit), he will have to somehow bypass the signature requirement for the driver. The ability to call some functions or instructions from kernel mode in kernel mode can give an attacker a tool to elevate privileges, disclose information or cause a denial of service. We call this functionality a dual-purpose functionality (in some cases, this may be called vulnerabilities or backdoors, however, the discussion on the correct definition is beyond the scope of this article).
Let's look at what options an attacker generally has to bypass DSE (you must somehow penetrate ring0). The table below summarizes the ways to bypass DSE with their advantages and disadvantages (for the attacker, and security guards take note). It is worth noting that this information applies to Windows x64, starting with Vista.
|Setting Boot Configuration Data (Test Mode)||Simplicity|
|Using a compromised private key||Ability to install any driver|
|Using Vulnerability in Implementing DSE Control||Not detected by Windows antivirus and security systems|
|Modification of driver checking mechanisms (bootmgr, winload.exe, winresume.exe, ci.dll)||Ability to install any driver without OC checks|
|Using a signed driver with vulnerability||Attack detection difficulty|
|Using a signed driver with dual-purpose functionality||Not detected by Windows antivirus and security systems|
As you can see from the table, a signed driver with dual-purpose functionality is the most attractive way to bypass DSE for an attacker.
Dangerous or dual purpose functionality
Let's look at examples of malicious capabilities that an attacker appears in the presence of a driver with dangerous dual-purpose functions.
- Privilege escalation to admin level / SYSTEM. Read / write physical memory required. This attack can be accomplished, for example, using the ASMMAP driver from ASUS. To do this, read the physical memory and find the EPROCESS structure (it is an element of a linked list), then go through the list in search of the process whose privilege level we want to increase, as well as some well-known process with the SYSTEM level (for example, lsass, wininit). Then copy the value of the Token field of the system process structure to the structure of the target process. A more detailed description of the attack is given here.
- Disabling SMEP. To do this, you need to write to the control register cr4 (more precisely, reset its 20th bit). For example, the bandainamcoonline.sys driver not only disables SMEP, but also helpfully executes the code according to the pointer passed to it from the user. For those interested, there is an article with a detailed description of the driver.
Execution of arbitrary code in kernel mode. Read / write physical memory and MSR required. The point is to replace the address (located in one of the MSRs), to which the transition will be made when making a system call, to the address of the location of the attacker code. Here you can find more information about this. PatchGuard will interfere along the way, but you can figure it out if you wish.
Since the driver and PatchGuard both run in Ring 0, nothing prevents the driver from disabling PatchGuard checks (until, of course, until Microsoft listens to Intel and goes beyond the model with two protection rings). The kernel developers at Microsoft are well aware of this fact and perform various actions to hide the location of this code, obfuscate its actions and the internal structures used. In other words, because of the inability to prevent you from modifying the PatchGuard code, they try their best to hide it.
– Blunden B. The Rootkit arsenal: Escape and evasion in the dark corners of the system.Original
Given that driver code and PatchGuard code both execute in Ring 0, there's nothing to prevent a KMD from disabling PatchGuard checks (unless, of course, Microsoft takes a cue from Intel and moves beyond a two-ring privilege model). The kernel engineers at Microsoft are acutely aware of this fact and perform all sorts of programming acrobatics to obfuscate where the code resides, what it does, and the internal data-structures that it manipulates. In other words, they can't keep you from modifying PatchGuard code, so they're going to try like hell to hide it.
– Blunden B. The Rootkit arsenal: Escape and evasion in the dark corners of the system.
- BIOS entry. An example in the wild is Lojax. Attackers took the well-known RwDrv.sys and used it for their dirty purposes: they read the BIOS, modified and wrote back. Reinstalling Windows will not help here, since the malicious code sits in the firmware on SPI-flash. If the BIOS overwrite is unsuccessful (or specially overwritten), then it will also be unpleasant. In any case, you will have to drive for the programmer to fix the annoying consequences.
- Call SMI handler. Firstly, not all BIOS’s are equally defenseless against code in ring0 mode: there are various mechanisms for reading / writing protection, so there may be a situation where you need to go lower — into SMM mode (the most privileged). One way to get there from kernel mode is to pull the SMI handler (quite often there are vulnerable ones among them). To call the SMI handler, you must be able to write to the I / O port, and this can only be done with ring0 privileges. That is, a driver with the ability to write to I / O ports is able to detect a vulnerable SMI handler that can allow an attacker to execute code in SMM mode. In the example, the author uses the RwDrv.sys driver.
- Information about the system. Reading kernel memory (through reading physical memory), reading BIOS, information about system settings, connected devices and enabled / disabled protection mechanisms (through reading MSR, control registers, access to input / output ports), in some cases, a known hypervisor can be detected ( like VirtualBox via MSR). For this task, even a driver that can only read, not necessarily write, is most often suitable. For example, RamCaptureDriver64.sys from Belkasoft is suitable for reading physical memory.
If we analyze various articles and notes about CVE, we can distinguish some classification of potentially dangerous functions when accessing from ring3 functions in drivers. The table below lists the hazardous functions and sources of information about them.
Identified Hazardous Functions Sources of information on security practices Read / write MSR registers CVE-2018-10711, CVE-2018-18535, CVE-2018-19323, CVE-2007-5633, CVE-2007-5761 Read / Write I / O Ports CVE-2018-10712, CVE-2018-18536, CVE-2018-19322 Read / Write Physical Memory CVE-2018-16712, CVE-2018-10710, CVE-2017-15302, CVE-2017-15303, CVE-2018-19321 Read / write control registers CVE-2018-10709, Eset – Windows exploitation in 2016 Access Performance / Clock Counters Leif Uhsadel, Andy Georges, Ingrid Verbauwhed – Exploiting Hardware Performance Counters Read / write flag register Wojtczuk R., Rutkowska J. Following the White Rabbit: Software attacks against Intel VT-d technolog Cache access instructions Cache-Based Side-Channel Attacks Detection through Intel Cache Monitoring Technology and Hardware Performance Counters
And this is not the whole list of possible dangerous functions. You can also talk about reading / writing kernel virtual memory, reading / writing MMIO, access to PCI devices, etc.
The first three functions are of the greatest interest, as well as the greatest danger (and the most likely to detect a driver with such functions): read / write MSR registers, read / write I / O ports, read / write physical memory. Using control registers, you can bypass some protection mechanisms, writing to the flag register allows you to enable read / write input / output ports in ring3 (by the way, it is mentioned in this article on Habré), the success of attacks on third-party channels (by accessing the cache, monitoring counters performance / cycles) is most likely unlikely.
In the process of creating this material at the DEFCON 27 conference in Las Vegas, researchers Jesse Michael and Mickey Shkatov presented the work “Get off the kernel if you cant drive”, which also discusses this problem, and we recommend that you study this material to complete the picture. The scenarios for using such drivers are very simple and clear, and examples of code sections responsible for the most critical functionality are presented. And also provides code for working and finding similar drivers.
In general, it is worth noting that this topic has long been concerned about security researchers. Back in 2018, researcher Alexander Matrosov in his article "What makes OS drivers dangerous for BIOS?" raised this question and demonstrated how simple it is to exploit BIOS.
Below are the most famous representatives of drivers with dual-purpose functions.
RwDrv.sys is a very popular driver (comes with the RWeverything utility). Reads and writes physical memory, I / O ports, MSR and control registers. It was repeatedly used in different PoC’s, and then in the previously mentioned Lojax rootkit. An interface is written for it in C ++, and it is also used in chipsec.
cpuz / gpuz