Blasting Event-Driven Cornucopia: WMI-based User-Space Attacks Blind SIEMs and EDRs: this mp4 audio file was automatically transcribed by Sonix with the best speech-to-text algorithms. This transcript may contain errors.
Claudiu Teodorescu:
So, Claudiu Teodorescu, I presenting the Binarly and very happy to be here. Good morning, everybody. It will be a short presentation of WMI. I'll go over some of the information that I presented at Black Hat 2022 and then add two new attacks presented only at this conference.
Claudiu Teodorescu:
So who is Binarly? So Binarly a startup in LA focused on device security and monitoring threats below the operating system and see how they're moving up the stack into the operating system kernel and user land and then deploy their next level components. Unfortunately, Andrei and Igor, which contributed to this research, could not make the trip to LABScon. But I'll take the credit for them and then maybe have a drink when we first meet in person.
So let's go a little bit into the agenda. So I'll present a little touch, a little bit brief on the architecture and features of WMI. Just a primer for for people that are not familiar with WMI. And also show some artifacts, forensic artifacts that I was deeply involved while reversing the format five, six, seven years ago. Then I'll show how WMI is leveraged for formal policy orchestration. And next one moving into actually the meat of the discussion on attacks on WMI, how WMI is leveraged for evil, how that will present a threat model WMI threat model and the different attack vectors. And then we'll move to present the two new attacks that I already advertised.
Claudiu Teodorescu:
So WMI architecture, it's a pretty comprehensive image. But in short, WMI is the Windows implementation of two standards WBEM, which is web based enterprise management and the CIM, which is a common information model. It's available systemwide in all operating systems and doesn't have to be installed, and it offers a standardized framework to produce and consume events that are represented as WMI objects.
And in short, the architecture consists of the producers, WMI producers, which produce device telemetry as WMI objects, clients that consume those devices do those events to get device telemetry. One good example is PowerShell, which can be used to gather this type of telemetry both remotely and locally. Next is the CIM standard, the Common Common Information Module standard, which consists of the repository itself that stores the class definitions and namespace definitions as well as persistent WMI objects. Then we have the MOF, which is an object oriented language used to specify WMI artifacts to extend the frame the the standard. Next we have the query language, which is the WQL. It's a SQL like query to filter events and DICOM and and when a RAM are used to remotely connect, to transmit and receive data. And last but not least, not the least is the WMI service, which is implemented as the services host DLL service in the Net VCS Group.
WMI providers. We already touched on this. Just a little reminder, it's an instance of __Win32 provider, which is a standard class since providers are implemented as common com based the DLLs. That identifiable class ID and all the information of the column is in the interfaces, is in the registry, and the Windows 11 are more than 4000 built in WMI providers.
So one of the main ability of WMI is to act on events that cover pretty much any operating system event. And another ability that is very is used by in the wild by attackers is the ability to to register permanent event subscriptions which survive system reboots. We'll see an example of that.
There are two types of events intrinsic events and existing events. I left here the definition of both for future reference. Now event filters specify which events should be should be transmitted to the bound consumer to act on those. The main the main properties of of of event filter is the namespace in which it operates the query language that is used mostly the WQL and the last but not the least is the the query itself that specify how to filter the events and send it to the bound consumer. And here we have the syntax, the general syntax of WQL for, for a for filtering. And then two examples. One is the first is the intrinsic event example that triggers whenever, notepad.exe is launched. The other one is an example of extrinsic event which monitors the run key for registry key for malware persistence.
And now we talk about the consumers. So the consumer specify the action that should be taken when when an event filter triggers. And as we can see that the the standard defines already five or six default consumers to log files, to log events, to run scripts or command lines or send notifications. And let's go a little bit more into detail. I mentioned the persistence, the permanent event subscription that's that's actually done for persistence and code execution is the method. How you do it and how you do it is just define the filter, which specify which event to trigger the action that is defined by the by the event consumer and then binding bind them into an instance of filter to consumer binding.
So now let's talk a little bit about the repository. So repository is the WMI repository. It's a path and files can be found in the registry and consists of three types of files. First is the INDEX.BTR, which is the index file for the for the WMI repository implemented as a B-Tree on disk and stores the the search path strings in pages. Then is OBJECTS.DATA which consists actually the the which contains actually the namespace definitions, class definitions and persistent WMI objects. And then again stored in pages and consisting of records.
Claudiu Teodorescu:
And then the last not the least is the historic versioning of three three historic versions of mapping.map, which contains the mapping records. Because in in WMI there is abstraction logic to to physical logic, page number to physical page number. So the mappings are used to actually translate the logical page number to its physical correspondent.
So let's look in in practice how this will should work. So we have the INDEX.BTR. First we need to create the search path string for the WMI object that we're looking for so that how it's done, you get the identifier for the namespace class, an instance name, you concatenate them using some prefixes that are there mention and then the index that is search for that for that path string. And then the index record is identified. And what's important in that, the first the first number is the logical page number of the record we are looking for in OBJECT.DATA file. Then the other one is the record identifier, and the third one is the the size of the record. So in order to do the translation, to find out where the physical offset is, we have to use the the mapping map, which actually consists of two arrays of Dwords, one for OBJECT.DATA, the other one for INDEX.BTR and how it works. The logical number actually represents the index in the array. The value of that index is the corresponding physical page number.
The same thing the same algorithm can be used for for parsing the INDEX.BTR, it's a B-Tree on disk, as I said. So they are the format is using a logical page number for the pointers to the next next nodes in the in the tree.
And now knowing how this can how we can parse the database, looking in on a novel system. In the WMI namespace. We found some interesting classes with Lenovo underscore prefix and one of them is Lenovo BIOS setting. The other one is Lenovo set a BIOS setting and the third one is Lenovo set BIOS password. And if we're looking at the definition of Lenovo BIOS setting, we see that there is a property called the CurrentSetting, a type string that looks interesting to us.
Doing a search on the on the repository for for the for an instance of this class, we come up with empty results, which means those instances are not persistent. So are they're generated on the fly by a WMI provider, which in theory should be provided by the by the BIOS vendor. Using PowerShell as a WMI client. We are looking for non empty, non non empty instances of this class. And then where were displaying when when a non instance we found non non non empty instance, we display the CurrentSetting property and we have some information here.
By magnifying on that we get some interesting bios configurations. About trusting execution. BIOSUpdate TPM and so forth. So what does it mean? We we talked about getting and setting class instances and there is a WMI provider that provides that information. So how does this work? So the way the in this case Lenovo implemented so he provided they provided an interface below the operating system that is implemented below the operating system. So the WMI provider calls on that interface to be able to read and alter this this type of information. So pretty much from the user land, you have access to these settings that are very important for your computer.
And from the management perspective or from a firmware policy orchestration. This is a great feature because you can manage everything locally or remotely through through WMI. But. Is dangerous because in the last update from from Lenovo, we have two CVEs that identify two vulnerabilities exactly in the interface that was provided for the WMI provider. And it's exactly for the SetBIOSPassword the SMI Handler SetBIOSPassword is used to actually complete the instance for the WMI SetPassword class. So the WMI provider calls on that SMI Handler to get the information and create the instance for the WMI SetPassword. And as you can see here, this are industry wide vulnerabilities.
So WMI standard also provides a basic class to get some information about BIOS version the vendor of your BIOS and the device configuratio as part of the standard, so is Win32 BIOS.
So now let's let's move to how WMI used by mostly attackers but also for defenders offers greater flexibility in terms of devices providing device telemetry to to security, to Endpoint Security solutions, but for attackers offers a great living on the land infrastructure to do evil. And some of the ways WMI is leveraged is reconnaissance, AV detection, persistence, code execution and so on. So.
That was from last yesterday's presentation on Matador. Forgive my lacking skills of taking selfies. I'm not used to do that, but I think I saw here the event WMI event subscription. So and getting some more information from the talk. I divide a scenario of how this can be implemented in WMI, which is very, very simple. You create a trigger that tells you that to execute the consumer whenever the system reboots. Whenever the system reboots. And wait a little bit for the boot sequence to finish. And then in the consumer, you just call the CDB.exe To debug the defrag.exe file and to to make the the event subscription permanent event subscription complete. You just need to to bind the evil consumer to to the evil to the evil of filter that specified the trigger to the evil consumer that specified the action to be taken.
Claudiu Teodorescu:
Attacks on WMI. So this is the threat model. The threat model consists of a couple of components. One is the WMI service that communicates with WMI providers and consumers via ALPC Advanced local procedure calls channels. Then we have the the WMI files on disk, the repository and the DLLs for the providers and more files and so on, configuration in registry. And that's under actually yeah, under the data inside the WMI service. And on the right there are the types of the, the attack vectors that can be used on this threat model. So if we have attacks on data inside of WMI process attacks, attacks on pipes, connections, attacks on files and registries, sandboxing of the WMI using a user land attack and then using a kernel driver. At Black Hat, I already talk about this this attack vectors. But today we'll focus on one attack, one more attack on data inside of WMI process and actually showcase the attack on ALPC pipe connections.
So most of the attacks on on the data inside of WMI process, WMI service process are done using this type of template, which is pretty simple. You have a global flag that is set in the initialization phase to its init value, and then when a consumer on a new client comes in or new request comes in, there is some dispatch routine that is called and that flag is is checked. If the flag is set to the required value, then the the event is processed and then no error. A success is returned. If it's not set correctly, then it drops the event and returns an error code.
And we have here a list of flags that can be attacked and actually disable the WMI. Almost all of them I covered during my Black Hat talk. The m_pEseSession is the one I'll cover today and the one one thing to mention. Attacking those flags using the template provided before will disable WMI, but it will return different error codes. That's that's one of the things that happens.
So let's look at the pEseSession. So in the in the init function, a pointer to the interface IWmiDbSession is set into that that variable which is which is a member of the C repository class. To note there is a global object of the CRepository class in the wbemcore.dll. So it's very easy to find this this member. And then as we can see in the shutdown method, we have the pointer is released. Then when a new WMI connection comes in, we have this call stack and at the end we have get, getDefaultSession when the default getDefaultSession is called that pointer is checked against the null. If it's null, then a critical error is returned. If not, the ref count is increased on the pointer and then no error is returned. So the attack is pretty simple. Set this member variable to to null so that the function gets the default session. Returns the critical error.
Now the WMI attacks on ALPC channels, the items involved in this attack, the processes involved in this attack, services.exe, the WMI service and the WMI consumers that interact with the WMI service. On the right we have the. The kernel structures that are involved.
So how does it work? From the services perspective, services.exe perspective a name, the name, the Connection Port called ntsvcs is created by the services.exe and waits for the request from WMI service to connect. Once such request comes in the services.exe allows the connection and then the WMI service receives a handle to the client communication port and the services.exe receives a handle to the services communication port and thus the communication channel between services.exe, the server side and the WMI service, the client side, is established. The same thing. The same mechanism happens with WMI service and their consumers, each consumer WMI consumer will have a channel to the WMI service to actually receive events that are produced by by WMI providers.
So the first attack is pretty, pretty obvious. We cut the cord by closing the handle on the on the client side. So this way, the targeted WMI, WMI client is not going to receive any any WMI events. What you can do, you can retry the client, can try to reestablish the connection or restart itself, but the attacker app can act as a watchdog and then monitor the reconnection and then close the the client communication port handle again.
So time for the first demo. So we're launching Command.exe. We validate that we have the latest version. We go to our main folder. We have two applications. One is the consumer, the WMI consumer receive WMI events. The other one is the attacker app. So the received WMI events is just monitoring for new processes that are launched.
So as you can see, multiple calls, multiple notepads and everything is logged in the into the WMI client and now we run the attacker and then we run the attack on the consumer, which is the client side. No events are generated. And then. That WMI event the WMI client is disabled and now we relaunch it again. And again, it can because it reestablished the connection, the ALPC connection with the WMI service it can get events back.
I'll disable it again. So from this perspective, this is a different client. Even if it's the same process, it's the same application. Yeah. So now again works. So now we have stacked the client side. The same attack can happen on the on the server side, on the server side. So what we're going to do, we are closing the server communication port in the WMI service. Again, we're checking. We have the latest version.
We're running the WMI tester, which is a way to interrogate WMI. So it is running. Now we do our attack. This time on the WMI service.
No more events I received. Now try to restart. We cannot restart because the server side of the pipe has been closed. Cool. Going back.
And now conclusions. So. WMI created for performance monitoring and telemetry gathering. Without security first in mind. That's one of the points that we want to make for this for this talk. We want to make sure that people are aware about risks that they can, they can have if they rely on this telemetry. Yes, you can use WMI as a as a data point, but you should be able either if you rely only on WMI to detect this type of attack attacks or use different data points and correlate them to get an idea of what's happening in your system. And as we saw, the attacks are very simple because WMI has been designed for a different purpose.
And one one last thing that I want to leave everybody here. All this attack can originate in the firmware, which right now it's a big blindspot for the industry in terms of detection. Thank you very much, everybody.
Sonix has many features that you’d love including upload many different filetypes, automatic transcription software, secure transcription and file storage, automated translation, and easily transcribe your Zoom meetings. Try Sonix for free today.