How to Track Active Directory Changes with WMI Events

Published:5 May 2021 - 4 min. read

Azure Cloud Labs: these FREE, on‑demand Azure Cloud Labs will get you into a real‑world environment and account, walking you through step‑by‑step how to best protect, secure, and recover Azure data.

Active Directory is a critical component of many organizations. It can also get overwhelming containing hundreds of thousands of objects changing constantly. Luckily, you can track Active Directory changes with some PowerShell expertise and a little time.

In this tutorial, you’re going to learn how to use WMI events to track Active Directory changes and keep you in the know about what’s going on with your Active Directory objects!

Prerequisites

This article will be a hands-on tutorial. If you’d like to follow along, be sure you have the following:

  • An Active Directory domain – This tutorial will use Windows Server 2019 with an Active Directory and forest functional level set to 2019, but domain controllers (DCs) running Windows 2008 R2 or later should work. The tutorial will be using a domain called test.local with two DCs, DC01 and DC02.
  • A domain-joined Windows PC with PowerShell installed. This tutorial will use Windows 10 with Windows PowerShell v5.1 or PowerShell 7.
  • PowerShell Active Directory Module.
  • A user account as a member of the Domain Admins groups in the domain.

Finding Active Directory Groups with WMI

Before you can get notified when an object changes in Active Directory, you must first know the WMI class that the WMI event will show up in and query group members. To do that, on a DC:

1. Open PowerShell.

2. Run Get-CimClass to connect to the namespace and find all available classes in the namespace. In the CimClassName column, you’ll see a ds_group. This class lists all groups in Active Directory and their attributes.

Get-CimClass -Namespace 'ROOT\Directory\LDAP'
ds_group Active Directory WMI attribute
ds_group Active Directory WMI attribute

3. Now, run Get-CimInstance to find all instances of the ds_group class which will return the cn property of each group.

Get-CimInstance -Namespace 'root\directory\ldap' -ClassName ds_group | Select-Object -Property DS_cn
All AD groups in the ds_group WMI class
All AD groups in the ds_group WMI class

Creating a WMI Event Subscription

Now that you know where to find the groups in WMI, the next step is set up a WMI event subscription to “listen” for changes to those WMI instances. To monitor for a specific event (like a change to an Active Directory group), you must subscribe to the WMI event.

You can subscribe to many different types of WMI events from creation, removal, and modification events. In this case, you need to know when a CIM instance (AD group) is modified. In that case, you’ll use a class named CIM_InstModification. The CIM_InstModification class monitors any CIM instance for modifications.

Develop the WQL Query

To set up the WMI event subscription, you must first develop a WQL query. WQL is a simple language dedicated to WMI that allows you to find WMI instances in a SQL-like syntax. In this example, the query you’re looking for looks like the below example.

The below WQL query will look for all events that modify instances matching the name of DS_group. You’ll also notice the within operator. This operator is the polling interval telling Windows to check for new events every 10 seconds.

Select * from CIM_InstModification within 10 where TargetInstance ISA 'DS_group'

You can also query for changes to specific AD groups by including more conditions such as adding AND TargetInstance.ds_cn='Enterprise Admins' to the end of your WQL statement.

Create the WMI Subscription in PowerShell

Now that you’ve crafted the WQL query, the next step is to drop into PowerShell and use it to subscribe to the event. To do that:

1. Open PowerShell on the domain controller.

2. Create a variable called $query assigning the query you just came up with as the value.

$query = "Select * from CIM_InstModification within 10 where TargetInstance ISA 'DS_group'"

3. Use that query to create the subscription (register the event) using the Register-CimIndicationEvent cmdlet. The below command registers a WMI subscription called GroupMonitoring using the query to limit results to only DS_Group modification events within the ROOT\directory\LDAP namespace.

Register-CimIndicationEvent -Query $query -SourceIdentifier 'GroupMonitoring' -MessageData 'Group Info Changed' -Namespace 'ROOT\directory\LDAP'

Register-CimIndicationEvent creates a temporary WMI event subscription. When you close the PowerShell console, the subscription will no longer be active. Use a permanent event subscription to monitor AD groups long term.

4. Now, confirm you’ve successfully registered a subscription by running Get-EventSubscriber which should return an object that looks like below.

The Get-EventSubscriber output.
The Get-EventSubscriber output.

Reading WMI Events

Windows should now be monitoring all modification events to all Active Directory groups. To test this, let’s now add a member to a group and see what happens.

Assuming you’re still in PowerShell on the DC:

1. Run the Add-ADGroupMember cmdlet to add a user to the Enterprise Admins group. The below example is adding a user account named User2.

After 10 seconds or so, the event should have fired you set up a subscription for earlier.

Add-ADGroupMember -Identity 'Enterprise Admins' -Members User2

2. To find the event, run the Get-Event cmdlet to search for all newly registered events. If all goes well, you should then see output similar to the below screenshot. In the screenshot, the SourceInstance is the current value of the object attribute. The PreviousInstance value is the previous value of the object attribute.

(Get-Event).SourceEventArgs.newevent
Running Get-Event to see the event.
Running Get-Event to see the event.

3. Now, narrow down the result and only display the current alert values as shown below. You will now see the current list of group members in the Enterprise Admins group.

(Get-Event).SourceEventArgs.newevent.SourceInstance | Select-Object -Property ds_member
The current value of the Enterprise Admins Group
The current value of the Enterprise Admins Group

If you’d like to get the value before the change happened, look at the PreviousInstance object’s DS_Member property as shown below.

(Get-Event).SourceEventArgs.newevent.PreviousInstance | select DS_member
Previous Instance
Previous Instance

Conclusion

Now that you know how to set up a WMI event subscription to track Active Directory changes, you can take this PowerShell code and build a monitoring script from it.

See if you can now build a monitoring tool by perhaps logging these events to the Windows event log with the New-WinEvent cmdlet or sending an email with Send-MailMessage!

Hate ads? Want to support the writer? Get many of our tutorials packaged as an ATA Guidebook.

Explore ATA Guidebooks

Looks like you're offline!