Binarly Research Team
In our previous blog, we discussed post-exploitation impact from firmware vulnerabilities which can lead to long-time persistence on the device. A firmware implant is the ultimate goal for an attacker to obtain persistence. An attacker can install the malicious implant on different levels of the firmware, either as a modified legitimate module or a standalone driver. The impact of targeting unprivileged non-SMM DXE runtime drivers or applications by a threat actor is often underestimated. This kind of malicious DXE driver can bypass Secure Boot and influence further boot stages. All these firmware threats have been discovered only after many years of being deployed in the wild.
Name of Implant | Implanted Module | Year of Discovery |
DXE Runtime Driver | 2022 | |
DXE Runtime Application | 2022 | |
EFI Bootloader (bootmgfw.efi) | 2021 | |
EFI Bootloader (bootmgfw.efi) | 2021 | |
DXE Runtime Application | 2020 | |
DXE Runtime Application | 2018 | |
DXE Runtime Application | 2015 |
When it comes to detecting firmware threats, the industry is just scratching the surface. Current discoveries reveal that threat actors have been stealthy operating since 2015 or even earlier. The majority of these techniques are outdated and won't work on modern devices with recent updates on the operating system level. In our research for Black Hat 2022, we continued to demonstrate the reality and weak spots in modern endpoint solutions.
In our previous chapter (“Design Issues Of Modern EDRs: Bypassing ETW-Based Solutions”) about blinding ETW-based EDR solutions, we explored some of the design problems. However, in our new research we dive deeper into how we can blind security orchestration and event management solutions (SIEM’s) over attacks on WMI.
Windows Management Instrumentation (WMI)
It’s important for security solution architects to understand the risks of relying on an infrastructure such as Windows Management Instrumentation (WMI) to collect device telemetry data. Raising awareness of attacks that disable WMI will allow solutions engineers to find suitable integrations that have protection mechanisms against tampering to disrupt normal operations.
Windows Management Instrumentation provides functionality to manage Windows enterprise devices both locally and remotely. Various tools (for example, SIEM and EDR solutions) leverage WMI for performance monitoring and gathering device telemetry. However, attacks on this Windows built-in technology can blind a whole class of security solutions that rely on such telemetry to detect malicious behavior or correlate with other endpoint signals.
Last year, at Black Hat Europe, Binarly presented a deep-dive into attacks on Event Tracing for Windows (ETW), a Windows technology that was initially designed and implemented as a logging mechanism to observe and analyze application behavior. Endpoint security solutions rely on ETW as another source of information to detect malicious behavior above the Operating System level. During that talk, Binarly demonstrated two new attacks on ETW that blinded both Process Monitor (procmon) and Windows Defender.
This year, we turned our attention to WMI, another highly leveraged Windows infrastructure by various tools and endpoint security solutions, and showcased different attack vectors to disable WMI, mostly leveraging the one-bit change method from user mode.
Researching ways to disable WMI is important given that these types of attacks can blind an entire class of security solutions, but even more important is developing ways to detect if the WMI has been tampered with and notify on such an event. During our Black Hat presentation, WMICheck and MemoryRanger were introduced, two solutions that can detect and prevent attacks that disable WMI.
Windows Management Instrumentation (WMI) Architecture
Windows Management Infrastructure is a built-in Windows mechanism designed to collect and transmit information related to many components in an enterprise such as running processes and services, registry keys, file system information, endpoint security, etc. WMI is the Windows implementation of two standards: Web-based Enterprise Management (WBEM) and Common Information Model (CIM).
Some of the advantages of relying on WMI for device telemetry data include:
- System-wide availability by default, in all Windows Operating System starting with Windows NT 4.0
- Supports a standardized framework to produce and consume device events via COM interfaces
- WMI events cover almost all Operating System events
- Provides the ability to register permanent event subscriptions to associate an action with an WMI event
The WMI implementation consists of the following components:
- Providers – implemented as COM based DLLs that produce device telemetry as WMI Objects (i.e. WMI class instances)
- Clients – consumers that use the WMI data to obtain the device telemetry. PowerShell represents an easily accessible tool to obtain WMI telemetry both locally & remotely.
- CIM Standard – implements the structuring, querying and transmitting the WMI data
- Repository – keeps the namespace and class definitions, as well as the persistent WMI objects
- MOF – Managed Object Format, an Object-Oriented language to specify WMI artifacts and extend the standard
- WQL – SQL-like query language to filter events
- WinRM and DCOM are leveraged to remotely connect to transmit or receive WMI data
- WMI Service – implemented as a Svchost DLL based service in the netsvcs Group named Winmgmt
Permanent Event Subscription
To implement permanent event subscription via WMI the following steps are required:
- Specify the triggering event by creating an event filter instance
- Describe the action to be performed via an event consumer when the event filter fires
- Link the trigger to its corresponding action in a binding instance
As an example, we can leverage the permanent event subscription to monitor and notify when a new service is installed.
The three steps required to implement such monitoring are:
- Install an event filter to query for any instance creation event, at a polling interval, where the target instance is a service.
- Specify the action via an event consumer to populate the EventLog with a notification whenever a new service is installed.
- Link the trigger to the action to be performed by binding the event filter to the corresponding consumer.
CIM Repository
This repository is the WMI database that stores the namespace and class definitions together with their qualifiers and properties, as well as the persistent WMI class instances or objects. Its location can be read from the registry (HKLM\SOFTWARE\Microsoft\Wbem).
The database consists of three types of files:
index.btr
– file storing the WMI index as a B-tree, organized in index records, stored in pages, and containing the search stringsobjects.data
– containing the WMI namespace and class definitions as well as the persistent objects organized in records, stored in pages- Three versioned
mapping.map
files – containing the mapping records to translate logical page numbers to physical page numbers for bothobjects.data
andindex.btr
To dig deeper into the forensic format of the CIM repository, the search string is constructed by concatenating the identifier of the namespace, of the class and of the instance representing the path of the instance:
NS_<namespaceID>\CI_<classID>\IL_<instanceID>
The string is searched in the B-tree in index.btr
and the index record identified. The index record contains the WMI object.data
instance record location information (logical page number and the record identifier) and its size.
Next, the mapping file is used to convert the logical page number into its corresponding physical page number. The mapping file consists of two arrays of 32-bit values, one corresponding to objects.data
translation and the other to the index.btr
. The index in the array represents the logical page number, and the value of the array at that index represents its corresponding physical page.
The physical page number gives us the location in the objects.data
file where the corresponding record is located; the record identifier in the index record is used to search through the records in the objects.data
page and pinpoint the WMI object data. To validate further that the searched instance is correctly identified, the size of the record in objects.data
should match the size found in the index record.
The same approach is used to parse the B-tree in the index file, since the pointers to the next nodes in the tree are represented as logical page numbers.
WMI and Firmware
Using the described forensic approach, we can parse any WMI Repository and discover what data is stored in it. Performing such an exercise on a Lenovo system, we identified, in the ROOT\wmi
namespace, several interesting classes starting with the Lenovo_
prefix related to the system BIOS, such as Lenovo_BiosSetting
, Lenovo_SetBiosSetting
or Lenovo_SetBiosPassword
.
Looking at the properties of the Lenovo_BiosSetting
, the CurrentSetting
property of type string
piqued our interest. Searching for instances of this class in the CIM Repository returns empty results, which means this data is not persistent, and it is produced by a specific WMI provider deployed by the OEM vendor.
Using PS and querying for non-empty instances of the Lenovo_BiosSetting
class, we get the following output for the CurrentSetting
property. Magnifying these results we find some interesting settings related to trusted execution, TPM, BIOS update.
The OEM vendor provides an interface, below the OS, so that the custom WMI Provider can interact with the firmware to be able to read and alter those settings from userland via instances of Lenovo_BIOSSetting
and Lenovo_SetBIOSSetting
classes.
The CIM standard contains the Win32_Bios
class to obtain information about the system BIOS version, OEM vendor and its serial number. An instance of the Win32_Bios
is presented below:
Attackers leverage WMI to do evil
WMI is offering great visibility at the device level, including firmware telemetry, to any endpoint security solution. For attackers, it is a great living-off-the-land infrastructure to perform malicious actions. Attackers can leverage WMI in a multitude of ways:
- Reconnaissance - get information about the OS and installed patches, file system, processes, services, etc.
- Antivirus Detection - understanding the level of security by gathering information about the installed endpoint security solution
- Fileless Persistence - obtaining persistence via __EventFilter and __EventConsumer binding
- Code Execution - triggering code execution via Win32_Process::Create, ActiveScriptEventConsumer or CommandLineEventConsumer
- Lateral Movement - remotely creating a WMI class to transfer data
- Data Storage - storing data encoded in string properties of custom classes
- C2 communication - remotely create/modify a class to store/retrieve data.
Attacks on WMI to blind Security Solutions
Attacks on WMI have existed for decades, since it has not been designed with security first in mind - WMI’s main purpose is to provide device telemetry data. For exactly this reason, WMI service doesn’t have any protection features, it is not considered a critical service.
The attacks that will be presented next, run in user-mode with the same privilege level as the WMI service, are based on WMI design and cannot be fixed with a simple code update.
Now let's introduce a WMI threat model and its attack vectors. Later, we will present a template of an attack on WMI internal data.
The main WMI components of the Threat Model are:
- WMI Service process that communicates with providers and consumer clients via Advanced Local Procedure Calls (ALPC) channels
- WMI files on the disk and configuration in the registry
- WMI data in service runtime memory (global variables, pointers to objects and their members)
The attacks on WMI are divided into five buckets, each one represented by a different color. We will focus on WMI attacks on data inside the WMI service process and introduce several new internal objects that, if modified, can disable the WMI ecosystem.
Attacks on WMI-related files and registry configuration
Attackers can modify the content, remove values as well as restricting access to objects related to WMI:
- Binary files on the disk:
- user-mode and kernel-mode providers;
- repository files, which are the heart of WMI.
- WMI-related data in the registry:
- Configuration of installed WMI service;
- WMI internal flags and other data.
As an example of an attack on WMI internal flags in the registry, let’s look at the EnableEvents
registry value:
When a new WMI client makes a connection request, the following call stack is executed. The pseudocode of the InitESS()
WMI internal function to initialize the WMI event sub-system is presented below.
In the InitESS()
function the EnableEvents
registry value is read and if its value is 1 then the pointer to the Event Sub-System interface is retrieved and success returned. An attacker can modify the EnableEvents
registry value to set it to a value different from 1 and restart the WMI service. As a result, the Event Sub-System is not initialized and any WMI client won’t receive events any longer.
Template of an attack on WMI data
The code snippet below shows a typical code pattern encountered in many DLLs from the WMI infrastructure. Additionally, the runtime memory content is also displayed. After the DLL is loaded in the address space of the WMI service, a global_Flag
variable is set to its default value 0 (false
). After the initialization function or constructor is called, the global_Flag
is set to its initialization value 1 (true
). When a new connection request is received, the dispatch routine is called and the global_Flag
is checked to either establish the connection and install a new event filter or to execute the error branch.
An attacker can patch the global_Flag
variable and toggle its value so that the error branch is executed, causing the event to be dropped and an error code to be returned.
This attack template can be applied to the following WMI internal flags from different DLLs loaded in the WMI service address space:
The error codes returned by each attack against the WMI infrastructure are detailed below:
DLL Name | Internal Function | Internal Flag | Error Description |
wbemcore | EnsureInitialized() | g_bDontAllowNewConnections | Any attempt to connect to WMI fails with error code 0x80080008 (CO_E_SERVER_STOPPING) |
CCoreServices::DeliverIntrinsicEvent() | EventDelivery | All intrinsic events are disabled. | |
CWbemNamespace::ExecNotficationQueryAsync() | g_pEss_m4m_pEseSession | Client Consumers fail to install callback - error code 0x8004100C (WBEM_E_NOT_SUPPORTED) | |
repdrvfs | More than 50 internal calls | g_bShuttingDown | New connect requests to WMI fails with error code: 0x8004100A (WBEM_E_CRITICAL_ERROR) Registered callback routines return error code: 0x80041032 (WBEM_E_CALL_CANCELLED ) |
CSession::PutObject() | g_Glob+0x00 | All attempts to add Event Filter fail error code 0x80041014 ( WBEM_E_INITIALIZATION_FAILURE) | |
CSession::PutObject() | g_Glob+0x38 | All attempts to add Event Filter fail error code 0x80041014 ( WBEM_E_INITIALIZATION_FAILURE) | |
CNamespaceHandle::FileToInstance() | g_Glob+0xBC | New client connections to WMI fail with error code 0x80041033 (WBEM_E_SHUTTING_DOWN)Already connected clients fail to interact with WMI, error code 0x80041010 (WBEM_E_INVALID_CLASS) |
A demonstration of the attack on the g_bDontAllowNewConnections
in wbemcore.dll can be found in the Binarly’s Youtube channel.
Introducing Binarly’s WMICheck, a tool that detects attacks on WMI data
WMICheck is a freeware tool developed to detect attacks on WMI data by reading and parsing WMI internal objects from a running system’s memory. WMICheck can scan the memory of a specified process or the whole system memory for WMI artifacts. It includes a user-mode console app and a kernel-mode driver, and supports a multitude of command-line options.
The next demo in Binarly’s Youtube channel shows how WMICheck is used to reveal the attack on the DontAllowNewConnections
flag.
Another demo presented during the BlackHat US 2022 talk shows the attack and its detection on the EventDelivery
internal flag in wbemcore.dll.
Sandboxing of the WMI Service
WMI service interacts with WMI providers and client consumers via Advanced Local Procedure Calls (ALPC) channels. Furthermore, WMI service accesses the filesystem and registry.
Another way of attacking WMI is to isolate the WMI service from the rest of the Operating System by:
- Isolating the WMI service from filesystem and registry by downgrading its Integrity Level of the WMI Service process to the Untrusted Level.
- Preventing WMI service from accessing ALPC channels by revoking its SeImpersonatePrivilege privilege.
This attack can be performed both from user-mode using certain APIs or from the kernel via a DKOM (Direct Kernel Object Manipulation) attack. See details below:
Memory Ranger is an open-source project that can be easily customized to prevent new attacks on the Windows kernel, including the WMI service sandboxing via DKOM attack. It can trap the loading of the attacker’s driver and allocates a separate memory enclave for this driver. As a result, the attacker’s driver is executed inside its own enclave, where any access to the WMI Token structure is restricted.
Conclusion
The endpoint security solution at the operating system level is a very important piece of the infrastructure of modern enterprises, but it isn’t a silver bullet and, as we demonstrated, it contains design problems which are hard to fix in a general way. We are frequently facing the same question about whether the endpoint solution will stop a second-stage exploit with firmware implant delivery payload. Unfortunately, the answer is not a positive one.
WMI infrastructure is both leveraged by defenders and attackers since it offers great visibility at the device level including the firmware. Security solutions should leverage this information as another data point in the decision making process and should not unilaterally rely on this telemetry to detect malicious behavior. The criticality of these attacks should be measured from case to case depending on the weight the WMI data point has in the decision making process that particular OS events describe a potential malicious activity.
Since the WMI service doesn’t have any protection mechanisms, WMI event delivery can easily be disabled by attackers without triggering any security alert thus breaking the defense mechanism that relies on such telemetry. All the attacks presented in the Black Hat talk have been carried out from user-land, most of them following the one-bit change attack template.
These attack vectors can originate in the firmware - a big blind spot for the endpoint security - to achieve persistence across different versions of Windows and survive OS reinstallations. Publicly known firmware threats, introduced earlier, have persisted for more than five years without being detected by the endpoint security solutions which gave attackers plenty of time to influence the device telemetry coming from multiple data points, including WMI.
Through the ETW and WMI pieces of research and BlackHat talks, the Binarly mission was to raise awareness of the security community not to blindly rely on technologies that can easily be disabled by an attacker as they have not been designed and implemented with security first in mind.