How to use WMI Event Classes


WMI has a lot of Event Classes that can be used for notifications about various events in OS. To get the list of such classes, use the following Powershell commands:

Get-WMIObject -list -nameSpace “root\cimv2″| Where-Object {$_.Name -match ‘event’} | ft -prop name

Get-WMIObject -list -nameSpace “root\default” | Where-Object {$_.Name -match ‘event’} | ft -prop name

Simple Monitoring

The easiest way to get notified is (was to the recent past) VB Script:

strComputer = “.”
Set objWMIService = GetObject(“winmgmts:\\” & strComputer & “\root\cimv2”)

strQuery = “SELECT * FROM __InstanceCreationEvent WHERE “ _
& “TargetInstance ISA ‘Win32_NTLogEvent’ “ _
& “AND TargetInstance.Logfile = ‘Application’ “
Set colEvents = objWMIService.ExecNotificationQuery (strQuery)

Set objReceivedEvent = colEvents.NextEvent

The following translation can be used for PowerShell v1.0

$Computer = “.”
$TimeSpan = New-Object System.TimeSpan(0, 0, 1) # to be notified within 1 sec.

$Scope = New-Object System.Management.ManagementScope(‘\\’+$Computer+ ’.\root\cimV2’)

$QueryString = “SELECT * FROM __InstanceCreationEvent WHERE “ +
“TargetInstance ISA ‘Win32_NTLogEvent’ “ +
“AND TargetInstance.Logfile = ‘Application’ “

$Query = New-Object System.Management.WQLEventQuery($QueryString)
$Watcher = New-Object System.Management.ManagementEventWatcher($Scope,$Query)

Do
{
$Event = $watcher.WaitForNextEvent()
$Event.TargetInstance.Name
}
While ($True)

PowerShell v2.0 was significantly improved in this field.

$Computer = “.”
$QueryString = “SELECT * FROM __InstanceCreationEvent WHERE “ +
“TargetInstance ISA ‘Win32_NTLogEvent’ “ +
“AND TargetInstance.Logfile = ‘Application’ “
Register-WMIEvent -query $QueryString -sourceIdentifier “AppLogEntry” –computerName $Computer

$Event = Wait-Event
$EventInstance = $Event.SourceeventArgs.NewEvent.TargetInstance
Remove-Event -EventIdentifier $Event.EventIdentifier

It creates the subscription for any event and keep them in the session event queue. That’s why we need to use the remove-event cmdlet. It removes the event from the PowerShell session queue, not from the original location

There can be a variety of queries

Process Deletion
“SELECT * FROM __InstanceDeletionEvent WHERE TargetInstance ISA ‘Win32_Process'”

Process Start
“SELECT * FROM __InstanceCreationEvent WHERE TargetInstance ISA ‘Win32_Process'”

Device Removal
“SELECT * FROM Win32_SystemConfigurationChangeEvent AND EventType=3”

Computer Shutdonw
“SELECT * FROM Win32_ComputerShutdownEvent”

Security log monitoring

At the first sight it seems to be very similar to the other event logs. Just put TargetInstance.Logfile = ‘Security’ and… oops… Access Denied
The access to the Security event log is restricted, so we need to get permission to do this. The WMI Security moniker is a solution

strComputer = “.”
Set objWMIService = GetObject(“winmgmts:{impersonationLevel=impersonate, (security)}!\\” & strComputer & “\root\cimv2”)

strQuery = “SELECT * FROM __InstanceCreationEvent WHERE “ _
& “TargetInstance ISA ‘Win32_NTLogEvent’ “ _
& “AND TargetInstance.Logfile = ‘Security‘ “
Set colEvents = objWMIService.ExecNotificationQuery (strQuery)

Set objReceivedEvent = colEvents.NextEvent

More about monikers you can find here.
WMI, Windows Event Logs and User Privileges by Uros Calakovic is very good article
Here is a List of WMI monikers

PowerShell v2.0 can use monikers automatically. For example, this modification of the script will work without explicit using the Security moniker

$Computer = “.”
$QueryString = “SELECT * FROM __InstanceCreationEvent WHERE “ +
“TargetInstance ISA ‘Win32_NTLogEvent’ “ +
“AND TargetInstance.Logfile = ‘Security‘ “
Register-WMIEvent -query $QueryString -sourceIdentifier “AppLogEntry” –computerName $Computer

Note: For Get-WMIObject you can use the –EnableAllPrivileges option

Registry Monitoring

Good enough, what about registry?
Nothing special, just all the registry-related events are located in the root\default namespace and are not available by default :o)

A bit of modification
strComputer = “.”
Set objWMIService = GetObject(“winmgmts:\\” & strComputer & “\root\default”)

strQuery = “SELECT * from RegistryValueChangeEvent Where ” & _
“Hive = ‘HKEY_LOCAL_MACHINE’ and ” & _
“KeyPath = ‘SYSTEM\\ControlSet001\\Control’ and ” & _
“ValueName = ‘CurrentUser'”

Set colEvents = objWMIService.ExecNotificationQuery (strQuery)

Set objReceivedEvent = colEvents.NextEvent

Or just use the -nameSpace option in PowerShell

$Hive = “HKEY_LOCAL_MACHINE”
$KeyPath = “‘SYSTEM\\ControlSet001\\Control ”
$ValueName = “CurrentUser”
$Query = “SELECT * FROM RegistryValueChangeEvent WHERE Hive = ‘” + $Hive + “‘ AND KeyPath = ‘” + $KeyPath + “‘ AND ValueName = ‘” + $ValueName + “‘”

Register-WMIEvent -query $QueryString -sourceIdentifier “AppLogEntry” –computerName $Computer –nameSpace “root\default

Note: All registry paths are escaped by backslash

There are three registry events
• RegistryTreeChangeEvent – to track the changes in the key tree
• RegistryKeyChangeEvent – to track the changes in the particular key
• RegistryValueChangeEvent – to track the changes in the particular registry value

Note: All these events just indicate that the change happened. They cannot provide any additional information
Note: All this events cannot be used with HKEY_CLASSES_ROOT or HKEY_CURRENT_USER hives.

Appendix

This is slightly different approach to the event log monitoring

Sub SINK_OnObjectReady(objObject, objAsyncContext)
WScript.Echo (objObject.TargetInstance.Message)
End Sub

Set objWMIServices = GetObject( _
“WinMgmts:{impersonationLevel=impersonate, (security)}”)

‘ Create the event sink object that receives the events
Set sink = WScript.CreateObject(“WbemScripting.SWbemSink”,”SINK_”)

‘ Set up the event selection. SINK_OnObjectReady is called when
‘ a Win32_NTLogEvent event occurs
objWMIServices.ExecNotificationQueryAsync sink, _
“SELECT * FROM __InstanceCreationEvent ” & _
“WHERE TargetInstance ISA ‘Win32_NTLogEvent’ “

WScript.Echo “Waiting for events”

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: