Mar 31 2010

Track GPO changes: Monitoring GPT

We will explain in this post how to monitor GPO changes by tracking modifications on the GPT. Only deletion, computer/user configuration modification and creation can be overlooked. About GPO monitoring you can read this article,which shows you how to activate auditing on your Sysvol share \\domainname\sysvol\domainfqdn\Policies and retrieve GPO changes via the eventlog. We will use another method, taking advantage of the replication of this folder.

When GPOs replicate on your domain, GPT part is replicated with the DFS-R system under Windows 2008 and with the FRS system under Windows 2003 (See migration guide here.) The SYSVOL share is modified on every DC when a GPO creation/deletion/configuration modification occurs. So you can control modifications made by administrators on a single DC.

When you create/delete a GPO a folder named \\domainname\sysvol\domainfqdn\Policies\{%GPO_GUID%} is created/deleted. When you modify the computer/user configuration of a GPO the file \\domainname\sysvol\domainfqdn\Policies\{%GPO_GUID%}\gpt.ini is modified, for more information, read this post. The purpose of our script will be to notify us in quasi real time of modifications occuring on those files and folders.

What are the pros and cons of our method in comparison to the eventlog monitoring method?

  • Cons: You should expect a CPU load on the DC where you run the script. You need a lag site if you want to retrieve accurate information when a GPO deletion occurs. You cannot get the username of the person who made the modification. You are notified of GPO modification when the SYSVOL replication occurs on the DC where you run the script.
  • Pros: If you want to track in real time the security log of your DCs you need a Syslog software (like Kiwi or Snare), but you need to pay for that. You need to activate auditing and install a Snare service on every DC, our script runs on just one DC.

So, how do you create a service (script) that will monitor GPO changes on your domain? For this you will need WMI code creator, this tool will help to create a script that tracks {%GPO_GUID%} folder creation/deletion and {%GPO_GUID%}gpt.ini file modification on the sysvol share.

We will use WMI asynchronous event monitoring. You just need to follow those steps to monitor the creation of {%GPO_GUID%}: folders.

During step 5 you need to input the name of the root folder you are monitoring :‘Win32_Directory.Name=””F:\WINDOWS\SYSVOL\domain\Policies””‘”, that contains all the subfolders {%GPO_GUID%} created.

And here we have our WMI asynchronous event query:

For more information about this method you can browse this webpage.
Now we can monitor {%GPO_GUID%} folder creation/deletion, we just need to retrieve the GPO display name with an LDAP query by using this script:

On error resume next
strComputer = "."
DomainDN = "DC=ldap389,DC=info"
DomainDNSFQDN = "ldap389.info"
LAGDC = "LAG_DC"
BackupLocationTool = "G:Tool"
Const ForAppending = 8
Set FSO = CreateObject("Scripting.FileSystemObject")
 
Set objWMIService = GetObject("winmgmts:" & strComputer & "rootCIMV2")
Set MySink = WScript.CreateObject( _
    "WbemScripting.SWbemSink","SINK_")
 
Set MySink2 = WScript.CreateObject( _
    "WbemScripting.SWbemSink","SINK2_")
 
objWMIservice.ExecNotificationQueryAsync MySink, _
    "SELECT * FROM __InstanceCreationEvent WITHIN 60 WHERE " & _
                    "TargetInstance ISA 'Win32_SubDirectory'" & _
                    " AND TargetInstance.GroupComponent = 'Win32_Directory.Name=""F:\WINDOWS\SYSVOL\domain\Policies""'"
 
objWMIservice.ExecNotificationQueryAsync MySink2, _
    "SELECT * FROM __InstanceDeletionEvent WITHIN 60 WHERE " & _
                    "TargetInstance ISA 'Win32_SubDirectory'" & _
                    " AND TargetInstance.GroupComponent = 'Win32_Directory.Name=""F:\WINDOWS\SYSVOL\domain\Policies""'
 
While (True)
    Wscript.Sleep(1000)
Wend
 
Sub SINK_OnObjectReady(objObject, objAsyncContext)
	gpofullpath = objObject.TargetInstance.Properties_.item("PartComponent").value
	gpoid1 = split(lcase(gpofullpath),"policies")
	gpouid = replace(gpoid1(1),chr(34),"")
 
	strGPODN = "CN="&gpouid&",CN=Policies,CN=System,"&DomainDN
 
		Set objGPO = GetObject("LDAP://" & strGPODN)
		StrGPOName = objGPO.DisplayName
 
	Set df80 = FSO.OpenTextFile(BackupLocationTool&"GPM-Modified.log",ForAppending)
	df80.writeline(now&";CREATED;"&gpouid&";"&StrGPOName)
	df80.close
End Sub
 
Sub SINK2_OnObjectReady(objObject, objAsyncContext)
    gpofullpath = objObject.TargetInstance.Properties_.item("PartComponent").value
StrGPOName = "N/A"
	gpoid1 = split(lcase(gpofullpath),"policies")
	gpouid = replace(gpoid1(1),chr(34),"")
		if LAGDC <> "" then
		strGPODN = "CN="&gpouid&",CN=Policies,CN=System,"&DomainDN
		err.clear
		Set objGPO = GetObject("LDAP://" &LAGDC&"/"&strGPODN)
		if err.number <> 0 then
		StrGPOName = "N/A"
		else
		StrGPOName = objGPO.DisplayName
		End if
		End if
	Set df80 = FSO.OpenTextFile(BackupLocationTool&"GPM-Modified.log",ForAppending)
df80.writeline(now&";DELETED;"&gpouid&";"&StrGPOName)
df80.close
End Sub
 
Sub SINK_OnCompleted(objObject, objAsyncContext)
End Sub

Download vbs script here (recomanded):

You will need to change the following values on the script:

  • DomainDN = “DC=ldap389,DC=info”, Your domain Distinguished Name.
  • DomainDNSFQDN = “ldap389.info”, fully qualified domain name
  • BackupLocationTool = “G:Tool”, Folder where the script runs.
  • LAGDC = “LAG_DC”, If you want to get GPO friendly name and not GUID when a deletion occurs you will need a Lag site, the DC with delayed replication will help you to get deleted GPO displayname, because attribute might be already deleted on other DCs.If you do not have a lag site just input LAGDC = “”

We now want to monitor modifications happening on GPT.INI files that are located on the SYSVOL share, we will use the following script:

objWMIservice.ExecNotificationQueryAsync MySink3, _
    "SELECT * FROM __InstanceModificationEvent WITHIN 60 WHERE " & _
                    "TargetInstance ISA 'CIM_DataFile'" & _
                    " AND TargetInstance.Drive = 'F:'" & _
                    " AND TargetInstance.Extension = 'ini'" & _
                    " AND TargetInstance.FileName = 'gpt'"
 
Sub SINK3_OnObjectReady(objObject, objAsyncContext)
 
if objObject.TargetInstance.Properties_.item("LastModified").value <> objObject.PreviousInstance.Properties_.item("LastModified").value then
	gpofullpath = objObject.TargetInstance.Properties_.item("Name").value
 
	if instr(gpofullpath,DomainDNSFQDN) = 0 then
 
		gpoid1 = split(lcase(gpofullpath),"policies")
 
		gpoid2 = split(lcase(gpoid1(1)),"gpt.in")
		gpouid = gpoid2(0)
 
		strGPODN = "CN="&gpouid&",CN=Policies,CN=System,"&DomainDN
		Set objGPO = GetObject("LDAP://" & strGPODN)
		StrGPOName = objGPO.DisplayName
 
	End if
End if
 
End Sub

Download vbs script here (recomanded for syntax problem in plug-in):

If you want to know more on how to monitor changes on the file system you can read this post. Once you have adapted the script to your needs it will run on a SYSVOL that is not too big otherwise you might encounter performance problems.

If you have thousands of GPOs in your domain, your script has to monitor loads of folders and files and you might reach a WMI quota. You will get this kind of error message: wmi quota violation 0x8004106C (check WMI error codes here). When monitoring 3500 GPOs our script crashed with this error after a few minutes. We used wbemtest.exe to change some values in the __ArbitratorConfiguration super class. We used the following rule: %Total = %PerUser. This way the account running the service (script) will not be limited by a user quota, the quota limitation will just be the total. In that case you should expect an additional CPU/Memory load on your DC. Here is a CPU Graph (dual core 2,5Ghz) monitoring 3500 GPOs.

We will now need to create a Windows service from a script: Just read this tutorial which is really well explained. We just followed the different steps explained in the post.

You can also add a dependence on the WMI service. Your service will not start until WMI is ready:

That’s it, your service can monitor SYSVOL changes. You can be aware of GPT changes occurring in your domain. Next post will show how to monitor Group Policy Links, for this we will use the GPLink attribute which is enabled in default audit settings. Just see this tab:

Once you can monitor GPLinks changes on a OU/site/domain you will be able, in combination with GPT modification information, to get all major changes on your GPOs:

  • GPO creations
  • GPO deletions
  • User/Computer settings modifications
  • GPO Link modification

This post is also available in: French

No Comments

No comments yet.

RSS feed for comments on this post. TrackBack URI

Leave a comment

*

WordPress Themes

Blossom Icon Set

Software Top Blogs