WMI Eventing (Subscription)

Aus Wiki-WebPerfect
Wechseln zu: Navigation, Suche

Description

WMI provide the capability to monitor system wide events and notify user. There are two types of events in WMI Intrinsic and Extrinsic events.
Only on Instrinsic Events we have to define a pooling interval for example: Select * from __InstanceCreationEvent within 10


Instrinsic WMI Events

Intrinsic events are tied closer to WMI itself. They are triggered in response to changes in WMI structure. For example, if a new process is created on the system it will result in a new instance being created for the WIN32_Process class, this will result in an event of type __Instancecreationevent. Another example would be a new class being created in WMI this will result in an event of type __ClassCreationEvent. Just like everything in WMI is represented as objects, events are represented as objects too and each event type has an associated class as listed below. However, one thing to keep in mind is that these objects representing an event are short-lived hence we use pooling when we are creating our event filter else we can miss these objects being created.

Following are different types of Intrinsic events:

  • __NamespaceOperationEvent
  • __NamespaceModificationEvent
  • __NamespaceDeletionEvent
  • __NamespaceCreationEvent
  • __ClassOperationEvent
  • __ClassDeletionEvent
  • __ClassModificationEvent
  • __ClassCreationEvent
  • __InstanceOperationEvent
  • __InstanceCreationEvent
  • __MethodInvocationEvent
  • __InstanceModificationEvent
  • __InstanceDeletionEvent
  • __TimerEvent


Extrinsic Events

Extrinsic events are generated based on underlying OS level changes. This is a major difference while intrinsic events are looking for changes within WMI structure, extrinsic events are looking for changes outside WMI at OS level. For example, Computer shutdown event is an OS level event hence its classified as Extrinsic event. Extrinsic events do not require pooling.

Following are different types of extrinsic events:

  • Win32_ComputerShutdownEvent
  • Win32_IP4RouteTableEvent
  • Win32_ProcessStartTrace
  • Win32_ModuleLoadTrace
  • Win32_ThreadStartTrace
  • Win32_VolumeChangeEvent
  • Msft_WmiProvider*
  • RegistryKeyChangeEvent
  • RegistryValueChangeEvent

In order to work with these events, we need to understand the concept of filters, but before we talk about filter, we take a quick segue to WQL. WQL is WMI query language and is like SQL. It uses the same syntax as SQL to query WMI for information.


Persistent Event Subscription

WMI provides permanent WMI event subscription which makes our subscription permanent and persist system reboot. Persistent event subscriptions consits of following "components":

  • Event Filter
  • Event Consumer
  • Event Filter to Consumer Binding

Event Filters

Event filters are used to subscribe for particular events. You can think of them as search condition to look for particular events. But there is a difference: Wer have to initialize an object of class __EventFilter and supply our filter as one of the properties of this object.

Event Consumer

Once our event filter matches the criteria we would like to take certain action. For permanent event subscription we have five action types provided by five different consumer classes to choose from.

  • LogFileEventConsumer: Writes to a log file.
  • ActiveScriptEventConsumer: Execute a Script. (Unfortunately only VBScripts)
  • NTEventLogEventConsumer: Write to Windows event log.
  • SMTPEventConsumer: Send an email.
  • CommandLineEventConsumer: Command line execution.

Just like in the case of Event filters once we know what action we like to take we need to initialize an object of that class and supply it with values for certain properties.
More information's about the Event Consumers: https://docs.microsoft.com/en-us/windows/win32/wmisdk/standard-consumer-classes

Event Filter to Consumer binding

Once you have the event filter and consumer defined the only work left is to join them together, filter to consumer binding do exactly that for us. We create an object of __FilterToConsumerBinding class and supply it with values for Filter and Consumer objects. In the "Example 2" you can see all three "components" (Filter, Consumer, Binding).


Examples

Example 1: Windows Eventlogs (All Windows Eventlogs)

Register/Create Subscription (remote)

This Event subscription is not persitent!

##Event log watch -- Windows Eventlog
$WMI = @{
    SourceIdentifier = "RHEEventlog"
    Query = "select * from __InstanceCreationEvent within 5 where TargetInstance isa 'Win32_NtLogEvent'" #and (TargetInstance.EventCode = '3108')"
    Action = {
        $Eventrhe = $event.SourceEventArgs.NewEvent.TargetInstance
        $InsertStrings = $Eventrhe.InsertionStrings #InsertStrings = Windows Eventlog Variables
        $MemberNames = (($Eventrhe | Get-Member) | ? {($_.MemberType -eq "Property") -and !($_.Name -match "__")}).Name
 
            Foreach ($MemberName in $MemberNames) {
                Write-Host $MemberName":" $Eventrhe.$MemberName
            } 
 
            $Nr = 0
            Foreach ($InsertString in $InsertStrings) {
                $Nr++
                Write-Host "InsertString($nr):" $InsertString -ForegroundColor red
            }
        Write-Host "---------------------------------------------------------------" -ForegroundColor Green
    }
}
$Null = Register-WMIEvent @WMI -ComputerName <Remote-Hostname>

Unregister/Remove Subscription

 Unregister-Event -SourceIdentifier "RHEEventlog"

Get Subscriptions

 Get-EventSubscriber


Example 2: Service Modification (persistent Event Subscription)

The following Service modification subscription logs everytime a service changed (start, stop).

#Filter
#Creating a new event filter
$wmiParams.Class = '__EventFilter'
$wmiParams.Arguments = @{
    Name = 'ServiceFilter'
    EventNamespace = 'root\CIMV2'
    QueryLanguage = 'WQL'
    Query = "select * from __instanceModificationEvent within 5 where targetInstance isa 'win32_Service'"
}
$filterResult = Set-WmiInstance @wmiParams
 
 
#Consumer
$wmiParams.Class = 'LogFileEventConsumer'
$wmiParams.Arguments = @{
    Name = 'ServiceConsumer'
    Text = 'A change has occurred on the service: %TargetInstance.DisplayName%'
    FileName = "C:\Temp\Log.log"
}
$consumerResult = Set-WmiInstance @wmiParams
 
 
#Binding
$wmiParams.Class = '__FilterToConsumerBinding'
$wmiParams.Arguments = @{
    Filter = $filterResult
    Consumer = $consumerResult
}
$bindingResult = Set-WmiInstance @wmiParams


Remove persistent Event Subscription

Please be careful. If you delete the wrong CIM-Instances, you can break something!

#Remove the Event Filter
Get-CimInstance -ClassName __EventFilter -Namespace root\Subscription -Filter "Name='<YOUR_FILTER_NAME>'" | Remove-CimInstance -Verbose
 
#Remove the Event Consumer
## YOUR_CONSUMER = LogFileEventConsumer, ActiveScriptEventConsumer, NTEventLogEventConsumer, SMTPEventConsumer or CommandLineEventConsumer
Get-CimInstance -ClassName <YOUR_CONSUMER> -Namespace root\Subscription -Filter "Name='<YOUR_CONSUMER_NAME>'" | Remove-CimInstance -Verbose
 
#Remove the Event Filter to Consumer Binding
Get-CimInstance -ClassName __FilterToConsumerBinding -Namespace root\Subscription -filter "Filter = ""__EventFilter.Name='<YOUR_FILTER_NAME>'"""



More useful information's: https://www.scriptrunner.com/de/blog/handling-events-powershell-and-wmi