-
Notifications
You must be signed in to change notification settings - Fork 47
New Blog post - Permanent WMI Event Handling #51
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
337da23
54037e2
286ac7e
ad51a35
9595830
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,363 @@ | ||||||||||||||
| --- | ||||||||||||||
| post_title: How Do I Discover Changes to an AD Group's Membership | ||||||||||||||
| username: tfl@psp.co.uk | ||||||||||||||
| Catagories: PowerShell | ||||||||||||||
| tags: AD, WMI, WMI Eventing | ||||||||||||||
| Summary: How to create a permanent event handler to detect changes in an AD Group | ||||||||||||||
| --- | ||||||||||||||
|
|
||||||||||||||
| **Q:** Is there an easy way to detect and changes to important the membership of AD Groups? | ||||||||||||||
|
|
||||||||||||||
| **A:** Easy using PowerShell 7, WMI, and the CIM Cmdlets. | ||||||||||||||
|
|
||||||||||||||
| ## WMI | ||||||||||||||
| Windows Management Instrumentation (WMI) is an important component of the Windows operating system. | ||||||||||||||
| WMI is an infrastructure of both management data and management operations on Windows-based computers. | ||||||||||||||
| You can use PowerShell to retrieve information about your host, such as the BIOS Serial number. | ||||||||||||||
| Additionally, you can perform management actions, such as creating an SMB share. | ||||||||||||||
|
|
||||||||||||||
| WMI is, in many cases, just another way to do things. | ||||||||||||||
| For example, you can use WMI to create an SMB share by using the `Create` method of the **Win32_Share** class. | ||||||||||||||
| For more information, see the (class documentation page for the class)[https://docs.microsoft.com/windows/win32/cimwin32prov/win32-share]. | ||||||||||||||
| In most cases, you use PowerShell cmdlets, such as the SMB cmdlets, to manage your SMB shares. | ||||||||||||||
| The value of WMI is that it can provide you access to more information and features that are not available using cmdlets. | ||||||||||||||
|
|
||||||||||||||
| In writing this article, I assume you have an understanding of WMI. | ||||||||||||||
| In specific, I assume you understand WMI namespaces, classes, properties, and methods. | ||||||||||||||
| If not, you might like to look at the [WMI Documentation](https://docs.microsoft.com/windows/win32/wmisdk/wmi-start-page) | ||||||||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. will add the full stop. |
||||||||||||||
| And for some more details on using WMI and Powershell, look at using PowerShell 7 and WMI, look at [my recently published PowerShell 7 book](https://www.wiley.com/en-gb/PowerShell+7+for+IT+Professionals-p-9781119644705). | ||||||||||||||
| In chapter 9, I devote a chapter to WMI and using the CIM cmdlets. | ||||||||||||||
| To see just the scripts for that chapter, see my [GitHub repository](https://github.com/doctordns/Wiley20/tree/master/09%20-%20WMI). | ||||||||||||||
| The scripts show you the basics of WMI and PowerShell 7. | ||||||||||||||
|
Comment on lines
+28
to
+31
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. One of the tenets of this blog is that we don't allow marketing. I am OK with linking to your book, in the right context. See my suggestion at the bottom of the article. I think it reads better there and comes off like a pitch for your book.
Suggested change
|
||||||||||||||
|
|
||||||||||||||
| ## WMI Eventing | ||||||||||||||
|
|
||||||||||||||
| A cool and very powerful feature of WMI is eventing. | ||||||||||||||
| With WMI eventing, you can subscribe to an event, such as the change of an AD group's membership. | ||||||||||||||
| If and when that event occurs, you can take some action, such as writing to a log file or sending an email. | ||||||||||||||
| WMI event handling is fairly straightforward and very powerful - if you know what classes to use and how to use them! | ||||||||||||||
|
|
||||||||||||||
| There are two broad types of eventing within WMI. | ||||||||||||||
| With temporary eventing, you use PowerShell inside a PowerShell session to subscribe to the events and process them. | ||||||||||||||
| If you close that session, the event subscriptions and event handlers are lost. | ||||||||||||||
| To enable temporary WMI event monitoring to continue, you must leave the host turned on and logged in, which may be a suboptimal situation. | ||||||||||||||
| Temporary event handling can be great for troubleshooting but not ideal for longer-term monitoring. | ||||||||||||||
|
|
||||||||||||||
| With permanent event handling, you also tell WMI what events to do and what to do when they occur. | ||||||||||||||
| To do that, you add the details of event handling to the WMI repository. | ||||||||||||||
| By doing so, WMI can continue to monitor the event after close your session, logoff, or even reboot your host. | ||||||||||||||
| And with PowerShell and PowerShell remoting, it is pretty easy to deploy WMI event detection on multiple servers. | ||||||||||||||
|
|
||||||||||||||
| I warn you that the documentation for eventing may not be great in all cases. | ||||||||||||||
| Some documentation is focused on developers and thus lacks good PowerShell examples. | ||||||||||||||
|
|
||||||||||||||
| ## Permanent Event Consumers | ||||||||||||||
|
|
||||||||||||||
| Within WMI, a permanent event consumer is a built-in COM component that does something when any given event occurs. | ||||||||||||||
| In theory, I suppose you could develop a private WMI event consumer, but I have never seen one developed. | ||||||||||||||
| I am not suggesting that someone has not done it, of course. | ||||||||||||||
| If you have seen this - please comment as I'd love to see the code and understand the details. | ||||||||||||||
|
|
||||||||||||||
| There are five key WMI permanent event consumers which Microsoft provides within Windows: | ||||||||||||||
|
|
||||||||||||||
| * **Active Script Consumer**: You use this to run a specific VBS script. | ||||||||||||||
| * **Log File Consumer**: This handler writes strings of customisable text to a text file. | ||||||||||||||
| * **NT Event Log Consumer**: This consumer writes event details into the Windows Application event log. | ||||||||||||||
| * **SMTP Event Consumer**: You use this consumer to send an SMTP email message when an event occurs | ||||||||||||||
| * **Command Line Consumer**: This consumer runs a program with parameters, for example, run PowerShell 7 and specific a script to run. | ||||||||||||||
|
|
||||||||||||||
| The Active Script consumer _only_ runs VBS scripts. | ||||||||||||||
| Short of redeveloping the COM component, you can not use this consumer with Powershell scripts. | ||||||||||||||
| The Log File Consumer is excellent for writing short highly-customised messages to a text file but can take some time and effort to implement. | ||||||||||||||
| For most IT Pros, the Command Line consumer is the one to choose. | ||||||||||||||
| With this consumer, you get WMI to run a PowerShell script any time an event occurs, such as a change to an AD group. | ||||||||||||||
| Let's look at how you use this permanent event consumer to discover changes to the membership of the Enterprise Admins group. | ||||||||||||||
|
|
||||||||||||||
| ## Creating a permanent event handler | ||||||||||||||
|
|
||||||||||||||
| With WMI permanent event handling, you need to create three objects within the CIM database | ||||||||||||||
|
|
||||||||||||||
| * Event filter - the filter tells WMI which event to detect, such as a change in the change to an AD group. | ||||||||||||||
| * Event consumer - this tells WMI which permanent event consumer to run and how to invoke the consumer, such as to run the Command Line consumer and run `Monitor.ps1`. | ||||||||||||||
| * Event binding - this binds the filter (what event to look out for) to the consumer (what to do when the event occurs happens) | ||||||||||||||
|
|
||||||||||||||
| To carry out these three operations, you inserting new objects into three specific WMI system classes. | ||||||||||||||
| The WMI system class instances enable WMI to continue to process events after you stop your PowerShell session, log off, or restart your host. | ||||||||||||||
|
|
||||||||||||||
| In the code below, you use the Command Line consumer to detect changes to the AD's Enterprise Admins group. | ||||||||||||||
| Every time the change event occurs, you want WMI to run a specific script, namely `Monitor.ps1`. | ||||||||||||||
| This script displays a list of the current members of the Enterprise Admins group to a log file and reports whether the membership now contains unauthorised users. | ||||||||||||||
| If the script finds that an unauthorised user is now a group member, it writes details to a text file for you to review later. | ||||||||||||||
|
Comment on lines
+89
to
+90
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. will revise for American English |
||||||||||||||
|
|
||||||||||||||
| ## The Solution | ||||||||||||||
|
|
||||||||||||||
| There are several steps in this solution. | ||||||||||||||
| So please, fasten your seat belts, and away we go. | ||||||||||||||
|
|
||||||||||||||
| ### Setting up | ||||||||||||||
|
|
||||||||||||||
| In this post, you want to detect whether an unauthorised user is a member of the Enterprise Admins group. | ||||||||||||||
| You must first create a file of authorised users. | ||||||||||||||
|
Comment on lines
+99
to
+100
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. will update for US english |
||||||||||||||
| Then you create two helper functions to assist you in testing the code. | ||||||||||||||
| The function to delete all aspects of the WMI event filter from your host is useful unless you plan to keep the filter running forever. | ||||||||||||||
|
|
||||||||||||||
| ```powershell | ||||||||||||||
|
|
||||||||||||||
| # 1. Create a list of valid users for the Enterprise Admins group | ||||||||||||||
|
Comment on lines
+105
to
+106
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Remove the leading and trailing blank lines in a code block.
Suggested change
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. will do |
||||||||||||||
| $OKUsersFile = 'C:\Foo\OKUsers.Txt' | ||||||||||||||
| $OKUsers = @' | ||||||||||||||
| Administrator | ||||||||||||||
| JerryG | ||||||||||||||
| '@ | ||||||||||||||
| $OKUsers | | ||||||||||||||
| Out-File -FilePath $OKUsersFile | ||||||||||||||
|
|
||||||||||||||
| # 2. Define two helper functions to get/remove permanent events | ||||||||||||||
| Function Get-WMIPE { | ||||||||||||||
| '*** Event Filters Defined ***' | ||||||||||||||
| Get-CimInstance -Namespace ROOT\subscription -ClassName __EventFilter | | ||||||||||||||
| Where-Object Name -eq "EventFilter1" | | ||||||||||||||
| Format-Table Name, Query | ||||||||||||||
| '***Consumer Defined ***' | ||||||||||||||
| $NS = 'ROOT\subscription' | ||||||||||||||
| $CN = 'CommandLineEventConsumer' | ||||||||||||||
| Get-CimInstance -Namespace $ns -ClassName $CN | | ||||||||||||||
| Where-Object {$_.name -eq "EventConsumer1"} | | ||||||||||||||
| Format-Table Name, CommandLineTemplate | ||||||||||||||
| '***Bindings Defined ***' | ||||||||||||||
| Get-CimInstance -Namespace ROOT\subscription -ClassName __FilterToConsumerBinding | | ||||||||||||||
| Where-Object -FilterScript {$_.Filter.Name -eq "EventFilter1"} | | ||||||||||||||
| Format-Table Filter, Consumer | ||||||||||||||
| } | ||||||||||||||
| Function Remove-WMIPE { | ||||||||||||||
| Get-CimInstance -Namespace ROOT\subscription __EventFilter | | ||||||||||||||
| Where-Object Name -eq "EventFilter1" | | ||||||||||||||
| Remove-CimInstance | ||||||||||||||
| Get-CimInstance -Namespace ROOT\subscription CommandLineEventConsumer | | ||||||||||||||
| Where-Object Name -eq 'EventConsumer1' | | ||||||||||||||
| Remove-CimInstance | ||||||||||||||
| Get-CimInstance -Namespace ROOT\subscription __FilterToConsumerBinding | | ||||||||||||||
| Where-Object -FilterScript {$_.Filter.Name -eq 'EventFilter1'} | | ||||||||||||||
| Remove-CimInstance | ||||||||||||||
| } | ||||||||||||||
|
|
||||||||||||||
|
Comment on lines
+142
to
+143
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. removing the blank lines |
||||||||||||||
| ``` | ||||||||||||||
|
|
||||||||||||||
| These two steps produce no output. | ||||||||||||||
| When you create the ``OkUsers.txt`` file - ensure the users in the file are actually in your AD. | ||||||||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Single backticks for inline code.
Suggested change
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ok! |
||||||||||||||
|
|
||||||||||||||
| ### Create a WQL event query and WMI event filter | ||||||||||||||
|
|
||||||||||||||
| To tell WMI what event you want WMI to detect, you create a WMI Query Language (WQL) query. | ||||||||||||||
| In each WMI namespace, you can find various system classes representing event notification. | ||||||||||||||
| You can use the **__InstanceModificationEvent** class, for example, to detect any modification of an instance (in that namespace). | ||||||||||||||
| You can likewise use the **__MethodInvocationEvent** class to track WMI method invocations. | ||||||||||||||
| If things change anywhere in a Windows host, you can probably use a WMI event to detect the change. | ||||||||||||||
|
|
||||||||||||||
| Here's the code to create the WQL query and the WMI event filter | ||||||||||||||
|
|
||||||||||||||
| ```powershell | ||||||||||||||
|
|
||||||||||||||
| # 3. Create a WQL event filter query | ||||||||||||||
| $Group = 'Enterprise Admins' | ||||||||||||||
| $Query = @" | ||||||||||||||
| SELECT * From __InstanceModificationEvent Within 10 | ||||||||||||||
| WHERE TargetInstance ISA 'ds_group' AND | ||||||||||||||
| TargetInstance.ds_name = '$Group' | ||||||||||||||
| "@ | ||||||||||||||
|
|
||||||||||||||
| # 4. Create the event filter | ||||||||||||||
| $Param = @{ | ||||||||||||||
| QueryLanguage = 'WQL' | ||||||||||||||
| Query = $Query | ||||||||||||||
| Name = 'EventFilter1' | ||||||||||||||
| EventNameSpace = 'ROOT/directory/LDAP' | ||||||||||||||
| } | ||||||||||||||
| $IHT = @{ | ||||||||||||||
| ClassName = '__EventFilter' | ||||||||||||||
| Namespace = 'ROOT/subscription' | ||||||||||||||
| Property = $Param | ||||||||||||||
| } | ||||||||||||||
| $InstanceFilter = New-CimInstance @IHT | ||||||||||||||
|
|
||||||||||||||
| ``` | ||||||||||||||
|
|
||||||||||||||
| In this code (which produces no output), the filter query does not state which namespace the query is looking at, just that there is a target class for WMI to monitor. | ||||||||||||||
| In the event filter, you create a new occurrence in the **EventFilter** class in the **ROOT/Subscription** namespace. | ||||||||||||||
| This occurrence tells WMI to monitor the **ROOT/directory/LDAP** namespace for the **ds_group** class. | ||||||||||||||
|
|
||||||||||||||
| ### Creating the Event Consumer | ||||||||||||||
|
|
||||||||||||||
| The next step is to create an event consumer - what you want WMI to do when it detects the event has occurred. | ||||||||||||||
| In our example, you want the WMI permanent event handler COM object to run a script `Monitor.ps1` any time the event occurs. | ||||||||||||||
| So whenever WMI detects a change to the Enterprise admins group, you want WMI to run the script. | ||||||||||||||
|
|
||||||||||||||
| ```powershell | ||||||||||||||
|
|
||||||||||||||
| # 5. Create Monitor.ps1 | ||||||||||||||
|
Comment on lines
+196
to
+197
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. removing blank line |
||||||||||||||
| $MONITOR = @' | ||||||||||||||
| $LogFile = 'C:\Foo\Grouplog.Txt' | ||||||||||||||
| $Group = 'Enterprise Admins' | ||||||||||||||
| "On: [$(Get-Date)] Group [$Group] was changed" | | ||||||||||||||
| Out-File -Force $LogFile -Append -Encoding Ascii | ||||||||||||||
| $ADGM = Get-ADGroupMember -Identity $Group | ||||||||||||||
| # Display who's in the group | ||||||||||||||
| "Group Membership" | ||||||||||||||
| $ADGM | Format-Table Name, DistinguishedName | | ||||||||||||||
| Out-File -Force $LogFile -Append -Encoding Ascii | ||||||||||||||
| $OKUsers = Get-Content -Path C:\Foo\OKUsers.txt | ||||||||||||||
| # Look at who is not authorized | ||||||||||||||
| foreach ($User in $ADGM) { | ||||||||||||||
| if ($User.SamAccountName -notin $OKUsers) { | ||||||||||||||
| "Unauthorized user [$($User.SamAccountName)] added to $Group" | | ||||||||||||||
| Out-File -Force $LogFile -Append -Encoding Ascii | ||||||||||||||
| } | ||||||||||||||
| } | ||||||||||||||
| "**********************************`n`n" | | ||||||||||||||
| Out-File -Force $LogFile -Append -Encoding Ascii | ||||||||||||||
| '@ | ||||||||||||||
| $MONITOR | Out-File -Path C:\Foo\Monitor.ps1 | ||||||||||||||
|
|
||||||||||||||
| # 6. Create a WMI event consumer | ||||||||||||||
| # The consumer runs PowerShell 7 to execute C:\Foo\Monitor.ps1 | ||||||||||||||
| $CLT = 'Pwsh.exe -File C:\Foo\Monitor.ps1' | ||||||||||||||
| $Param =[ordered] @{ | ||||||||||||||
| Name = 'EventConsumer1' | ||||||||||||||
| CommandLineTemplate = $CLT | ||||||||||||||
| } | ||||||||||||||
| $ECHT = @{ | ||||||||||||||
| Namespace = 'ROOT/subscription' | ||||||||||||||
| ClassName = "CommandLineEventConsumer" | ||||||||||||||
| Property = $param | ||||||||||||||
| } | ||||||||||||||
| $InstanceConsumer = New-CimInstance @ECHT | ||||||||||||||
| ``` | ||||||||||||||
|
|
||||||||||||||
| The monitoring script is fairly simple - each time the event occurs, it prints some information to a log file. | ||||||||||||||
| Then it looks to see if the Enterprise Admins group contains unauthorised users - and if so, the script reports that fact to the log file. | ||||||||||||||
| This script is fairly simple, and you can embellish. as needed. | ||||||||||||||
| You could, for example, remove all unauthorised users. | ||||||||||||||
|
Comment on lines
+237
to
+239
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. changed to US ENglish |
||||||||||||||
|
|
||||||||||||||
| To create a WMI event consumer, you add a new occurrence to the **CommandLineEventConsumer** class within the namespace **ROOT/Subscription**. | ||||||||||||||
|
|
||||||||||||||
|
|
||||||||||||||
| ### Binding the Event Filter and the Event Consumer | ||||||||||||||
|
|
||||||||||||||
| With the event filter and event consumer details added to WMI, you need to bind the two - telling WMI to detect THAT event and when it occurs, run THIS script. | ||||||||||||||
| You could pre-create, for example, multiple event filters and event consumers. | ||||||||||||||
| Once the binding is in place, WMI starts the monitoring process. | ||||||||||||||
|
|
||||||||||||||
| ```powershell | ||||||||||||||
|
|
||||||||||||||
| # 7. Bind the filter and consumer | ||||||||||||||
|
Comment on lines
+251
to
+252
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. removed blank line |
||||||||||||||
| $Param = @{ | ||||||||||||||
| Filter = [ref]$InstanceFilter | ||||||||||||||
| Consumer = [ref]$InstanceConsumer | ||||||||||||||
| } | ||||||||||||||
| $IBHT = @{ | ||||||||||||||
| Namespace = 'ROOT/subscription' | ||||||||||||||
| ClassName = '__FilterToConsumerBinding' | ||||||||||||||
| Property = $Param | ||||||||||||||
| } | ||||||||||||||
| $InstanceBinding = New-CimInstance @IBHT | ||||||||||||||
|
|
||||||||||||||
|
Comment on lines
+262
to
+263
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||||||
| ``` | ||||||||||||||
|
|
||||||||||||||
| ### Checking your work | ||||||||||||||
|
|
||||||||||||||
| A great way to check your work is to call the ``Get-WMIPE`` function you create earlier. | ||||||||||||||
| What you should see is: | ||||||||||||||
|
Comment on lines
+268
to
+269
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||||||
|
|
||||||||||||||
| ```powershell-console | ||||||||||||||
|
|
||||||||||||||
| PS > # 8. Viewing the event registration details | ||||||||||||||
|
Comment on lines
+272
to
+273
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. removed blank line |
||||||||||||||
| PS > Get-WMIPE | ||||||||||||||
| *** Event Filters Defined *** | ||||||||||||||
|
|
||||||||||||||
| Name Query | ||||||||||||||
| ---- ----- | ||||||||||||||
| EventFilter1 SELECT * From __InstanceModificationEvent Within 10 | ||||||||||||||
| WHERE TargetInstance ISA 'ds_group' AND | ||||||||||||||
| TargetInstance.ds_name = 'Enterprise Admins' | ||||||||||||||
|
|
||||||||||||||
| ***Consumer Defined *** | ||||||||||||||
|
|
||||||||||||||
| Name CommandLineTemplate | ||||||||||||||
| ---- ------------------- | ||||||||||||||
| EventConsumer1 Pwsh.exe -File C:\Foo\Monitor.ps1 | ||||||||||||||
|
|
||||||||||||||
| ***Bindings Defined *** | ||||||||||||||
|
|
||||||||||||||
| Filter Consumer | ||||||||||||||
| ------ -------- | ||||||||||||||
| __EventFilter (Name = "EventFilter1") CommandLineEventConsumer (Name = "EventConsumer1") | ||||||||||||||
|
|
||||||||||||||
|
Comment on lines
+293
to
+294
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. removed blank line |
||||||||||||||
| ``` | ||||||||||||||
|
|
||||||||||||||
| ### Testing your work | ||||||||||||||
|
|
||||||||||||||
| So having created the event query, the event filter, the event consumer and the filter to consumer binding, you can test your work. | ||||||||||||||
| The easiest way to test this is to add a new user to the group. | ||||||||||||||
| Then, wait a few seconds for WMI to process the event, then look at the output. | ||||||||||||||
| If everything is working correctly, you should see this output: | ||||||||||||||
|
|
||||||||||||||
|
|
||||||||||||||
| ```powershell-console | ||||||||||||||
|
|
||||||||||||||
| PS > # 9. Adding a user to the Enterprise Admins group | ||||||||||||||
|
Comment on lines
+306
to
+307
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||||||
| PS > Add-ADGroupMember -Identity 'Enterprise admins' -Members Malcolm | ||||||||||||||
| PS > | ||||||||||||||
| PS > # 10. Viewing the Grouplog.txt file | ||||||||||||||
| PS > Get-Content -Path C:\Foo\Grouplog.txt | ||||||||||||||
| On: [04/20/2021 15:41:49] Group [Enterprise Admins] was changed | ||||||||||||||
|
|
||||||||||||||
| Name DistinguishedName | ||||||||||||||
| ---- ----------------- | ||||||||||||||
| Malcolm CN=Malcolm,OU=IT,DC=Reskit,DC=Org | ||||||||||||||
| Jerry Garcia CN=Jerry Garcia,OU=IT,DC=Reskit,DC=Org | ||||||||||||||
| Administrator CN=Administrator,CN=Users,DC=Reskit,DC=Org | ||||||||||||||
|
|
||||||||||||||
| Unauthorized user [Malcolm] added to Enterprise Admins | ||||||||||||||
| ********************************** | ||||||||||||||
|
|
||||||||||||||
|
Comment on lines
+321
to
+322
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. removed blank line |
||||||||||||||
| ``` | ||||||||||||||
|
|
||||||||||||||
| ### Troubleshooting | ||||||||||||||
| This code, of course should "just work". | ||||||||||||||
|
Comment on lines
+325
to
+326
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||||||
| If not, you need to perform troubleshooting and here are three things to look for: | ||||||||||||||
| * Is the WQL query correct and correctly formatted? | ||||||||||||||
| * Is the event class you are monitoring in the namespace you think it is in? | ||||||||||||||
| * Is the `Monitor.ps1` script doing what you actually wanted | ||||||||||||||
|
|
||||||||||||||
| You may also find that the **Microsoft-Windows-WMI-Activity/Operational** event log useful in tracking down issues. | ||||||||||||||
|
|
||||||||||||||
| ### Tidying up | ||||||||||||||
|
|
||||||||||||||
| After you play with a WMI filter like this, make sure you clean up. | ||||||||||||||
| You probably don't want the filter to run forever, so remove it as soon as you can. | ||||||||||||||
| To remove it, invoke the ``Remove-WMIPE`` function. | ||||||||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. fixed |
||||||||||||||
| And you should probably remove any inappropriate users from the Enterprise Admins group | ||||||||||||||
|
|
||||||||||||||
| ```powershell | ||||||||||||||
|
|
||||||||||||||
| # 11. Tidying up | ||||||||||||||
|
Comment on lines
+342
to
+343
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. removed blank line. |
||||||||||||||
| Remove-WMIPE # invoke this function you defined above | ||||||||||||||
| $RGMHT = @{ | ||||||||||||||
| Identity = 'Enterprise admins' | ||||||||||||||
| Member = 'Malcolm' | ||||||||||||||
| Confirm = $false | ||||||||||||||
| } | ||||||||||||||
| Remove-ADGroupMember @RGMHT | ||||||||||||||
|
|
||||||||||||||
|
Comment on lines
+350
to
+351
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. removed blank line |
||||||||||||||
| ``` | ||||||||||||||
|
|
||||||||||||||
| This step creates no output. | ||||||||||||||
| You might wish to call Get-WMIPE again to verify all three class occurrences no longer exist. | ||||||||||||||
|
|
||||||||||||||
|
|
||||||||||||||
| ## Summary | ||||||||||||||
|
|
||||||||||||||
| WMI eventing is very powerful and straightforward to implement. | ||||||||||||||
| There are thousands of WMI events you could subscribe to and which may help troubleshooting activities. | ||||||||||||||
| In this case, you are examining unauthorised changers to an AD group. | ||||||||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. fixed |
||||||||||||||
| The WMI documentation does not provide a definitive guide to the events you might be interested in - at least that I can find. | ||||||||||||||
doctordns marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.