[TOC]
0x00 Preface Brief
Q: What is WMI? Answer: WMI has been around for many years, but many people are not familiar with it. Know it's nice and powerful, but don't know where it came from, how it works, what's the scope of use?
WMI has a set of APIs, whether we use VBScript, PowerShell scripts or C# to access the WMI class library, it is because of the set of APIs exposed by WMI. These API s are installed when the system installs the WMI module, and through them we can get the classes we want. WMI has a repository. Although most instance data for WMI is not stored in WMI, WMI does have a repository for class information provided by providers, otherwise known as class blueprints or schemas. WMI has a Service. WMI is always responsive to user access because it has a running Windows service called Winmgmt. Stop this service and all operations on WMI will be unresponsive. WMI is extensible. Everyone knows that WMI can do many things, read local hard disk information, read remote computer user information, read domain user information, and so on. Basically it can do anything you can think of to get or change resources. It can be said to eat less and do more. Why is it so capable? This is based on the extensibility of WMI. The operation of WMI on resources is not what method it implements, but depends entirely on the provider registered with it. WMI is one of the powerful tools that administrators must have on a daily basis and is a scripting companion. Of course, it is also possible to build a large system on top of WMI and WMI providers
Q: What can WMI do? A: By making your driver a WMI provider, you can:
- Make custom data available to WMI consumers.
- Allows WMI consumers to configure devices through standard interfaces rather than custom control panel applications.
- Notifies WMI consumers of driver-defined events without the consumer polling or sending IRPs.
- Reduce driver overhead by collecting only the requested data and sending it to a single target.
- Data and event blocks are annotated with a descriptive driver-defined class name and optional description, which WMI clients can then enumerate and display to the user.
Q: Common commands and tools for WMI management
- wmic.exe - Cmd Command
- Get-CimClass - Powershell Command
- Get-CimInstance - Powershell Command
- Get-WmiObject - Powershell Command
0x01 command parsing
1.Get-CimClass command - get a list of CIM classes in a specific namespace
Syntax parameters:
copyGet-CimClass [[-ClassName] <System.String>] [[-Namespace] <System.String>] -CimSession <Microsoft.Management.Infrastructure.CimSession[]> [-MethodName <System.String>] [-OperationTimeoutSec <System.UInt32>] [-PropertyName <System.String>] [-QualifierName <System.String>] [<CommonParameters>] Get-CimClass [[-ClassName] <System.String>] [[-Namespace] <System.String>] [-ComputerName <System.String[]>] [-MethodName <System.String>] [-OperationTimeoutSec <System.UInt32>] [-PropertyName <System.String>] [-QualifierName <System.String>] [<CommonParameters>]
Basic example:
copy# - 1. Get all class definitions and the number of entries Get-CimClass ; (Get-CimClass).count # NameSpace:ROOT/CIMV2 # Win32_DeviceChangeEvent {} {SECURITY_DESCRIPTOR, TIME_CREATED, EventType} # Win32_SystemConfigurationChangeE... {} {SECURITY_DESCRIPTOR, TIME_CREATED, EventType} # Win32_VolumeChangeEvent {} {SECURITY_DESCRIPTOR, TIME_CREATED, EventType, DriveName} # MSFT_WMI_GenericNonCOMEvent {} {SECURITY_DESCRIPTOR, TIME_CREATED, ProcessId, PropertyName... # MSFT_NCProvEvent {} {SECURITY_DESCRIPTOR, TIME_CREATED, Namespace, ProviderName... # 1234 # - 2. Get a class with a specific name and get a class with a specific method name, property, qualifier name, namespace Get-CimClass -ClassName *disk* # CimClassName CimClassMethods CimClassProperties # ------------ --------------- ------------------ # CIM_DiskDrive {SetPowerState, R... {Caption, Description, InstallDate, Name...} # Win32_DiskDrive {SetPowerState, R... {Caption, Description, InstallDate, Name... Get-CimClass -ClassName Win32* -MethodName Term* Get-CimClass -ClassName Win32* -PropertyName Handle Get-CimClass -ClassName Win32*Disk* -QualifierName Association # - Get WMI classes and sort Get-CimClass -Namespace root/CIMV2 | Where-Object CimClassName -like Win32* | Select-Object CimClassName # - 3. Get class definition from remote server and get class using CIM session $s = New-CimSession -ComputerName Server01, Server02 Get-CimClass -ClassName *disk* -CimSession $s # or Get-CimClass -ClassName *disk* -ComputerName Server01, Server02
2.Get-CimInstance - Get the CIM instance of the class from the CIM server
Basic syntax:
copyGet-CimInstance -CimSession <Microsoft.Management.Infrastructure.CimSession[]> [-Filter <System.String>] [-KeyOnly] [-Namespace <System.String>] [-OperationTimeoutSec <System.UInt32>] [-Property <System.String[]>] [-ResourceUri <System.Uri>] [-Shallow] [<CommonParameters>] Get-CimInstance -CimSession <Microsoft.Management.Infrastructure.CimSession[]> [-Namespace <System.String>] [-OperationTimeoutSec <System.UInt32>] -Query <System.String> [-QueryDialect <System.String>] [-ResourceUri <System.Uri>] [-Shallow] [<CommonParameters>] Get-CimInstance [-ClassName] <System.String> -CimSession <Microsoft.Management.Infrastructure.CimSession[]> [-Filter <System.String>] [-KeyOnly] [-Namespace <System.String>] [-OperationTimeoutSec <System.UInt32>] [-Property <System.String[]>] [-QueryDialect <System. String>] [-Shallow] [<CommonParameters>] Get-CimInstance [-InputObject] <Microsoft.Management.Infrastructure.CimInstance> -CimSession <Microsoft.Management.Infrastructure.CimSession[]> [-OperationTimeoutSec <System.UInt32>] [-ResourceUri <System.Uri>] [<CommonParameters>] Get-CimInstance [-ClassName] <System.String> [-ComputerName <System.String[]>] [-Filter <System.String>] [-KeyOnly] [-Namespace <System.String>] [-OperationTimeoutSec <System.UInt32>] [-Property <System.String[]>] [-QueryDialect <System.String>] [-Shallow] [<CommonParameters>] Get-CimInstance [-InputObject] <Microsoft.Management.Infrastructure.CimInstance> [-ComputerName <System.String[]>] [-OperationTimeoutSec <System.UInt32>] [-ResourceUri <System.Uri>] [<CommonParameters>] Get-CimInstance [-ComputerName <System.String[]>] [-Filter <System.String>] [-KeyOnly] [-Namespace <System.String>] [-OperationTimeoutSec <System.UInt32>] [-Property <System.String[]>] [-ResourceUri <System.Uri>] [-Shallow] [<CommonParameters>] Get-CimInstance [-ComputerName <System.String[]>] [-Namespace <System.String>] [-OperationTimeoutSec <System.UInt32>] -Query <System.String> [-QueryDialect <System.String>] [-ResourceUri <System.Uri>] [-Shallow] [<CommonParameters>]
Basic example:
copy# - 1. Get the CIM instance of the specified class Get-CimInstance -ClassName Win32_Process # ProcessId Name HandleCount WorkingSetSize VirtualSize # --------- ---- ----------- -------------- ----------- # 0 System Idle Process 0 8192 8192 # 4 System 6692 32768 3985408 Get-CimInstance Win32_ComputerSystemProduct # Get computer hardware information # IdentifyingNumber : 8QVY862 # Name : OptiPlex 9020 # Vendor : Dell Inc. # Version : 01 # Caption : Computer System Products # Specify the class name and namespace to format the output to select the first ten lines Get-CimInstance -Namespace ROOT\CIMV2 -Class Win32_Process|format-table processid,name,executablepath |Select-Object -First 10 # - 2. Get the namespace list from the WMI server Get-CimInstance -Namespace root -ClassName __Namespace # Name PSComputerName # ---- -------------- # subscription # DEFAULT # CIMV2 # msdtc # Cli # SECURITY # SecurityCenter2 # RSOP # PEH # StandardCimv2 # WMI # IntelNCS2 # directory # Policy # Interop # Hardware # ServiceModel # SecurityCenter # Microsoft # Appv # - 3. Get an instance of the class filtered using the query Get-CimInstance -Query "SELECT * from Win32_Process WHERE name LIKE 'P%'" # ProcessId Name HandleCount WorkingSetSize VirtualSize # --------- ---- ----------- -------------- ----------- # 2816 PresentationFontCache.exe 242 1204224 4868018176 # 28800 powershell.exe 870 101203968 2204067848192 # - 4. Get instance of class filtered by using class name and filter expression Get-CimInstance -ClassName Win32_Process -Filter "Name like 'P%'" Get-CimInstance -Class Win32_Process -Namespace ROOT\CIMV2 -Filter "name = 'qq.exe'"|format-table processid,name,executablepath # - 5. Get the CIM instance with only key attributes filled in $x = New-CimInstance -ClassName Win32_Process -Namespace root\cimv2 -Property @{ "Handle"=0 } -Key Handle -ClientOnly Get-CimInstance -CimInstance $x # ProcessId Name HandleCount WorkingSetSize VirtualSize # --------- ---- ----------- -------------- ----------- # 0 System Idle Process 0 8192 8192 # Get only key properties instead of all properties $x = Get-CimInstance -Class Win32_Process -KeyOnly $x | Invoke-CimMethod -MethodName GetOwner # Get only a subset of properties, not all properties # Instances retrieved using property parameters can be used to perform other CIM operations such as "Set CimInstance" or "Invoke CimMethod". $x = Get-CimInstance -Class Win32_Process -Property Name,KernelModeTime $x | Invoke-CimMethod -MethodName GetOwner # - 6. Retrieve CIM instances and reuse them $x,$y = Get-CimInstance -ClassName Win32_Process $x | Format-Table -Property Name,KernelModeTime -AutoSize # Name KernelModeTime # ---- -------------- # System Idle Process 57588234843750 # - 7. Get CIM instance from remote computer Get-CimInstance -ClassName Win32_ComputerSystem -ComputerName Server01,Server02 # using CIM session $s = New-CimSession -ComputerName Server01,Server02 Get-CimInstance -ClassName Win32_ComputerSystem -CimSession $s # - 8. Create and delete processes # Get-CimInstance -Namespace ROOT\CIMV2 -Class Win32_Process -Path "'C:\Windows\System32\cmd.exe'" | Invoke-CimMethod -Name create Get-CimInstance -Namespace ROOT\CIMV2 -Class Win32_Process -Filter "name = 'qq.exe'" | Invoke-CimMethod -Name Terminate # - 9. Query service information and turn on/off services Get-CimInstance -Namespace ROOT\CIMV2 -Class Win32_Service -Filter "State='Running'" # Get a list of running services Get-CimInstance -Namespace ROOT\CIMV2 -Class Win32_Service -Filter "name='spooler'"|Invoke-CimMethod -Name startservice # Turn on print spooler Get-CimInstance -Namespace ROOT\CIMV2 -Class Win32_Service -Filter "name='spooler'"|Invoke-CimMethod -Name stopservice # Turn off the print spooler # - 10. View installed software information Get-CimInstance -Namespace ROOT\CIMV2 -Class Win32_Product |format-table name,version | Select-Object -First 10 # - 11. Get list of executable files Get-CimInstance -Namespace ROOT\CIMV2 -Class Win32_Process -Filter "NOT ExecutablePath LIKE '%Windows%'" | format-table ExecutablePath # - 12. Get directory attributes and delete directories Get-CimInstance -Namespace ROOT\CIMV2 -Class win32_directory -filter "drive='f:' and filename='kk'" |select-object -first 10 Get-CimInstance -Namespace ROOT\CIMV2 -Class win32_directory -filter"drive='f:' and filename='test'" |Invoke-CimMethod -Name delete # - 13. User account management and user group management Get-CimInstance -Namespace ROOT\CIMV2 -Class win32_useraccount # Name Caption AccountType SID Domain # ---- ------- ----------- --- ------ # Administrator WEIYIGEEK\Administrator 512 S-1-5-21-923396991-33996... WEIYIGEEK Get-CimInstance -Namespace ROOT\CIMV2 -Class win32_useraccount-filter "name='%UserName%'" |Invoke-CimMethod -Name rename("newUserName") # User account rename Get-CimInstance -Namespace ROOT\CIMV2 -Class Win32_Group |format-table caption,InstallDate,LocalAccount,Domain,SID,Status # get SID # - 14. Information collection of system GIM Get-CimInstance -Namespace ROOT\CIMV2 -Class win32_computersystem |select-object Name,Domain,Manufacturer,Model,Username,Roles # Get system role, username and manufacturer Get-CimInstance -Namespace ROOT\CIMV2 -Class Win32_QuickFixEngineering |select-object Caption,Description,HotFixID,InstalledOn # Get patch information Get-CimInstance -Namespace ROOT\SecurityCenter2 -Class AntiVirusProduct | select-object displayName,productState, pathToSignedProductExe # Get Anti-Virus Product Details Get-CimInstance -Namespace ROOT\CIMV2 -Class Win32_OnBoardDevice | select-object Desciption,DeviceType,Enabled,Status # Determine whether the target system is a virtual machine # Desciption DeviceType Enabled Status # ---------- ---------- ------- ------ # 3 False # 7 False Get-CimInstance -Namespace ROOT\CIMV2 -classname Win32_DiskDrive # View disk information # DeviceID Caption Partitions Size Model # -------- ------- ---------- ---- ----- # \\.\PHYSICALDRIVE0 ST1000DM010-2EP102 6 1000202273280 ST1000DM010-2EP102 # \\.\PHYSICALDRIVE1 WD Elements SE 25FE USB Device 1 1000169372160 WD Elements SE 25FE USB Device Get-CimInstance -Namespace ROOT\CIMV2 -Class Win32_NTEventlogFile -filter "logfilename='windows powershell'" |Invoke-CimMethod -Name ClearEventlog # clean system log
3.Get-WmiObject - Get information about WMI classes
Description: Get an instance of a Windows Management Instrumentation (WMI) class or information about available classes.
Tips: Starting from PowerShell 3.0, this cmdlet has been supported by Get-CimInstance. Tips: Get-Alias gwmi You can see that gwmi is the alias of Get-WmiObject
Syntax parameters:
copyGet-WmiObject [[-Class] <System.String>] [[-Property] <System.String[]>] [-Amended] [-AsJob] [-Authentication {Default | None | Connect | Call | Packet | PacketIntegrity | PacketPrivacy | Unchanged}] [-Authority <System.String>] [-ComputerName <System.String[]>] [-Credential <System.Management.Automation.PSCredential>] [-DirectRead] [-EnableAllPrivileges] [-Filter <System.String>] [-Impersonation {Default | Anonymous | Identify | Impersonate | Delegate}] [-Locale <System.String>] [-Namespace <System.String>] [-ThrottleLimit <System.Int32>] [<CommonParameters>] Get-WmiObject [[-Class] <System.String>] [-Amended] [-AsJob] [-Authentication {Default | None | Connect | Call | Packet | PacketIntegrity | PacketPrivacy | Unchanged}] [-Authority <System.String>] [-ComputerName <System.String[]>] [-Credential <System.Management.Automation.PSCredential>] [-EnableAllPrivileges] [-Impersonation {Default | Anonymous | Identify | Impersonate | Delegate}] [-List] [-Locale <System.String>] [-Namespace <System.String>] [-Recurse] [-ThrottleLimit <System.Int32>] [<CommonParameters>] Get-WmiObject [-Amended] [-AsJob] [-Authentication {Default | None | Connect | Call | Packet | PacketIntegrity | PacketPrivacy | Unchanged}] [-Authority <System.String>] [-ComputerName <System.String[]>] [-Credential <System.Management.Automation.PSCredential>] [-DirectRead] [-EnableAllPrivileges] [-Impersonation {Default | Anonymous | Identify | Impersonate | Delegate}] [-Locale <System.String>] [-Namespace <System.String>] -Query <System.String> [-ThrottleLimit <System.Int32>] [<CommonParameters>] # Parameter Description: -ComputerName : Specifies the target computer for administrative operations. Enter the fully qualified domain name ( FQDN),NetBIOS name or IP address. -Authentication : WMI The authentication level of the connection (`Default, None, Connect, Call, Packet, PacketIntegrity, PacketPrivacy, Unchanged`) -Credential : The default is the user account name and the user will be prompted for a password. -Filter: use WMI query language WQL syntax, Specifies the filter to use Where clause, use WMI query language ( WQL)syntax.
Simple example:
copy# 1) Acquisition and operation of computer-related information Get-WmiObject Win32_UserAccount # Get the account number in the computer (Class can be omitted) Get-WmiObject Win32_Processor # Get CPU processor information # Caption : Intel64 Family 6 Model 60 Stepping 3 # DeviceID : CPU0 # Manufacturer : GenuineIntel # MaxClockSpeed : 3301 # Name : Intel(R) Core(TM) i5-4590 CPU @ 3.30GHz # SocketDesignation : SOCKET 0 Get-WmiObject -Class Win32_Process # Get processes on the local computer. Get-WmiObject -Class Win32_Bios | Format-List -Property * # Local computer gets BIOS information Get-WmiObject -class win32_OperatingSystem # Get operating system information Get-WmiObject -Class Win32_OperatingSystem | Format-List BootDevice,BuildNumber,BuildType,Caption,CodeSet,CountryCode # Get the system version and whether the system is Professional or Educational Get-WmiObject -class win32_ComputerSystem # Obtain information on computer systems Get-WmiObject -class Win32_LogicalDisk # Get computer disk information Get-WMIObject -Class Win32_DiskDrive # View hard disk information Get-WmiObject -Class Win32_Product | Select-Object -Property Name,Version,IdentifyingNumber # View the list of installed software on the machine (slightly slower) Get-WMIObject -Class Win32_PhysicalMemory # Get memory information gwmi Win32_PhysicalMemory | %{$sum = 0} { $sum += $_.Capacity } {Write-Host ($sum / 1GB) "GB"} # Query memory in GB Get-WmiObject win32_OperatingSystem FreePhysicalMemory # Query free memory Get-WmiObject -class Win32_NetworkAdapterConfiguration # Get network information gwmi Win32_PerfFormattedData_Tcpip_NetworkInterface | select Name,CurrentBandwidth # Get network card and bandwidth gwmi Win32_DiskDrive | %{$sum = 0} { $sum += $_.Size } {Write-Host ($sum / 1GB) "GB"} # Query hard disk in GB 1862.99127101898 GB Get-WmiObject Win32_LogicalDisk | Foreach-Object { 'Disk {0} has {1:0.0} MB space available' -f $_.Caption, ($_.FreeSpace / 1MB) } # Query the remaining space of the hard disk # 2) Remote computer information acquisition and operation Get-WmiObject -Class Win32_Service -ComputerName 10.1.4.62 # Get a service on a remote computer Get-WmiObject Win32_Service -Credential FABRIKAM\administrator -ComputerName Fabrikam # Remote Computer Authentication (Get-WmiObject -Class Win32_Service -Filter "name='WinRM'" -ComputerName Server01).StopService() # To stop the WinRM service on the remote computer, call the StopService method of the Win32_Service WMI class on the object. # 3) Get the WMI class in the root/default, root/cimv2 namespace of the local computer Get-WmiObject -Namespace "root/default" -List # NameSpace:ROOT\default Get-WmiObject -Namespace "root/cimv2" -List # NameSpace:ROOT\CIMV2 # Name Methods Properties # Win32_DeviceChangeEvent {} {EventType, SECURITY_DESCRIPTOR, TIME_CREATED} # 4) Conditions are added with WMI-like SQL query statements WMI Query Language (WQL). Get-WmiObject Win32_LogicalDisk -filter "DeviceID = 'c:' " # Specify Logical Disk Information Get-WmiObject win32_service -filter "name='WinRM'" # Specify service information Get-WmiObject -Query "select * from win32_service where name='WinRM'" | Format-List -Property PSComputerName, Name, ExitCode, Name, ProcessID, StartMode, State, Status # PSComputerName : WEIYIGEEK # Name : WinRM # ExitCode : 1077 # Name : WinRM # ProcessID : 0 # StartMode : Manual # State : Stopped # Status : OK # 5) How to find Windows product key using PowerShell? Windows product keys can be retrieved using PowerShell or CMD. We need to query the SoftwareLicesingService class and have a property called OA3xOriginalProductKey to store the product key. Get-WmiObject -query 'select * from SoftwareLicensingService' | Select OA3xOriginalProductKey,ClientMachineID,KeyManagementServiceProductKeyID # OA3xOriginalProductKey ClientMachineID KeyManagementServiceProductKeyID # ---------------------- --------------- -------------------------------- # bf4de4ea-3318-494e-b37b-727fcae6492d 55041-00206-262-110359-03-6154-6002.0000-2512019 # we can also use cmd query this WMI like: wmic path softwarelicensingservice get OA3xOriginalProductKey # Windows 10 OA3xOriginalProductKey This is empty # 6) Three ways to get the current machine temperature Get-CimInstance -Namespace ROOT/WMI -Class MSAcpi_ThermalZoneTemperature wmic /namespace:\\root\cimv2 PATH Win32_PerfFormattedData_Counters_ThermalZoneInformation get Temperature # way 1 $t = Get-WmiObject -Namespace "root/wmi" -ClassName MSAcpi_ThermalZoneTemperature # Get Open Kelvin and Celsius and Fahrenheit Fahrenheit from computer sensors foreach ($temp in $t.CurrentTemperature) { $currentTempKelvin = $temp / 10 $currentTempCelsius = $currentTempKelvin - 273.15 $currentTempFahrenheit = ( 9/ 5 ) * $currentTempCelsius + 32 Write-host $currentTempCelsius.ToString() "C" : $currentTempFahrenheit.ToString() "F" : $currentTempKelvin "K" # 29.85 C : 85.73 F : 303 K } # way 2 Get-CimInstance -Namespace ROOT/WMI -Class MSAcpi_ThermalZoneTemperature | % { $currentTempKelvin = $_.CurrentTemperature / 10 $currentTempCelsius = $currentTempKelvin - 273.15 $currentTempFahrenheit = (9/5) * $currentTempCelsius + 32 "InstanceName: " + $_.InstanceName+ " ==>> " + $currentTempCelsius.ToString() + " Celsius(C); " + $currentTempFahrenheit.ToString() + " Fahrenheit(F) ; " + $currentTempKelvin + "Kelvin(K)" } # 7) System patch last update (get-wmiobject -class win32_quickfixengineering).InstalledOn | Sort-Object | select -Last 1 # June 9, 2021 0:00:00
Syntax example:
Simple example: