# GPOAudit.ps1 # Advanced Audit Policy (audit.csv) with subcategory GUID lookup table. # Depends on: GPOCore.ps1 (Get-GPOSysvolPath, Add-GPOExtensionGuids) # Well-known subcategory GUIDs -- static across all Windows versions. $Script:AuditSubcategoryGuid = @{ # System 'Security State Change' = '{0CCE9210-69AE-11D9-BED3-505054503030}' 'Security System Extension' = '{0CCE9211-69AE-11D9-BED3-505054503030}' 'System Integrity' = '{0CCE9212-69AE-11D9-BED3-505054503030}' 'IPsec Driver' = '{0CCE9213-69AE-11D9-BED3-505054503030}' 'Other System Events' = '{0CCE9214-69AE-11D9-BED3-505054503030}' # Logon/Logoff 'Logon' = '{0CCE9215-69AE-11D9-BED3-505054503030}' 'Logoff' = '{0CCE9216-69AE-11D9-BED3-505054503030}' 'Account Lockout' = '{0CCE9217-69AE-11D9-BED3-505054503030}' 'IPsec Main Mode' = '{0CCE9218-69AE-11D9-BED3-505054503030}' 'IPsec Quick Mode' = '{0CCE9219-69AE-11D9-BED3-505054503030}' 'IPsec Extended Mode' = '{0CCE921A-69AE-11D9-BED3-505054503030}' 'Special Logon' = '{0CCE921B-69AE-11D9-BED3-505054503030}' 'Other Logon/Logoff Events' = '{0CCE921C-69AE-11D9-BED3-505054503030}' 'Network Policy Server' = '{0CCE9243-69AE-11D9-BED3-505054503030}' 'User / Device Claims' = '{0CCE9247-69AE-11D9-BED3-505054503030}' 'Group Membership' = '{0CCE9249-69AE-11D9-BED3-505054503030}' # Object Access 'File System' = '{0CCE921D-69AE-11D9-BED3-505054503030}' 'Registry' = '{0CCE921E-69AE-11D9-BED3-505054503030}' 'Kernel Object' = '{0CCE921F-69AE-11D9-BED3-505054503030}' 'SAM' = '{0CCE9220-69AE-11D9-BED3-505054503030}' 'Certification Services' = '{0CCE9221-69AE-11D9-BED3-505054503030}' 'Application Generated' = '{0CCE9222-69AE-11D9-BED3-505054503030}' 'Handle Manipulation' = '{0CCE9223-69AE-11D9-BED3-505054503030}' 'File Share' = '{0CCE9224-69AE-11D9-BED3-505054503030}' 'Filtering Platform Packet Drop' = '{0CCE9225-69AE-11D9-BED3-505054503030}' 'Filtering Platform Connection' = '{0CCE9226-69AE-11D9-BED3-505054503030}' 'Other Object Access Events' = '{0CCE9227-69AE-11D9-BED3-505054503030}' 'Detailed File Share' = '{0CCE9244-69AE-11D9-BED3-505054503030}' 'Removable Storage' = '{0CCE9245-69AE-11D9-BED3-505054503030}' 'Central Policy Staging' = '{0CCE9246-69AE-11D9-BED3-505054503030}' # Privilege Use 'Sensitive Privilege Use' = '{0CCE9228-69AE-11D9-BED3-505054503030}' 'Non Sensitive Privilege Use' = '{0CCE9229-69AE-11D9-BED3-505054503030}' 'Other Privilege Use Events' = '{0CCE922A-69AE-11D9-BED3-505054503030}' # Detailed Tracking 'Process Creation' = '{0CCE922B-69AE-11D9-BED3-505054503030}' 'Process Termination' = '{0CCE922C-69AE-11D9-BED3-505054503030}' 'DPAPI Activity' = '{0CCE922D-69AE-11D9-BED3-505054503030}' 'RPC Events' = '{0CCE922E-69AE-11D9-BED3-505054503030}' 'Plug and Play Events' = '{0CCE9248-69AE-11D9-BED3-505054503030}' # Policy Change 'Audit Policy Change' = '{0CCE922F-69AE-11D9-BED3-505054503030}' 'Authentication Policy Change' = '{0CCE9230-69AE-11D9-BED3-505054503030}' 'Authorization Policy Change' = '{0CCE9231-69AE-11D9-BED3-505054503030}' 'MPSSVC Rule-Level Policy Change' = '{0CCE9232-69AE-11D9-BED3-505054503030}' 'Filtering Platform Policy Change' = '{0CCE9233-69AE-11D9-BED3-505054503030}' 'Other Policy Change Events' = '{0CCE9234-69AE-11D9-BED3-505054503030}' # Account Management 'User Account Management' = '{0CCE9235-69AE-11D9-BED3-505054503030}' 'Computer Account Management' = '{0CCE9236-69AE-11D9-BED3-505054503030}' 'Security Group Management' = '{0CCE9237-69AE-11D9-BED3-505054503030}' 'Distribution Group Management' = '{0CCE9238-69AE-11D9-BED3-505054503030}' 'Application Group Management' = '{0CCE9239-69AE-11D9-BED3-505054503030}' 'Other Account Management Events' = '{0CCE923A-69AE-11D9-BED3-505054503030}' # DS Access 'Directory Service Access' = '{0CCE923B-69AE-11D9-BED3-505054503030}' 'Directory Service Changes' = '{0CCE923C-69AE-11D9-BED3-505054503030}' 'Directory Service Replication' = '{0CCE923D-69AE-11D9-BED3-505054503030}' 'Detailed Directory Service Replication' = '{0CCE923E-69AE-11D9-BED3-505054503030}' # Account Logon 'Credential Validation' = '{0CCE923F-69AE-11D9-BED3-505054503030}' 'Kerberos Service Ticket Operations' = '{0CCE9240-69AE-11D9-BED3-505054503030}' 'Other Account Logon Events' = '{0CCE9241-69AE-11D9-BED3-505054503030}' 'Kerberos Authentication Service' = '{0CCE9242-69AE-11D9-BED3-505054503030}' } # Maps human-readable setting strings to numeric values for audit.csv $Script:AuditSettingValue = @{ 'No Auditing' = 0 'Success' = 1 'Failure' = 2 'Success and Failure' = 3 } function Set-GPOAdvancedAuditPolicy { <# .SYNOPSIS Writes an Advanced Audit Policy (audit.csv) to a GPO's SYSVOL path. This provides subcategory-level audit control (53 subcategories) instead of the 9 legacy Event Audit categories. #> param( [Parameter(Mandatory)] [string]$GPOName, [Parameter(Mandatory)] [hashtable]$AuditPolicy, [string]$Domain = (Get-ADDomain).DNSRoot ) $sysvolPath = Get-GPOSysvolPath -GPOName $GPOName -Domain $Domain $auditDir = Join-Path $sysvolPath 'Machine\Microsoft\Windows NT\Audit' $auditCsvPath = Join-Path $auditDir 'audit.csv' if (-not (Test-Path $auditDir)) { New-Item -ItemType Directory -Path $auditDir -Force | Out-Null } # Build CSV content $sb = [System.Text.StringBuilder]::new() [void]$sb.AppendLine('Machine Name,Policy Target,Subcategory,Subcategory GUID,Inclusion Setting,Exclusion Setting,Setting Value') foreach ($subcategory in $AuditPolicy.Keys) { $guid = $Script:AuditSubcategoryGuid[$subcategory] if (-not $guid) { Write-Host " [WARN] Unknown audit subcategory: '$subcategory'" -ForegroundColor Yellow continue } $settingName = $AuditPolicy[$subcategory] $settingValue = $Script:AuditSettingValue[$settingName] if ($null -eq $settingValue) { Write-Host " [WARN] Unknown audit setting value: '$settingName' for '$subcategory'" -ForegroundColor Yellow continue } [void]$sb.AppendLine(",System,$subcategory,$guid,$settingName,,$settingValue") } # audit.csv uses UTF-8 with BOM $utf8Bom = [System.Text.UTF8Encoding]::new($true) [System.IO.File]::WriteAllText($auditCsvPath, $sb.ToString(), $utf8Bom) Write-Host " Written: $auditCsvPath" -ForegroundColor Green Write-Host " $($AuditPolicy.Count) audit subcategory setting(s) configured." -ForegroundColor Green # Register Audit Policy CSE GUID $auditCseGuid = '{F3BC9527-C350-4C90-861C-1EC90034520B}' $auditToolGuid = '{D02B1F72-3407-48AE-BA88-E8213C6761F1}' Add-GPOExtensionGuids -GPOName $GPOName -CseGuid $auditCseGuid -ToolGuid $auditToolGuid -Scope Machine -Domain $Domain } function Compare-GPOAdvancedAuditPolicy { <# .SYNOPSIS Compares desired Advanced Audit Policy settings against the current audit.csv in SYSVOL. Returns diff objects for mismatches. #> param( [Parameter(Mandatory)] [string]$GPOName, [Parameter(Mandatory)] [hashtable]$AuditPolicy, [string]$Domain = (Get-ADDomain).DNSRoot ) $sysvolPath = Get-GPOSysvolPath -GPOName $GPOName -Domain $Domain $auditCsvPath = Join-Path $sysvolPath 'Machine\Microsoft\Windows NT\Audit\audit.csv' $diffs = @() Write-Host " Comparing advanced audit policy..." -ForegroundColor Yellow # Parse existing audit.csv into a lookup $currentSettings = @{} if (Test-Path $auditCsvPath) { $csvLines = [System.IO.File]::ReadAllLines($auditCsvPath, [System.Text.UTF8Encoding]::new($true)) foreach ($line in $csvLines) { # Skip header and empty lines if ($line -match '^Machine Name,' -or [string]::IsNullOrWhiteSpace($line)) { continue } $fields = $line -split ',' if ($fields.Count -ge 5) { $subcategory = $fields[2].Trim() $inclusionSetting = $fields[4].Trim() $currentSettings[$subcategory] = $inclusionSetting } } } foreach ($subcategory in $AuditPolicy.Keys) { $guid = $Script:AuditSubcategoryGuid[$subcategory] if (-not $guid) { continue } $desired = $AuditPolicy[$subcategory] $current = $currentSettings[$subcategory] if ($current -ne $desired) { $currentDisplay = if ($null -eq $current) { '(not set)' } else { $current } Write-Host " [DRIFT] $subcategory`: '$currentDisplay' -> '$desired'" -ForegroundColor Red $diffs += [PSCustomObject]@{ Type = 'AdvancedAudit' Subcategory = $subcategory Current = $currentDisplay Desired = $desired } } } if ($diffs.Count -eq 0) { Write-Host " [OK] Advanced audit policy matches desired state" -ForegroundColor Green } else { Write-Host " [DRIFT] $($diffs.Count) audit policy difference(s) found" -ForegroundColor Red } return $diffs }