GPOZaurr.psm1
function ConvertFrom-DistinguishedName { <# .SYNOPSIS Short description .DESCRIPTION Long description .PARAMETER DistinguishedName Parameter description .PARAMETER ToOrganizationalUnit Parameter description .EXAMPLE $DistinguishedName = 'CN=Przemyslaw Klys,OU=Users,OU=Production,DC=ad,DC=evotec,DC=xyz' ConvertFrom-DistinguishedName -DistinguishedName $DistinguishedName -ToOrganizationalUnit Output: OU=Users,OU=Production,DC=ad,DC=evotec,DC=xyz .EXAMPLE $DistinguishedName = 'CN=Przemyslaw Klys,OU=Users,OU=Production,DC=ad,DC=evotec,DC=xyz' ConvertFrom-DistinguishedName -DistinguishedName $DistinguishedName Output: Przemyslaw Klys .NOTES General notes #> [CmdletBinding()] param([string[]] $DistinguishedName, [switch] $ToOrganizationalUnit, [switch] $ToDC) if ($ToOrganizationalUnit) { return [Regex]::Match($DistinguishedName, '(?=OU=)(.*\n?)(?<=.)').Value } elseif ($ToDC) { $DistinguishedName -replace '.*?((DC=[^=]+,)+DC=[^=]+)$', '$1' } else { $Regex = '^CN=(?<cn>.+?)(?<!\\),(?<ou>(?:(?:OU|CN).+?(?<!\\),)+(?<dc>DC.+?))$' $Output = foreach ($_ in $DistinguishedName) { $_ -match $Regex $Matches } $Output.cn } } function ConvertFrom-SID { [cmdletbinding()] param([string[]] $SID, [switch] $OnlyWellKnown) $wellKnownSIDs = @{'S-1-0' = 'Null Authority' 'S-1-0-0' = 'Nobody' 'S-1-1' = 'World Authority' 'S-1-1-0' = 'Everyone' 'S-1-2' = 'Local Authority' 'S-1-2-0' = 'Local' 'S-1-2-1' = 'Console Logon' 'S-1-3' = 'Creator Authority' 'S-1-3-0' = 'Creator Owner' 'S-1-3-1' = 'Creator Group' 'S-1-3-2' = 'Creator Owner Server' 'S-1-3-3' = 'Creator Group Server' 'S-1-3-4' = 'Owner Rights' 'S-1-5-80-0' = 'All Services' 'S-1-4' = 'Non-unique Authority' 'S-1-5' = 'NT Authority' 'S-1-5-1' = 'Dialup' 'S-1-5-2' = 'Network' 'S-1-5-3' = 'Batch' 'S-1-5-4' = 'Interactive' 'S-1-5-6' = 'Service' 'S-1-5-7' = 'Anonymous' 'S-1-5-8' = 'Proxy' 'S-1-5-9' = 'Enterprise Domain Controllers' 'S-1-5-10' = 'Principal Self' 'S-1-5-11' = 'Authenticated Users' 'S-1-5-12' = 'Restricted Code' 'S-1-5-13' = 'Terminal Server Users' 'S-1-5-14' = 'Remote Interactive Logon' 'S-1-5-15' = 'This Organization' 'S-1-5-17' = 'This Organization' 'S-1-5-18' = 'Local System' 'S-1-5-19' = 'NT Authority\Local Service' 'S-1-5-20' = 'NT Authority\Network Service' 'S-1-5-32-544' = 'Administrators' 'S-1-5-32-545' = 'Users' 'S-1-5-32-546' = 'Guests' 'S-1-5-32-547' = 'Power Users' 'S-1-5-32-548' = 'Account Operators' 'S-1-5-32-549' = 'Server Operators' 'S-1-5-32-550' = 'Print Operators' 'S-1-5-32-551' = 'Backup Operators' 'S-1-5-32-552' = 'Replicators' 'S-1-5-64-10' = 'NTLM Authentication' 'S-1-5-64-14' = 'SChannel Authentication' 'S-1-5-64-21' = 'Digest Authority' 'S-1-5-80' = 'NT Service' 'S-1-5-83-0' = 'NT VIRTUAL MACHINE\Virtual Machines' 'S-1-16-0' = 'Untrusted Mandatory Level' 'S-1-16-4096' = 'Low Mandatory Level' 'S-1-16-8192' = 'Medium Mandatory Level' 'S-1-16-8448' = 'Medium Plus Mandatory Level' 'S-1-16-12288' = 'High Mandatory Level' 'S-1-16-16384' = 'System Mandatory Level' 'S-1-16-20480' = 'Protected Process Mandatory Level' 'S-1-16-28672' = 'Secure Process Mandatory Level' 'S-1-5-32-554' = 'BUILTIN\Pre-Windows 2000 Compatible Access' 'S-1-5-32-555' = 'BUILTIN\Remote Desktop Users' 'S-1-5-32-556' = 'BUILTIN\Network Configuration Operators' 'S-1-5-32-557' = 'BUILTIN\Incoming Forest Trust Builders' 'S-1-5-32-558' = 'BUILTIN\Performance Monitor Users' 'S-1-5-32-559' = 'BUILTIN\Performance Log Users' 'S-1-5-32-560' = 'BUILTIN\Windows Authorization Access Group' 'S-1-5-32-561' = 'BUILTIN\Terminal Server License Servers' 'S-1-5-32-562' = 'BUILTIN\Distributed COM Users' 'S-1-5-32-569' = 'BUILTIN\Cryptographic Operators' 'S-1-5-32-573' = 'BUILTIN\Event Log Readers' 'S-1-5-32-574' = 'BUILTIN\Certificate Service DCOM Access' 'S-1-5-32-575' = 'BUILTIN\RDS Remote Access Servers' 'S-1-5-32-576' = 'BUILTIN\RDS Endpoint Servers' 'S-1-5-32-577' = 'BUILTIN\RDS Management Servers' 'S-1-5-32-578' = 'BUILTIN\Hyper-V Administrators' 'S-1-5-32-579' = 'BUILTIN\Access Control Assistance Operators' 'S-1-5-32-580' = 'BUILTIN\Remote Management Users' } foreach ($_ in $SID) { if ($OnlyWellKnown) { [PSCustomObject] @{Name = $wellKnownSIDs[$_] SID = $_ } } else { if ($wellKnownSIDs[$_]) { [PSCustomObject] @{Name = $wellKnownSIDs[$_] SID = $_ } } else { try { [PSCustomObject] @{Name = (([System.Security.Principal.SecurityIdentifier]::new($_)).Translate([System.Security.Principal.NTAccount])).Value SID = $_ } } catch { [PSCustomObject] @{Name = $_ SID = $_ } } } } } } function Get-WinADForestDetails { [CmdletBinding()] param([alias('ForestName')][string] $Forest, [string[]] $ExcludeDomains, [string[]] $ExcludeDomainControllers, [alias('Domain', 'Domains')][string[]] $IncludeDomains, [alias('DomainControllers', 'ComputerName')][string[]] $IncludeDomainControllers, [switch] $SkipRODC, [string] $Filter = '*', [switch] $TestAvailability, [ValidateSet('All', 'Ping', 'WinRM', 'PortOpen', 'Ping+WinRM', 'Ping+PortOpen', 'WinRM+PortOpen')] $Test = 'All', [int[]] $Ports = 135, [int] $PortsTimeout = 100, [int] $PingCount = 1, [switch] $Extended, [System.Collections.IDictionary] $ExtendedForestInformation) if ($Global:ProgressPreference -ne 'SilentlyContinue') { $TemporaryProgress = $Global:ProgressPreference $Global:ProgressPreference = 'SilentlyContinue' } if (-not $ExtendedForestInformation) { $Findings = [ordered] @{ } try { if ($Forest) { $ForestInformation = Get-ADForest -ErrorAction Stop -Identity $Forest } else { $ForestInformation = Get-ADForest -ErrorAction Stop } } catch { Write-Warning "Get-WinADForestDetails - Error discovering DC for Forest - $($_.Exception.Message)" return } if (-not $ForestInformation) { return } $Findings['Forest'] = $ForestInformation $Findings['ForestDomainControllers'] = @() $Findings['QueryServers'] = @{ } $Findings['DomainDomainControllers'] = @{ } [Array] $Findings['Domains'] = foreach ($_ in $ForestInformation.Domains) { if ($IncludeDomains) { if ($_ -in $IncludeDomains) { $_.ToLower() } continue } if ($_ -notin $ExcludeDomains) { $_.ToLower() } } [Array] $Findings['ForestDomainControllers'] = foreach ($Domain in $Findings.Domains) { try { $DC = Get-ADDomainController -DomainName $Domain -Discover -ErrorAction Stop $OrderedDC = [ordered] @{Domain = $DC.Domain Forest = $DC.Forest HostName = [Array] $DC.HostName IPv4Address = $DC.IPv4Address IPv6Address = $DC.IPv6Address Name = $DC.Name Site = $DC.Site } } catch { Write-Warning "Get-WinADForestDetails - Error discovering DC for domain $Domain - $($_.Exception.Message)" continue } if ($Domain -eq $Findings['Forest']['Name']) { $Findings['QueryServers']['Forest'] = $OrderedDC } $Findings['QueryServers']["$Domain"] = $OrderedDC [Array] $AllDC = try { try { $DomainControllers = Get-ADDomainController -Filter $Filter -Server $DC.HostName[0] -ErrorAction Stop } catch { Write-Warning "Get-WinADForestDetails - Error listing DCs for domain $Domain - $($_.Exception.Message)" continue } foreach ($S in $DomainControllers) { if ($IncludeDomainControllers.Count -gt 0) { If (-not $IncludeDomainControllers[0].Contains('.')) { if ($S.Name -notin $IncludeDomainControllers) { continue } } else { if ($S.HostName -notin $IncludeDomainControllers) { continue } } } if ($ExcludeDomainControllers.Count -gt 0) { If (-not $ExcludeDomainControllers[0].Contains('.')) { if ($S.Name -in $ExcludeDomainControllers) { continue } } else { if ($S.HostName -in $ExcludeDomainControllers) { continue } } } $Server = [ordered] @{Domain = $Domain HostName = $S.HostName Name = $S.Name Forest = $ForestInformation.RootDomain Site = $S.Site IPV4Address = $S.IPV4Address IPV6Address = $S.IPV6Address IsGlobalCatalog = $S.IsGlobalCatalog IsReadOnly = $S.IsReadOnly IsSchemaMaster = ($S.OperationMasterRoles -contains 'SchemaMaster') IsDomainNamingMaster = ($S.OperationMasterRoles -contains 'DomainNamingMaster') IsPDC = ($S.OperationMasterRoles -contains 'PDCEmulator') IsRIDMaster = ($S.OperationMasterRoles -contains 'RIDMaster') IsInfrastructureMaster = ($S.OperationMasterRoles -contains 'InfrastructureMaster') OperatingSystem = $S.OperatingSystem OperatingSystemVersion = $S.OperatingSystemVersion OperatingSystemLong = ConvertTo-OperatingSystem -OperatingSystem $S.OperatingSystem -OperatingSystemVersion $S.OperatingSystemVersion LdapPort = $S.LdapPort SslPort = $S.SslPort DistinguishedName = $S.ComputerObjectDN Pingable = $null WinRM = $null PortOpen = $null Comment = '' } if ($TestAvailability) { if ($Test -eq 'All' -or $Test -like 'Ping*') { $Server.Pingable = Test-Connection -ComputerName $Server.IPV4Address -Quiet -Count $PingCount } if ($Test -eq 'All' -or $Test -like '*WinRM*') { $Server.WinRM = (Test-WinRM -ComputerName $Server.HostName).Status } if ($Test -eq 'All' -or '*PortOpen*') { $Server.PortOpen = (Test-ComputerPort -Server $Server.HostName -PortTCP $Ports -Timeout $PortsTimeout).Status } } [PSCustomObject] $Server } } catch { [PSCustomObject]@{Domain = $Domain HostName = '' Name = '' Forest = $ForestInformation.RootDomain IPV4Address = '' IPV6Address = '' IsGlobalCatalog = '' IsReadOnly = '' Site = '' SchemaMaster = $false DomainNamingMasterMaster = $false PDCEmulator = $false RIDMaster = $false InfrastructureMaster = $false LdapPort = '' SslPort = '' DistinguishedName = '' Pingable = $null WinRM = $null PortOpen = $null Comment = $_.Exception.Message -replace "`n", " " -replace "`r", " " } } if ($SkipRODC) { [Array] $Findings['DomainDomainControllers'][$Domain] = $AllDC | Where-Object { $_.IsReadOnly -eq $false } } else { [Array] $Findings['DomainDomainControllers'][$Domain] = $AllDC } [Array] $Findings['DomainDomainControllers'][$Domain] } if ($Extended) { $Findings['DomainsExtended'] = @{ } foreach ($DomainEx in $Findings['Domains']) { try { $Findings['DomainsExtended'][$DomainEx] = Get-ADDomain -Server $Findings['QueryServers'][$DomainEx].HostName[0] } catch { Write-Warning "Get-WinADForestDetails - Error gathering Domain Information for domain $DomainEx - $($_.Exception.Message)" continue } } } if ($TemporaryProgress) { $Global:ProgressPreference = $TemporaryProgress } $Findings } else { $Findings = Copy-Dictionary -Dictionary $ExtendedForestInformation [Array] $Findings['Domains'] = foreach ($_ in $Findings.Domains) { if ($IncludeDomains) { if ($_ -in $IncludeDomains) { $_.ToLower() } continue } if ($_ -notin $ExcludeDomains) { $_.ToLower() } } foreach ($_ in [string[]] $Findings.DomainDomainControllers.Keys) { if ($_ -notin $Findings.Domains) { $Findings.DomainDomainControllers.Remove($_) } } foreach ($_ in [string[]] $Findings.QueryServers.Keys) { if ($_ -notin $Findings.Domains -and $_ -ne 'Forest') { $Findings.QueryServers.Remove($_) } } [Array] $Findings['ForestDomainControllers'] = foreach ($Domain in $Findings.Domains) { [Array] $AllDC = foreach ($S in $Findings.DomainDomainControllers["$Domain"]) { if ($IncludeDomainControllers.Count -gt 0) { If (-not $IncludeDomainControllers[0].Contains('.')) { if ($S.Name -notin $IncludeDomainControllers) { continue } } else { if ($S.HostName -notin $IncludeDomainControllers) { continue } } } if ($ExcludeDomainControllers.Count -gt 0) { If (-not $ExcludeDomainControllers[0].Contains('.')) { if ($S.Name -in $ExcludeDomainControllers) { continue } } else { if ($S.HostName -in $ExcludeDomainControllers) { continue } } } $S } if ($SkipRODC) { [Array] $Findings['DomainDomainControllers'][$Domain] = $AllDC | Where-Object { $_.IsReadOnly -eq $false } } else { [Array] $Findings['DomainDomainControllers'][$Domain] = $AllDC } [Array] $Findings['DomainDomainControllers'][$Domain] } $Findings } } function ConvertTo-OperatingSystem { [CmdletBinding()] param([string] $OperatingSystem, [string] $OperatingSystemVersion) if ($OperatingSystem -like '*Windows 10*') { $Systems = @{'10.0 (18363)' = "Windows 10 1909" '10.0 (18362)' = "Windows 10 1903" '10.0 (17763)' = "Windows 10 1809" '10.0 (17134)' = "Windows 10 1803" '10.0 (16299)' = "Windows 10 1709" '10.0 (15063)' = "Windows 10 1703" '10.0 (14393)' = "Windows 10 1607" '10.0 (10586)' = "Windows 10 1511" '10.0 (10240)' = "Windows 10 1507" '10.0 (18898)' = 'Windows 10 Insider Preview' '10.0.18363' = "Windows 10 1909" '10.0.18362' = "Windows 10 1903" '10.0.17763' = "Windows 10 1809" '10.0.17134' = "Windows 10 1803" '10.0.16299' = "Windows 10 1709" '10.0.15063' = "Windows 10 1703" '10.0.14393' = "Windows 10 1607" '10.0.10586' = "Windows 10 1511" '10.0.10240' = "Windows 10 1507" '10.0.18898' = 'Windows 10 Insider Preview' } $System = $Systems[$OperatingSystemVersion] if (-not $System) { $System = $OperatingSystem } } elseif ($OperatingSystem -like '*Windows Server*') { $Systems = @{'5.2 (3790)' = 'Windows Server 2003' '6.1 (7601)' = 'Windows Server 2008 R2' '10.0 (18362)' = "Windows Server, version 1903 (Semi-Annual Channel) 1903" '10.0 (17763)' = "Windows Server 2019 (Long-Term Servicing Channel) 1809" '10.0 (17134)' = "Windows Server, version 1803 (Semi-Annual Channel) 1803" '10.0 (14393)' = "Windows Server 2016 (Long-Term Servicing Channel) 1607" '10.0.18362' = "Windows Server, version 1903 (Semi-Annual Channel) 1903" '10.0.17763' = "Windows Server 2019 (Long-Term Servicing Channel) 1809" '10.0.17134' = "Windows Server, version 1803 (Semi-Annual Channel) 1803" '10.0.14393' = "Windows Server 2016 (Long-Term Servicing Channel) 1607" } $System = $Systems[$OperatingSystemVersion] if (-not $System) { $System = $OperatingSystem } } else { $System = $OperatingSystem } if ($System) { $System } else { 'Unknown' } } function Test-ComputerPort { [CmdletBinding()] param ([alias('Server')][string[]] $ComputerName, [int[]] $PortTCP, [int[]] $PortUDP, [int]$Timeout = 5000) begin { if ($Global:ProgressPreference -ne 'SilentlyContinue') { $TemporaryProgress = $Global:ProgressPreference $Global:ProgressPreference = 'SilentlyContinue' } } process { foreach ($Computer in $ComputerName) { foreach ($P in $PortTCP) { $Output = [ordered] @{'ComputerName' = $Computer 'Port' = $P 'Protocol' = 'TCP' 'Status' = $null 'Summary' = $null 'Response' = $null } $TcpClient = Test-NetConnection -ComputerName $Computer -Port $P -InformationLevel Detailed -WarningAction SilentlyContinue if ($TcpClient.TcpTestSucceeded) { $Output['Status'] = $TcpClient.TcpTestSucceeded $Output['Summary'] = "TCP $P Successful" } else { $Output['Status'] = $false $Output['Summary'] = "TCP $P Failed" $Output['Response'] = $Warnings } [PSCustomObject]$Output } foreach ($P in $PortUDP) { $Output = [ordered] @{'ComputerName' = $Computer 'Port' = $P 'Protocol' = 'UDP' 'Status' = $null 'Summary' = $null } $UdpClient = [System.Net.Sockets.UdpClient]::new($Computer, $P) $UdpClient.Client.ReceiveTimeout = $Timeout $Encoding = [System.Text.ASCIIEncoding]::new() $byte = $Encoding.GetBytes("Evotec") [void]$UdpClient.Send($byte, $byte.length) $RemoteEndpoint = [System.Net.IPEndPoint]::new([System.Net.IPAddress]::Any, 0) try { $Bytes = $UdpClient.Receive([ref]$RemoteEndpoint) [string]$Data = $Encoding.GetString($Bytes) If ($Data) { $Output['Status'] = $true $Output['Summary'] = "UDP $P Successful" $Output['Response'] = $Data } } catch { $Output['Status'] = $false $Output['Summary'] = "UDP $P Failed" $Output['Response'] = $_.Exception.Message } $UdpClient.Close() $UdpClient.Dispose() [PSCustomObject]$Output } } } end { if ($TemporaryProgress) { $Global:ProgressPreference = $TemporaryProgress } } } function Test-WinRM { [CmdletBinding()] param ([alias('Server')][string[]] $ComputerName) $Output = foreach ($Computer in $ComputerName) { $Test = [PSCustomObject] @{Output = $null Status = $null ComputerName = $Computer } try { $Test.Output = Test-WSMan -ComputerName $Computer -ErrorAction Stop $Test.Status = $true } catch { $Test.Status = $false } $Test } $Output } function Get-ADADministrativeGroups { <# .SYNOPSIS Short description .DESCRIPTION Long description .PARAMETER Type Parameter description .PARAMETER Forest Parameter description .PARAMETER ExcludeDomains Parameter description .PARAMETER IncludeDomains Parameter description .PARAMETER ExtendedForestInformation Parameter description .EXAMPLE Get-ADADministrativeGroups -Type DomainAdmins, EnterpriseAdmins Output (Where VALUE is Get-ADGroup output): Name Value ---- ----- ByNetBIOS {EVOTEC\Domain Admins, EVOTEC\Enterprise Admins, EVOTECPL\Domain Admins} ad.evotec.xyz {DomainAdmins, EnterpriseAdmins} ad.evotec.pl {DomainAdmins} .NOTES General notes #> [cmdletBinding()] param( [parameter(Mandatory)][validateSet('DomainAdmins', 'EnterpriseAdmins')][string[]] $Type, [alias('ForestName')][string] $Forest, [string[]] $ExcludeDomains, [alias('Domain', 'Domains')][string[]] $IncludeDomains, [System.Collections.IDictionary] $ExtendedForestInformation ) $ADDictionary = [ordered] @{ } $ADDictionary['ByNetBIOS'] = [ordered] @{ } $ADDictionary['BySID'] = [ordered] @{ } $ForestInformation = Get-WinADForestDetails -Forest $Forest -IncludeDomains $IncludeDomains -ExcludeDomains $ExcludeDomains -ExtendedForestInformation $ExtendedForestInformation foreach ($Domain in $ForestInformation.Domains) { $ADDictionary[$Domain] = [ordered] @{ } $QueryServer = $ForestInformation['QueryServers'][$Domain]['HostName'][0] $DomainInformation = Get-ADDomain -Server $QueryServer if ($Type -contains 'DomainAdmins') { Get-ADGroup -Filter "SID -eq '$($DomainInformation.DomainSID)-512'" -Server $QueryServer -ErrorAction SilentlyContinue | ForEach-Object { $ADDictionary['ByNetBIOS']["$($DomainInformation.NetBIOSName)\$($_.Name)"] = $_ $ADDictionary[$Domain]['DomainAdmins'] = "$($DomainInformation.NetBIOSName)\$($_.Name)" $ADDictionary['BySID'][$_.SID.Value] = $_ } } if ($Type -contains 'EnterpriseAdmins') { Get-ADGroup -Filter "SID -eq '$($DomainInformation.DomainSID)-519'" -Server $QueryServer -ErrorAction SilentlyContinue | ForEach-Object { $ADDictionary['ByNetBIOS']["$($DomainInformation.NetBIOSName)\$($_.Name)"] = $_ $ADDictionary[$Domain]['EnterpriseAdmins'] = "$($DomainInformation.NetBIOSName)\$($_.Name)" $ADDictionary['BySID'][$_.SID.Value] = $_ #"$($DomainInformation.NetBIOSName)\$($_.Name)" } } } return $ADDictionary } #Get-ADADministrativeGroups -Type DomainAdmins, EnterpriseAdmins function Get-PrivPermission { [cmdletBinding()] param( [Microsoft.GroupPolicy.Gpo] $GPO, [switch] $SkipWellKnown, [switch] $SkipAdministrative, [switch] $IncludeOwner, [Microsoft.GroupPolicy.GPPermissionType[]] $IncludePermissionType, [Microsoft.GroupPolicy.GPPermissionType[]] $ExcludePermissionType, [switch] $IncludeGPOObject, [System.Collections.IDictionary] $ADAdministrativeGroups, [string[]] $Type, [System.Collections.IDictionary] $Accounts ) Write-Verbose "Get-GPOZaurrPermission - Processing $($GPO.DisplayName) from $($GPO.DomainName)" $SecurityRights = $GPO.GetSecurityInfo() $SecurityRights | ForEach-Object -Process { #Get-GPPermissions -Guid $GPO.ID -DomainName $GPO.DomainName -All -Server $QueryServer | ForEach-Object -Process { $GPOPermission = $_ if ($ExcludePermissionType -contains $GPOPermission.Permission) { return } if ($IncludePermissionType) { if ($IncludePermissionType -notcontains $GPOPermission.Permission) { return } } if ($SkipWellKnown.IsPresent) { if ($GPOPermission.Trustee.SidType -eq 'WellKnownGroup') { return } } if ($SkipAdministrative.IsPresent) { $IsAdministrative = $ADAdministrativeGroups['BySID'][$GPOPermission.Trustee.Sid.Value] if ($IsAdministrative) { return } } if ($Type -contains 'Unknown' -and $Type -notcontains 'All') { # May need updates if there's more types if ($GPOPermission.Trustee.SidType -ne 'Unknown') { return } } $ReturnObject = [ordered] @{ DisplayName = $GPO.DisplayName # : ALL | Enable RDP GUID = $GPO.ID DomainName = $GPO.DomainName # : ad.evotec.xyz Enabled = $GPO.GpoStatus Description = $GPO.Description CreationDate = $GPO.CreationTime ModificationTime = $GPO.ModificationTime Permission = $GPOPermission.Permission # : GpoEditDeleteModifySecurity Inherited = $GPOPermission.Inherited # : False Domain = $GPOPermission.Trustee.Domain #: EVOTEC DistinguishedName = $GPOPermission.Trustee.DSPath #: CN = Domain Admins, CN = Users, DC = ad, DC = evotec, DC = xyz Name = $GPOPermission.Trustee.Name #: Domain Admins Sid = $GPOPermission.Trustee.Sid.Value #: S - 1 - 5 - 21 - 853615985 - 2870445339 - 3163598659 - 512 SidType = $GPOPermission.Trustee.SidType #: Group } if ($Accounts) { $A = -join ($GPOPermission.Trustee.Domain, '\', $GPOPermission.Trustee.Name) if ($A -and $Accounts[$A]) { $ReturnObject['UserPrincipalName'] = $Accounts[$A].UserPrincipalName $ReturnObject['AccountEnabled'] = $Accounts[$A].Enabled $ReturnObject['DistinguishedName'] = $Accounts[$A].DistinguishedName $ReturnObject['PasswordLastSet'] = if ($Accounts[$A].PasswordLastSet) { $Accounts[$A].PasswordLastSet } else { '' } $ReturnObject['LastLogonDate'] = if ($Accounts[$A].LastLogonDate ) { $Accounts[$A].LastLogonDate } else { '' } if (-not $ReturnObject['Sid']) { $ReturnObject['Sid'] = $Accounts[$A].Sid.Value } if ($Accounts[$A].ObjectClass -eq 'group') { $ReturnObject['SidType'] = 'Group' } elseif ($Accounts[$A].ObjectClass -eq 'user') { $ReturnObject['SidType'] = 'User' } elseif ($Accounts[$A].ObjectClass -eq 'computer') { $ReturnObject['SidType'] = 'Computer' } else { $ReturnObject['SidType'] = 'EmptyOrUnknown' } } else { $ReturnObject['UserPrincipalName'] = '' $ReturnObject['AccountEnabled'] = '' $ReturnObject['PasswordLastSet'] = '' $ReturnObject['LastLogonDate'] = '' } } if ($IncludeGPOObject) { $ReturnObject['GPOObject'] = $GPO $ReturnObject['GPOSecurity'] = $SecurityRights } [PSCustomObject] $ReturnObject } if ($IncludeOwner.IsPresent) { if ($GPO.Owner) { $SplittedOwner = $GPO.Owner.Split('\') $DomainOwner = $SplittedOwner[0] #: EVOTEC $DomainUserName = $SplittedOwner[1] #: Domain Admins $SID = $ADAdministrativeGroups['ByNetBIOS']["$($GPO.Owner)"].Sid.Value if ($SID) { $SIDType = 'Group' $DistinguishedName = $ADAdministrativeGroups['ByNetBIOS']["$($GPO.Owner)"].DistinguishedName } else { $SIDType = '' $DistinguishedName = '' } } else { $DomainOwner = $GPO.Owner $DomainUserName = '' $SID = '' $SIDType = 'EmptyOrUnknown' $DistinguishedName = '' } $ReturnObject = [ordered] @{ DisplayName = $GPO.DisplayName # : ALL | Enable RDP GUID = $GPO.Id DomainName = $GPO.DomainName # : ad.evotec.xyz Enabled = $GPO.GpoStatus Description = $GPO.Description CreationDate = $GPO.CreationTime ModificationTime = $GPO.ModificationTime Permission = 'GpoOwner' # : GpoEditDeleteModifySecurity Inherited = $false # : False Domain = $DomainOwner DistinguishedName = $DistinguishedName #: CN = Domain Admins, CN = Users, DC = ad, DC = evotec, DC = xyz Name = $DomainUserName Sid = $SID #: S - 1 - 5 - 21 - 853615985 - 2870445339 - 3163598659 - 512 SidType = $SIDType # #: Group } if ($Accounts) { $A = $GPO.Owner if ($A -and $Accounts[$A]) { $ReturnObject['UserPrincipalName'] = $Accounts[$A].UserPrincipalName $ReturnObject['AccountEnabled'] = $Accounts[$A].Enabled $ReturnObject['DistinguishedName'] = $Accounts[$A].DistinguishedName $ReturnObject['PasswordLastSet'] = if ($Accounts[$A].PasswordLastSet) { $Accounts[$A].PasswordLastSet } else { '' } $ReturnObject['LastLogonDate'] = if ($Accounts[$A].LastLogonDate ) { $Accounts[$A].LastLogonDate } else { '' } if (-not $ReturnObject['Sid']) { $ReturnObject['Sid'] = $Accounts[$A].Sid.Value } if ($Accounts[$A].ObjectClass -eq 'group') { $ReturnObject['SidType'] = 'Group' } elseif ($Accounts[$A].ObjectClass -eq 'user') { $ReturnObject['SidType'] = 'User' } elseif ($Accounts[$A].ObjectClass -eq 'computer') { $ReturnObject['SidType'] = 'Computer' } else { $ReturnObject['SidType'] = 'EmptyOrUnknown' } } else { $ReturnObject['UserPrincipalName'] = '' $ReturnObject['AccountEnabled'] = '' $ReturnObject['PasswordLastSet'] = '' $ReturnObject['LastLogonDate'] = '' } } if ($IncludeGPOObject) { $ReturnObject.GPOObject = $GPO $ReturnObject.GPOSecurity = $SecurityRights } [PSCustomObject] $ReturnObject } } function Get-XMLGPO { [cmdletBinding()] param( [XML] $XMLContent, [Microsoft.GroupPolicy.Gpo] $GPO, [switch] $PermissionsOnly, [switch] $OwnerOnly, [System.Collections.IDictionary] $ADAdministrativeGroups ) if ($XMLContent.GPO.LinksTo) { $Linked = $true $LinksCount = ([Array] $XMLContent.GPO.LinksTo).Count } else { $Linked = $false $LinksCount = 0 } # Find proper values for enabled/disabled user/computer settings if ($XMLContent.GPO.Computer.Enabled -eq 'False') { $ComputerEnabled = $false } elseif ($XMLContent.GPO.Computer.Enabled -eq 'True') { $ComputerEnabled = $true } if ($XMLContent.GPO.User.Enabled -eq 'False') { $UserEnabled = $false } elseif ($XMLContent.GPO.User.Enabled -eq 'True') { $UserEnabled = $true } # Translate Enabled to same as GPO GUI if ($UserEnabled -eq $True -and $ComputerEnabled -eq $true) { $Enabled = 'Enabled' } elseif ($UserEnabled -eq $false -and $ComputerEnabled -eq $false) { $Enabled = 'All settings disabled' } elseif ($UserEnabled -eq $true -and $ComputerEnabled -eq $false) { $Enabled = 'Computer configuration settings disabled' } elseif ($UserEnabled -eq $false -and $ComputerEnabled -eq $true) { $Enabled = 'User configuration settings disabled' } if (-not $PermissionsOnly) { if ($XMLContent.GPO.SecurityDescriptor.Owner.Name.'#text') { $AdministrativeGroup = $ADAdministrativeGroups['ByNetBIOS']["$($XMLContent.GPO.SecurityDescriptor.Owner.Name.'#text')"] $WellKnown = ConvertFrom-SID -SID $XMLContent.GPO.SecurityDescriptor.Owner.SID.'#text' -OnlyWellKnown if ($AdministrativeGroup) { $OwnerType = 'Administrative' } elseif ($WellKnown.Name) { $OwnerType = 'WellKnown' } else { $OwnerType = 'NonAdministrative' } } else { $OwnerType = 'EmptyOrUnknown' } } if ($PermissionsOnly) { [PsCustomObject] @{ 'DisplayName' = $XMLContent.GPO.Name 'DomainName' = $XMLContent.GPO.Identifier.Domain.'#text' 'GUID' = $XMLContent.GPO.Identifier.Identifier.InnerText 'Enabled' = $Enabled 'Name' = $XMLContent.GPO.SecurityDescriptor.Owner.Name.'#text' 'Sid' = $XMLContent.GPO.SecurityDescriptor.Owner.SID.'#text' #'SidType' = if (($XMLContent.GPO.SecurityDescriptor.Owner.SID.'#text').Length -le 10) { 'WellKnown' } else { 'Other' } 'PermissionType' = 'Allow' 'Inherited' = $false 'Permissions' = 'Owner' } $XMLContent.GPO.SecurityDescriptor.Permissions.TrusteePermissions | ForEach-Object -Process { if ($_) { [PsCustomObject] @{ 'DisplayName' = $XMLContent.GPO.Name 'DomainName' = $XMLContent.GPO.Identifier.Domain.'#text' 'GUID' = $XMLContent.GPO.Identifier.Identifier.InnerText 'Enabled' = $Enabled 'Name' = $_.trustee.name.'#Text' 'Sid' = $_.trustee.SID.'#Text' #'SidType' = if (($XMLContent.GPO.SecurityDescriptor.Owner.SID.'#text').Length -le 10) { 'WellKnown' } else { 'Other' } 'PermissionType' = $_.type.PermissionType 'Inherited' = if ($_.Inherited -eq 'false') { $false } else { $true } 'Permissions' = $_.Standard.GPOGroupedAccessEnum } } } } elseif ($OwnerOnly) { [PsCustomObject] @{ 'DisplayName' = $XMLContent.GPO.Name 'DomainName' = $XMLContent.GPO.Identifier.Domain.'#text' 'GUID' = $XMLContent.GPO.Identifier.Identifier.InnerText 'Enabled' = $Enabled 'Owner' = $XMLContent.GPO.SecurityDescriptor.Owner.Name.'#text' 'OwnerSID' = $XMLContent.GPO.SecurityDescriptor.Owner.SID.'#text' 'OwnerType' = $OwnerType } } else { [PsCustomObject] @{ 'DisplayName' = $XMLContent.GPO.Name 'DomainName' = $XMLContent.GPO.Identifier.Domain.'#text' 'GUID' = $XMLContent.GPO.Identifier.Identifier.InnerText 'Linked' = $Linked 'LinksCount' = $LinksCount 'Enabled' = $Enabled 'ComputerEnabled' = $ComputerEnabled 'UserEnabled' = $UserEnabled 'ComputerSettingsAvailable' = if ($null -eq $XMLContent.GPO.Computer.ExtensionData) { $false } else { $true } 'UserSettingsAvailable' = if ($null -eq $XMLContent.GPO.User.ExtensionData) { $false } else { $true } 'ComputerSettingsStatus' = if ($XMLContent.GPO.Computer.VersionDirectory -eq 0 -and $XMLContent.GPO.Computer.VersionSysvol -eq 0) { "NeverModified" } else { "Modified" } 'ComputerSetttingsVersionIdentical' = if ($XMLContent.GPO.Computer.VersionDirectory -eq $XMLContent.GPO.Computer.VersionSysvol) { $true } else { $false } 'ComputerSettings' = $XMLContent.GPO.Computer.ExtensionData.Extension 'UserSettingsStatus' = if ($XMLContent.GPO.User.VersionDirectory -eq 0 -and $XMLContent.GPO.User.VersionSysvol -eq 0) { "NeverModified" } else { "Modified" } 'UserSettingsVersionIdentical' = if ($XMLContent.GPO.User.VersionDirectory -eq $XMLContent.GPO.User.VersionSysvol) { $true } else { $false } 'UserSettings' = $XMLContent.GPO.User.ExtensionData.Extension 'CreationTime' = [DateTime] $XMLContent.GPO.CreatedTime 'ModificationTime' = [DateTime] $XMLContent.GPO.ModifiedTime 'ReadTime' = [DateTime] $XMLContent.GPO.ReadTime 'WMIFilter' = $GPO.WmiFilter.name 'WMIFilterDescription' = $GPO.WmiFilter.Description 'DistinguishedName' = $GPO.Path 'SDDL' = if ($Splitter -ne '') { $XMLContent.GPO.SecurityDescriptor.SDDL.'#text' -join $Splitter } else { $XMLContent.GPO.SecurityDescriptor.SDDL.'#text' } 'Owner' = $XMLContent.GPO.SecurityDescriptor.Owner.Name.'#text' 'OwnerSID' = $XMLContent.GPO.SecurityDescriptor.Owner.SID.'#text' 'OwnerType' = $OwnerType 'ACL' = @( [PsCustomObject] @{ 'Name' = $XMLContent.GPO.SecurityDescriptor.Owner.Name.'#text' 'Sid' = $XMLContent.GPO.SecurityDescriptor.Owner.SID.'#text' 'PermissionType' = 'Allow' 'Inherited' = $false 'Permissions' = 'Owner' } $XMLContent.GPO.SecurityDescriptor.Permissions.TrusteePermissions | ForEach-Object -Process { if ($_) { [PsCustomObject] @{ 'Name' = $_.trustee.name.'#Text' 'Sid' = $_.trustee.SID.'#Text' 'PermissionType' = $_.type.PermissionType 'Inherited' = if ($_.Inherited -eq 'false') { $false } else { $true } 'Permissions' = $_.Standard.GPOGroupedAccessEnum } } } ) 'Auditing' = if ($XMLContent.GPO.SecurityDescriptor.AuditingPresent.'#text' -eq 'true') { $true } else { $false } 'Links' = $XMLContent.GPO.LinksTo | ForEach-Object -Process { if ($_) { [PSCustomObject] @{ CanonicalName = $_.SOMPath Enabled = $_.Enabled NoOverride = $_.NoOverride } } } <# SOMName SOMPath Enabled NoOverride ------- ------- ------- ---------- ad ad.evotec.xyz true false #> #| Select-Object -ExpandProperty SOMPath } } #break } function New-ADForestDrives { [cmdletbinding()] param( [string] $ForestName, [string] $ObjectDN ) if (-not $Global:ADDrivesMapped) { if ($ForestName) { $Forest = Get-ADForest -Identity $ForestName } else { $Forest = Get-ADForest } if ($ObjectDN) { # This doesn't work because no Domain and no $Server $DNConverted = (ConvertFrom-DistinguishedName -DistinguishedName $ObjectDN -ToDC) -replace '=' -replace ',' if (-not(Get-PSDrive -Name $DNConverted -ErrorAction SilentlyContinue)) { try { if ($Server) { $null = New-PSDrive -Name $DNConverted -Root '' -PsProvider ActiveDirectory -Server $Server.Hostname[0] -Scope Global -WhatIf:$false Write-Verbose "New-ADForestDrives - Mapped drive $Domain / $($Server.Hostname[0])" } else { $null = New-PSDrive -Name $DNConverted -Root '' -PsProvider ActiveDirectory -Server $Domain -Scope Global -WhatIf:$false } } catch { Write-Warning "New-ADForestDrives - Couldn't map new AD psdrive for $Domain / $($Server.Hostname[0])" } } } else { foreach ($Domain in $Forest.Domains) { try { $Server = Get-ADDomainController -Discover -DomainName $Domain $DomainInformation = Get-ADDomain -Server $Server.Hostname[0] } catch { Write-Warning "New-ADForestDrives - Can't process domain $Domain - $($_.Exception.Message)" continue } $ObjectDN = $DomainInformation.DistinguishedName $DNConverted = (ConvertFrom-DistinguishedName -DistinguishedName $ObjectDN -ToDC) -replace '=' -replace ',' if (-not(Get-PSDrive -Name $DNConverted -ErrorAction SilentlyContinue)) { try { if ($Server) { $null = New-PSDrive -Name $DNConverted -Root '' -PsProvider ActiveDirectory -Server $Server.Hostname[0] -Scope Global -WhatIf:$false Write-Verbose "New-ADForestDrives - Mapped drive $Domain / $Server" } else { $null = New-PSDrive -Name $DNConverted -Root '' -PsProvider ActiveDirectory -Server $Domain -Scope Global -WhatIf:$false } } catch { Write-Warning "New-ADForestDrives - Couldn't map new AD psdrive for $Domain / $Server $($_.Exception.Message)" } } } } $Global:ADDrivesMapped = $true } } $Script:GPOPropetiesComputers = [ordered] @{ 'Account' = '' 'Audit' = '' 'AuditSetting' = '' 'AutoEnrollmentSettings' = '' 'Blocked' = '' 'certSettingsTrustedPublishers' = '' 'DataSourcesSettings' = '' 'DomainProfile' = '' 'Dot3SvcSetting' = '' 'EFSRecoveryAgent' = '' 'EFSSettings' = '' 'EnvironmentVariables' = '' 'EventLog' = '' 'File' = '' 'FilesSettings' = '' 'Folders' = '' 'General' = '' 'Global' = '' 'GlobalSettings' = '' 'InboundFirewallRules' = '' 'IntermediateCACertificate' = '' 'InternetZoneRule' = '' 'LocalUsersAndGroups' = '' 'MsiApplication' = '' 'NetworkOptions' = '' 'NetworkShares' = '' 'NTServices' = '' 'OutboundFirewallRules' = '' 'PathRule' = '' 'Policy' = '' 'PowerOptions' = '' 'PrinterConnection' = '' 'Printers' = '' 'PrivateProfile' = '' 'PublicProfile' = '' 'Registry' = '' 'RegistrySetting' = '' 'RegistrySettings' = '' 'RestrictedGroups' = '' 'RootCertificate' = '' 'RootCertificateSettings' = '' 'ScheduledTasks' = '' 'Script' = '' 'SecurityOptions' = '' 'ShortcutSettings' = '' 'SystemServices' = '' 'TrustedPublishersCertificate' = '' 'type' = '' 'UserRightsAssignment' = '' 'WLanSvcSetting' = '' } $Script:GPOPropertiesUsers = [ordered] @{ 'AutoDetectConfigSettings' = '' 'AutoEnrollmentSettings' = '' 'AutomaticConfiguration' = '' 'AutoSetupSetting' = '' 'Blocked' = '' 'BrowserTitle' = '' 'CustomSetupSetting' = '' 'DataSourcesSettings' = '' 'DefinesConnectionSettings' = '' 'DefinesEscOffSettings' = '' 'DefinesEscOnSettings' = '' 'DeleteChannels' = '' 'DriveMapSettings' = '' 'EscOffLocalSites' = '' 'EscOffSecurityZoneAndPrivacy' = '' 'EscOffTrustedSites' = '' 'EscOnLocalSites' = '' 'EscOnSecurityZoneAndPrivacy' = '' 'EscOnTrustedSites' = '' 'FavoriteURL' = '' 'FilesSettings' = '' 'Folder' = '' 'FolderOptions' = '' 'Folders' = '' 'General' = '' 'HomePage' = '' 'ImportedContentRatings' = '' 'InternetOptions' = '' 'LocalUsersAndGroups' = '' 'MsiApplication' = '' 'NetworkOptions' = '' 'PathRule' = '' 'PlaceFavoritesAtTop' = '' 'Policy' = '' 'PowerOptions' = '' 'PreferenceMode' = '' 'PrinterConnection' = '' 'Printers' = '' 'Programs' = '' 'ProxySettings' = '' 'RegionalOptionsSettings' = '' 'RegistrySetting' = '' 'RegistrySettings' = '' 'RestartSetupSetting' = '' 'ScheduledTasks' = '' 'Script' = '' 'SearchBar' = '' 'ShortcutSettings' = '' 'StartMenuSettings' = '' 'ToolsSetting' = '' 'TrustedPublisherLockdown' = '' 'type' = '' } function Backup-GPOZaurr { [cmdletBinding(SupportsShouldProcess)] param( [int] $LimitProcessing, [validateset('All', 'Empty', 'Unlinked')][string[]] $Type = 'All', [alias('ForestName')][string] $Forest, [string[]] $ExcludeDomains, [alias('Domain', 'Domains')][string[]] $IncludeDomains, [System.Collections.IDictionary] $ExtendedForestInformation, [string[]] $GPOPath, [string] $BackupPath, [switch] $BackupDated ) Begin { if ($BackupDated) { $BackupFinalPath = "$BackupPath\$((Get-Date).ToString('yyyy-MM-dd_HH_mm_ss'))" } else { $BackupFinalPath = $BackupPath } Write-Verbose "Backup-GPOZaurr - Backing up to $BackupFinalPath" $null = New-Item -ItemType Directory -Path $BackupFinalPath -Force $Count = 0 } Process { Get-GPOZaurr -Forest $Forest -IncludeDomains $IncludeDomains -ExcludeDomains $ExcludeDomains -ExtendedForestInformation $ExtendedForestInformation -GPOPath $GPOPath | ForEach-Object { if ($Type -contains 'All') { Write-Verbose "Backup-GPOZaurr - Backing up GPO $($_.DisplayName) from $($_.DomainName)" $Count++ try { $BackupInfo = Backup-GPO -Guid $_.GUID -Domain $_.DomainName -Path $BackupFinalPath -ErrorAction Stop #-Server $QueryServer $BackupInfo } catch { Write-Warning "Backup-GPOZaurr - Backing up GPO $($_.DisplayName) from $($_.DomainName) failed: $($_.Exception.Message)" } if ($LimitProcessing -eq $Count) { break } } if ($Type -notcontains 'All' -and $Type -contains 'Empty') { if ($_.ComputerSettingsAvailable -eq $false -and $_.UserSettingsAvailable -eq $false) { Write-Verbose "Backup-GPOZaurr - Backing up GPO $($_.DisplayName) from $($_.DomainName)" $Count++ try { $BackupInfo = Backup-GPO -Guid $_.GUID -Domain $_.DomainName -Path $BackupFinalPath -ErrorAction Stop #-Server $QueryServer $BackupInfo } catch { Write-Warning "Backup-GPOZaurr - Backing up GPO $($_.DisplayName) from $($_.DomainName) failed: $($_.Exception.Message)" } if ($LimitProcessing -eq $Count) { break } } } if ($Type -notcontains 'All' -and $Type -contains 'Unlinked') { if ($_.Linked -eq $false) { Write-Verbose "Backup-GPOZaurr - Backing up GPO $($_.DisplayName) from $($_.DomainName)" $Count++ try { $BackupInfo = Backup-GPO -Guid $_.GUID -Domain $_.DomainName -Path $BackupFinalPath -ErrorAction Stop #-Server $QueryServer $BackupInfo } catch { Write-Warning "Backup-GPOZaurr - Backing up GPO $($_.DisplayName) from $($_.DomainName) failed: $($_.Exception.Message)" } if ($LimitProcessing -eq $Count) { break } } } } } End { } } function Get-GPOZaurr { [cmdletBinding()] param( [string] $GPOName, [alias('GUID', 'GPOID')][string] $GPOGuid, [alias('ForestName')][string] $Forest, [string[]] $ExcludeDomains, [alias('Domain', 'Domains')][string[]] $IncludeDomains, [System.Collections.IDictionary] $ExtendedForestInformation, [string[]] $GPOPath, [switch] $PermissionsOnly, [switch] $OwnerOnly, [switch] $Limited ) Begin { $ADAdministrativeGroups = Get-ADADministrativeGroups -Type DomainAdmins, EnterpriseAdmins -Forest $Forest -IncludeDomains $IncludeDomains -ExcludeDomains $ExcludeDomains -ExtendedForestInformation $ExtendedForestInformation if (-not $GPOPath) { $ForestInformation = Get-WinADForestDetails -Forest $Forest -IncludeDomains $IncludeDomains -ExcludeDomains $ExcludeDomains -ExtendedForestInformation $ExtendedForestInformation } } Process { if (-not $GPOPath) { foreach ($Domain in $ForestInformation.Domains) { $QueryServer = $ForestInformation.QueryServers[$Domain]['HostName'][0] if ($GPOName) { Get-GPO -Name $GPOName -Domain $Domain -Server $QueryServer -ErrorAction SilentlyContinue | ForEach-Object { Write-Verbose "Get-GPOZaurr - Getting GPO $($_.DisplayName) / ID: $($_.ID) from $Domain" if (-not $Limited) { $XMLContent = Get-GPOReport -ID $_.ID -ReportType XML -Server $ForestInformation.QueryServers[$Domain].HostName[0] -Domain $Domain Get-XMLGPO -OwnerOnly:$OwnerOnly.IsPresent -XMLContent $XMLContent -GPO $_ -PermissionsOnly:$PermissionsOnly.IsPresent -ADAdministrativeGroups $ADAdministrativeGroups } else { $_ } } } elseif ($GPOGuid) { Get-GPO -Guid $GPOGuid -Domain $Domain -Server $QueryServer -ErrorAction SilentlyContinue | ForEach-Object { Write-Verbose "Get-GPOZaurr - Getting GPO $($_.DisplayName) / ID: $($_.ID) from $Domain" if (-not $Limited) { $XMLContent = Get-GPOReport -ID $_.ID -ReportType XML -Server $ForestInformation.QueryServers[$Domain].HostName[0] -Domain $Domain Get-XMLGPO -OwnerOnly:$OwnerOnly.IsPresent -XMLContent $XMLContent -GPO $_ -PermissionsOnly:$PermissionsOnly.IsPresent -ADAdministrativeGroups $ADAdministrativeGroups } else { $_ } } } else { Get-GPO -All -Server $QueryServer -Domain $Domain -ErrorAction SilentlyContinue | ForEach-Object { Write-Verbose "Get-GPOZaurr - Getting GPO $($_.DisplayName) / ID: $($_.ID) from $Domain" if (-not $Limited) { $XMLContent = Get-GPOReport -ID $_.ID -ReportType XML -Server $ForestInformation.QueryServers[$Domain].HostName[0] -Domain $Domain Get-XMLGPO -OwnerOnly:$OwnerOnly.IsPresent -XMLContent $XMLContent -GPO $_ -PermissionsOnly:$PermissionsOnly.IsPresent -ADAdministrativeGroups $ADAdministrativeGroups } else { $_ } } } } } else { foreach ($Path in $GPOPath) { Get-ChildItem -LiteralPath $Path -Recurse -Filter *.xml | ForEach-Object { $XMLContent = [XML]::new() $XMLContent.Load($_.FullName) Get-XMLGPO -OwnerOnly:$OwnerOnly.IsPresent -XMLContent $XMLContent -PermissionsOnly:$PermissionsOnly.IsPresent } } } } End { } } function Get-GPOZaurrBackupInformation { [cmdletBinding()] param( [string[]] $BackupFolder ) Begin { } Process { foreach ($Folder in $BackupFolder) { if ($Folder) { if ((Test-Path -LiteralPath "$Folder\manifest.xml")) { [xml] $Xml = Get-Content -LiteralPath "$Folder\manifest.xml" $Xml.Backups.BackupInst | ForEach-Object { [PSCustomObject] @{ DisplayName = $_.GPODisplayName.'#cdata-section' DomainName = $_.GPODomain.'#cdata-section' Guid = $_.GPOGUid.'#cdata-section' DomainGuid = $_.GPODomainGuid.'#cdata-section' DomainController = $_.GPODomainController.'#cdata-section' BackupTime = $_.BackupTime.'#cdata-section' ID = $_.ID.'#cdata-section' Comment = $_.Comment.'#cdata-section' } } } else { Write-Warning "Get-GPOZaurrBackupInformation - No backup information available" } } } } End { } } function Get-GPOZaurrPassword { [cmdletBinding()] param( [alias('ForestName')][string] $Forest, [string[]] $ExcludeDomains, [alias('Domain', 'Domains')][string[]] $IncludeDomains, [System.Collections.IDictionary] $ExtendedForestInformation, [string[]] $GPOPath ) if (-not $GPOPath) { if (-not $ExtendedForestInformation) { $ForestInformation = Get-WinADForestDetails -Forest $Forest -IncludeDomains $IncludeDomains -ExcludeDomains $ExcludeDomains } else { $ForestInformation = $ExtendedForestInformation } $GPOPath = foreach ($Domain in $ForestInformation.Domains) { -join ('\\', $Domain, '\SYSVOL\', $Domain, '\Policies') } } if (-not $GPOPath) { return } foreach ($Path in $GPOPath) { #Extract the all XML files in the Folders $Items = Get-ChildItem -LiteralPath $Path -Recurse -Filter *.xml $Output = foreach ($XMLFileName in $Items) { #Convert XML in a String file [string]$XMLString = Get-Content ($XMLFileName.FullName) #Check if Cpassword Exist in the file if ($XMLString.Contains("cpassword")) { #Take the Cpassword Value from XML String file [string]$Cpassword = [regex]::matches($XMLString, '(cpassword=).+?(?=\")') $Cpassword = $Cpassword.split('(\")')[1] #Check if Cpassword has a value if ($Cpassword.Length -gt 20 -and $Cpassword -notlike '*cpassword*') { $Mod = ($Cpassword.length % 4) switch ($Mod) { '1' { $Cpassword = $Cpassword.Substring(0, $Cpassword.Length - 1) } '2' { $Cpassword += ('=' * (4 - $Mod)) } '3' { $Cpassword += ('=' * (4 - $Mod)) } } $Base64Decoded = [Convert]::FromBase64String($Cpassword) $AesObject = [System.Security.Cryptography.AesCryptoServiceProvider]::new() #Use th AES Key [Byte[]] $AesKey = @(0x4e, 0x99, 0x06, 0xe8, 0xfc, 0xb6, 0x6c, 0xc9, 0xfa, 0xf4, 0x93, 0x10, 0x62, 0x0f, 0xfe, 0xe8, 0xf4, 0x96, 0xe8, 0x06, 0xcc, 0x05, 0x79, 0x90, 0x20, 0x9b, 0x09, 0xa4, 0x33, 0xb6, 0x6c, 0x1b) $AesIV = New-Object Byte[]($AesObject.IV.Length) $AesObject.IV = $AesIV $AesObject.Key = $AesKey $DecryptorObject = $AesObject.CreateDecryptor() [Byte[]] $OutBlock = $DecryptorObject.TransformFinalBlock($Base64Decoded, 0, $Base64Decoded.length) #Convert Hash variable in a String valute $Password = [System.Text.UnicodeEncoding]::Unicode.GetString($OutBlock) } else { $Password = '' } #[string]$GPOguid = [regex]::matches($XMLFileName.DirectoryName, '(?<=\{).+?(?=\})') #$GPODetail = Get-GPO -guid $GPOguid [xml] $XMLContent = $XMLString #if (-not $XMLContent.gpo.Computer.ExtensionData.Extension.LocalUsersAndGroups.User.Properties.cpassword -and -not $XMLContent.gpo.User.ExtensionData.Extension.DriveMapSettings.Drive.Properties.cpassword) { #Write-Host '' #} if ($Password) { $PasswordStatus = $true } else { $PasswordStatus = $false } [PsCustomObject] @{ 'Name' = $XMLContent.GPO.Name 'Links' = $XMLContent.GPO.LinksTo #| Select-Object -ExpandProperty SOMPath 'Enabled' = $XMLContent.GPO.GpoStatus 'PasswordStatus' = $PasswordStatus #'GPO' = $XMLContent.gpo.Computer.ExtensionData.Extension.LocalUsersAndGroups 'User' = $XMLContent.gpo.Computer.ExtensionData.Extension.LocalUsersAndGroups.User.name 'Cpassword' = $XMLContent.gpo.Computer.ExtensionData.Extension.LocalUsersAndGroups.User.Properties.cpassword 'CpasswordMap' = $XMLContent.gpo.User.ExtensionData.Extension.DriveMapSettings.Drive.Properties.cpassword 'Password' = $Password 'GUID' = $XMLContent.GPO.Identifier.Identifier.InnerText 'Domain' = $XMLContent.GPO.Identifier.Domain 'ComputerSettingsAvailable' = if ($null -eq $XMLContent.GPO.Computer.ExtensionData) { $false } else { $true } 'ComputerSettingsStatus' = if ($XMLContent.GPO.Computer.VersionDirectory -eq 0 -and $XMLContent.GPO.Computer.VersionSysvol -eq 0) { "NeverModified" } else { "Modified" } 'ComputerEnabled' = [bool] $XMLContent.GPO.Computer.Enabled 'ComputerSetttingsVersionIdentical' = if ($XMLContent.GPO.Computer.VersionDirectory -eq $XMLContent.GPO.Computer.VersionSysvol) { $true } else { $false } 'ComputerSettings' = $XMLContent.GPO.Computer.ExtensionData.Extension 'UserSettingsAvailable' = if ($null -eq $XMLContent.GPO.User.ExtensionData) { $false } else { $true } 'UserEnabled' = [bool] $XMLContent.GPO.User.Enabled 'UserSettingsStatus' = if ($XMLContent.GPO.User.VersionDirectory -eq 0 -and $XMLContent.GPO.User.VersionSysvol -eq 0) { "NeverModified" } else { "Modified" } 'UserSettingsVersionIdentical' = if ($XMLContent.GPO.User.VersionDirectory -eq $XMLContent.GPO.User.VersionSysvol) { $true } else { $false } 'UserSettings' = $XMLContent.GPO.User.ExtensionData.Extension 'CreationTime' = [DateTime] $XMLContent.GPO.CreatedTime 'ModificationTime' = [DateTime] $XMLContent.GPO.ModifiedTime 'ReadTime' = [DateTime] $XMLContent.GPO.ReadTime 'WMIFilter' = $GPO.WmiFilter.name 'WMIFilterDescription' = $GPO.WmiFilter.Description 'Path' = $GPO.Path #'SDDL' = if ($Splitter -ne '') { $XMLContent.GPO.SecurityDescriptor.SDDL.'#text' -join $Splitter } else { $XMLContent.GPO.SecurityDescriptor.SDDL.'#text' } 'ACL' = $XMLContent.GPO.SecurityDescriptor.Permissions.TrusteePermissions | ForEach-Object -Process { [PSCustomObject] @{ 'User' = $_.trustee.name.'#Text' 'Permission Type' = $_.type.PermissionType 'Inherited' = $_.Inherited 'Permissions' = $_.Standard.GPOGroupedAccessEnum } } } #Write-Host "I find a Password [ " $Password " ] The GPO named:" $GPODetail" and th file is:" $XMLFileName } #if($XMLContent.Contains("cpassword") } $Output } } function Get-GPOZaurrPermission { [cmdletBinding(DefaultParameterSetName = 'GPO' )] param( [Parameter(ParameterSetName = 'GPOName')] [string] $GPOName, [Parameter(ParameterSetName = 'GPOGUID')] [alias('GUID', 'GPOID')][string] $GPOGuid, [validateSet('Unknown', 'All')][string[]] $Type = 'All', [switch] $SkipWellKnown, [switch] $SkipAdministrative, [switch] $ResolveAccounts, [switch] $IncludeOwner, [Microsoft.GroupPolicy.GPPermissionType[]] $IncludePermissionType, [Microsoft.GroupPolicy.GPPermissionType[]] $ExcludePermissionType, [switch] $IncludeGPOObject, [alias('ForestName')][string] $Forest, [string[]] $ExcludeDomains, [alias('Domain', 'Domains')][string[]] $IncludeDomains, [System.Collections.IDictionary] $ExtendedForestInformation ) Begin { $ForestInformation = Get-WinADForestDetails -Forest $Forest -IncludeDomains $IncludeDomains -ExcludeDomains $ExcludeDomains -ExtendedForestInformation $ExtendedForestInformation $ADAdministrativeGroups = Get-ADADministrativeGroups -Type DomainAdmins, EnterpriseAdmins -Forest $Forest -IncludeDomains $IncludeDomains -ExcludeDomains $ExcludeDomains -ExtendedForestInformation $ExtendedForestInformation if ($Type -eq 'Unknown') { if ($SkipAdministrative -or $SkipWellKnown) { Write-Warning "Get-GPOZaurrPermission - Using SkipAdministrative or SkipWellKnown while looking for Unknown doesn't make sense as only Unknown will be displayed." } } if ($ResolveAccounts) { $Accounts = @{ } foreach ($Domain in $ForestInformation.Domains) { $QueryServer = $ForestInformation['QueryServers'][$Domain]['HostName'][0] $DomainInformation = Get-ADDomain -Server $QueryServer $Users = Get-ADUser -Filter * -Server $QueryServer -Properties PasswordLastSet, LastLogonDate, UserPrincipalName foreach ($User in $Users) { $U = -join ($DomainInformation.NetBIOSName, '\', $User.SamAccountName) $Accounts[$U] = $User } $Groups = Get-ADGroup -Filter * -Server $QueryServer foreach ($Group in $Groups) { $G = -join ($DomainInformation.NetBIOSName, '\', $Group.SamAccountName) $Accounts[$G] = $Group } } } } Process { foreach ($Domain in $ForestInformation.Domains) { $QueryServer = $ForestInformation['QueryServers'][$Domain]['HostName'][0] if ($GPOName) { Get-GPO -Name $GPOName -Domain $Domain -Server $QueryServer -ErrorAction SilentlyContinue | ForEach-Object -Process { Get-PrivPermission -Accounts $Accounts -Type $Type -GPO $_ -SkipWellKnown:$SkipWellKnown.IsPresent -SkipAdministrative:$SkipAdministrative.IsPresent -IncludeOwner:$IncludeOwner.IsPresent -IncludeGPOObject:$IncludeGPOObject.IsPresent -IncludePermissionType $IncludePermissionType -ExcludePermissionType $ExcludePermissionType -ADAdministrativeGroups $ADAdministrativeGroups } } elseif ($GPOGuid) { Get-GPO -Guid $GPOGuid -Domain $Domain -Server $QueryServer -ErrorAction SilentlyContinue | ForEach-Object -Process { Get-PrivPermission -Accounts $Accounts -Type $Type -GPO $_ -SkipWellKnown:$SkipWellKnown.IsPresent -SkipAdministrative:$SkipAdministrative.IsPresent -IncludeOwner:$IncludeOwner.IsPresent -IncludeGPOObject:$IncludeGPOObject.IsPresent -IncludePermissionType $IncludePermissionType -ExcludePermissionType $ExcludePermissionType -ADAdministrativeGroups $ADAdministrativeGroups } } else { Get-GPO -All -Domain $Domain -Server $QueryServer | ForEach-Object -Process { Get-PrivPermission -Accounts $Accounts -Type $Type -GPO $_ -SkipWellKnown:$SkipWellKnown.IsPresent -SkipAdministrative:$SkipAdministrative.IsPresent -IncludeOwner:$IncludeOwner.IsPresent -IncludeGPOObject:$IncludeGPOObject.IsPresent -IncludePermissionType $IncludePermissionType -ExcludePermissionType $ExcludePermissionType -ADAdministrativeGroups $ADAdministrativeGroups } } } } End { } } function Get-GPOZaurrWMI { [cmdletBinding()] Param( [Guid[]] $Guid, [string[]] $Name, [alias('ForestName')][string] $Forest, [string[]] $ExcludeDomains, [alias('Domain', 'Domains')][string[]] $IncludeDomains, [System.Collections.IDictionary] $ExtendedForestInformation ) $wmiFilterAttr = "msWMI-Name", "msWMI-Parm1", "msWMI-Parm2", "msWMI-Author", "msWMI-ID", 'CanonicalName', 'Created', 'Modified' $ForestInformation = Get-WinADForestDetails -Forest $Forest -IncludeDomains $IncludeDomains -ExcludeDomains $ExcludeDomains -ExtendedForestInformation $ExtendedForestInformation foreach ($Domain in $ForestInformation.Domains) { $QueryServer = $ForestInformation['QueryServers'][$Domain]['HostName'][0] if ($Guid -or $Name) { foreach ($N in $Name) { try { $ldapFilter = "(&(objectClass=msWMI-Som)(msWMI-Name=$N))" Get-ADObject -LDAPFilter $ldapFilter -Properties $wmiFilterAttr -Server $QueryServer | ForEach-Object -Process { $WMI = $_.'msWMI-Parm2' -split ';' [PSCustomObject] @{ DisplayName = $_.'msWMI-Name' Description = $_.'msWMI-Parm1' DomainName = $Domain NameSpace = $WMI[5] Query = $WMI[6] Author = $_.'msWMI-Author' ID = $_.'msWMI-ID' Created = $_.Created Modified = $_.Modified ObjectGUID = $_.'ObjectGUID' CanonicalName = $_.CanonicalName DistinguishedName = $_.'DistinguishedName' } } } catch { Write-Warning "Get-GPOZaurrWMI - Error processing WMI for $Domain`: $($_.Error.Exception)" } } foreach ($G in $GUID) { $ldapFilter = "(&(objectClass=msWMI-Som)(Name={$G}))" try { Get-ADObject -LDAPFilter $ldapFilter -Properties $wmiFilterAttr -Server $QueryServer | ForEach-Object -Process { $WMI = $_.'msWMI-Parm2' -split ';' [PSCustomObject] @{ DisplayName = $_.'msWMI-Name' Description = $_.'msWMI-Parm1' DomainName = $Domain NameSpace = $WMI[5] Query = $WMI[6] Author = $_.'msWMI-Author' ID = $_.'msWMI-ID' Created = $_.Created Modified = $_.Modified ObjectGUID = $_.'ObjectGUID' CanonicalName = $_.CanonicalName DistinguishedName = $_.'DistinguishedName' } } } catch { Write-Warning "Get-GPOZaurrWMI - Error processing WMI for $Domain`: $($_.Error.Exception)" } } } else { $ldapFilter = "(objectClass=msWMI-Som)" try { Get-ADObject -LDAPFilter $ldapFilter -Properties $wmiFilterAttr -Server $QueryServer | ForEach-Object -Process { $WMI = $_.'msWMI-Parm2' -split ';' [PSCustomObject] @{ DisplayName = $_.'msWMI-Name' Description = $_.'msWMI-Parm1' DomainName = $Domain NameSpace = $WMI[5] Query = $WMI[6] Author = $_.'msWMI-Author' ID = $_.'msWMI-ID' Created = $_.Created Modified = $_.Modified ObjectGUID = $_.'ObjectGUID' CanonicalName = $_.CanonicalName DistinguishedName = $_.'DistinguishedName' } } } catch { Write-Warning "Get-GPOZaurrWMI - Error processing WMI for $Domain`: $($_.Error.Exception)" } } } } <# CanonicalName : ad.evotec.xyz/System/WMIPolicy/SOM/{E988C890-BDBC-4946-87B5-BF70F39F4686} CN : {E988C890-BDBC-4946-87B5-BF70F39F4686} Created : 08.04.2020 19:04:06 createTimeStamp : 08.04.2020 19:04:06 Deleted : Description : DisplayName : DistinguishedName : CN={E988C890-BDBC-4946-87B5-BF70F39F4686},CN=SOM,CN=WMIPolicy,CN=System,DC=ad,DC=evotec,DC=xyz dSCorePropagationData : {01.01.1601 01:00:00} instanceType : 4 isDeleted : LastKnownParent : Modified : 08.04.2020 19:04:06 modifyTimeStamp : 08.04.2020 19:04:06 msWMI-Author : przemyslaw.klys@evotec.pl msWMI-ChangeDate : 20200408170406.280000-000 msWMI-CreationDate : 20200408170406.280000-000 msWMI-ID : {E988C890-BDBC-4946-87B5-BF70F39F4686} msWMI-Name : Virtual Machines msWMI-Parm1 : Oh my description msWMI-Parm2 : 1;3;10;66;WQL;root\CIMv2;SELECT * FROM Win32_ComputerSystem WHERE Model = "Virtual Machine"; Name : {E988C890-BDBC-4946-87B5-BF70F39F4686} nTSecurityDescriptor : System.DirectoryServices.ActiveDirectorySecurity ObjectCategory : CN=ms-WMI-Som,CN=Schema,CN=Configuration,DC=ad,DC=evotec,DC=xyz ObjectClass : msWMI-Som ObjectGUID : c1ee708d-7a67-46e2-b13f-d11a573d2597 ProtectedFromAccidentalDeletion : False sDRightsEffective : 15 showInAdvancedViewOnly : True uSNChanged : 12785589 uSNCreated : 12785589 whenChanged : 08.04.2020 19:04:06 whenCreated : 08.04.2020 19:04:06 #> function New-GPOZaurrWMI { [cmdletBinding(SupportsShouldProcess)] param( [parameter(Mandatory)][string] $Name, [string] $Description = ' ', [parameter(Mandatory)][string] $Query, [switch] $SkipQueryCheck, [switch] $Force, [alias('ForestName')][string] $Forest, [string[]] $ExcludeDomains, [alias('Domain', 'Domains')][string[]] $IncludeDomains, [System.Collections.IDictionary] $ExtendedForestInformation ) if (-not $Forest -and -not $ExcludeDomains -and -not $IncludeDomains -and -not $ExtendedForestInformation) { $IncludeDomains = $Env:USERDNSDOMAIN } if (-not $SkipQueryCheck) { try { $null = Get-CimInstance -Query $Query -ErrorAction Stop -Verbose:$false } catch { Write-Warning "New-GPOZaurrWMI - Query error $($_.Exception.Message). Terminating." return } } $ForestInformation = Get-WinADForestDetails -Forest $Forest -IncludeDomains $IncludeDomains -ExcludeDomains $ExcludeDomains -ExtendedForestInformation $ExtendedForestInformation foreach ($Domain in $ForestInformation.Domains) { $QueryServer = $ForestInformation['QueryServers'][$Domain]['HostName'][0] $DomainInformation = Get-ADDomain -Server $QueryServer $defaultNamingContext = $DomainInformation.DistinguishedName #$defaultNamingContext = (Get-ADRootDSE).defaultnamingcontext [string] $Author = (([ADSI]"LDAP://<SID=$([System.Security.Principal.WindowsIdentity]::GetCurrent().User.Value)>").UserPrincipalName).ToString() [string] $GUID = "{" + ([System.Guid]::NewGuid()) + "}" [string] $DistinguishedName = -join ("CN=", $GUID, ",CN=SOM,CN=WMIPolicy,CN=System,", $defaultNamingContext) $CurrentTime = (Get-Date).ToUniversalTime() [string] $CurrentDate = -join ( ($CurrentTime.Year).ToString("0000"), ($CurrentTime.Month).ToString("00"), ($CurrentTime.Day).ToString("00"), ($CurrentTime.Hour).ToString("00"), ($CurrentTime.Minute).ToString("00"), ($CurrentTime.Second).ToString("00"), ".", ($CurrentTime.Millisecond * 1000).ToString("000000"), "-000" ) [Array] $ExistingWmiFilter = Get-GPOZaurrWMI -ExtendedForestInformation $ForestInformation -IncludeDomains $Domain -Name $Name if ($ExistingWmiFilter.Count -eq 0) { [string] $WMIParm2 = -join ("1;3;10;", $Query.Length.ToString(), ";WQL;root\CIMv2;", $Query , ";") $OtherAttributes = @{ "msWMI-Name" = $Name "msWMI-Parm1" = $Description "msWMI-Parm2" = $WMIParm2 "msWMI-Author" = $Author "msWMI-ID" = $GUID "instanceType" = 4 "showInAdvancedViewOnly" = "TRUE" "distinguishedname" = $DistinguishedName "msWMI-ChangeDate" = $CurrentDate "msWMI-CreationDate" = $CurrentDate } $WMIPath = -join ("CN=SOM,CN=WMIPolicy,CN=System,", $defaultNamingContext) try { Write-Verbose "New-GPOZaurrWMI - Creating WMI filter $Name in $Domain" New-ADObject -name $GUID -type "msWMI-Som" -Path $WMIPath -OtherAttributes $OtherAttributes -Server $QueryServer } catch { Write-Warning "New-GPOZaurrWMI - Creating GPO filter error $($_.Exception.Message). Terminating." return } } else { foreach ($_ in $ExistingWmiFilter) { Write-Warning "New-GPOZaurrWMI - Skipping creation of GPO because name: $($_.DisplayName) guid: $($_.ID) for $($_.DomainName) already exists." } } } } function Remove-GPOZaurr { [cmdletBinding(SupportsShouldProcess)] param( [parameter(Mandatory)][validateset('Empty', 'Unlinked')][string[]] $Type, [int] $LimitProcessing, [alias('ForestName')][string] $Forest, [string[]] $ExcludeDomains, [alias('Domain', 'Domains')][string[]] $IncludeDomains, [System.Collections.IDictionary] $ExtendedForestInformation, [string[]] $GPOPath, [string] $BackupPath, [switch] $BackupDated ) Begin { if ($BackupPath) { $BackupRequired = $true if ($BackupDated) { $BackupFinalPath = "$BackupPath\$((Get-Date).ToString('yyyy-MM-dd_HH_mm_ss'))" } else { $BackupFinalPath = $BackupPath } Write-Verbose "Remove-GPOZaurr - Backing up to $BackupFinalPath" $null = New-Item -ItemType Directory -Path $BackupFinalPath -Force } else { $BackupRequired = $false } $Count = 0 } Process { Get-GPOZaurr -Forest $Forest -IncludeDomains $IncludeDomains -ExcludeDomains $ExcludeDomains -ExtendedForestInformation $ExtendedForestInformation -GPOPath $GPOPath | ForEach-Object { if ($Type -contains 'Empty') { if ($_.ComputerSettingsAvailable -eq $false -and $_.UserSettingsAvailable -eq $false) { if ($BackupRequired) { try { Write-Verbose "Remove-GPOZaurr - Backing up GPO $($_.DisplayName) from $($_.DomainName)" $BackupInfo = Backup-GPO -Guid $_.Guid -Domain $_.DomainName -Path $BackupFinalPath -ErrorAction Stop #-Server $QueryServer $BackupInfo } catch { Write-Warning "Remove-GPOZaurr - Backing up GPO $($_.DisplayName) from $($_.DomainName) failed: $($_.Exception.Message)" } } if (($BackupRequired -and $BackupInfo) -or (-not $BackupRequired)) { try { Write-Verbose "Remove-GPOZaurr - Removing GPO $($_.DisplayName) from $($_.DomainName)" Remove-GPO -Domain $_.DomainName -Guid $_.Guid -ErrorAction Stop #-Server $QueryServer } catch { Write-Warning "Remove-GPOZaurr - Removing GPO $($_.DisplayName) from $($_.DomainName) failed: $($_.Exception.Message)" } } $Count++ if ($LimitProcessing -eq $Count) { break } } } if ($Type -contains 'Unlinked') { if ($_.Linked -eq $false) { if ($BackupRequired) { try { Write-Verbose "Remove-GPOZaurr - Backing up GPO $($_.DisplayName) from $($_.DomainName)" $BackupInfo = Backup-GPO -Guid $_.Guid -Domain $_.DomainName -Path $BackupFinalPath -ErrorAction Stop #-Server $QueryServer $BackupInfo } catch { Write-Warning "Remove-GPOZaurr - Backing up GPO $($_.DisplayName) from $($_.DomainName) failed: $($_.Exception.Message)" } } if (($BackupRequired -and $BackupInfo) -or (-not $BackupRequired)) { try { Write-Verbose "Remove-GPOZaurr - Removing GPO $($_.DisplayName) from $($_.DomainName)" Remove-GPO -Domain $_.DomainName -Guid $_.Guid -ErrorAction Stop #-Server $QueryServer } catch { Write-Warning "Remove-GPOZaurr - Removing GPO $($_.DisplayName) from $($_.DomainName) failed: $($_.Exception.Message)" } } $Count++ if ($LimitProcessing -eq $Count) { break } } } } } End { } } function Remove-GPOZaurrPermission { [cmdletBinding(SupportsShouldProcess)] param( [Parameter(ParameterSetName = 'GPOName', Mandatory)] [string] $GPOName, [Parameter(ParameterSetName = 'GPOGUID', Mandatory)] [alias('GUID', 'GPOID')][string] $GPOGuid, [Parameter(ParameterSetName = 'GPOGUID', Mandatory)] [validateset('Unknown', 'Named')][string[]] $Type, [Microsoft.GroupPolicy.GPPermissionType[]] $IncludePermissionType, [Microsoft.GroupPolicy.GPPermissionType[]] $ExcludePermissionType, [switch] $SkipWellKnown, [switch] $SkipAdministrative, [string[]]$NamedObjects, [alias('ForestName')][string] $Forest, [string[]] $ExcludeDomains, [alias('Domain', 'Domains')][string[]] $IncludeDomains, [System.Collections.IDictionary] $ExtendedForestInformation, [int] $LimitProcessing ) Begin { $Count = 0 } Process { if ($Type -contains 'Named' -and $NamedObjects.Count -eq 0) { Write-Warning "Remove-GPOZaurrPermission - When using type Named you need to provide names to remove. Terminating." return } Get-GPOZaurrPermission -IncludeGPOObject -Forest $Forest -IncludeDomains $IncludeDomains -ExcludeDomains $ExcludeDomains -ExtendedForestInformation $ExtendedForestInformation -ExcludePermissionType $ExcludePermissionType -IncludePermissionType $IncludePermissionType -SkipWellKnown:$SkipWellKnown.IsPresent -SkipAdministrative:$SkipAdministrative.IsPresent | ForEach-Object -Process { $GPOPermission = $_ if ($Type -contains 'Unknown') { if ($GPOPermission.SidType -eq 'Unknown') { #Write-Verbose "Remove-GPOZaurrPermission - Removing $($GPOPermission.Sid) from $($GPOPermission.DisplayName) at $($GPOPermission.DomainName)" if ($PSCmdlet.ShouldProcess($GPOPermission.DisplayName, "Removing $($GPOPermission.Sid) from $($GPOPermission.DisplayName) at $($GPOPermission.DomainName)")) { $GPOPermission.GPOSecurity.RemoveTrustee($GPOPermission.Sid) $GPOPermission.GPOObject.SetSecurityInfo($GPOPermission.GPOSecurity) # Set-GPPPermission doesn't work on Unknown Accounts } $Count++ if ($Count -eq $LimitProcessing) { # skipping skips per removed permission not per gpo. break } } } if ($Type -contains 'Named') { if ($Named -contains $GPOPermission.Sid) { #Write-Verbose "Remove-GPOZaurrPermission - Removing $($GPOPermission.Sid) from $($GPOPermission.DisplayName) at $($GPOPermission.DomainName)" if ($PSCmdlet.ShouldProcess($GPOPermission.DisplayName, "Removing $($GPOPermission.Sid) from $($GPOPermission.DisplayName) at $($GPOPermission.DomainName)")) { $GPOPermission.GPOSecurity.RemoveTrustee($GPOPermission.Sid) $GPOPermission.GPOObject.SetSecurityInfo($GPOPermission.GPOSecurity) # Set-GPPPermission doesn't work on Unknown Accounts } $Count++ if ($Count -eq $LimitProcessing) { # skipping skips per removed permission not per gpo. break } } } #Set-GPPermission -PermissionLevel None -TargetName $GPOPermission.Sid -Verbose -DomainName $GPOPermission.DomainName -Guid $GPOPermission.GUID #-WhatIf #Set-GPPermission -PermissionLevel GpoRead -TargetName 'Authenticated Users' -TargetType Group -Verbose -DomainName $Domain -Guid $_.GUID -WhatIf } } End { } } function Remove-GPOZaurrWMI { [CmdletBinding(SupportsShouldProcess)] Param ( [Guid[]] $Guid, [string[]] $Name, [alias('ForestName')][string] $Forest, [string[]] $ExcludeDomains, [alias('Domain', 'Domains')][string[]] $IncludeDomains, [System.Collections.IDictionary] $ExtendedForestInformation ) if (-not $Forest -and -not $ExcludeDomains -and -not $IncludeDomains -and -not $ExtendedForestInformation) { $IncludeDomains = $Env:USERDNSDOMAIN } $ForestInformation = Get-WinADForestDetails -Forest $Forest -IncludeDomains $IncludeDomains -ExcludeDomains $ExcludeDomains -ExtendedForestInformation $ExtendedForestInformation foreach ($Domain in $ForestInformation.Domains) { $QueryServer = $ForestInformation['QueryServers'][$Domain]['HostName'][0] [Array] $Objects = @( if ($Guid) { Get-GPOZaurrWMI -Guid $Guid -ExtendedForestInformation $ForestInformation -IncludeDomains $Domain } if ($Name) { Get-GPOZaurrWMI -Name $Name -ExtendedForestInformation $ForestInformation -IncludeDomains $Domain } ) $Objects | ForEach-Object -Process { if ($_.DistinguishedName) { Write-Verbose "Remove-GPOZaurrWMI - Removing WMI Filter $($_.DistinguishedName)" Remove-ADObject $_.DistinguishedName -Confirm:$false -Server $QueryServer } } } } function Restore-GPOZaurr { [cmdletBinding()] param( [parameter(Mandatory)][string] $BackupFolder, [alias('Name')][string] $DisplayName, [string] $NewDisplayName, [string] $Domain, [switch] $SkipBackupSummary ) if ($BackupFolder) { if (Test-Path -LiteralPath $BackupFolder) { if ($DisplayName) { if (-not $SkipBackupSummary) { $BackupSummary = Get-GPOZaurrBackupInformation -BackupFolder $BackupFolder if ($Domain) { [Array] $FoundGPO = $BackupSummary | Where-Object { $_.DisplayName -eq $DisplayName -and $_.DomainName -eq $Domain } } else { [Array] $FoundGPO = $BackupSummary | Where-Object { $_.DisplayName -eq $DisplayName } } foreach ($GPO in $FoundGPO) { if ($NewDisplayName) { Import-GPO -Path $BackupFolder -BackupID $GPO.ID -Domain $GPO.Domain -TargetName $NewDisplayName -CreateIfNeeded } else { Write-Verbose "Restore-GPOZaurr - Restoring GPO $($GPO.DisplayName) from $($GPO.DomainName) / BackupId: $($GPO.ID)" try { Restore-GPO -Path $BackupFolder -BackupID $GPO.ID -Domain $GPO.DomainName } catch { Write-Warning "Restore-GPOZaurr - Restoring GPO $($GPO.DisplayName) from $($GPO.DomainName) failed: $($_.Exception.Message)" } } } } else { if ($Domain) { Write-Verbose "Restore-GPOZaurr - Restoring GPO $($Name) from $($Domain)" try { Restore-GPO -Path $BackupFolder -Name $Name -Domain $Domain } catch { Write-Warning "Restore-GPOZaurr - Restoring GPO $($Name) from $($Domain) failed: $($_.Exception.Message)" } } else { Write-Verbose "Restore-GPOZaurr - Restoring GPO $($Name)" try { Restore-GPO -Path $BackupFolder -Name $Name } catch { Write-Warning "Restore-GPOZaurr - Restoring GPO $($Name) failed: $($_.Exception.Message)" } } } } else { $BackupSummary = Get-GPOZaurrBackupInformation -BackupFolder $BackupFolder foreach ($GPO in $BackupSummary) { Write-Verbose "Restore-GPOZaurr - Restoring GPO $($GPO.DisplayName) from $($GPO.DomainName) / BackupId: $($GPO.ID)" try { Restore-GPO -Path $BackupFolder -Domain $GPO.DomainName -BackupId $GPO.ID } catch { Write-Warning "Restore-GPOZaurr - Restoring GPO $($GPO.DisplayName) from $($GPO.DomainName) failed: $($_.Exception.Message)" } } } } else { Write-Warning "Restore-GPOZaurr - BackupFolder incorrect ($BackupFolder)" } } } function Save-GPOZaurrFiles { [cmdletBinding()] param( [alias('ForestName')][string] $Forest, [string[]] $ExcludeDomains, [alias('Domain', 'Domains')][string[]] $IncludeDomains, [System.Collections.IDictionary] $ExtendedForestInformation, [string[]] $GPOPath, [switch] $DeleteExisting ) if ($GPOPath) { if (-not $ExtendedForestInformation) { $ForestInformation = Get-WinADForestDetails -Forest $Forest -IncludeDomains $IncludeDomains -ExcludeDomains $ExcludeDomains } else { $ForestInformation = $ExtendedForestInformation } if ($DeleteExisting) { $Test = Test-Path -LiteralPath $GPOPath if ($Test) { Write-Verbose "Save-GPOZaurrFiles - Removing existing content in $GPOPath" Remove-Item -LiteralPath $GPOPath -Recurse } } $null = New-Item -ItemType Directory -Path $GPOPath -Force foreach ($Domain in $ForestInformation.Domains) { Write-Verbose "Save-GPOZaurrFiles - Processing GPO for $Domain" Get-GPO -All -Server $ForestInformation.QueryServers[$Domain].HostName[0] -Domain $Domain | ForEach-Object { $XMLContent = Get-GPOReport -ID $_.ID.Guid -ReportType XML -Server $ForestInformation.QueryServers[$Domain].HostName[0] -Domain $Domain $Path = [io.path]::Combine($GPOPath, "$($_.ID.Guid).xml") $XMLContent | Set-Content -LiteralPath $Path -Force -Encoding Unicode } } } } function Set-GPOZaurrOwner { [cmdletBinding(SupportsShouldProcess, DefaultParameterSetName = 'Type')] param( [Parameter(ParameterSetName = 'Type', Mandatory)] [validateset('EmptyOrUnknown', 'NonAdministrative')][string[]] $Type, [Parameter(ParameterSetName = 'Named')][string] $GPOName, [Parameter(ParameterSetName = 'Named')][alias('GUID', 'GPOID')][string] $GPOGuid, [Parameter(ParameterSetName = 'Type')] [Parameter(ParameterSetName = 'Named')] [alias('ForestName')][string] $Forest, [Parameter(ParameterSetName = 'Type')] [Parameter(ParameterSetName = 'Named')] [string[]] $ExcludeDomains, [Parameter(ParameterSetName = 'Type')] [Parameter(ParameterSetName = 'Named')] [alias('Domain', 'Domains')][string[]] $IncludeDomains, [Parameter(ParameterSetName = 'Type')] [Parameter(ParameterSetName = 'Named')] [System.Collections.IDictionary] $ExtendedForestInformation, [Parameter(Mandatory, ParameterSetName = 'Named')] [string] $Principal, [Parameter(ParameterSetName = 'Type')] [Parameter(ParameterSetName = 'Named')] [int] $LimitProcessing ) Begin { if ($Type -contains 'NonAdministrative') { $ADAdministrativeGroups = Get-ADADministrativeGroups -Type DomainAdmins, EnterpriseAdmins -Forest $Forest -IncludeDomains $IncludeDomains -ExcludeDomains $ExcludeDomains -ExtendedForestInformation $ExtendedForestInformation } $Count = 0 } Process { if ($Type) { Get-GPOZaurr -Forest $Forest -IncludeDomains $IncludeDomains -ExcludeDomains $ExcludeDomains -ExtendedForestInformation $ExtendedForestInformation -Verbose:$false | ForEach-Object -Process { $GPO = $_ if ($Type -contains 'NonAdministrative') { if ($GPO.Owner) { $AdministrativeGroup = $ADAdministrativeGroups['ByNetBIOS']["$($GPO.Owner)"] $DefaultPrincipal = $ADAdministrativeGroups["$($GPO.DomainName)"]['DomainAdmins'] if ($AdministrativeGroup) { #Write-Verbose "Set-GPOZaurrOwner - Skipping GPO: $($GPO.DisplayName) from domain: $($GPO.DomainName). Already owner $($GPO.Owner)." } else { Write-Verbose "Set-GPOZaurrOwner - Changing GPO: $($GPO.DisplayName) from domain: $($GPO.DomainName) from owner $($GPO.Owner) to $DefaultPrincipal" Set-ADACLOwner -ADObject $GPO.DistinguishedName -Principal $DefaultPrincipal -Verbose:$false $Count++ if ($Count -eq $LimitProcessing) { break } } } } if ($Type -contains 'EmptyOrUnknown') { if ($null -eq $GPO.Owner) { $DefaultPrincipal = $ADAdministrativeGroups["$($GPO.DomainName)"]['DomainAdmins'] Write-Verbose "Set-GPOZaurrOwner - Changing GPO: $($GPO.DisplayName) from domain: $($GPO.DomainName) from owner NULL/$($GPO.OwnerSID) to $DefaultPrincipal" Set-ADACLOwner -ADObject $GPO.DistinguishedName -Principal $DefaultPrincipal -Verbose:$false $Count++ if ($Count -eq $LimitProcessing) { break } } } } } else { Get-GPOZaurr -GPOName $GPOName -GPOGuid $GPOGUiD -Forest $Forest -IncludeDomains $IncludeDomains -ExcludeDomains $ExcludeDomains -ExtendedForestInformation $ExtendedForestInformation -Verbose:$false | ForEach-Object -Process { $GPO = $_ Write-Verbose "Set-GPOZaurrOwner - Changing GPO: $($GPO.DisplayName) from domain: $($GPO.DomainName) from owner $($GPO.Owner)/$($GPO.OwnerSID) to $Principal" Set-ADACLOwner -ADObject $GPO.DistinguishedName -Principal $Principal -Verbose:$false $Count++ if ($Count -eq $LimitProcessing) { break } } } } End { } } Export-ModuleMember -Function @('Backup-GPOZaurr', 'Get-GPOZaurr', 'Get-GPOZaurrBackupInformation', 'Get-GPOZaurrPassword', 'Get-GPOZaurrPermission', 'Get-GPOZaurrWMI', 'New-GPOZaurrWMI', 'Remove-GPOZaurr', 'Remove-GPOZaurrPermission', 'Remove-GPOZaurrWMI', 'Restore-GPOZaurr', 'Save-GPOZaurrFiles', 'Set-GPOZaurrOwner') -Alias @() |