WMI was designed to allow local and remote system administration using DCOM or WSMan, it's enabled on all systems by default. Generally it's used to get information about a system, set parameters, execute methods and subscribe to events.
From an offensive PoV, WMI is excellent for recon, remote code execution, persistence and convert storage as WMI-based detection is far behind the rest. WMI persistence can technically be considered RCE as well but it doesn't involve invoking a method.
WMI uses SQL-like syntax, for example
SELECT [Class property name / names | *] FROM [Class name] <WHERE [Condition]>
SELECT * FROM Win32_Service WHERE Name = "PSEXESVC"
PowerShell is considered to be the best tool to interact with WMI and here are some commands to interact with the service
Get-WmiObject-Class Win32_ServiceGet-WmiObject-Class Win32_Service -Filter 'Name = "WinDefend"'Get-WmiObject-Class Win32_Service -Filter 'Name = "WinDefend"'-Property State, PathNameGet-WmiObject-Namespace 'root/cimv2'-Query 'SELECT State, PathName FROM Win32_Service WHERE Name = "WinDefend"'Get-CimInstance-ClassName Win32_ServiceGet-CimInstance-ClassName Win32_Service -Filter 'Name = "WinDefend"'Get-CimInstance-ClassName Win32_Service -Filter 'Name = "WinDefend"'-Property State, PathNameGet-CimInstance-Namespace 'root/cimv2'-Query 'SELECT State, PathName FROM Win32_Service WHERE Name = "WinDefend"'
Most WMI classes are not well documented but we can use WMI to query for them
Association queries can be used to get further information remotely
ASSOCIATORS OF {[Object].[Key]=[KeyValue]} <WHERE [AssocClass|ResultClass = ClassName]>
for example
List all running processes that have wldp.dll loaded
Get-WmiObject-Query 'ASSOCIATORS OF {CIM_DataFile.Name="c:\\windows\\system32\\wldp.dll"} WHERE AssocClass=CIM_ProcessExecutable'
Get-CimInstance-ClassName CIM_DataFile -Filter 'Drive = "C:" AND Path="\\Windows\\System32\\" AND (Name="C:\\Windows\\System32\\wldp.dll")'-Property Name |Get-CimAssociatedInstance-Association CIM_ProcessExecutable
SELECT [Class property name[s]|*] FROM [INTRINSIC CLASS NAME] WITHIN [POLLING INTERVAL] <WHERE [CONSTRAINT]>
SELECT [Class property name[s]|*] FROM [EXTRINSIC CLASS NAME] <WHERE [CONSTRAINT]>
Register-WmiEvent-Query 'SELECT ProcessName FROM Win32_ProcessStartTrace'-Action { Write-Host"New process: $($EventArgs.NewEvent.ProcessName)" }Register-CimIndicationEvent-Namespace root/subscription -Query 'SELECT * FROM __InstanceCreationEvent WHERE TargetInstance ISA "__FilterToConsumerBinding"'-Action {Write-Host'New WMI persistence!'}
Event queries can persist beyond reboots and execute something in response instead of just being executed in the context of the PowerShell process they're executed from; for this to be possible there are 3 requirements
__EventConsumer: the action to execute
__EventFilter: the event to trigger off of
__FilterToConsumerBinding: binds the filter and consumer together