AuditPolicy.psm1
function Get-PSRegistry { <# .SYNOPSIS Get registry key values. .DESCRIPTION Get registry key values. .PARAMETER RegistryPath The registry path to get the values from. .PARAMETER ComputerName The computer to get the values from. If not specified, the local computer is used. .EXAMPLE Get-PSRegistry -RegistryPath 'HKLM\SYSTEM\CurrentControlSet\Services\Netlogon\Parameters' -ComputerName AD1 .EXAMPLE Get-PSRegistry -RegistryPath 'HKLM\SYSTEM\CurrentControlSet\Services\Netlogon\Parameters' .EXAMPLE Get-PSRegistry -RegistryPath "HKLM\SYSTEM\CurrentControlSet\Services\DFSR\Parameters" -ComputerName AD1,AD2,AD3 | ft -AutoSize .EXAMPLE Get-PSRegistry -RegistryPath 'HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\EventLog\Directory Service' .EXAMPLE Get-PSRegistry -RegistryPath 'HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\EventLog\Windows PowerShell' | Format-Table -AutoSize .EXAMPLE Get-PSRegistry -RegistryPath 'HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\EventLog\Directory Service' -ComputerName AD1 -Advanced .EXAMPLE Get-PSRegistry -RegistryPath "HKLM:\Software\Microsoft\Powershell\1\Shellids\Microsoft.Powershell\" .EXAMPLE # Get default key and it's value Get-PSRegistry -RegistryPath "HKEY_CURRENT_USER\Tests" -Key "" .EXAMPLE # Get default key and it's value (alternative) o Get-PSRegistry -RegistryPath "HKEY_CURRENT_USER\Tests" -DefaultKey .NOTES General notes #> [cmdletbinding()] param([alias('Path')][string[]] $RegistryPath, [string[]] $ComputerName = $Env:COMPUTERNAME, [string] $Key, [switch] $Advanced, [switch] $DefaultKey) Get-PSRegistryDictionaries $RegistryPath = foreach ($R in $RegistryPath) { If ($R -like '*:*') { foreach ($DictionaryKey in $Script:Dictionary.Keys) { if ($R.StartsWith($DictionaryKey, [System.StringComparison]::CurrentCultureIgnoreCase)) { $R -replace $DictionaryKey, $Script:Dictionary[$DictionaryKey] break } } } else { $R } } [Array] $Computers = Get-ComputerSplit -ComputerName $ComputerName [Array] $RegistryTranslated = Get-PSConvertSpecialRegistry -RegistryPath $RegistryPath -Computers $ComputerName -HiveDictionary $Script:HiveDictionary if ($PSBoundParameters.ContainsKey("Key") -or $DefaultKey) { [Array] $RegistryValues = Get-PSSubRegistryTranslated -RegistryPath $RegistryTranslated -HiveDictionary $Script:HiveDictionary -Key $Key foreach ($Computer in $Computers[0]) { foreach ($R in $RegistryValues) { Get-PSSubRegistry -Registry $R -ComputerName $Computer } } foreach ($Computer in $Computers[1]) { foreach ($R in $RegistryValues) { Get-PSSubRegistry -Registry $R -ComputerName $Computer -Remote } } } else { [Array] $RegistryValues = Get-PSSubRegistryTranslated -RegistryPath $RegistryTranslated -HiveDictionary $Script:HiveDictionary foreach ($Computer in $Computers[0]) { foreach ($R in $RegistryValues) { Get-PSSubRegistryComplete -Registry $R -ComputerName $Computer -Advanced:$Advanced } } foreach ($Computer in $Computers[1]) { foreach ($R in $RegistryValues) { Get-PSSubRegistryComplete -Registry $R -ComputerName $Computer -Remote -Advanced:$Advanced } } } } function Set-PSRegistry { <# .SYNOPSIS Sets/Updates registry entries locally and remotely using .NET methods. .DESCRIPTION Sets/Updates registry entries locally and remotely using .NET methods. If the registry path to key doesn't exists it will be created. .PARAMETER ComputerName The computer to run the command on. Defaults to local computer. .PARAMETER RegistryPath Registry Path to Update .PARAMETER Type Registry type to use. Options are: REG_SZ, REG_EXPAND_SZ, REG_BINARY, REG_DWORD, REG_MULTI_SZ, REG_QWORD, string, expandstring, binary, dword, multistring, qword .PARAMETER Key Registry key to set. If the path to registry key doesn't exists it will be created. .PARAMETER Value Registry value to set. .PARAMETER Suppress Suppresses the output of the command. By default the command outputs PSObject with the results of the operation. .EXAMPLE Set-PSRegistry -RegistryPath 'HKLM\SYSTEM\CurrentControlSet\Services\NTDS\Diagnostics' -Type REG_DWORD -Key "16 LDAP Interface Events" -Value 2 -ComputerName AD1 .EXAMPLE Set-PSRegistry -RegistryPath 'HKLM\SYSTEM\CurrentControlSet\Services\NTDS\Diagnostics' -Type REG_SZ -Key "LDAP Interface Events" -Value 'test' -ComputerName AD1 .EXAMPLE Set-PSRegistry -RegistryPath "HKCU:\\Tests" -Key "LimitBlankPass1wordUse" -Value "0" -Type REG_DWORD .EXAMPLE Set-PSRegistry -RegistryPath "HKCU:\\Tests\MoreTests\Tests1" -Key "LimitBlankPass1wordUse" -Value "0" -Type REG_DWORD .EXAMPLE # Setting default value $ValueData = [byte[]] @( 0, 1, 0, 0, 9, 0, 0, 0, 128, 0, 0, 0, 3, 0, 3, 0, 3, 0, 3, 0, 3, 0, 3, 0, 3, 0, 3, 0, 3, 0, 3, 0, 3, 0, 3, 0, 3, 0, 3, 0, 3, 0, 3, 0, 3, 0, 3, 0, 3, 0, 3, 0, 3, 0, 3, 0, 3, 0, 3, 0, 3, 0, 3, 0, 3, 0, 3, 0, 3, 0, 3, 0, 3, 0, 3, 0, 3, 0, 3, 0, 3, 0, 3, 0, 3, 0, 3, 0, 3, 0, 3, 0, 3, 0, 3, 0, 3, 0, 3, 0, 3, 0, 3, 0, 3, 0, 3, 0, 3, 0, 3, 0, 3, 0, 3, 0, 3, 0, 3, 0, 3, 0, 3, 0, 3, 0, 0, 0, 5, 0, 10, 0, 14, 0, 3, 0, 5, 0, 6, 0, 6, 0, 4, 0, 4, 0 ) Set-PSRegistry -RegistryPath "HKEY_CURRENT_USER\Tests" -Key '' -Value $ValueData -Type 'NONE' .NOTES General notes #> [cmdletbinding(SupportsShouldProcess)] param([string[]] $ComputerName = $Env:COMPUTERNAME, [Parameter(Mandatory)][string] $RegistryPath, [Parameter(Mandatory)][ValidateSet('REG_SZ', 'REG_NONE', 'None', 'REG_EXPAND_SZ', 'REG_BINARY', 'REG_DWORD', 'REG_MULTI_SZ', 'REG_QWORD', 'string', 'binary', 'dword', 'qword', 'multistring', 'expandstring')][string] $Type, [Parameter()][string] $Key, [Parameter(Mandatory)][object] $Value, [switch] $Suppress) Get-PSRegistryDictionaries [Array] $ComputersSplit = Get-ComputerSplit -ComputerName $ComputerName If ($RegistryPath -like '*:*') { foreach ($DictionaryKey in $Script:Dictionary.Keys) { if ($RegistryPath.StartsWith($DictionaryKey, [System.StringComparison]::CurrentCultureIgnoreCase)) { $RegistryPath = $RegistryPath -replace $DictionaryKey, $Script:Dictionary[$DictionaryKey] break } } } $RegistryPath = $RegistryPath.Replace("\\", "\").Replace("\\", "\") [Array] $RegistryTranslated = Get-PSConvertSpecialRegistry -RegistryPath $RegistryPath -Computers $ComputerName -HiveDictionary $Script:HiveDictionary foreach ($Registry in $RegistryTranslated) { $RegistryValue = Get-PrivateRegistryTranslated -RegistryPath $Registry -HiveDictionary $Script:HiveDictionary -Key $Key -Value $Value -Type $Type -ReverseTypesDictionary $Script:ReverseTypesDictionary if ($RegistryValue.HiveKey) { foreach ($Computer in $ComputersSplit[0]) { Set-PrivateRegistry -RegistryValue $RegistryValue -Computer $Computer -Suppress:$Suppress.IsPresent -ErrorAction $ErrorActionPreference -WhatIf:$WhatIfPreference } foreach ($Computer in $ComputersSplit[1]) { Set-PrivateRegistry -RegistryValue $RegistryValue -Computer $Computer -Remote -Suppress:$Suppress.IsPresent -ErrorAction $ErrorActionPreference -WhatIf:$WhatIfPreference } } else { if ($PSBoundParameters.ErrorAction -eq 'Stop') { throw } else { Write-Warning "Set-PSRegistry - Setting registry to $Registry have failed. Couldn't translate HIVE." } } } } function Get-ComputerSplit { [CmdletBinding()] param([string[]] $ComputerName) if ($null -eq $ComputerName) { $ComputerName = $Env:COMPUTERNAME } try { $LocalComputerDNSName = [System.Net.Dns]::GetHostByName($Env:COMPUTERNAME).HostName } catch { $LocalComputerDNSName = $Env:COMPUTERNAME } $ComputersLocal = $null [Array] $Computers = foreach ($Computer in $ComputerName) { if ($Computer -eq '' -or $null -eq $Computer) { $Computer = $Env:COMPUTERNAME } if ($Computer -ne $Env:COMPUTERNAME -and $Computer -ne $LocalComputerDNSName) { $Computer } else { $ComputersLocal = $Computer } } , @($ComputersLocal, $Computers) } function Get-PrivateRegistryTranslated { [cmdletBinding()] param([Array] $RegistryPath, [System.Collections.IDictionary] $HiveDictionary, [System.Collections.IDictionary] $ReverseTypesDictionary, [Parameter(Mandatory)][ValidateSet('REG_SZ', 'REG_NONE', 'None', 'REG_EXPAND_SZ', 'REG_BINARY', 'REG_DWORD', 'REG_MULTI_SZ', 'REG_QWORD', 'string', 'binary', 'dword', 'qword', 'multistring', 'expandstring')][string] $Type, [Parameter()][string] $Key, [Parameter(Mandatory)][object] $Value) foreach ($Registry in $RegistryPath) { if ($Registry -is [string]) { $Registry = $Registry.Replace("\\", "\").Replace("\\", "\").TrimStart("\").TrimEnd("\") } else { $Registry.RegistryPath = $Registry.RegistryPath.Replace("\\", "\").Replace("\\", "\").TrimStart("\").TrimEnd("\") } foreach ($Hive in $HiveDictionary.Keys) { if ($Registry -is [string] -and $Registry.StartsWith($Hive, [System.StringComparison]::CurrentCultureIgnoreCase)) { if ($Hive.Length -eq $Registry.Length) { [ordered] @{HiveKey = $HiveDictionary[$Hive] SubKeyName = $null ValueKind = [Microsoft.Win32.RegistryValueKind]::($ReverseTypesDictionary[$Type]) Key = $Key Value = $Value } } else { [ordered] @{HiveKey = $HiveDictionary[$Hive] SubKeyName = $Registry.substring($Hive.Length + 1) ValueKind = [Microsoft.Win32.RegistryValueKind]::($ReverseTypesDictionary[$Type]) Key = $Key Value = $Value } } break } elseif ($Registry -isnot [string] -and $Registry.RegistryPath.StartsWith($Hive, [System.StringComparison]::CurrentCultureIgnoreCase)) { if ($Hive.Length -eq $Registry.RegistryPath.Length) { [ordered] @{ComputerName = $Registry.ComputerName HiveKey = $HiveDictionary[$Hive] SubKeyName = $null ValueKind = [Microsoft.Win32.RegistryValueKind]::($ReverseTypesDictionary[$Type]) Key = $Key Value = $Value } } else { [ordered] @{ComputerName = $Registry.ComputerName HiveKey = $HiveDictionary[$Hive] SubKeyName = $Registry.RegistryPath.substring($Hive.Length + 1) ValueKind = [Microsoft.Win32.RegistryValueKind]::($ReverseTypesDictionary[$Type]) Key = $Key Value = $Value } } break } } } } function Get-PSConvertSpecialRegistry { [cmdletbinding()] param([Array] $RegistryPath, [Array] $Computers, [System.Collections.IDictionary] $HiveDictionary) $FixedPath = foreach ($R in $RegistryPath) { foreach ($DictionaryKey in $HiveDictionary.Keys) { if ($R.StartsWith($DictionaryKey, [System.StringComparison]::CurrentCultureIgnoreCase)) { if ($HiveDictionary[$DictionaryKey] -in 'All', 'All+Default', 'Default', 'AllDomain+Default', 'AllDomain') { foreach ($Computer in $Computers) { $SubKeys = Get-PSRegistry -RegistryPath "HKEY_USERS" -ComputerName $Computer if ($SubKeys.PSSubKeys) { $RegistryKeys = ConvertTo-HKeyUser -SubKeys ($SubKeys.PSSubKeys | Sort-Object) -HiveDictionary $HiveDictionary -DictionaryKey $DictionaryKey foreach ($S in $RegistryKeys) { [PSCustomObject] @{ComputerName = $Computer RegistryPath = $S Error = $null ErrorMessage = $null } } } else { [PSCustomObject] @{ComputerName = $Computer RegistryPath = $R Error = $true ErrorMessage = "Couldn't connect to $Computer to list HKEY_USERS" } } } } else { $R } break } } } $FixedPath } function Get-PSRegistryDictionaries { [cmdletBinding()] param() if ($Script:Dictionary) { return } $Script:Dictionary = @{'HKUAD:' = 'HKEY_ALL_USERS_DEFAULT' 'HKUA:' = 'HKEY_ALL_USERS' 'HKUD:' = 'HKEY_DEFAULT_USER' 'HKUDUD:' = 'HKEY_ALL_DOMAIN_USERS_DEFAULT' 'HKUDU:' = 'HKEY_ALL_DOMAIN_USERS' 'HKCR:' = 'HKEY_CLASSES_ROOT' 'HKCU:' = 'HKEY_CURRENT_USER' 'HKLM:' = 'HKEY_LOCAL_MACHINE' 'HKU:' = 'HKEY_USERS' 'HKCC:' = 'HKEY_CURRENT_CONFIG' 'HKDD:' = 'HKEY_DYN_DATA' 'HKPD:' = 'HKEY_PERFORMANCE_DATA' } $Script:HiveDictionary = [ordered] @{'HKEY_ALL_USERS_DEFAULT' = 'All+Default' 'HKUAD' = 'All+Default' 'HKEY_ALL_USERS' = 'All' 'HKUA' = 'All' 'HKEY_ALL_DOMAIN_USERS_DEFAULT' = 'AllDomain+Default' 'HKUDUD' = 'AllDomain+Default' 'HKEY_ALL_DOMAIN_USERS' = 'AllDomain' 'HKUDU' = 'AllDomain' 'HKEY_DEFAULT_USER' = 'Default' 'HKUD' = 'Default' 'HKEY_CLASSES_ROOT' = 'ClassesRoot' 'HKCR' = 'ClassesRoot' 'ClassesRoot' = 'ClassesRoot' 'HKCU' = 'CurrentUser' 'HKEY_CURRENT_USER' = 'CurrentUser' 'CurrentUser' = 'CurrentUser' 'HKLM' = 'LocalMachine' 'HKEY_LOCAL_MACHINE' = 'LocalMachine' 'LocalMachine' = 'LocalMachine' 'HKU' = 'Users' 'HKEY_USERS' = 'Users' 'Users' = 'Users' 'HKCC' = 'CurrentConfig' 'HKEY_CURRENT_CONFIG' = 'CurrentConfig' 'CurrentConfig' = 'CurrentConfig' 'HKDD' = 'DynData' 'HKEY_DYN_DATA' = 'DynData' 'DynData' = 'DynData' 'HKPD' = 'PerformanceData' 'HKEY_PERFORMANCE_DATA ' = 'PerformanceData' 'PerformanceData' = 'PerformanceData' } $Script:ReverseTypesDictionary = [ordered] @{'REG_SZ' = 'string' 'REG_NONE' = 'none' 'REG_EXPAND_SZ' = 'expandstring' 'REG_BINARY' = 'binary' 'REG_DWORD' = 'dword' 'REG_MULTI_SZ' = 'multistring' 'REG_QWORD' = 'qword' 'string' = 'string' 'expandstring' = 'expandstring' 'binary' = 'binary' 'dword' = 'dword' 'multistring' = 'multistring' 'qword' = 'qword' 'none' = 'none' } } function Get-PSSubRegistry { [cmdletBinding()] param([System.Collections.IDictionary] $Registry, [string] $ComputerName, [switch] $Remote) if ($Registry.ComputerName) { if ($Registry.ComputerName -ne $ComputerName) { return } } if (-not $Registry.Error) { try { if ($Remote) { $BaseHive = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey($Registry.HiveKey, $ComputerName, 0) } else { $BaseHive = [Microsoft.Win32.RegistryKey]::OpenBaseKey($Registry.HiveKey, 0) } $PSConnection = $true $PSError = $null } catch { $PSConnection = $false $PSError = $($_.Exception.Message) } } else { $PSConnection = $false $PSError = $($Registry.ErrorMessage) } if ($PSError) { [PSCustomObject] @{PSComputerName = $ComputerName PSConnection = $PSConnection PSError = $true PSErrorMessage = $PSError PSPath = $Registry.Registry PSKey = $Registry.Key PSValue = $null PSType = $null } } else { try { $SubKey = $BaseHive.OpenSubKey($Registry.SubKeyName, $false) if ($null -ne $SubKey) { [PSCustomObject] @{PSComputerName = $ComputerName PSConnection = $PSConnection PSError = $false PSErrorMessage = $null PSPath = $Registry.Registry PSKey = $Registry.Key PSValue = $SubKey.GetValue($Registry.Key) PSType = $SubKey.GetValueKind($Registry.Key) } } else { [PSCustomObject] @{PSComputerName = $ComputerName PSConnection = $PSConnection PSError = $true PSErrorMessage = "Registry path $($Registry.Registry) doesn't exists." PSPath = $Registry.Registry PSKey = $Registry.Key PSValue = $null PSType = $null } } } catch { [PSCustomObject] @{PSComputerName = $ComputerName PSConnection = $PSConnection PSError = $true PSErrorMessage = $_.Exception.Message PSPath = $Registry.Registry PSKey = $Registry.Key PSValue = $null PSType = $null } } } } function Get-PSSubRegistryComplete { [cmdletBinding()] param([System.Collections.IDictionary] $Registry, [string] $ComputerName, [switch] $Remote, [switch] $Advanced) if ($Registry.ComputerName) { if ($Registry.ComputerName -ne $ComputerName) { return } } if (-not $Registry.Error) { try { if ($Remote) { $BaseHive = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey($R.HiveKey, $ComputerName, 0) } else { $BaseHive = [Microsoft.Win32.RegistryKey]::OpenBaseKey($R.HiveKey, 0) } $PSConnection = $true $PSError = $null } catch { $PSConnection = $false $PSError = $($_.Exception.Message) } } else { $PSConnection = $false $PSError = $($Registry.ErrorMessage) } if ($PSError) { [PSCustomObject] @{PSComputerName = $ComputerName PSConnection = $PSConnection PSError = $true PSErrorMessage = $PSError PSSubKeys = $null PSPath = $Registry.Registry PSKey = $Registry.Key } } else { try { $SubKey = $BaseHive.OpenSubKey($Registry.SubKeyName, $false) if ($null -ne $SubKey) { $Object = [ordered] @{PSComputerName = $ComputerName PSConnection = $PSConnection PSError = $false PSErrorMessage = $null PSSubKeys = $SubKey.GetSubKeyNames() PSPath = $Registry.Registry } $Keys = $SubKey.GetValueNames() foreach ($K in $Keys) { if ($K -eq "") { if ($Advanced) { $Object['DefaultKey'] = [ordered] @{Value = $SubKey.GetValue($K) Type = $SubKey.GetValueKind($K) } } else { $Object['DefaultKey'] = $SubKey.GetValue($K) } } else { if ($Advanced) { $Object[$K] = [ordered] @{Value = $SubKey.GetValue($K) Type = $SubKey.GetValueKind($K) } } else { $Object[$K] = $SubKey.GetValue($K) } } } [PSCustomObject] $Object } else { [PSCustomObject] @{PSComputerName = $ComputerName PSConnection = $PSConnection PSError = $true PSErrorMessage = "Registry path $($Registry.Registry) doesn't exists." PSSubKeys = $null PSPath = $Registry.Registry } } } catch { [PSCustomObject] @{PSComputerName = $ComputerName PSConnection = $PSConnection PSError = $true PSErrorMessage = $_.Exception.Message PSSubKeys = $null PSPath = $Registry.Registry } } } } function Get-PSSubRegistryTranslated { [cmdletBinding()] param([Array] $RegistryPath, [System.Collections.IDictionary] $HiveDictionary, [string] $Key) foreach ($Registry in $RegistryPath) { if ($Registry -is [string]) { $Registry = $Registry.Replace("\\", "\").Replace("\\", "\").TrimStart("\").TrimEnd("\") } else { $Registry.RegistryPath = $Registry.RegistryPath.Replace("\\", "\").Replace("\\", "\").TrimStart("\").TrimEnd("\") } foreach ($Hive in $HiveDictionary.Keys) { if ($Registry -is [string] -and $Registry.StartsWith($Hive, [System.StringComparison]::CurrentCultureIgnoreCase)) { if ($Hive.Length -eq $Registry.Length) { [ordered] @{Registry = $Registry HiveKey = $HiveDictionary[$Hive] SubKeyName = $null Key = if ($Key -eq "") { $null } else { $Key } Error = $null ErrorMessage = $null } } else { [ordered] @{Registry = $Registry HiveKey = $HiveDictionary[$Hive] SubKeyName = $Registry.substring($Hive.Length + 1) Key = if ($Key -eq "") { $null } else { $Key } Error = $null ErrorMessage = $null } } break } elseif ($Registry -isnot [string] -and $Registry.RegistryPath.StartsWith($Hive, [System.StringComparison]::CurrentCultureIgnoreCase)) { if ($Hive.Length -eq $Registry.RegistryPath.Length) { [ordered] @{ComputerName = $Registry.ComputerName Registry = $Registry.RegistryPath HiveKey = $HiveDictionary[$Hive] SubKeyName = $null Key = if ($Key -eq "") { $null } else { $Key } Error = $Registry.Error ErrorMessage = $Registry.ErrorMessage } } else { [ordered] @{ComputerName = $Registry.ComputerName Registry = $Registry.RegistryPath HiveKey = $HiveDictionary[$Hive] SubKeyName = $Registry.RegistryPath.substring($Hive.Length + 1) Key = if ($Key -eq "") { $null } else { $Key } Error = $Registry.Error ErrorMessage = $Registry.ErrorMessage } } break } } } } function Set-PrivateRegistry { [cmdletBinding(SupportsShouldProcess)] param([System.Collections.IDictionary] $RegistryValue, [string] $Computer, [switch] $Remote, [switch] $Suppress) if ($RegistryValue.ComputerName) { if ($RegistryValue.ComputerName -ne $Computer) { return } } if ($PSCmdlet.ShouldProcess($Computer, "Setting registry $($RegistryValue.HiveKey)\$($RegistryValue.SubKeyName) on $($RegistryValue.Key) to $($RegistryValue.Value) of $($RegistryValue.ValueKind)")) { try { if ($Remote) { $BaseHive = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey($RegistryValue.HiveKey, $Computer, 0) } else { $BaseHive = [Microsoft.Win32.RegistryKey]::OpenBaseKey($RegistryValue.HiveKey, 0) } $PSConnection = $true $PSError = $null } catch { $PSConnection = $false $PSError = $($_.Exception.Message) if ($PSBoundParameters.ErrorAction -eq 'Stop') { throw } else { Write-Warning "Set-PSRegistry - Setting registry $($RegistryValue.HiveKey)\$($RegistryValue.SubKeyName) on $($RegistryValue.Key) to $($RegistryValue.Value) of $($RegistryValue.ValueKind) on $Computer have failed. Error: $($_.Exception.Message.Replace([System.Environment]::NewLine, " "))" } } if ($PSError) { if (-not $Suppress) { [PSCustomObject] @{PSComputerName = $Computer PSConnection = $PSConnection PSError = $true PSErrorMessage = $PSError Path = "$($RegistryValue.HiveKey)\$($RegistryValue.SubKeyName)" Key = $RegistryValue.Key Value = $RegistryValue.Value Type = $RegistryValue.ValueKind } } } else { try { $SubKey = $BaseHive.OpenSubKey($RegistryValue.SubKeyName, $true) if (-not $SubKey) { $SubKeysSplit = $RegistryValue.SubKeyName.Split('\') $SubKey = $BaseHive.OpenSubKey($SubKeysSplit[0], $true) if (-not $SubKey) { $SubKey = $BaseHive.CreateSubKey($SubKeysSplit[0]) } $SubKey = $BaseHive.OpenSubKey($SubKeysSplit[0], $true) foreach ($S in $SubKeysSplit | Select-Object -Skip 1) { $SubKey = $SubKey.CreateSubKey($S) } } if ($RegistryValue.ValueKind -eq [Microsoft.Win32.RegistryValueKind]::MultiString) { $SubKey.SetValue($RegistryValue.Key, [string[]] $RegistryValue.Value, $RegistryValue.ValueKind) } elseif ($RegistryValue.ValueKind -in [Microsoft.Win32.RegistryValueKind]::None, [Microsoft.Win32.RegistryValueKind]::Binary) { $SubKey.SetValue($RegistryValue.Key, [byte[]] $RegistryValue.Value, $RegistryValue.ValueKind) } else { $SubKey.SetValue($RegistryValue.Key, $RegistryValue.Value, $RegistryValue.ValueKind) } if (-not $Suppress) { [PSCustomObject] @{PSComputerName = $Computer PSConnection = $PSConnection PSError = $false PSErrorMessage = $null Path = "$($RegistryValue.HiveKey)\$($RegistryValue.SubKeyName)" Key = $RegistryValue.Key Value = $RegistryValue.Value Type = $RegistryValue.ValueKind } } } catch { if ($PSBoundParameters.ErrorAction -eq 'Stop') { throw } else { Write-Warning "Set-PSRegistry - Setting registry $($RegistryValue.HiveKey)\$($RegistryValue.SubKeyName) on $($RegistryValue.Key) to $($RegistryValue.Value) of $($RegistryValue.ValueKind) on $Computer have failed. Error: $($_.Exception.Message.Replace([System.Environment]::NewLine, " "))" } if (-not $Suppress) { [PSCustomObject] @{PSComputerName = $Computer PSConnection = $PSConnection PSError = $true PSErrorMessage = $_.Exception.Message Path = "$($RegistryValue.HiveKey)\$($RegistryValue.SubKeyName)" Key = $RegistryValue.Key Value = $RegistryValue.Value Type = $RegistryValue.ValueKind } } } } } } function ConvertTo-HkeyUser { [CmdletBinding()] param([System.Collections.IDictionary] $HiveDictionary, [Array] $SubKeys, [string] $DictionaryKey) foreach ($Sub in $Subkeys) { if ($HiveDictionary[$DictionaryKey] -eq 'All') { if ($Sub -notlike "*_Classes*" -and $Sub -ne '.DEFAULT') { $R.Replace($DictionaryKey, "Users\$Sub") } } elseif ($HiveDictionary[$DictionaryKey] -eq 'All+Default') { if ($Sub -notlike "*_Classes*") { $R.Replace($DictionaryKey, "Users\$Sub") } } elseif ($HiveDictionary[$DictionaryKey] -eq 'Default') { if ($Sub -eq '.DEFAULT') { $R.Replace($DictionaryKey, "Users\.DEFAULT") } } elseif ($HiveDictionary[$DictionaryKey] -eq 'AllDomain+Default') { if (($Sub.StartsWith("S-1-5-21") -and $Sub -notlike "*_Classes*") -or $Sub -eq '.DEFAULT') { $R.Replace($DictionaryKey, "Users\$Sub") } } elseif ($HiveDictionary[$DictionaryKey] -eq 'AllDomain') { if ($Sub.StartsWith("S-1-5-21") -and $Sub -notlike "*_Classes*") { $R.Replace($DictionaryKey, "Users\$Sub") } } } } function Clear-SystemAuditPolicy { <# .SYNOPSIS Clears all audit policies to their default values (Not Configured) .DESCRIPTION Clears all audit policies to their default values (Not Configured) .PARAMETER ComputerName ComputerName for remote system to clear audit policy from. Requires permissions on the destination. .EXAMPLE Clear-SystemAuditPolicy -WhatIf .NOTES General notes #> [cmdletBinding(SupportsShouldProcess)] param([string] $ComputerName) $CurrentPolicies = Get-SystemAuditPolicy -ComputerName $ComputerName foreach ($Policy in $CurrentPolicies.Keys) { $SubPolicies = $CurrentPolicies[$Policy] foreach ($Sub in $SubPolicies.Keys) { if ($SubPolicies[$Sub] -ne 'NotConfigured') { $setSystemAuditPolicySplat = @{"$Policy" = $Sub ComputerName = $ComputerName WhatIf = $WhatIfPreference Value = 'NotConfigured' } $Success = Set-SystemAuditPolicy @setSystemAuditPolicySplat if ($Success.PSError -eq $false -and $Success.PSConnection -eq $true) {} else { Write-Warning -Message " Clear-SystemAuditPolicy - Failed to clear $Policy\$Sub. Error: $($Success.PSErrorMessage)" } } } } } function Get-SystemAuditPolicy { <# .SYNOPSIS Small functions that reads Audit Policy (the same way as auditpol.exe) and returns a hashtable with the values. .DESCRIPTION Small functions that reads Audit Policy (the same way as auditpol.exe) and returns a hashtable with the values. .PARAMETER ComputerName ComputerName for remote system to read audit policy from. Requires permissions on the destination. .EXAMPLE $AuditPolicies = Get-SystemAuditPolicy $AuditPolicies | Format-Table $AuditPolicies.AccountLogon | Format-Table $AuditPolicies.AccountManagement | Format-Table $AuditPolicies.DetailedTracking | Format-Table .NOTES General notes #> [CmdletBinding()] param([string] $ComputerName) Add-Type -TypeDefinition @" using System; namespace AuditPolicies { public enum Events { NotConfigured = 0, Success = 1, Failure = 2, SuccessAndFailure = 3 } } "@ $Audit = Get-PSRegistry -RegistryPath "HKEY_LOCAL_MACHINE\SECURITY\Policy\PolAdtEv" -Key "" -ComputerName $ComputerName if ($Audit.PSConnection -eq $true -and $Audit.PSError -eq $false) { $Data = $Audit.PSValue $AuditPolicies = [ordered] @{AccountLogon = [ordered] @{'CredentialValidation' = [AuditPolicies.Events] $Data[122] 'KerberosServiceTicketOperations' = [AuditPolicies.Events] $Data[124] 'OtherAccountLogonEvents' = [AuditPolicies.Events] $Data[126] 'KerberosAuthenticationService' = [AuditPolicies.Events] $Data[128] } AccountManagement = [ordered] @{'UserAccountManagement' = [AuditPolicies.Events] $Data[102] 'ComputerAccountManagement' = [AuditPolicies.Events] $Data[104] 'SecurityGroupManagement' = [AuditPolicies.Events] $Data[106] 'DistributionGroupManagement' = [AuditPolicies.Events] $Data[108] 'ApplicationGroupManagement' = [AuditPolicies.Events] $Data[110] 'OtherAccountManagementEvents' = [AuditPolicies.Events] $Data[112] } DetailedTracking = [ordered] @{'ProcessCreation' = [AuditPolicies.Events] $Data[78] 'ProcessTermination' = [AuditPolicies.Events] $Data[80] 'DPAPIActivity' = [AuditPolicies.Events] $Data[82] 'RPCEvents' = [AuditPolicies.Events] $Data[84] 'PNPActivity' = [AuditPolicies.Events] $Data[86] 'TokenRightAdjusted' = [AuditPolicies.Events] $Data[88] } DSAccess = [ordered] @{'DirectoryServiceAccess' = [AuditPolicies.Events] $Data[114] 'DirectoryServiceChanges' = [AuditPolicies.Events] $Data[116] 'DirectoryServiceReplication' = [AuditPolicies.Events] $Data[118] 'DetailedDirectoryServiceReplication' = [AuditPolicies.Events] $Data[120] } LogonLogoff = [ordered] @{'Logon' = [AuditPolicies.Events] $Data[22] 'Logoff' = [AuditPolicies.Events] $Data[24] 'AccountLockout' = [AuditPolicies.Events] $Data[26] 'IPSecMainMode' = [AuditPolicies.Events] $Data[28] 'SpecialLogon' = [AuditPolicies.Events] $Data[30] 'IPSecQuickMode' = [AuditPolicies.Events] $Data[32] 'IPSecExtendedMode' = [AuditPolicies.Events] $Data[34] 'OtherLogonLogoffEvents' = [AuditPolicies.Events] $Data[36] 'NetworkPolicyServer' = [AuditPolicies.Events] $Data[38] 'UserDeviceClaims' = [AuditPolicies.Events] $Data[40] 'GroupMembership' = [AuditPolicies.Events] $Data[42] } ObjectAccess = [ordered] @{'FileSystem' = [AuditPolicies.Events] $Data[44] 'Registry' = [AuditPolicies.Events] $Data[46] 'KernelObject' = [AuditPolicies.Events] $Data[48] 'SAM' = [AuditPolicies.Events] $Data[50] 'OtherObjectAccessEvents' = [AuditPolicies.Events] $Data[52] 'CertificationServices' = [AuditPolicies.Events] $Data[54] 'ApplicationGenerated' = [AuditPolicies.Events] $Data[56] 'HandleManipulation' = [AuditPolicies.Events] $Data[58] 'FileShare' = [AuditPolicies.Events] $Data[60] 'FilteringPlatformPacketDrop' = [AuditPolicies.Events] $Data[62] 'FilteringPlatformConnection' = [AuditPolicies.Events] $Data[64] 'DetailedFileShare' = [AuditPolicies.Events] $Data[66] 'RemovableStorage' = [AuditPolicies.Events] $Data[68] 'CentralAccessPolicyStaging' = [AuditPolicies.Events] $Data[70] } PolicyChange = [ordered] @{'AuditPolicyChange' = [AuditPolicies.Events] $Data[90] 'AuthenticationPolicyChange' = [AuditPolicies.Events] $Data[92] 'AuthorizationPolicyChange' = [AuditPolicies.Events] $Data[94] 'MPSSVCRuleLevelPolicyChange' = [AuditPolicies.Events] $Data[96] 'FilteringPlatformPolicyChange' = [AuditPolicies.Events] $Data[98] 'OtherPolicyChangeEvents' = [AuditPolicies.Events] $Data[100] } PrivilegeUse = [ordered] @{'SensitivePrivilegeUse' = [AuditPolicies.Events] $Data[72] 'NonSensitivePrivilegeUse' = [AuditPolicies.Events] $Data[74] 'OtherPrivilegeUseEvents' = [AuditPolicies.Events] $Data[76] } System = [ordered] @{'SecurityStateChange' = [AuditPolicies.Events] $Data[12] 'SecuritySystemExtension' = [AuditPolicies.Events] $Data[14] 'SystemIntegrity' = [AuditPolicies.Events] $Data[16] 'IPsecDriver' = [AuditPolicies.Events] $Data[18] 'OtherSystemEvents' = [AuditPolicies.Events] $Data[20] } } $AuditPolicies } else { Write-Warning -Message "Get-SystemAuditPolicies - Audit policies couldn't be read: $($Audit.PSErrorMessage)" } } function Set-SystemAuditPolicy { <# .SYNOPSIS Sets the audit policy similary to what auditpol.exe does. .DESCRIPTION Sets the audit policy similary to what auditpol.exe does. .PARAMETER ComputerName ComputerName for remote system to clear audit policy from. Requires permissions on the destination. .PARAMETER AccountLogon Choose one of the options for the AccountLogon parameter. .PARAMETER AccountManagement Choose one of the options for the AccountManagement parameter. .PARAMETER DetailedTracking Choose one of the options for the DetailedTracking parameter. .PARAMETER DSAccess Choose one of the options for the DSAccess parameter. .PARAMETER LogonLogoff Choose one of the options for the LogonLogoff parameter. .PARAMETER ObjectAccess Choose one of the options for the ObjectAccess parameter. .PARAMETER PolicyChange Choose one of the options for the PolicyChange parameter. .PARAMETER PrivilegeUse Choose one of the options for the PrivilegeUse parameter. .PARAMETER System Choose one of the options for the System parameter. .PARAMETER Value Choose one of the options for the Value parameter. .EXAMPLE $WhatIf = $false Set-SystemAuditPolicy -AccountLogon KerberosServiceTicketOperations -Value Failure -Verbose -WhatIf:$WhatIf Set-SystemAuditPolicy -AccountLogon OtherAccountLogonEvents -Value Failure -Verbose -WhatIf:$WhatIf Set-SystemAuditPolicy -AccountLogon KerberosAuthenticationService -Value SuccessAndFailure -Verbose -WhatIf:$WhatIf Set-SystemAuditPolicy -AccountLogon CredentialValidation -Value Success -Verbose -WhatIf:$WhatIf Set-SystemAuditPolicy -AccountManagement ComputerAccountManagement -Value Failure -Verbose -WhatIf:$WhatIf Set-SystemAuditPolicy -AccountManagement ApplicationGroupManagement -Value Success -Verbose -WhatIf:$WhatIf Set-SystemAuditPolicy -AccountManagement DistributionGroupManagement -Value Failure -Verbose -WhatIf:$WhatIf Set-SystemAuditPolicy -AccountManagement OtherAccountManagementEvents -Value Failure -Verbose -WhatIf:$WhatIf Set-SystemAuditPolicy -AccountManagement SecurityGroupManagement -Value Failure -Verbose -WhatIf:$WhatIf Set-SystemAuditPolicy -AccountManagement UserAccountManagement -Value Failure -Verbose -WhatIf:$WhatIf .NOTES General notes #> [CmdletBinding(SupportsShouldProcess)] param([string] $ComputerName, [parameter(Mandatory, ParameterSetName = 'AccountLogon')][ValidateSet('CredentialValidation', 'KerberosServiceTicketOperations', 'OtherAccountLogonEvents', 'KerberosAuthenticationService')][string] $AccountLogon, [parameter(Mandatory, ParameterSetName = 'AccountManagement')][ValidateSet('UserAccountManagement', 'ComputerAccountManagement', 'SecurityGroupManagement', 'DistributionGroupManagement', 'ApplicationGroupManagement', 'OtherAccountManagementEvents')][string] $AccountManagement, [parameter(Mandatory, ParameterSetName = 'DetailedTracking')][ValidateSet('ProcessCreation', 'ProcessTermination', 'DPAPIActivity' , 'RPCEvents' , 'PNPActivity' , 'TokenRightAdjusted')][string] $DetailedTracking, [parameter(Mandatory, ParameterSetName = 'DSAccess')][ValidateSet('DirectoryServiceAccess', 'DirectoryServiceChanges', 'DirectoryServiceReplication', 'DetailedDirectoryServiceReplication')][string] $DSAccess, [parameter(Mandatory, ParameterSetName = 'LogonLogoff')][ValidateSet('Logon', 'Logoff', 'AccountLockout', 'IPSecMainMode', 'SpecialLogon', 'IPSecQuickMode', 'IPSecExtendedMode', 'OtherLogonLogoffEvents', 'NetworkPolicyServer', 'UserDeviceClaims', 'GroupMembership')][string] $LogonLogoff, [parameter(Mandatory, ParameterSetName = 'ObjectAccess')][ValidateSet('FileSystem', 'Registry', 'KernelObject', 'SAM', 'OtherObjectAccessEvents', 'CertificationServices', 'ApplicationGenerated', 'HandleManipulation', 'FileShare', 'FilteringPlatformPacketDrop', 'FilteringPlatformConnection', 'DetailedFileShare', 'RemovableStorage', 'CentralAccessPolicyStaging')][string] $ObjectAccess, [parameter(Mandatory, ParameterSetName = 'PolicyChange')][ValidateSet('FileSystem', 'AuditPolicyChange', 'AuthenticationPolicyChange', 'AuthorizationPolicyChange', 'MPSSVCRuleLevelPolicyChange', 'FilteringPlatformPolicyChange', 'OtherPolicyChangeEvents')][string] $PolicyChange, [parameter(Mandatory, ParameterSetName = 'PrivilegeUse')][ValidateSet('SensitivePrivilegeUse', 'NonSensitivePrivilegeUse', 'OtherPrivilegeUseEvents')][string] $PrivilegeUse, [parameter(Mandatory, ParameterSetName = 'System')][ValidateSet('SecurityStateChange', 'SecuritySystemExtension', 'SystemIntegrity', 'IPsecDriver', 'OtherSystemEvents')][string] $System, [parameter(Mandatory)][validateSet('NotConfigured', 'Success', 'Failure', 'SuccessAndFailure')][string] $Value) Add-Type -TypeDefinition @" using System; namespace AuditPolicies { public enum Events { NotConfigured = 0, Success = 1, Failure = 2, SuccessAndFailure = 3 } } "@ $AuditValues = @{'NotConfigured' = 0 'Success' = 1 'Failure' = 2 'SuccessAndFailure' = 3 } $AuditPoliciesByte = [ordered] @{AccountLogon = [ordered] @{'CredentialValidation' = 122 'KerberosServiceTicketOperations' = 124 'OtherAccountLogonEvents' = 126 'KerberosAuthenticationService' = 128 } AccountManagement = [ordered] @{'UserAccountManagement' = 102 'ComputerAccountManagement' = 104 'SecurityGroupManagement' = 106 'DistributionGroupManagement' = 108 'ApplicationGroupManagement' = 110 'OtherAccountManagementEvents' = 112 } DetailedTracking = [ordered] @{'ProcessCreation' = 78 'ProcessTermination' = 80 'DPAPIActivity' = 82 'RPCEvents' = 84 'PNPActivity' = 86 'TokenRightAdjusted' = 88 } DSAccess = [ordered] @{'DirectoryServiceAccess' = 114 'DirectoryServiceChanges' = 116 'DirectoryServiceReplication' = 118 'DetailedDirectoryServiceReplication' = 120 } LogonLogoff = [ordered] @{'Logon' = 22 'Logoff' = 24 'AccountLockout' = 26 'IPSecMainMode' = 28 'SpecialLogon' = 30 'IPSecQuickMode' = 32 'IPSecExtendedMode' = 34 'OtherLogonLogoffEvents' = 36 'NetworkPolicyServer' = 38 'UserDeviceClaims' = 40 'GroupMembership' = 42 } ObjectAccess = [ordered] @{'FileSystem' = 44 'Registry' = 46 'KernelObject' = 48 'SAM' = 50 'OtherObjectAccessEvents' = 52 'CertificationServices' = 54 'ApplicationGenerated' = 56 'HandleManipulation' = 58 'FileShare' = 60 'FilteringPlatformPacketDrop' = 62 'FilteringPlatformConnection' = 64 'DetailedFileShare' = 66 'RemovableStorage' = 68 'CentralAccessPolicyStaging' = 70 } PolicyChange = [ordered] @{'AuditPolicyChange' = 90 'AuthenticationPolicyChange' = 92 'AuthorizationPolicyChange' = 94 'MPSSVCRuleLevelPolicyChange' = 96 'FilteringPlatformPolicyChange' = 98 'OtherPolicyChangeEvents' = 100 } PrivilegeUse = [ordered] @{'SensitivePrivilegeUse' = 72 'NonSensitivePrivilegeUse' = 74 'OtherPrivilegeUseEvents' = 76 } System = [ordered] @{'SecurityStateChange' = 12 'SecuritySystemExtension' = 14 'SystemIntegrity' = 16 'IPsecDriver' = 18 'OtherSystemEvents' = 20 } } $Audit = Get-PSRegistry -RegistryPath "HKEY_LOCAL_MACHINE\SECURITY\Policy\PolAdtEv" -Key "" -ComputerName $ComputerName if ($Audit.PSConnection -eq $true -and $Audit.PSError -eq $false) {} else { Write-Warning -Message "Set-SystemAuditPolicies - Audit policies couldn't be read: $($Audit.PSErrorMessage)" return } $BoundParameters = $PSBoundParameters $CurrentParameterSet = $PsCmdlet.ParameterSetName $ChosenParameter = $BoundParameters.$CurrentParameterSet if ($CurrentParameterSet) { $ByteNumber = $AuditPoliciesByte[$CurrentParameterSet][$ChosenParameter] $ExpectedValue = $AuditValues[$Value] $CurrentValue = $Audit.PSValue[$ByteNumber] $CurrentTranslatedValue = [AuditPolicies.Events] $CurrentValue $ExpectedTranslatedValue = [AuditPolicies.Events] $ExpectedValue Write-Verbose -Message "Set-SystemAuditPolicies - Current value for $CurrentParameterSet\$ChosenParameter is $CurrentTranslatedValue ($CurrentValue) to be replaced with $ExpectedTranslatedValue ($ExpectedValue)" if ($CurrentTranslatedValue -ne $ExpectedTranslatedValue) { $ValueToSet = $Audit.PSValue $ValueToSet[$ByteNumber] = $ExpectedValue $AuditOutput = Set-PSRegistry -RegistryPath "HKEY_LOCAL_MACHINE\SECURITY\Policy\PolAdtEv" -Key "" -ComputerName $ComputerName -Type None -Value $ValueToSet -WhatIf:$WhatIfPreference $AuditOutput } else { Write-Verbose -Message "Set-SystemAuditPolicies - Current value for $CurrentParameterSet\$ChosenParameter ($ByteNumber) is $CurrentTranslatedValue ($CurrentValue) - nothing to do." } } } Export-ModuleMember -Function @('Clear-SystemAuditPolicy', 'Get-SystemAuditPolicy', 'Set-SystemAuditPolicy') -Alias @() # SIG # Begin signature block # MIIhjgYJKoZIhvcNAQcCoIIhfzCCIXsCAQExCzAJBgUrDgMCGgUAMGkGCisGAQQB # gjcCAQSgWzBZMDQGCisGAQQBgjcCAR4wJgIDAQAABBAfzDtgWUsITrck0sYpfvNR # AgEAAgEAAgEAAgEAAgEAMCEwCQYFKw4DAhoFAAQUmBiw5sTZzIxzI3gvQHbwEpQA # 5k6gghusMIIDtzCCAp+gAwIBAgIQDOfg5RfYRv6P5WD8G/AwOTANBgkqhkiG9w0B # AQUFADBlMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYD # VQQLExB3d3cuZGlnaWNlcnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVk # IElEIFJvb3QgQ0EwHhcNMDYxMTEwMDAwMDAwWhcNMzExMTEwMDAwMDAwWjBlMQsw # CQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cu # ZGlnaWNlcnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3Qg # Q0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCtDhXO5EOAXLGH87dg # +XESpa7cJpSIqvTO9SA5KFhgDPiA2qkVlTJhPLWxKISKityfCgyDF3qPkKyK53lT # XDGEKvYPmDI2dsze3Tyoou9q+yHyUmHfnyDXH+Kx2f4YZNISW1/5WBg1vEfNoTb5 # a3/UsDg+wRvDjDPZ2C8Y/igPs6eD1sNuRMBhNZYW/lmci3Zt1/GiSw0r/wty2p5g # 0I6QNcZ4VYcgoc/lbQrISXwxmDNsIumH0DJaoroTghHtORedmTpyoeb6pNnVFzF1 # roV9Iq4/AUaG9ih5yLHa5FcXxH4cDrC0kqZWs72yl+2qp/C3xag/lRbQ/6GW6whf # GHdPAgMBAAGjYzBhMA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MB0G # A1UdDgQWBBRF66Kv9JLLgjEtUYunpyGd823IDzAfBgNVHSMEGDAWgBRF66Kv9JLL # gjEtUYunpyGd823IDzANBgkqhkiG9w0BAQUFAAOCAQEAog683+Lt8ONyc3pklL/3 # cmbYMuRCdWKuh+vy1dneVrOfzM4UKLkNl2BcEkxY5NM9g0lFWJc1aRqoR+pWxnmr # EthngYTffwk8lOa4JiwgvT2zKIn3X/8i4peEH+ll74fg38FnSbNd67IJKusm7Xi+ # fT8r87cmNW1fiQG2SVufAQWbqz0lwcy2f8Lxb4bG+mRo64EtlOtCt/qMHt1i8b5Q # Z7dsvfPxH2sMNgcWfzd8qVttevESRmCD1ycEvkvOl77DZypoEd+A5wwzZr8TDRRu # 838fYxAe+o0bJW1sj6W3YQGx0qMmoRBxna3iw/nDmVG3KwcIzi7mULKn+gpFL6Lw # 8jCCBTAwggQYoAMCAQICEAQJGBtf1btmdVNDtW+VUAgwDQYJKoZIhvcNAQELBQAw # ZTELMAkGA1UEBhMCVVMxFTATBgNVBAoTDERpZ2lDZXJ0IEluYzEZMBcGA1UECxMQ # d3d3LmRpZ2ljZXJ0LmNvbTEkMCIGA1UEAxMbRGlnaUNlcnQgQXNzdXJlZCBJRCBS # b290IENBMB4XDTEzMTAyMjEyMDAwMFoXDTI4MTAyMjEyMDAwMFowcjELMAkGA1UE # BhMCVVMxFTATBgNVBAoTDERpZ2lDZXJ0IEluYzEZMBcGA1UECxMQd3d3LmRpZ2lj # ZXJ0LmNvbTExMC8GA1UEAxMoRGlnaUNlcnQgU0hBMiBBc3N1cmVkIElEIENvZGUg # U2lnbmluZyBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPjTsxx/ # DhGvZ3cH0wsxSRnP0PtFmbE620T1f+Wondsy13Hqdp0FLreP+pJDwKX5idQ3Gde2 # qvCchqXYJawOeSg6funRZ9PG+yknx9N7I5TkkSOWkHeC+aGEI2YSVDNQdLEoJrsk # acLCUvIUZ4qJRdQtoaPpiCwgla4cSocI3wz14k1gGL6qxLKucDFmM3E+rHCiq85/ # 6XzLkqHlOzEcz+ryCuRXu0q16XTmK/5sy350OTYNkO/ktU6kqepqCquE86xnTrXE # 94zRICUj6whkPlKWwfIPEvTFjg/BougsUfdzvL2FsWKDc0GCB+Q4i2pzINAPZHM8 # np+mM6n9Gd8lk9ECAwEAAaOCAc0wggHJMBIGA1UdEwEB/wQIMAYBAf8CAQAwDgYD # VR0PAQH/BAQDAgGGMBMGA1UdJQQMMAoGCCsGAQUFBwMDMHkGCCsGAQUFBwEBBG0w # azAkBggrBgEFBQcwAYYYaHR0cDovL29jc3AuZGlnaWNlcnQuY29tMEMGCCsGAQUF # BzAChjdodHRwOi8vY2FjZXJ0cy5kaWdpY2VydC5jb20vRGlnaUNlcnRBc3N1cmVk # SURSb290Q0EuY3J0MIGBBgNVHR8EejB4MDqgOKA2hjRodHRwOi8vY3JsNC5kaWdp # Y2VydC5jb20vRGlnaUNlcnRBc3N1cmVkSURSb290Q0EuY3JsMDqgOKA2hjRodHRw # Oi8vY3JsMy5kaWdpY2VydC5jb20vRGlnaUNlcnRBc3N1cmVkSURSb290Q0EuY3Js # ME8GA1UdIARIMEYwOAYKYIZIAYb9bAACBDAqMCgGCCsGAQUFBwIBFhxodHRwczov # L3d3dy5kaWdpY2VydC5jb20vQ1BTMAoGCGCGSAGG/WwDMB0GA1UdDgQWBBRaxLl7 # KgqjpepxA8Bg+S32ZXUOWDAfBgNVHSMEGDAWgBRF66Kv9JLLgjEtUYunpyGd823I # DzANBgkqhkiG9w0BAQsFAAOCAQEAPuwNWiSz8yLRFcgsfCUpdqgdXRwtOhrE7zBh # 134LYP3DPQ/Er4v97yrfIFU3sOH20ZJ1D1G0bqWOWuJeJIFOEKTuP3GOYw4TS63X # X0R58zYUBor3nEZOXP+QsRsHDpEV+7qvtVHCjSSuJMbHJyqhKSgaOnEoAjwukaPA # JRHinBRHoXpoaK+bp1wgXNlxsQyPu6j4xRJon89Ay0BEpRPw5mQMJQhCMrI2iiQC # /i9yfhzXSUWW6Fkd6fp0ZGuy62ZD2rOwjNXpDd32ASDOmTFjPQgaGLOBm0/GkxAG # /AeB+ova+YJJ92JuoVP6EpQYhS6SkepobEQysmah5xikmmRR7zCCBT0wggQloAMC # AQICEATV3B9I6snYUgC6zZqbKqcwDQYJKoZIhvcNAQELBQAwcjELMAkGA1UEBhMC # VVMxFTATBgNVBAoTDERpZ2lDZXJ0IEluYzEZMBcGA1UECxMQd3d3LmRpZ2ljZXJ0 # LmNvbTExMC8GA1UEAxMoRGlnaUNlcnQgU0hBMiBBc3N1cmVkIElEIENvZGUgU2ln # bmluZyBDQTAeFw0yMDA2MjYwMDAwMDBaFw0yMzA3MDcxMjAwMDBaMHoxCzAJBgNV # BAYTAlBMMRIwEAYDVQQIDAnFmmzEhXNraWUxETAPBgNVBAcTCEthdG93aWNlMSEw # HwYDVQQKDBhQcnplbXlzxYJhdyBLxYJ5cyBFVk9URUMxITAfBgNVBAMMGFByemVt # eXPFgmF3IEvFgnlzIEVWT1RFQzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC # ggEBAL+ygd4sga4ZC1G2xXvasYSijwWKgwapZ69wLaWaZZIlY6YvXTGQnIUnk+Tg # 7EoT7mQiMSaeSPOrn/Im6N74tkvRfQJXxY1cnt3U8//U5grhh/CULdd6M3/Z4h3n # MCq7LQ1YVaa4MYub9F8WOdXO84DANoNVG/t7YotL4vzqZil3S9pHjaidp3kOXGJc # vxrCPAkRFBKvUmYo23QPFa0Rd0qA3bFhn97WWczup1p90y2CkOf28OVOOObv1fNE # EqMpLMx0Yr04/h+LPAAYn6K4YtIu+m3gOhGuNc3B+MybgKePAeFIY4EQzbqvCMy1 # iuHZb6q6ggRyqrJ6xegZga7/gV0CAwEAAaOCAcUwggHBMB8GA1UdIwQYMBaAFFrE # uXsqCqOl6nEDwGD5LfZldQ5YMB0GA1UdDgQWBBQYsTUn6BxQICZOCZA0CxS0TZSU # ZjAOBgNVHQ8BAf8EBAMCB4AwEwYDVR0lBAwwCgYIKwYBBQUHAwMwdwYDVR0fBHAw # bjA1oDOgMYYvaHR0cDovL2NybDMuZGlnaWNlcnQuY29tL3NoYTItYXNzdXJlZC1j # cy1nMS5jcmwwNaAzoDGGL2h0dHA6Ly9jcmw0LmRpZ2ljZXJ0LmNvbS9zaGEyLWFz # c3VyZWQtY3MtZzEuY3JsMEwGA1UdIARFMEMwNwYJYIZIAYb9bAMBMCowKAYIKwYB # BQUHAgEWHGh0dHBzOi8vd3d3LmRpZ2ljZXJ0LmNvbS9DUFMwCAYGZ4EMAQQBMIGE # BggrBgEFBQcBAQR4MHYwJAYIKwYBBQUHMAGGGGh0dHA6Ly9vY3NwLmRpZ2ljZXJ0 # LmNvbTBOBggrBgEFBQcwAoZCaHR0cDovL2NhY2VydHMuZGlnaWNlcnQuY29tL0Rp # Z2lDZXJ0U0hBMkFzc3VyZWRJRENvZGVTaWduaW5nQ0EuY3J0MAwGA1UdEwEB/wQC # MAAwDQYJKoZIhvcNAQELBQADggEBAJq9bM+JbCwEYuMBtXoNAfH1SRaMLXnLe0py # VK6el0Z1BtPxiNcF4iyHqMNVD4iOrgzLEVzx1Bf/sYycPEnyG8Gr2tnl7u1KGSjY # enX4LIXCZqNEDQCeTyMstNv931421ERByDa0wrz1Wz5lepMeCqXeyiawqOxA9fB/ # 106liR12vL2tzGC62yXrV6WhD6W+s5PpfEY/chuIwVUYXp1AVFI9wi2lg0gaTgP/ # rMfP1wfVvaKWH2Bm/tU5mwpIVIO0wd4A+qOhEia3vn3J2Zz1QDxEprLcLE9e3Gmd # G5+8xEypTR23NavhJvZMgY2kEXBEKEEDaXs0LoPbn6hMcepR2A4wggauMIIElqAD # AgECAhAHNje3JFR82Ees/ShmKl5bMA0GCSqGSIb3DQEBCwUAMGIxCzAJBgNVBAYT # AlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2Vy # dC5jb20xITAfBgNVBAMTGERpZ2lDZXJ0IFRydXN0ZWQgUm9vdCBHNDAeFw0yMjAz # MjMwMDAwMDBaFw0zNzAzMjIyMzU5NTlaMGMxCzAJBgNVBAYTAlVTMRcwFQYDVQQK # Ew5EaWdpQ2VydCwgSW5jLjE7MDkGA1UEAxMyRGlnaUNlcnQgVHJ1c3RlZCBHNCBS # U0E0MDk2IFNIQTI1NiBUaW1lU3RhbXBpbmcgQ0EwggIiMA0GCSqGSIb3DQEBAQUA # A4ICDwAwggIKAoICAQDGhjUGSbPBPXJJUVXHJQPE8pE3qZdRodbSg9GeTKJtoLDM # g/la9hGhRBVCX6SI82j6ffOciQt/nR+eDzMfUBMLJnOWbfhXqAJ9/UO0hNoR8XOx # s+4rgISKIhjf69o9xBd/qxkrPkLcZ47qUT3w1lbU5ygt69OxtXXnHwZljZQp09ns # ad/ZkIdGAHvbREGJ3HxqV3rwN3mfXazL6IRktFLydkf3YYMZ3V+0VAshaG43IbtA # rF+y3kp9zvU5EmfvDqVjbOSmxR3NNg1c1eYbqMFkdECnwHLFuk4fsbVYTXn+149z # k6wsOeKlSNbwsDETqVcplicu9Yemj052FVUmcJgmf6AaRyBD40NjgHt1biclkJg6 # OBGz9vae5jtb7IHeIhTZgirHkr+g3uM+onP65x9abJTyUpURK1h0QCirc0PO30qh # HGs4xSnzyqqWc0Jon7ZGs506o9UD4L/wojzKQtwYSH8UNM/STKvvmz3+DrhkKvp1 # KCRB7UK/BZxmSVJQ9FHzNklNiyDSLFc1eSuo80VgvCONWPfcYd6T/jnA+bIwpUzX # 6ZhKWD7TA4j+s4/TXkt2ElGTyYwMO1uKIqjBJgj5FBASA31fI7tk42PgpuE+9sJ0 # sj8eCXbsq11GdeJgo1gJASgADoRU7s7pXcheMBK9Rp6103a50g5rmQzSM7TNsQID # AQABo4IBXTCCAVkwEgYDVR0TAQH/BAgwBgEB/wIBADAdBgNVHQ4EFgQUuhbZbU2F # L3MpdpovdYxqII+eyG8wHwYDVR0jBBgwFoAU7NfjgtJxXWRM3y5nP+e6mK4cD08w # DgYDVR0PAQH/BAQDAgGGMBMGA1UdJQQMMAoGCCsGAQUFBwMIMHcGCCsGAQUFBwEB # BGswaTAkBggrBgEFBQcwAYYYaHR0cDovL29jc3AuZGlnaWNlcnQuY29tMEEGCCsG # AQUFBzAChjVodHRwOi8vY2FjZXJ0cy5kaWdpY2VydC5jb20vRGlnaUNlcnRUcnVz # dGVkUm9vdEc0LmNydDBDBgNVHR8EPDA6MDigNqA0hjJodHRwOi8vY3JsMy5kaWdp # Y2VydC5jb20vRGlnaUNlcnRUcnVzdGVkUm9vdEc0LmNybDAgBgNVHSAEGTAXMAgG # BmeBDAEEAjALBglghkgBhv1sBwEwDQYJKoZIhvcNAQELBQADggIBAH1ZjsCTtm+Y # qUQiAX5m1tghQuGwGC4QTRPPMFPOvxj7x1Bd4ksp+3CKDaopafxpwc8dB+k+YMjY # C+VcW9dth/qEICU0MWfNthKWb8RQTGIdDAiCqBa9qVbPFXONASIlzpVpP0d3+3J0 # FNf/q0+KLHqrhc1DX+1gtqpPkWaeLJ7giqzl/Yy8ZCaHbJK9nXzQcAp876i8dU+6 # WvepELJd6f8oVInw1YpxdmXazPByoyP6wCeCRK6ZJxurJB4mwbfeKuv2nrF5mYGj # VoarCkXJ38SNoOeY+/umnXKvxMfBwWpx2cYTgAnEtp/Nh4cku0+jSbl3ZpHxcpzp # SwJSpzd+k1OsOx0ISQ+UzTl63f8lY5knLD0/a6fxZsNBzU+2QJshIUDQtxMkzdwd # eDrknq3lNHGS1yZr5Dhzq6YBT70/O3itTK37xJV77QpfMzmHQXh6OOmc4d0j/R0o # 08f56PGYX/sr2H7yRp11LB4nLCbbbxV7HhmLNriT1ObyF5lZynDwN7+YAN8gFk8n # +2BnFqFmut1VwDophrCYoCvtlUG3OtUVmDG0YgkPCr2B2RP+v6TR81fZvAT6gt4y # 3wSJ8ADNXcL50CN/AAvkdgIm2fBldkKmKYcJRyvmfxqkhQ/8mJb2VVQrH4D6wPIO # K+XW+6kvRBVK5xMOHds3OBqhK/bt1nz8MIIGxjCCBK6gAwIBAgIQCnpKiJ7JmUKQ # BmM4TYaXnTANBgkqhkiG9w0BAQsFADBjMQswCQYDVQQGEwJVUzEXMBUGA1UEChMO # RGlnaUNlcnQsIEluYy4xOzA5BgNVBAMTMkRpZ2lDZXJ0IFRydXN0ZWQgRzQgUlNB # NDA5NiBTSEEyNTYgVGltZVN0YW1waW5nIENBMB4XDTIyMDMyOTAwMDAwMFoXDTMz # MDMxNDIzNTk1OVowTDELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDkRpZ2lDZXJ0LCBJ # bmMuMSQwIgYDVQQDExtEaWdpQ2VydCBUaW1lc3RhbXAgMjAyMiAtIDIwggIiMA0G # CSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC5KpYjply8X9ZJ8BWCGPQz7sxcbOPg # JS7SMeQ8QK77q8TjeF1+XDbq9SWNQ6OB6zhj+TyIad480jBRDTEHukZu6aNLSOiJ # QX8Nstb5hPGYPgu/CoQScWyhYiYB087DbP2sO37cKhypvTDGFtjavOuy8YPRn80J # xblBakVCI0Fa+GDTZSw+fl69lqfw/LH09CjPQnkfO8eTB2ho5UQ0Ul8PUN7UWSxE # dMAyRxlb4pguj9DKP//GZ888k5VOhOl2GJiZERTFKwygM9tNJIXogpThLwPuf4UC # yYbh1RgUtwRF8+A4vaK9enGY7BXn/S7s0psAiqwdjTuAaP7QWZgmzuDtrn8oLsKe # 4AtLyAjRMruD+iM82f/SjLv3QyPf58NaBWJ+cCzlK7I9Y+rIroEga0OJyH5fsBrd # Gb2fdEEKr7mOCdN0oS+wVHbBkE+U7IZh/9sRL5IDMM4wt4sPXUSzQx0jUM2R1y+d # +/zNscGnxA7E70A+GToC1DGpaaBJ+XXhm+ho5GoMj+vksSF7hmdYfn8f6CvkFLIW # 1oGhytowkGvub3XAsDYmsgg7/72+f2wTGN/GbaR5Sa2Lf2GHBWj31HDjQpXonrub # S7LitkE956+nGijJrWGwoEEYGU7tR5thle0+C2Fa6j56mJJRzT/JROeAiylCcvd5 # st2E6ifu/n16awIDAQABo4IBizCCAYcwDgYDVR0PAQH/BAQDAgeAMAwGA1UdEwEB # /wQCMAAwFgYDVR0lAQH/BAwwCgYIKwYBBQUHAwgwIAYDVR0gBBkwFzAIBgZngQwB # BAIwCwYJYIZIAYb9bAcBMB8GA1UdIwQYMBaAFLoW2W1NhS9zKXaaL3WMaiCPnshv # MB0GA1UdDgQWBBSNZLeJIf5WWESEYafqbxw2j92vDTBaBgNVHR8EUzBRME+gTaBL # hklodHRwOi8vY3JsMy5kaWdpY2VydC5jb20vRGlnaUNlcnRUcnVzdGVkRzRSU0E0 # MDk2U0hBMjU2VGltZVN0YW1waW5nQ0EuY3JsMIGQBggrBgEFBQcBAQSBgzCBgDAk # BggrBgEFBQcwAYYYaHR0cDovL29jc3AuZGlnaWNlcnQuY29tMFgGCCsGAQUFBzAC # hkxodHRwOi8vY2FjZXJ0cy5kaWdpY2VydC5jb20vRGlnaUNlcnRUcnVzdGVkRzRS # U0E0MDk2U0hBMjU2VGltZVN0YW1waW5nQ0EuY3J0MA0GCSqGSIb3DQEBCwUAA4IC # AQANLSN0ptH1+OpLmT8B5PYM5K8WndmzjJeCKZxDbwEtqzi1cBG/hBmLP13lhk++ # kzreKjlaOU7YhFmlvBuYquhs79FIaRk4W8+JOR1wcNlO3yMibNXf9lnLocLqTHbK # odyhK5a4m1WpGmt90fUCCU+C1qVziMSYgN/uSZW3s8zFp+4O4e8eOIqf7xHJMUpY # tt84fMv6XPfkU79uCnx+196Y1SlliQ+inMBl9AEiZcfqXnSmWzWSUHz0F6aHZE8+ # RokWYyBry/J70DXjSnBIqbbnHWC9BCIVJXAGcqlEO2lHEdPu6cegPk8QuTA25POq # aQmoi35komWUEftuMvH1uzitzcCTEdUyeEpLNypM81zctoXAu3AwVXjWmP5UbX9x # qUgaeN1Gdy4besAzivhKKIwSqHPPLfnTI/KeGeANlCig69saUaCVgo4oa6TOnXbe # qXOqSGpZQ65f6vgPBkKd3wZolv4qoHRbY2beayy4eKpNcG3wLPEHFX41tOa1DKKZ # pdcVazUOhdbgLMzgDCS4fFILHpl878jIxYxYaa+rPeHPzH0VrhS/inHfypex2Efq # HIXgRU4SHBQpWMxv03/LvsEOSm8gnK7ZczJZCOctkqEaEf4ymKZdK5fgi9OczG21 # Da5HYzhHF1tvE9pqEG4fSbdEW7QICodaWQR2EaGndwITHDGCBUwwggVIAgEBMIGG # MHIxCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsT # EHd3dy5kaWdpY2VydC5jb20xMTAvBgNVBAMTKERpZ2lDZXJ0IFNIQTIgQXNzdXJl # ZCBJRCBDb2RlIFNpZ25pbmcgQ0ECEATV3B9I6snYUgC6zZqbKqcwCQYFKw4DAhoF # AKB4MBgGCisGAQQBgjcCAQwxCjAIoAKAAKECgAAwGQYJKoZIhvcNAQkDMQwGCisG # AQQBgjcCAQQwHAYKKwYBBAGCNwIBCzEOMAwGCisGAQQBgjcCARUwIwYJKoZIhvcN # AQkEMRYEFNy/4h8QU0UzrWooQt6byQWp2JECMA0GCSqGSIb3DQEBAQUABIIBACPQ # wyyODnzADc8nAL3Yo67tPCFLqrGqHrze0Qf5SE9OLQNGTBIUTba/5c2Rmj3FTzLL # nFR7O+wlyZUcsXXFEqZ8SD+O+3KTfQi/iERdGah99jSUITQb90596LhNw5KVZtwO # 8RK6McDv/IfYMVxeKoEsEWu60y28YT0Up590Ln6akHkmR0PByC1MBl9uYepmLuZc # sbLJ/EMNUou907aiNyqipBNbZiEGtsMPNSiQMsWzZ3qonrKOSvdxdzMUsvacbTIU # 9x18czSj01gKAMOdmHRbEUYd9A9dyZTkQiWualDhtOEf1oFOGJyqY+BkHgvUHClq # ciMvqciWUz2ePTcQvTKhggMgMIIDHAYJKoZIhvcNAQkGMYIDDTCCAwkCAQEwdzBj # MQswCQYDVQQGEwJVUzEXMBUGA1UEChMORGlnaUNlcnQsIEluYy4xOzA5BgNVBAMT # MkRpZ2lDZXJ0IFRydXN0ZWQgRzQgUlNBNDA5NiBTSEEyNTYgVGltZVN0YW1waW5n # IENBAhAKekqInsmZQpAGYzhNhpedMA0GCWCGSAFlAwQCAQUAoGkwGAYJKoZIhvcN # AQkDMQsGCSqGSIb3DQEHATAcBgkqhkiG9w0BCQUxDxcNMjIwNDEyMjE1NDA0WjAv # BgkqhkiG9w0BCQQxIgQgRhRPjbEMp4+p6tCcmK8A+nOh76uZEAj4jwndzfGLi3Mw # DQYJKoZIhvcNAQEBBQAEggIAniGsRCGhcvwCjYCEAkMqfZAjaiy6QbJrlRQs4zDF # A5qjCFRFav/ic35RbjTbtEvpNLcs6qKwfQmHJqA3aliSMCNLZ7YXLkyUJ1WPzAIe # Ty8pe0SwbMsaQW9rQScbKNOg8VXpTqSQ1UxU+OH6uPXjeswjm00Rro2TBbw01id0 # 4/3KxL8ukKqIg9t1QNGLopVoU84FHguPJ03OglWloB4h20S7CYKjg0X97nMV9I+L # HTvXZsT8vcscHRH+aNsAJbURKWZyV39NRX8ShzlRZ/wqT41EcnK+7jXF4LJQhgB6 # f00tVkiA712zxVBCrDcoqiOvBRp01QUpEvD08Z4bOMJgPWj01ZrjewBRULQlsvkb # peJRPmTcB8gt6eXf07etjgrrQoGC71u6jkFRlq/7+cmHHrUrl9duR/WnFy4QGSNB # B5WSC8lsSfxuG81oRBvsUbtrXwAxPgA4P3j5qPw0DCOMvp12f9T9adUgA4x3WRHu # uQqCCjBBCY0v1ifdhhCntYuQS3Syoanc993Mz97lyWo1IZ6bB8OtXAx/xZqOUd3y # Ysr5koJkmTSnfr1py1OTkAsT71wAkYuCeAu+NshDv2evY/9uPVVKoR/fsWQOsGEG # YcBoY0DkBRsks+Djit2EYcPY5Ul8ZNjcUPjF8itl+Ah50retZezTvEv8gu31jp0H # t3k= # SIG # End signature block |