PowerShell has gained popularity with SysAdmins and for good reason. It’s on every Windows machine (and now some Linux machines as well), has capabilities to interact with almost every service on every machine on the network, and it’s a command line utility. For the same exact reasons, PowerShell has also become a favorite method of attackers interacting with a victim machine. Because of this, organizations have gotten wise to this attack vector and have put measures in place to mitigate it’s use. But there’s another way! Many don’t know of another built-in Windows utility that actually pre-dates PowerShell and can also help them in their hacking pentesting engagements. That tool is Windows Management Instrumentation (WMI). This tutorial will be a small introduction to not only understand the usage of WMI to enumerate information from local and remote machines, but we’ll also show you how to start and kill processes! So let’s jump into WMI 101 for pentesters.

Background on WMI

I will keep this article at an introductory level to understand how to enumerate information in a high level. But as most tutorials, let’s define some terms and provide some historical background. This may get dry but stick with me.

Windows Management Instrumentation (WMI) is Microsoft’s implementation of Web-based Business Management Standards (WBEM), the common information model (CIM) and the Distributed Management Task Force (DMTF). Microsoft has officially stated:

“Windows Management Instrumentation (WMI) is the infrastructure for management data and operations on Windows-based operating systems.”

So what does that mean? Simply, WMI stores a bunch of information about the local machine and allows you to access tat data as well as manage Windows computers locally and remotely.

WMI came pre-installed in Windows 2000. It was made available as a download for Windows NT and Windows 95/98. For historical purposes, Monad, was born in 2002 with its first public appearance in 2003. In the spring of 2006, Monad was renamed Windows PowerShell and didn’t make a final release until November of 2006.

By default, WMI can be accessed by the Windows Script Host (WSH) languages such as VBScript and JScript. From Windows 7 PowerShell can be also used to access WMI. Furthermore, the IWbem COM API can be used with C/C++ and the ‘System.Management’ namespace with .Net languages such as C#, VB.Net and F#. Almost every popular programming languages such as Python, Ruby, PHP, Delphi, et al have third party libraries or built-in libraries which support WMI.

The command-line interface to acess WMI is called the Windows Management Instrumentation Command-line (WMIC). However, WMI can also be accessed directly with PowerShell. From PowerShell v3 onwards, CIM (Common Information Model) cmdlets can be found. The CIM cmdlets can be used to interact with WMI over WS-MAN (WinRM). These CIM cmdlets will aid us when WMI is blocked but WinRM is allowed on the target machine.

Exploring Namespaces

WMI namespaces can be explored in several different ways from using WMIC directly or by using PowerShell.

Using WMIC

C:\>wmic /namespace:\\root path __namespace

Name

subscription

DEFAULT

CIMV2

msdtc

Cli

SECURITY

SecurityCenter2

RSOP

District

PEH

StandardCimv2

WMI

directory

Policy

Interop

Hardware

ServiceModel

SecurityCenter

Microsoft

aspnet

Appv

Using PowerShell

Get-WmiObject -namespace "root" -class "__Namespace" | Select Name

Another method is by using WQL, the WMI Query Language. Microsoft’s documentation defines WQL as, “a subset of standard American National Standards Institute Structured Query Language (ANSI SQL) with minor semantic changes to support WMI.” So, we can use commonly understood SQL statement in quotes such as:

Get-WmiObject -Query “Select * from __Namespace” -Namespace Root | select Name

Exploring Classes

To get a list of WMI classes of a specific Namespace using PowerShell, we can use the ‘List’ parameter. In this example we are listing the classes of default namespace, ‘root\cimv2’.

PS C:\>Get-WmiObject -Namespace root\cimv2 -List

… Output Omitted …

Win32_ShadowContext {} {Caption, ClientAccessible, Description

Differential...}

Win32_MSIResource {} {Caption, Description, SettingID}

Win32_ServiceControl {} {Arguments, Caption, Description, Event...}

Win32_Property {} {Caption, Description, ProductCode, Property...}

Win32_Patch {} {Attributes, Caption, Description, File...}

Win32_PatchPackage {} {Caption, Description, PatchID, ProductCode...}

… Output Omitted …

Another method is by using “Get-CimClass” cmdlet:

Get-CimClass -Namespace root\cimv2

If we want only the classes that start with “win32” inside the “root\cimv2” namespace, we can use a wildcard like this:

Get-WmiObject -Namespace root\cimv2 -Class *Win32* -List

Furthermore, the tool WMI Explorer can be used to have a better view on the namespaces, classes and methods with descriptions and examples.

In summary each Namespace contains Classes. Classes contain:

Properties – Information that can be retrieved.

Methods – Functions that be performed.

Instances – Instances of the class objects. Each instance with Methods and Properties.

Events – Produces notifications about changes in WMI data and services.

WMI Query Language – WQL

We briefly mentioned WQL in an example above, but let’s dive a little deeper. WQL queries can be directly accessed by the ‘wbemtest.exe’ binary and using PowerShell. WQL is used in scripting languages and programming languages when accessing WMI. For this article I will not go in depth regarding each type, however WQL Queries can be categorized as follows:

Instance Queries

Event Queries

Meta Queries

Once you open the wbemtest binary, click on Connect and create a new connection to required namespaces as shown above. If you are creating a connection to a remote machine, you can provide the credentials in this dialog box. In this example I will connect to the default namespace ‘root\cimv2’.

After creating the connection, click on ‘Query’ to test a WQL query. In this example I will use the following query to enumerate files on the disk from path “C:\temp”

Select * From Cim_DataFile Where Drive = "C:" And Path = "\\temp\\"

It will enumerate the files on the ‘temp´ folder and display the file name.

This is the PowerShell syntax for the same request:

Get-WmiObject -Query 'Select FileName From Cim_DataFile Where Drive = "C:" And Path = "\\temp\\"'

WMI Verbs

The following is for usage with WMIC:

List – List Information

Get – Retrieve values

Call – Execute a method

Set – Set value of a property

Create – Creates a new instance

Delete – Deletes an instance

Assoc – Displays the Associators

Putting WMI All Together

Using WMIC

The following command can be used to list the aliases used in WMIC for the corresponding WQL Query.

wmic alias list brief

The list is much longer than what you see in the screenshot above. I highly recommend you try this on your own machine to see what I mean. Much lower in the list, you will find the ‘process’ alias, and it uses the “Select * from Win32_Process” WQL query. By using the alias, we can shorten the command in the following way:

wmic process where name='lsass.exe' list brief

In this next example I am using the ‘get’ verb to retrieve specific properties from the class.

wmic process where name='winword.exe' get name, executablepath

This is an example of using a method ‘GetOwner’ to retrieve the owner of the target process.

wmic process where name='winword.exe' call GetOwner

To create a process we can use the ‘Create’ method. This is widely used by pentesters and in malware to create a remote process.

wmic process call create 'calc.exe'

To kill a process the ‘Terminate’ method can be used.

wmic process where name='notepad.exe' call Terminate

Using PowerShell

Now let’s try some similar activites using PowerShell. This time, let’s look for Word.

Get-WmiObject -Class Win32_Process -Filter 'name="winword.exe"'

Next we’ll filter our data even more to get the information we want.

Get-CimInstance -Class Win32_Process -Filter "name='winword.exe'" -Property Caption, ProcessID, ExecutablePath

Using WQL

And how would this look using PowerShell and some WQL? Here, I am selecting the Caption, Process ID and the Executable Path properties from the ‘winword.exe’ process.

Get-WmiObject -Query "Select Caption,ProcessID,ExecutablePath from Win32_Process where name='winword.exe'" -Namespace root\cimv2

Using the CIM cmdlets you can retrieve all information or retrieve a specific property like this:

(Get-CimInstance -Query "Select * from Win32_Process where name='winword.exe'" -Namespace root\cimv2).ProcessID

Listing all the methods of the ‘Win32_Process’ Class can be done like this:

(Get-WmiObject -Class Win32_Process -List).Methods

For executing a method, the ‘Invoke-WmiMethod’ is used:

Invoke-WmiMethod -Class Win32_Process -Name Create -ArgumentList @(calc.exe)

Using CIM we can call a method like this:

Invoke-CimMethod -ClassName Win32_Process -Name Create -Arguments @{Commandline = 'calc.exe'}

Remote WMIC

We also mentioned above that the same tools can be used over the network. This is the syntax you can use to accomplish the above example in remote computers:

WMIC

wmic /NODE:"servername" /USER:"yourdomain\administrator" /PASSWORD:password OS GET Name

Powershell

And, as we did before, here’s how it can be done using PowerShell:

$cred = Get-Credential domain\user

Invoke-WmiMethod -Class Win32_Process -Name Create -ArgumentList @(calc.exe) -ComputerName servername -Credential $cred

Furthermore, in Linux the tool ‘pth-wmic’ can be used to pass-the-hash instead of the password:

pth-wmic -U domain/adminuser%LM:NT //host "select * from Win32_ComputerSystem"

Conclusion

As you can see, WMI has loads of functionality, most of which has yet to be explored in this article. But even in the little we explored, you can clearly see that WMI can be used as an alternative when PowerShell is monitored or blocking certain scenarios. In a future article, we can play with WMI’s power in other ways good for pentesters such as using it as a C2C in engagements.

I hope this article covered the fundamentals of WMI usage and encouraged you to continue researching on your own. With that in mind, here’s a little homework. As with all useful technologies, there will eventually be a new version to expand on the capabilities proven by the previous version. Windows Management Instrumentation (WMI) is no different as it also has been updated to the Windows Management Infrastructure (MI). Microsoft says that MI is fully backwards compatible while reducing dev time and has tighter integration with Powershell. Go check it out and share what you discover.

References

Author Bio

Osanda Malith Jayathissa is a security researcher who is passionate about application security. He is interested in reverse engineering, malware analysis and penetration testing. He started his hacking life with a single quote (SQL injection) at the age of 12. He has provided manual penetration testing for clients across many sectors, including Banking, Insurance, Media, Entertainment, Healthcare and Financial in the UK. He currently works as an IT Security Consultant for a reputed company in the UK.

He got acknowledged by many organizations for reporting vulnerabilities including Microsoft, Facebook, Apple, AT&T, Oracle, Adobe, Nokia, Twitter, Sony, eBay, SoundCloud, RedHat, Github, Huawei, Dell, Samsung, Intel, etc. He currently holds eCPPTX, eCRE, eCPPT Gold, eWPTX, eWPT, CREST CRT Pen, OSCP, OSCE, OSWP, CRTP.

Be sure to also check out Osanda’s Blog and follow him @OsandaMalith.

Tags: