This is the fourth part of the “Offensive WMI” series which will focus a bit more on information gathering and enumeration. WMI provides a plethora of classes from which we can enumerate a lot of stuff. So let’s dive in without wasting any more time.

Gathering basic information

In our previous blogs, we have already seen a lot of classes that provide us with valuable information about a system, e.g. StdRegProv for the registry, Win32_Process for processes running on the system, Win32_Bios for BIOS information etc. Let us try exploring a bit more.

Host/OS info

Getting to know the host/OS is a very basic step when it comes to reconnaissance. WMI has two classes, namely Win32_OperatingSystem and Win32_ComputerSystem that provides us with the relevant information. For our example, we’ll be filtering out junk to print only the necessary information needed.

Get-WmiObject -Class win32_computersystem -Property bootupstate,username,totalphysicalmemory,systemtype,systemfamily,domain,dnshostname,oemstringarray

So most of the information that we have now helps us in one major thing – figuring out whether we are in an emulated environment. The bootup state for our current run indicates that the system wasn’t booted in fail-safe mode. We can also see that our current user is pew and the box is not a part of any AD domain. We also get the processor architecture and the RAM available for us to use. This is useful for VM detection, for example – if the number of logical processors is less than 4 and the RAM available is below 2 Gigs, then the probability of the box being a VM is high. Of course, the same data is given away by the SystemFamily and the OEMStringArray properties, but in controlled environments, there might be other indicators as well.

The other class Win32_OperatingSystem too provides us with a lot of useful info:

Get-WmiObject -Class win32_operatingsystem | fl *

Directory listing

Listing files on a system is a very fundamental operation. WMI has a class called Win32_Directory that helps in listing the files. Alternatively, there is another class named CIM_DataFile that can also be utilized to achieve the same.

Get-WmiObject -Class win32_directory

Often searching for file patterns using wildcards is helpful. We can make use of the -Filter argument of the cmdlet to achieve something similar. Let’s say we’re interested in directory paths that have a folder called snapshots. Querying it with WMI would look like this:

Get-WmiObject -Class win32_directory -Filter 'name LIKE "%snapshots%"'

AV product

One of the first steps when it comes to recon is to enumerate what kind of product is providing security to a system. WMI provides a class called AntiVirusProduct under the root\SecurityCenter2 namespace that contains information about the AV installed on the system. In my case, it’s the default Windows Defender.

Get-WmiObject -Namespace root\securitycenter2 -Class antivirusproduct


Services on a Windows system are similar to Unix daemons, or simply non-UI processes running in the background. This is useful information when it comes to privilege escalation, especially, in cases where there is a service created by SYSTEM with weak file permissions.

To list the services, we need to make use of the Win32_Service class. For our example, we’ll only print those services which are initiated by the LocalSystem (or the NT Authority\System). Note the usage of the select Powershell utility that expands the output significantly as compared to without it.

Get-WmiObject -Class win32_service -Filter 'startname="localsystem"' | select *

WMI also provides several methods when it comes to interacting with services. They allow creation, deletion, starting, stopping, resuming, updating and a lot of other capabilities to manipulate the services. To list the methods available under the Win32_Service class, we can use the following command:

Get-WmiObject -Class win32_service -List | select -ExpandProperty methods

Logged-on Users

Getting the logged-on users on a system is pretty trivial. There are two classes – Win32_LoggedOnUser and Win32_LogOnSession that holds the particulars about the session and users logged onto the system. Querying the class from a privileged user gives us much more information about the logged in users:

Get-WmiObject -Class win32_loggedonuser

From the above, we can see that each logged-in user has an LUID (locally-unique identifier). Some LUIDs are predefined. For example, the LUID for the System account’s logon session is always 0x3e7 (999 decimal), the LUID for Network Service’s session is 0x3e4 (996), and Local Service’s is 0x3e5 (997). Most other LUIDs are randomly generated.

Each logged-on user defines its dependents via the Dependent property. We can get a list of logon IDs, the authentication type, start time and scope of every session using the Win32_LogOnSession class:

Get-WmiObject -Class win32_logonsession | select authenticationpackage,logonid,starttime,scope

Installed patches

It’s often useful to enumerate the updates/patches installed on a machine. If the system is missing important patches, that might open up an easy possibility to compromise the system in one quick shot. WMI has a class known as Win32_QuickFixEngineering which contains info about the installed updates and security patches. Querying the class is a piece of cake:

Get-WmiObject -Class win32_quickfixengineering

Event logs

The class Win32_NtLogEvent gives us useful data about the events logs captured by the system. We can query it like the following:

Get-WmiObject -Class win32_ntlogevent

Each log entry carries details like time, the source generating the event, severity and a message. The severity is indicated by the Type property in the output. Talking about event types, there are five different levels which are depicted in the table below:

Value Meaning
1 Error
2 Warning
4 Information
8 Security Audit Success
16 Security Audit Failure

We can, of course, make use of the -Filter switch to search for specific event types.


The Win32_Share class represents a shared resource on a system. This may be a disk drive, printer, interprocess communication, or other sharable devices. In enterprise networks, there are usually a lot of shares that might come in handy during a penetration test. Let us see how we can enumerate the available shares:

Get-WmiObject -Class win32_share | select type,name,allowmaximum,description,scope

In the above example, we filtered only the required useful information using select. We have the share type, name, concurrent access permission, description and scope of every available share from the output of the command. Once again, types are constants that define the type of resources being shared:

Value Meaning
0 Disk Drive
1 Print Queue
2 Device
2147483648 Disk Drive Admin
2147483649 Print Queue Admin
2147483650 Device Admin
2147483651 IPC Admin

The AllowMaximum is a boolean property indicating whether concurrent access to the resource has been restricted or not. If the value is set to True, then there is no restriction on the shared access, which otherwise might indicate that there is something sensitive in the resource, or better might have monitoring for clients accessing the share.

WMI also provides methods like Create, SetShareInfo and Delete for creating, updating and deleting shares.


Network info

Network information is provided by the Win32_IP4RouteTable class. This gives us details similar to the ipconfig command but in a much more detailed fashion.

Get-WmiObject -Class win32_ip4routetable

I would like to mention another useful class called Win32_NetworkAdapter while talking about network stuff. Querying it can give us a useful indication about the network hardware that the system has. This in-turn is useful for VM detection, for example, we can run the following queries to identify whether the system is virtualized by VMWare:

Get-WmiObject -Class Win32_NetworkAdapter -Filter 'name like "%vmware%"'
Get-WmiObject -Class Win32_NetworkAdapter -Filter 'manufacturer like "%vmware%"'

User accounts

User account information is provided by the Win32_UserAccount class. For a default local system, there are only a few accounts, the most common ones being the administrator, guest, local users and the windows defender (WDAGUtilityAccount). We can get a list of users quickly via:

Get-WmiObject -Class win32_useraccount

However, for a domain-joined box or domain controller, there will be several others including krbtgt, sqladmin, webadmin, etc. For a default Windows Server 2012 setup, there are just 3 accounts as displayed below.


User groups

Similar to user accounts, user groups information is provided by the Win32_Group class. Querying the class on a local box is easy:

Get-WmiObject -Class win32_group

If the same command is run in an enterprise environment, e.g. a domain-joined network, the number of groups would increase giving us a wider view of the user groups present on a network. This will include the local ones, the current domain, the trusted domain and the trusted forest as well:


System secrets

System secrets are once again useful info to enumerate when it comes to recon. If we have enough privileges on the system, we can create shadow copies of the disk and try to extract secrets from there. But before that for those of you not familiar with shadow copies:

Shadow Copy is a technology included in Microsoft Windows that can create backup copies or snapshots of computer files or volumes, even when they are in use.

To interact with the shadow copies, we have 2 available methods as seen in the picture below:


Creating a quick shadow copy is easy, we just need to specify the volume and the context of the copy creation:

(Get-WmiObject -Class win32_shadowcopy -List).create("C:\", "ClientAccessible")

To add to this, we can create a symlink to easily access the shadow copy from our local explorer:

$link = (Get-WmiObject -Class win32_shadowcopy).deviceobject + "/"
cmd /c mklink /d C:\shadowcopy "$link"

Once we have the shadow copy ready to use, we can simply run tools like Invoke-SessionGopher.ps1 with the -Thorough switch to search for secrets on the filesystem. This would yield saved session information for PuTTY, WinSCP, FileZilla, SuperPuTTY, RDP, etc. In my case, I found a few saved RDP sessions and PuTTY sessions using the script.



So this was all about information gathering over WMI for a single blog post. We saw how we can gather so much useful data in just a few key taps so conveniently. Of course, the information presented above is not exhaustive and there are endless possibilities to consider when it comes to reconnaissance.

That’s it for now folks and I’ll meet you in our next blog that will focus on Active Directory enumeration via WMI. Sláinte! 🥂