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
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
namespace

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 rather root\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
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
    }
}
namespace

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
wmiclasses

The same can be achieved with the Get-CimClass cmdlet also:

Get-CimClass -ClassName *user*
cimclasses

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
dynamicclasses

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
users

TIP: To get a more verbose output, you can pipe the above command into Powershell’s Format-List or fl, 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
users

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"'
processes

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
processes

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.

calc

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
calc

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
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
classmethods

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
calcspawn

To use the CIM cmdlet, the syntax varies slightly:

Invoke-CimMethod -ClassName Win32_Process -MethodName create -Arguments @{commandline="calc.exe"}
calcspwn

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).

osdesc

Let us update the property name to PewOS using `Set-WmiInstance:

osdesc

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! 🥂