Offensive WMI - Exploring Namespaces, Classes & Methods (Part 2)
This blog post is the second part of the “Offensive WMI” series (the first is here), and this article will be focusing on the 3 major components in WMI that we’d be majorly dealing with. Throughout the article, we’ll be using both WMI and CIM cmdlets interchangeably so that we’re well-versed with both cmdlet types.
Namespaces
Let’s recall what namespaces are in simple terms:
A namespace organizes information similar to folders in a filesystem. However, instead of physical locations (like on a disk), they are more logical in nature.
All namespaces in WMI are instances of the __Namespace
system class. To get a list of all namespaces under the root
namespace, we can query the same class using:
Get-WmiObject -Namespace root -Class __Namespace
The output contains a lot of info, so to filter out the noise, we can use Powershell’s select
:
Get-WmiObject -Namespace root -Class __Namespace | select name
Now we have a list of namespaces on our system. All these namespaces will be referred to as root\<namespace>
, e.g. root\DEFAULT
, root\CIMV2
, etc, since they are namespaces under the root namespace.
NOTE: One weirdly intriguing fact is that the default namespace in WMI is not
root\DEFAULT
but ratherroot\CIMV2
(it has been like this since Windows 2000).
The same can be achieved using the CIM cmdlet Get-CimInstance
, where there is no need of :
Get-CimInstance -Namespace root -ClassName __Namespace
Okay, now that’s sorted, what about nested namespaces? We already saw that there are several namespaces under the root
namespace. We can simply write up a script that recursively gets us the namespaces (from PSMag):
Function Get-WmiNamespace {
Param (
$Namespace='root'
)
Get-WmiObject -Namespace $Namespace -Class __NAMESPACE | ForEach-Object {
($ns = '{0}\{1}' -f $_.__NAMESPACE,$_.Name)
Get-WmiNamespace $ns
}
}
NOTE: The classes and namespaces may vary from machine to machine depending upon the hardware available, applications installed, and many other factors.
Classes
Now that we have a list of namespaces available to make use of, let’s take a look at classes. So what are classes?
A WMI class represents a specific item in your system. It could be anything ranging from system processes to hardware (e.g. a network card), services, etc.
Now, classes are divided into 3 major categories (this is a requirement of the CIM standard):
- Core classes: They apply to all areas of management and provide few basic functionalities. You’ll usually see them starting with double underscores (e.g.
__SystemSecurity
). - Common classes: These are extensions of core classes, and apply to specific management areas. You’ll identify one when you see a class prefixed with
CIM_
(e.g.CIM_TemperatureSensor
). - Extended classes: These are extra additions to common classes based on tech stacks. (e.g.
Win32_Process
).
Classes are further divided into these types:
- Abstract classes: These are templates to define new classes.
- Static classes: Mostly used to store data.
- Dynamic classes: These are retrieved from a provider and represents a WMI managed resource. We’re mostly interested in classes of this type.
- Association classes: Describes relationships between classes and managed resources.
Listing Classes
Enough theory. Let’s try to find some classes. Once again, we can use the Get-WmiObject
cmdlet to list the available classes:
Get-WmiObject -Class * -List
This will list all the classes above, but for the sake of an example, let’s say we are interested in the users on the system. We can narrow down to our specific use case using the following command, which lists all available classes for fetching/manipulating user information:
Get-WmiObject -Class *user* -List
The same can be achieved with the Get-CimClass
cmdlet also:
Get-CimClass -ClassName *user*
NOTE: For a list of all Win32 classes, you can refer to Microsoft’s documentation on classes. The Win32 provider provides classes for 4 different categories: Computer System Hardware Classes, Operating System Classes, Performance Counter Classes and WMI Service Management Classes.
Remember that we talked about dynamic classes being the ones that provide us instances? To get only the dynamic classes, we can make use of the -QualifierName
switch of Get-CimClass
cmdlet:
Get-CimClass -ClassName *user* -QualifierName dynamic
So far so good. What’s next? Querying the classes to get the juicy stuff out of them.
Fetching Classes
We’re interested in the Win32_UserAccount
class this time. Fetching data is simple, we can simply:
Get-WmiObject -Class Win32_UserAccount
TIP: To get a more verbose output, you can pipe the above command into Powershell’s
Format-List
orfl
, something like:Get-WmiObject -Class Win32_UserAccount | fl *
which will get you everything the class has to offer.
The CIM cmdlet Get-CimInstance
can also be used to fetch the same info:
Get-CimInstance -ClassName Win32_UserAccount
Now we have a list of all user accounts on the system!
Let’s turn our attention to the processes running on the system. The class Win32_Process
gives us a list of processes running on the system:
Get-WmiObject -Class Win32_Process
It is not uncommon for a lot of processes to be running on a system that might make your terminal keep scrolling endlessly! To avoid that we can use the -Filter
switch to get a specific process we are looking for (here we’ve picked lsass.exe
):
Get-WmiObject -Class Win32_Process -Filter 'name="lsass.exe"'
The CIM cmdlet alternative Get-CimInstance
gives a shorter, more comprehensive output in this case (and it also supports the -Filter
switch):
Get-CimInstance -ClassName Win32_Process
An idiomatic expression doing the same with WQL is as below:
Get-WmiObject -Query 'select * from win32_process where name="lsass.exe"'
Okay, now we know about listing, fetching and filtering instances of classes in WMI. Let’s look at how removing instances works in WMI.
Removing Class Instances
The Remove-WmiObject
(for WMI cmdlets) and Remove-CimInstance
(for CIM cmdlets) are two cmdlets that have the capabilities of removing instances. You can pipe the output of a relevant command to the cmdlets. For a quick demo, let’s run our favourite calculator app and list the process.
What happens if we pipe the command to Remove-CimInstance
? The process gets killed!
Get-CimInstance -ClassName Win32_Process -Filter 'name="calculator.exe"' | Remove-CimInstance
This is extremely useful when messing around with Registry, or better, in a situation where we’ve created our own classes for storing our payloads and stuff – we can simply use the cmdlet to list all items under the class and thereby cleaning them up all in one go.
Methods
Methods are ways provided to manipulate WMI objects. If you scroll up to the place where we listed all the classes available, you’ll notice a column called Methods
which lists available methods.
Listing Methods
To repeat our chore and list all available methods, we can do something like:
Get-CimClass -MethodName *
To filter out instances that allow us to perform a specific method, we can pass a method name, for example, Create
(which is always interesting because it might allow us to create something):
Get-CimClass -MethodName Create
Further narrowing things down, to list available methods for a specific class, we need to use Powershell’s select
with the -ExpandProperty
switch:
With Get-WmiObject
:
Get-WmiObject -Class Win32_Process -List | select -ExpandProperty Methods
With Get-CimClass
:
Get-CimClass -ClassName Win32_Process | select -ExpandProperty CimClassMethods
NOTE: Please note that the value passed to
select
statement is the name of the column which we got when listing the classes. If you’re confused, scroll up to the paragraph where we listed a class and observe the output difference between WMI and CIM cmdlet output.
So, we have methods like Create
, Terminate
, GetOwner
, GetOwnerSid
, etc for the Win32_Process class. Great. Now let us see how we can use methods.
TIP: To use a method, we need to know what parameters do we need to supply when calling the method. To list all available parameters, we can use a combination of Powershell or better just read the documentation.
Using Methods
The Invoke-WmiMethod
(for WMI) and Invoke-CimMethod
(for CIM cmdlets) allows us to use the methods for a specific class. Let’s try to spawn a calculator:
Invoke-WmiMethod -Class Win32_Process -Name Create -ArgumentList calc.exe
To use the CIM cmdlet, the syntax varies slightly:
Invoke-CimMethod -ClassName Win32_Process -MethodName create -Arguments @{commandline="calc.exe"}
Well, now we know about spawning new processes!
Setting Properties of Objects
Last but not the least, we should take a look at updating instances of a class. However, it is important to keep in mind that the instance should be writable. With a bit of scripting, we can cook up a recipe for getting all writable properties of an class. Here’s the script (sourced from PSMag):
$class = [wmiclass]'<class_name>'
$class.Properties | ForEach-Object {
foreach ($qualifier in $_.Qualifiers) {
if ($qualifier.Name -eq "Write") {
$_.Name
}
}
}
For our example, we’ll use the class Win32_OperatingSystem
, which has a writable property called Description
(essentially the description of the OS).
Let us update the property name to PewOS
using `Set-WmiInstance:
The same could be achieved with Set-CimInstance
, but that is left up to the reader to explore. :)
Conclusion
Whew, that was a long read! By now, we have a solid foundation of both the WMI and CIM cmdlets and how they can be used to achieve significant control over a system. So far thanks for being here, and I’ll see you in the blog. Cheers! 🥂