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, [switch] $ToDomainCN) if ($ToDomainCN) { $DN = $DistinguishedName -replace '.*?((DC=[^=]+,)+DC=[^=]+)$', '$1' $CN = $DN -replace ',DC=', '.' -replace "DC=" $CN } elseif ($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, [switch] $OnlyWellKnownAdministrative) $WellKnownAdministrative = @{'S-1-5-18' = 'NT AUTHORITY\SYSTEM' } $wellKnownSIDs = @{'S-1-0' = 'Null AUTHORITY' 'S-1-0-0' = 'NULL SID' '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' = 'NT SERVICE\ALL SERVICES' 'S-1-4' = 'Non-unique Authority' 'S-1-5' = 'NT AUTHORITY' 'S-1-5-1' = 'NT AUTHORITY\DIALUP' 'S-1-5-2' = 'NT AUTHORITY\NETWORK' 'S-1-5-3' = 'NT AUTHORITY\BATCH' 'S-1-5-4' = 'NT AUTHORITY\INTERACTIVE' 'S-1-5-6' = 'NT AUTHORITY\SERVICE' 'S-1-5-7' = 'NT AUTHORITY\ANONYMOUS LOGON' 'S-1-5-8' = 'NT AUTHORITY\PROXY' 'S-1-5-9' = 'NT AUTHORITY\ENTERPRISE DOMAIN CONTROLLERS' 'S-1-5-10' = 'NT AUTHORITY\SELF' 'S-1-5-11' = 'NT AUTHORITY\Authenticated Users' 'S-1-5-12' = 'NT AUTHORITY\RESTRICTED' 'S-1-5-13' = 'NT AUTHORITY\TERMINAL SERVER USER' 'S-1-5-14' = 'NT AUTHORITY\REMOTE INTERACTIVE LOGON' 'S-1-5-15' = 'NT AUTHORITY\This Organization' 'S-1-5-17' = 'NT AUTHORITY\IUSR' 'S-1-5-18' = 'NT AUTHORITY\SYSTEM' 'S-1-5-19' = 'NT AUTHORITY\NETWORK SERVICE' 'S-1-5-20' = 'NT AUTHORITY\NETWORK SERVICE' 'S-1-5-32-544' = 'BUILTIN\Administrators' 'S-1-5-32-545' = 'BUILTIN\Users' 'S-1-5-32-546' = 'BUILTIN\Guests' 'S-1-5-32-547' = 'BUILTIN\Power Users' 'S-1-5-32-548' = 'BUILTIN\Account Operators' 'S-1-5-32-549' = 'BUILTIN\Server Operators' 'S-1-5-32-550' = 'BUILTIN\Print Operators' 'S-1-5-32-551' = 'BUILTIN\Backup Operators' 'S-1-5-32-552' = 'BUILTIN\Replicators' 'S-1-5-64-10' = 'NT AUTHORITY\NTLM Authentication' 'S-1-5-64-14' = 'NT AUTHORITY\SChannel Authentication' 'S-1-5-64-21' = 'NT AUTHORITY\Digest Authentication' '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 ($S in $SID) { if ($OnlyWellKnownAdministrative) { if ($WellKnownAdministrative[$S]) { [PSCustomObject] @{Name = $WellKnownAdministrative[$S] SID = $S Type = 'WellKnownAdministrative' Error = '' } } } elseif ($OnlyWellKnown) { if ($wellKnownSIDs[$S]) { [PSCustomObject] @{Name = $wellKnownSIDs[$S] SID = $S Type = 'WellKnownGroup' Error = '' } } } else { if ($wellKnownSIDs[$S]) { [PSCustomObject] @{Name = $wellKnownSIDs[$S] SID = $S Type = 'WellKnownGroup' Error = '' } } else { try { [PSCustomObject] @{Name = (([System.Security.Principal.SecurityIdentifier]::new($S)).Translate([System.Security.Principal.NTAccount])).Value SID = $S Type = 'Standard' Error = '' } } catch { [PSCustomObject] @{Name = $S SID = $S Error = $_.Exception.Message -replace [environment]::NewLine, ' ' Type = 'Unknown' } } } } } } 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] = $_ } } } return $ADDictionary } function Get-FileOwner { [cmdletBinding()] param([Array] $Path, [switch] $Recursive, [switch] $JustPath, [switch] $Resolve) Begin {} Process { foreach ($P in $Path) { if ($P -is [System.IO.FileSystemInfo]) { $FullPath = $P.FullName } elseif ($P -is [string]) { $FullPath = $P } if ($FullPath -and (Test-Path -Path $FullPath)) { if ($JustPath) { $FullPath | ForEach-Object -Process { $ACL = Get-Acl -Path $_ $Object = [ordered]@{FullName = $_ Owner = $ACL.Owner } if ($Resolve) { $Identity = Convert-Identity -Identity $ACL.Owner if ($Identity) { $Object['OwnerName'] = $Identity.Name $Object['OwnerSid'] = $Identity.SID $Object['OwnerType'] = $Identity.Type } else { $Object['OwnerName'] = '' $Object['OwnerSid'] = '' $Object['OwnerType'] = '' } } [PSCustomObject] $Object } } else { Get-ChildItem -LiteralPath $FullPath -Recurse:$Recursive | ForEach-Object -Process { $File = $_ $ACL = Get-Acl -Path $File.FullName $Object = [ordered] @{FullName = $_.FullName Extension = $_.Extension CreationTime = $_.CreationTime LastAccessTime = $_.LastAccessTime LastWriteTime = $_.LastWriteTime Attributes = $_.Attributes Owner = $ACL.Owner } if ($Resolve) { $Identity = Convert-Identity -Identity $ACL.Owner if ($Identity) { $Object['OwnerName'] = $Identity.Name $Object['OwnerSid'] = $Identity.SID $Object['OwnerType'] = $Identity.Type } else { $Object['OwnerName'] = '' $Object['OwnerSid'] = '' $Object['OwnerType'] = '' } } [PSCustomObject] $Object } } } } } End {} } 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'] = @{} $Findings['DomainsExtendedNetBIOS'] = @{} foreach ($DomainEx in $Findings['Domains']) { try { $Findings['DomainsExtended'][$DomainEx] = Get-ADDomain -Server $Findings['QueryServers'][$DomainEx].HostName[0] | ForEach-Object { [ordered] @{AllowedDNSSuffixes = $_.AllowedDNSSuffixes | ForEach-Object -Process { $_ } ChildDomains = $_.ChildDomains | ForEach-Object -Process { $_ } ComputersContainer = $_.ComputersContainer DeletedObjectsContainer = $_.DeletedObjectsContainer DistinguishedName = $_.DistinguishedName DNSRoot = $_.DNSRoot DomainControllersContainer = $_.DomainControllersContainer DomainMode = $_.DomainMode DomainSID = $_.DomainSID.Value ForeignSecurityPrincipalsContainer = $_.ForeignSecurityPrincipalsContainer Forest = $_.Forest InfrastructureMaster = $_.InfrastructureMaster LastLogonReplicationInterval = $_.LastLogonReplicationInterval LinkedGroupPolicyObjects = $_.LinkedGroupPolicyObjects | ForEach-Object -Process { $_ } LostAndFoundContainer = $_.LostAndFoundContainer ManagedBy = $_.ManagedBy Name = $_.Name NetBIOSName = $_.NetBIOSName ObjectClass = $_.ObjectClass ObjectGUID = $_.ObjectGUID ParentDomain = $_.ParentDomain PDCEmulator = $_.PDCEmulator PublicKeyRequiredPasswordRolling = $_.PublicKeyRequiredPasswordRolling QuotasContainer = $_.QuotasContainer ReadOnlyReplicaDirectoryServers = $_.ReadOnlyReplicaDirectoryServers | ForEach-Object -Process { $_ } ReplicaDirectoryServers = $_.ReplicaDirectoryServers | ForEach-Object -Process { $_ } RIDMaster = $_.RIDMaster SubordinateReferences = $_.SubordinateReferences | ForEach-Object -Process { $_ } SystemsContainer = $_.SystemsContainer UsersContainer = $_.UsersContainer } } $NetBios = $Findings['DomainsExtended'][$DomainEx]['NetBIOSName'] $Findings['DomainsExtendedNetBIOS'][$NetBios] = $Findings['DomainsExtended'][$DomainEx] } 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($_) } } foreach ($_ in [string[]] $Findings.DomainsExtended.Keys) { if ($_ -notin $Findings.Domains) { $Findings.DomainsExtended.Remove($_) $Findings.DomainsExtendedNetBIOS.Remove($_.NetBIOSName) } } [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 Convert-Identity { [cmdletBinding(DefaultParameterSetName = 'Identity')] param([parameter(ParameterSetName = 'Identity')][string[]] $Identity, [parameter(ParameterSetName = 'SID', Mandatory)][System.Security.Principal.SecurityIdentifier[]] $SID, [parameter(ParameterSetName = 'Name', Mandatory)][string[]] $Name) Begin { if (-not $Script:GlobalCacheSidConvert) { $Script:GlobalCacheSidConvert = @{'S-1-0' = 'Null AUTHORITY' 'S-1-0-0' = 'NULL SID' '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' = 'NT SERVICE\ALL SERVICES' 'S-1-4' = 'Non-unique Authority' 'S-1-5' = 'NT AUTHORITY' 'S-1-5-1' = 'NT AUTHORITY\DIALUP' 'S-1-5-2' = 'NT AUTHORITY\NETWORK' 'S-1-5-3' = 'NT AUTHORITY\BATCH' 'S-1-5-4' = 'NT AUTHORITY\INTERACTIVE' 'S-1-5-6' = 'NT AUTHORITY\SERVICE' 'S-1-5-7' = 'NT AUTHORITY\ANONYMOUS LOGON' 'S-1-5-8' = 'NT AUTHORITY\PROXY' 'S-1-5-9' = 'NT AUTHORITY\ENTERPRISE DOMAIN CONTROLLERS' 'S-1-5-10' = 'NT AUTHORITY\SELF' 'S-1-5-11' = 'NT AUTHORITY\Authenticated Users' 'S-1-5-12' = 'NT AUTHORITY\RESTRICTED' 'S-1-5-13' = 'NT AUTHORITY\TERMINAL SERVER USER' 'S-1-5-14' = 'NT AUTHORITY\REMOTE INTERACTIVE LOGON' 'S-1-5-15' = 'NT AUTHORITY\This Organization' 'S-1-5-17' = 'NT AUTHORITY\IUSR' 'S-1-5-18' = 'NT AUTHORITY\SYSTEM' 'S-1-5-19' = 'NT AUTHORITY\NETWORK SERVICE' 'S-1-5-20' = 'NT AUTHORITY\NETWORK SERVICE' 'S-1-5-32-544' = 'BUILTIN\Administrators' 'S-1-5-32-545' = 'BUILTIN\Users' 'S-1-5-32-546' = 'BUILTIN\Guests' 'S-1-5-32-547' = 'BUILTIN\Power Users' 'S-1-5-32-548' = 'BUILTIN\Account Operators' 'S-1-5-32-549' = 'BUILTIN\Server Operators' 'S-1-5-32-550' = 'BUILTIN\Print Operators' 'S-1-5-32-551' = 'BUILTIN\Backup Operators' 'S-1-5-32-552' = 'BUILTIN\Replicators' 'S-1-5-64-10' = 'NT AUTHORITY\NTLM Authentication' 'S-1-5-64-14' = 'NT AUTHORITY\SChannel Authentication' 'S-1-5-64-21' = 'NT AUTHORITY\Digest Authentication' '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' } } $wellKnownSIDs = @{'S-1-0' = 'WellKnown' 'S-1-0-0' = 'WellKnown' 'S-1-1' = 'WellKnown' 'S-1-1-0' = 'WellKnown' 'S-1-2' = 'WellKnown' 'S-1-2-0' = 'WellKnown' 'S-1-2-1' = 'WellKnown' 'S-1-3' = 'WellKnown' 'S-1-3-0' = 'WellKnown' 'S-1-3-1' = 'WellKnown' 'S-1-3-2' = 'WellKnown' 'S-1-3-3' = 'WellKnown' 'S-1-3-4' = 'WellKnown' 'S-1-5-80-0' = 'WellKnown' 'S-1-4' = 'WellKnown' 'S-1-5' = 'WellKnown' 'S-1-5-1' = 'WellKnown' 'S-1-5-2' = 'WellKnown' 'S-1-5-3' = 'WellKnown' 'S-1-5-4' = 'WellKnown' 'S-1-5-6' = 'WellKnown' 'S-1-5-7' = 'WellKnown' 'S-1-5-8' = 'WellKnown' 'S-1-5-9' = 'WellKnown' 'S-1-5-10' = 'WellKnown' 'S-1-5-11' = 'WellKnown' 'S-1-5-12' = 'WellKnown' 'S-1-5-13' = 'WellKnown' 'S-1-5-14' = 'WellKnown' 'S-1-5-15' = 'WellKnown' 'S-1-5-17' = 'WellKnown' 'S-1-5-18' = 'WellKnownAdministrative' 'S-1-5-19' = 'WellKnown' 'S-1-5-20' = 'WellKnown' 'S-1-5-32-544' = 'WellKnownAdministrative' 'S-1-5-32-545' = 'WellKnown' 'S-1-5-32-546' = 'WellKnown' 'S-1-5-32-547' = 'WellKnown' 'S-1-5-32-548' = 'WellKnown' 'S-1-5-32-549' = 'WellKnown' 'S-1-5-32-550' = 'WellKnown' 'S-1-5-32-551' = 'WellKnown' 'S-1-5-32-552' = 'WellKnown' 'S-1-5-64-10' = 'WellKnown' 'S-1-5-64-14' = 'WellKnown' 'S-1-5-64-21' = 'WellKnown' 'S-1-5-80' = 'WellKnown' 'S-1-5-83-0' = 'WellKnown' 'S-1-16-0' = 'WellKnown' 'S-1-16-4096' = 'WellKnown' 'S-1-16-8192' = 'WellKnown' 'S-1-16-8448' = 'WellKnown' 'S-1-16-12288' = 'WellKnown' 'S-1-16-16384' = 'WellKnown' 'S-1-16-20480' = 'WellKnown' 'S-1-16-28672' = 'WellKnown' 'S-1-5-32-554' = 'WellKnown' 'S-1-5-32-555' = 'WellKnown' 'S-1-5-32-556' = 'WellKnown' 'S-1-5-32-557' = 'WellKnown' 'S-1-5-32-558' = 'WellKnown' 'S-1-5-32-559' = 'WellKnown' 'S-1-5-32-560' = 'WellKnown' 'S-1-5-32-561' = 'WellKnown' 'S-1-5-32-562' = 'WellKnown' 'S-1-5-32-569' = 'WellKnown' 'S-1-5-32-573' = 'WellKnown' 'S-1-5-32-574' = 'WellKnown' 'S-1-5-32-575' = 'WellKnown' 'S-1-5-32-576' = 'WellKnown' 'S-1-5-32-577' = 'WellKnown' 'S-1-5-32-578' = 'WellKnown' 'S-1-5-32-579' = 'WellKnown' 'S-1-5-32-580' = 'WellKnown' } } Process { if ($Identity) { foreach ($Ident in $Identity) { if ($Ident -like '*-*-*') { if ($Script:GlobalCacheSidConvert[$Ident]) { if ($Script:GlobalCacheSidConvert[$Ident] -is [string]) { [ordered] @{Name = $Script:GlobalCacheSidConvert[$Ident] SID = $Ident Type = $wellKnownSIDs[$Ident] Error = '' } } else { $Script:GlobalCacheSidConvert[$Ident] } } else { try { [string] $Name = (([System.Security.Principal.SecurityIdentifier]::new($Ident)).Translate([System.Security.Principal.NTAccount])).Value $ErrorMessage = '' if ($Ident -like "S-1-5-21-*-519" -or $Ident -like "S-1-5-21-*-512") { $Type = 'Administrative' } elseif ($wellKnownSIDs[$Ident]) { $Type = $wellKnownSIDs[$Ident] } else { $Type = 'NotAdministrative' } } catch { [string] $Name = '' $ErrorMessage = $_.Exception.Message $Type = 'Unknown' } $Script:GlobalCacheSidConvert[$Ident] = [PSCustomObject] @{Name = $Name SID = $Ident Type = $Type Error = $ErrorMessage } $Script:GlobalCacheSidConvert[$Ident] } } else { if ($Script:GlobalCacheSidConvert[$Ident]) { $Script:GlobalCacheSidConvert[$Ident] } else { try { $SIDValue = ([System.Security.Principal.NTAccount] $Ident).Translate([System.Security.Principal.SecurityIdentifier]).Value if ($SIDValue -like "S-1-5-21-*-519" -or $SIDValue -like "S-1-5-21-*-512") { $Type = 'Administrative' } elseif ($wellKnownSIDs[$SIDValue]) { $Type = $wellKnownSIDs[$SIDValue] } else { $Type = 'NotAdministrative' } $ErrorMessage = '' } catch { $Type = 'Unknown' $ErrorMessage = $_.Exception.Message } $Script:GlobalCacheSidConvert[$Ident] = [PSCustomObject] @{Name = $Ident SID = $SIDValue Type = $Type Error = $ErrorMessage } $Script:GlobalCacheSidConvert[$Ident] } } } } else { if ($SID) { foreach ($S in $SID) { if ($Script:GlobalCacheSidConvert[$S]) { $Script:GlobalCacheSidConvert[$S] } else { $Script:GlobalCacheSidConvert[$S] = (([System.Security.Principal.SecurityIdentifier]::new($S)).Translate([System.Security.Principal.NTAccount])).Value $Script:GlobalCacheSidConvert[$S] } } } else { foreach ($Ident in $Name) { if ($Script:GlobalCacheSidConvert[$Ident]) { $Script:GlobalCacheSidConvert[$Ident] } else { $Script:GlobalCacheSidConvert[$Ident] = ([System.Security.Principal.NTAccount] $Ident).Translate([System.Security.Principal.SecurityIdentifier]).Value $Script:GlobalCacheSidConvert[$Ident] } } } } } End {} } 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 Copy-Dictionary { [alias('Copy-Hashtable', 'Copy-OrderedHashtable')] [cmdletbinding()] param([System.Collections.IDictionary] $Dictionary) $ms = [System.IO.MemoryStream]::new() $bf = [System.Runtime.Serialization.Formatters.Binary.BinaryFormatter]::new() $bf.Serialize($ms, $Dictionary) $ms.Position = 0 $clone = $bf.Deserialize($ms) $ms.Close() $clone } 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-PrivGPOZaurrLink { [cmdletBinding()] param( [Microsoft.ActiveDirectory.Management.ADObject] $Object, [switch] $Limited, [System.Collections.IDictionary] $GPOCache ) if ($Object.GpLink -and $Object.GpLink.Trim() -ne '') { $Object.GpLink -split { $_ -eq '[' -or $_ -eq ']' } -replace ';0' -replace 'LDAP://' | ForEach-Object -Process { if ($_) { $DomainCN = ConvertFrom-DistinguishedName -DistinguishedName $_ -ToDomainCN $Output = [ordered] @{ DistinguishedName = $Object.DistinguishedName CanonicalName = $Object.CanonicalName Guid = [Regex]::Match( $_, '(?={)(.*)(?<=})').Value -replace '{' -replace '}' } $Search = -join ($DomainCN, $Output['Guid']) if ($GPOCache -and -not $Limited) { $Output['DisplayName'] = $GPOCache[$Search].DisplayName $Output['DomainName'] = $GPOCache[$Search].DomainName $Output['Owner'] = $GPOCache[$Search].Owner $Output['GpoStatus'] = $GPOCache[$Search].GpoStatus $Output['Description'] = $GPOCache[$Search].Description $Output['CreationTime'] = $GPOCache[$Search].CreationTime $Output['ModificationTime'] = $GPOCache[$Search].ModificationTime } $Output['GPODomainDistinguishedName'] = ConvertFrom-DistinguishedName -DistinguishedName $_ -ToDC $Output['GPODistinguishedName'] = $_ [PSCustomObject] $Output } } } elseif ($Object.LinkedGroupPolicyObjects -and $Object.LinkedGroupPolicyObjects.Trim() -ne '') { $Object.LinkedGroupPolicyObjects -split { $_ -eq '[' -or $_ -eq ']' } -replace ';0' -replace 'LDAP://' | ForEach-Object -Process { if ($_) { $DomainCN = ConvertFrom-DistinguishedName -DistinguishedName $_ -ToDomainCN $Output = [ordered] @{ DistinguishedName = $Object.DistinguishedName CanonicalName = $Object.CanonicalName Guid = [Regex]::Match( $_, '(?={)(.*)(?<=})').Value -replace '{' -replace '}' } $Search = -join ($DomainCN, $Output['Guid']) if ($GPOCache -and -not $Limited) { $Output['Name'] = $GPOCache[$Search].DisplayName $Output['DomainName'] = $GPOCache[$Search].DomainName $Output['Owner'] = $GPOCache[$Search].Owner $Output['GpoStatus'] = $GPOCache[$Search].GpoStatus $Output['Description'] = $GPOCache[$Search].Description $Output['CreationTime'] = $GPOCache[$Search].CreationTime $Output['ModificationTime'] = $GPOCache[$Search].ModificationTime } $Output['GPODomainDistinguishedName'] = ConvertFrom-DistinguishedName -DistinguishedName $_ -ToDC $Output['GPODistinguishedName'] = $_ [PSCustomObject] $Output } } } } function Get-PrivPermission { [cmdletBinding()] param( [Microsoft.GroupPolicy.Gpo] $GPO, [string[]] $Principal, [validateset('DistinguishedName', 'Name', 'Sid')][string] $PrincipalType = 'Sid', [switch] $SkipWellKnown, [switch] $SkipAdministrative, [switch] $IncludeOwner, [Microsoft.GroupPolicy.GPPermissionType[]] $IncludePermissionType, [Microsoft.GroupPolicy.GPPermissionType[]] $ExcludePermissionType, [switch] $IncludeGPOObject, [System.Collections.IDictionary] $ADAdministrativeGroups, [validateSet('Unknown', 'NotWellKnown', 'NotWellKnownAdministrative', 'NotAdministrative', 'Administrative', 'All', 'Default')][string[]] $Type, [System.Collections.IDictionary] $Accounts ) Begin { Write-Verbose "Get-PrivPermission - Processing $($GPO.DisplayName) from $($GPO.DomainName)" } Process { $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 -or $Type -contains 'NotWellKnown') { if ($GPOPermission.Trustee.SidType -eq 'WellKnownGroup') { return } } if ($SkipAdministrative.IsPresent -or $Type -contains 'NotAdministrative') { $IsAdministrative = $ADAdministrativeGroups['BySID'][$GPOPermission.Trustee.Sid.Value] if ($IsAdministrative) { return } } if ($Type -contains 'Administrative' -and $Type -notcontains 'All') { $IsAdministrative = $ADAdministrativeGroups['BySID'][$GPOPermission.Trustee.Sid.Value] if (-not $IsAdministrative) { return } } if ($Type -contains 'NotWellKnownAdministrative' -and $Type -notcontains 'All') { # We check for SYSTEM account # Maybe we should make it a function and provide more if ($GPOPermission.Trustee.Sid -eq 'S-1-5-18') { return } } if ($Type -contains 'Unknown' -and $Type -notcontains 'All') { # May need updates if there's more types if ($GPOPermission.Trustee.SidType -ne 'Unknown') { return } } if ($Principal) { if ($PrincipalType -eq 'Sid') { if ($Principal -notcontains $GPOPermission.Trustee.Sid.Value) { return } } elseif ($PrincipalType -eq 'DistinguishedName') { if ($Principal -notcontains $GPOPermission.Trustee.DSPath) { return } } elseif ($PrincipalType -eq 'Name') { $UserMerge = -join ($GPOPermission.Trustee.Domain, '\', $GPOPermission.Trustee.Name) if ($Principal -notcontains $UserMerge -and $Principal -notcontains $GPOPermission.Trustee.Name) { 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 PermissionType = if ($GPOPermission.Denied -eq $true) { 'Deny' } else { 'Allow' } 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 $ReturnObject['GPOSecurityPermissionItem'] = $GPOPermission } [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 $ReturnObject['GPOSecurityPermissionItem'] = $null } [PSCustomObject] $ReturnObject } } End { } } 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 = 'NotAdministrative' } } else { $OwnerType = 'EmptyOrUnknown' } } if ($PermissionsOnly) { [PsCustomObject] @{ 'DisplayName' = $XMLContent.GPO.Name 'DomainName' = $XMLContent.GPO.Identifier.Domain.'#text' 'GUID' = $XMLContent.GPO.Identifier.Identifier.InnerText -replace '{' -replace '}' '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' 'GPODistinguishedName' = $GPO.Path } $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 -replace '{' -replace '}' '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 'GPODistinguishedName' = $GPO.Path } } } } elseif ($OwnerOnly) { [PsCustomObject] @{ 'DisplayName' = $XMLContent.GPO.Name 'DomainName' = $XMLContent.GPO.Identifier.Domain.'#text' 'GUID' = $XMLContent.GPO.Identifier.Identifier.InnerText -replace '{' -replace '}' 'Enabled' = $Enabled 'Owner' = $XMLContent.GPO.SecurityDescriptor.Owner.Name.'#text' 'OwnerSID' = $XMLContent.GPO.SecurityDescriptor.Owner.SID.'#text' 'OwnerType' = $OwnerType 'GPODistinguishedName' = $GPO.Path } } else { [PsCustomObject] @{ 'DisplayName' = $XMLContent.GPO.Name 'DomainName' = $XMLContent.GPO.Identifier.Domain.'#text' 'GUID' = $XMLContent.GPO.Identifier.Identifier.InnerText -replace '{' -replace '}' '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 'GPODistinguishedName' = $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 } } function Remove-PrivPermission { [cmdletBinding(SupportsShouldProcess)] param( [string] $Principal, [validateset('DistinguishedName', 'Name', 'Sid')][string] $PrincipalType = 'DistinguishedName', [PSCustomObject] $GPOPermission, [alias('PermissionType')][Microsoft.GroupPolicy.GPPermissionType[]] $IncludePermissionType ) if ($GPOPermission.Name) { $Text = "Removing SID: $($GPOPermission.Sid), Name: $($GPOPermission.Name), SidType: $($GPOPermission.SidType) from domain $($GPOPermission.DomainName)" } else { $Text = "Removing SID: $($GPOPermission.Sid), Name: EMPTY, SidType: $($GPOPermission.SidType) from domain $($GPOPermission.DomainName)" } if ($PrincipalType -eq 'DistinguishedName') { if ($GPOPermission.DistinguishedName -eq $Principal -and $GPOPermission.Permission -eq $IncludePermissionType) { if ($PSCmdlet.ShouldProcess($GPOPermission.DisplayName, $Text)) { try { Write-Verbose "Remove-GPOZaurrPermission - Removing permission $IncludePermissionType for $($Principal) / $($GPOPermission.Name) / Type: $($GPOPermission.PermissionType)" $GPOPermission.GPOSecurity.Remove($GPOPermission.GPOSecurityPermissionItem) $GPOPermission.GPOObject.SetSecurityInfo($GPOPermission.GPOSecurity) } catch { Write-Warning "Remove-GPOZaurrPermission - Removing permission $IncludePermissionType failed for $($Principal) with error: $($_.Exception.Message)" } } } } elseif ($PrincipalType -eq 'Sid') { if ($GPOPermission.Sid -eq $Principal -and $GPOPermission.Permission -eq $IncludePermissionType) { if ($PSCmdlet.ShouldProcess($GPOPermission.DisplayName, $Text)) { try { Write-Verbose "Remove-GPOZaurrPermission - Removing permission $IncludePermissionType for $($Principal) / $($GPOPermission.Name) / Type: $($GPOPermission.PermissionType)" $GPOPermission.GPOSecurity.Remove($GPOPermission.GPOSecurityPermissionItem) $GPOPermission.GPOObject.SetSecurityInfo($GPOPermission.GPOSecurity) } catch { if ($_.Exception.Message -like '*The request is not supported. (Exception from HRESULT: 0x80070032)*') { Write-Warning "Remove-GPOZaurrPermission - Bummer! The request is not supported, but lets fix it differently." # This is basically atomic approach. We will totally remove any permissions for that user on ACL level to get rid of this situation. # This situation should only happen if DENY is on FULL Control $ACL = Get-ADACL -ADObject $GPOPermission.GPOObject.Path -Bundle #-Verbose:$VerbosePreference if ($ACL) { Remove-ADACL -ACL $ACL -Principal $Principal -AccessControlType Deny -Verbose:$VerbosePreference } # I've noticed that in situation where Edit settings, delete, modify security is set and then set to Deny we need to fix it once more $ACL = Get-ADACL -ADObject $GPOPermission.GPOObject.Path -Bundle if ($ACL) { Remove-ADACL -ACL $ACL -Principal $Principal -AccessControlType Allow -Verbose:$VerbosePreference } } else { Write-Warning "Remove-GPOZaurrPermission - Removing permission $IncludePermissionType failed for $($Principal) with error: $($_.Exception.Message)" } } } } } elseif ($PrincipalType -eq 'Name') { if ($GPOPermission.Name -eq $Principal -and $GPOPermission.Permission -eq $IncludePermissionType) { if ($PSCmdlet.ShouldProcess($GPOPermission.DisplayName, $Text)) { try { Write-Verbose "Remove-GPOZaurrPermission - Removing permission $IncludePermissionType for $($Principal) / $($GPOPermission.Name) / Type: $($GPOPermission.PermissionType)" $GPOPermission.GPOSecurity.Remove($GPOPermission.GPOSecurityPermissionItem) $GPOPermission.GPOObject.SetSecurityInfo($GPOPermission.GPOSecurity) } catch { Write-Warning "Remove-GPOZaurrPermission - Removing permission $IncludePermissionType failed for $($Principal) with error: $($_.Exception.Message)" } } } } } $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 Add-GPOPermission { [cmdletBinding()] param( [validateset('WellKnownAdministrative', 'Administrative', 'AuthenticatedUsers', 'Default')][string] $Type = 'Default', [Microsoft.GroupPolicy.GPPermissionType] $IncludePermissionType, [alias('Principal')][Array] $Trustee, [alias('PrincipalType')][validateset('DistinguishedName', 'Name', 'Sid')][string] $TrusteeType = 'DistinguishedName' ) if ($Type -eq 'Default') { @{ Action = 'Add' Type = 'Standard' Trustee = $Trustee IncludePermissionType = $IncludePermissionType TrusteeType = $TrusteeType } } elseif ($Type -eq 'AuthenticatedUsers') { @{ Action = 'Add' Type = 'AuthenticatedUsers' IncludePermissionType = $IncludePermissionType } } elseif ($Type -eq 'Administrative') { @{ Action = 'Add' Type = 'Administrative' IncludePermissionType = $IncludePermissionType } } } function Add-GPOZaurrPermission { [cmdletBinding(SupportsShouldProcess, DefaultParameterSetName = 'GPOGUID')] param( [Parameter(ParameterSetName = 'GPOName', Mandatory)] [string] $GPOName, [Parameter(ParameterSetName = 'GPOGUID', Mandatory)] [alias('GUID', 'GPOID')][string] $GPOGuid, [Parameter(ParameterSetName = 'ADObject', Mandatory)] [alias('OrganizationalUnit', 'DistinguishedName')][Microsoft.ActiveDirectory.Management.ADObject[]] $ADObject, [validateset('WellKnownAdministrative', 'Administrative', 'AuthenticatedUsers', 'Default')][string] $Type = 'Default', [string] $Principal, [alias('IncludePermissionType')][Microsoft.GroupPolicy.GPPermissionType[]] $PermissionType, [switch] $Inheritable, [alias('ForestName')][string] $Forest, [string[]] $ExcludeDomains, [alias('Domain', 'Domains')][string[]] $IncludeDomains, [System.Collections.IDictionary] $ExtendedForestInformation, [System.Collections.IDictionary] $ADAdministrativeGroups, [int] $LimitProcessing ) Begin { #$Count = 0 $ForestInformation = Get-WinADForestDetails -Forest $Forest -IncludeDomains $IncludeDomains -ExcludeDomains $ExcludeDomains -ExtendedForestInformation $ExtendedForestInformation if (-not $ADAdministrativeGroups) { $ADAdministrativeGroups = Get-ADADministrativeGroups -Type DomainAdmins, EnterpriseAdmins -Forest $Forest -IncludeDomains $IncludeDomains -ExcludeDomains $ExcludeDomains -ExtendedForestInformation $ExtendedForestInformation } $ForestInformation = Get-ADForest } Process { if ($GPOName) { $Splat = @{ GPOName = $GPOName } } elseif ($GPOGUID) { $Splat = @{ GPOGUID = $GPOGUID } } else { $Splat = @{ } } $Splat['IncludeGPOObject'] = $true $Splat['Forest'] = $Forest $Splat['IncludeDomains'] = $Domain #$Splat['ExcludeDomains'] = $ExcludeDomains #$Splat['ExtendedForestInformation'] = $ExtendedForestInformation #$Splat['ExcludePermissionType'] = $ExcludePermissionType #$Splat['IncludePermissionType'] = $PermissionType- $Splat['SkipWellKnown'] = $SkipWellKnown.IsPresent $Splat['SkipAdministrative'] = $SkipAdministrative.IsPresent # Get-GPOZaurrPermission @Splat #Set-GPPermission -PermissionLevel $PermissionType -TargetName $Principal -TargetType Group -Verbose -DomainName 'ad.evotec.xyz' -Name $GPOName -Replace #-WhatIf $AdministrativeExists = @{ DomainAdmins = $false EnterpriseAdmins = $false } #continue [Array] $GPOPermissions = Get-GPOZaurrPermission @Splat [Array] $LimitedPermissions = foreach ($GPOPermission in $GPOPermissions) { #$GPOPermission = $_ # continue if ($Type -eq 'Default') { if ($GPOPermission.Name -eq $Principal -and $GPOPermission.Permission -eq $PermissionType) { #Write-Verbose "Add-GPOZaurrPermission - Permission $PermissionType already set for $($GPOPermission.Name) / $($GPOPermission.DomainName)" $GPOPermission break } } elseif ($Type -eq 'Administrative') { if ($GPOPermission.Permission -eq $PermissionType) { $AdministrativeGroup = $ADAdministrativeGroups['BySID'][$GPOPermission.SID] if ($AdministrativeGroup) { if ($GPOPermission.SID -like '*-512') { #Write-Verbose "Add-GPOZaurrPermission - Permission $PermissionType already set for $($GPOPermission.Name) / $($GPOPermission.DomainName)" $AdministrativeExists['DomainAdmins'] = $true } elseif ($GPOPermission.SID -like '*-519') { #Write-Verbose "Add-GPOZaurrPermission - Permission $PermissionType already set for $($GPOPermission.Name) / $($GPOPermission.DomainName)" $AdministrativeExists['EnterpriseAdmins'] = $true } } } } elseif ($Type -eq 'WellKnownAdministrative') { if ($GPOPermission.Name -eq $Principal -and $GPOPermission.Permission -eq $PermissionType) { #Write-Verbose "Add-GPOZaurrPermission - Permission $PermissionType already set for $($GPOPermission.Name) / $($GPOPermission.DomainName)" $GPOPermission break } } elseif ($Type -eq 'AuthenticatedUsers') { if ($GPOPermission.Name -eq $Principal -and $GPOPermission.Permission -eq $PermissionType) { #Write-Verbose "Add-GPOZaurrPermission - Permission $PermissionType already set for $($GPOPermission.Name) / $($GPOPermission.DomainName)" $GPOPermission break } } # Write-Verbose "Test" # $GPOPermission #$GPOPermission.GPOSecurity.Add #void Add(Microsoft.GroupPolicy.GPPermission item) #void ICollection[GPPermission].Add(Microsoft.GroupPolicy.GPPermission item) #int IList.Add(System.Object value) # $GPOPermission.GPOObject.SetSecurityInfo($GPOPermission.GPOSecurity) } if ($GPOPermissions.Count -gt 0) { if ($LimitedPermissions.Count -gt 0) { #$LimitedPermissions } else { if ($Type -eq 'Administrative') { if ($AdministrativeExists['DomainAdmins'] -eq $false) { $Principal = $ADAdministrativeGroups[$GPOPermission.DomainName]['DomainAdmins'] Write-Verbose "Add-GPOZaurrPermission - Adding permission $PermissionType for $($Principal)" $AddPermission = [Microsoft.GroupPolicy.GPPermission]::new($Principal, $PermissionType, $Inheritable.IsPresent) $GPOPermissions[0].GPOSecurity.Add($AddPermission) $GPOPermissions[0].GPOObject.SetSecurityInfo( $GPOPermissions[0].GPOSecurity) } if ($AdministrativeExists['EnterpriseAdmins'] -eq $false) { $Principal = $ADAdministrativeGroups[$ForestInformation.RootDomain]['EnterpriseAdmins'] Write-Verbose "Add-GPOZaurrPermission - Adding permission $PermissionType for $($Principal)" $AddPermission = [Microsoft.GroupPolicy.GPPermission]::new($Principal, $PermissionType, $Inheritable.IsPresent) $GPOPermissions[0].GPOSecurity.Add($AddPermission) $GPOPermissions[0].GPOObject.SetSecurityInfo( $GPOPermissions[0].GPOSecurity) } } elseif ($Type -eq 'Default') { try { Write-Verbose "Add-GPOZaurrPermission - Adding permission $PermissionType for $($Principal)" $AddPermission = [Microsoft.GroupPolicy.GPPermission]::new($Principal, $PermissionType, $Inheritable.IsPresent) $GPOPermissions[0].GPOSecurity.Add($AddPermission) $GPOPermissions[0].GPOObject.SetSecurityInfo($GPOPermission.GPOSecurity) } catch { Write-Warning "Add-GPOZaurrPermission - Adding permission $PermissionType failed for $($Principal) with error: $($_.Exception.Message)" } } <# [Microsoft.GroupPolicy.GPPermission]::new OverloadDefinitions ------------------- Microsoft.GroupPolicy.GPPermission new(string trustee, Microsoft.GroupPolicy.GPPermissionType rights, bool inheritable) Microsoft.GroupPolicy.GPPermission new(System.Security.Principal.IdentityReference identity, Microsoft.GroupPolicy.GPPermissionType rights, bool inheritable) #> } } else { Write-Warning "Add-GPOZaurrPermission - GPO $($GPOPermissions[0].GPOName) has no permissions. Weird." } } End { } } 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, [System.Collections.IDictionary] $ADAdministrativeGroups ) Begin { if (-not $ADAdministrativeGroups) { Write-Verbose "Get-GPOZaurr - Getting ADAdministrativeGroups" $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) { try { $XMLContent = Get-GPOReport -ID $_.ID -ReportType XML -Server $ForestInformation.QueryServers[$Domain].HostName[0] -Domain $Domain -ErrorAction Stop } catch { Write-Warning "Get-GPOZaurr - Failed to get GPOReport: $($_.Exception.Message). Skipping." continue } 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) { try { $XMLContent = Get-GPOReport -ID $_.ID -ReportType XML -Server $ForestInformation.QueryServers[$Domain].HostName[0] -Domain $Domain -ErrorAction Stop } catch { Write-Warning "Get-GPOZaurr - Failed to get GPOReport: $($_.Exception.Message). Skipping." continue } 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) { try { $XMLContent = Get-GPOReport -ID $_.ID -ReportType XML -Server $ForestInformation.QueryServers[$Domain].HostName[0] -Domain $Domain -ErrorAction Stop } catch { Write-Warning "Get-GPOZaurr - Failed to get GPOReport: $($_.Exception.Message). Skipping." continue } 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-GPOZaurrAD { [cmdletbinding(DefaultParameterSetName = 'Default')] param( [Parameter(ParameterSetName = 'GPOName')] [string] $GPOName, [Parameter(ParameterSetName = 'GPOGUID')] [alias('GUID', 'GPOID')][string] $GPOGuid, [alias('ForestName')][string] $Forest, [string[]] $ExcludeDomains, [alias('Domain', 'Domains')][string[]] $IncludeDomains, [System.Collections.IDictionary] $ExtendedForestInformation ) Begin { $ForestInformation = Get-WinADForestDetails -Extended -Forest $Forest -IncludeDomains $IncludeDomains -ExcludeDomains $ExcludeDomains -ExtendedForestInformation $ExtendedForestInformation } Process { foreach ($Domain in $ForestInformation.Domains) { if ($PSCmdlet.ParameterSetName -eq 'GPOGUID') { if ($GPOGuid) { if ($GPOGUID -notlike '*{*') { $GUID = -join ("{", $GPOGUID, '}') } else { $GUID = $GPOGUID } $Splat = @{ Filter = "(objectClass -eq 'groupPolicyContainer') -and (Name -eq '$GUID')" Server = $ForestInformation['QueryServers'][$Domain]['HostName'][0] } } else { Write-Warning "Get-GPOZaurrAD - GPOGUID parameter is empty. Provide name and try again." continue } } elseif ($PSCmdlet.ParameterSetName -eq 'GPOName') { if ($GPOName) { $Splat = @{ Filter = "(objectClass -eq 'groupPolicyContainer') -and (DisplayName -eq '$GPOName')" Server = $ForestInformation['QueryServers'][$Domain]['HostName'][0] } } else { Write-Warning "Get-GPOZaurrAD - GPOName parameter is empty. Provide name and try again." continue } } else { $Splat = @{ Filter = "(objectClass -eq 'groupPolicyContainer')" Server = $ForestInformation['QueryServers'][$Domain]['HostName'][0] } } Get-ADObject @Splat -Properties DisplayName, Name, Created, Modified, gPCFileSysPath, gPCFunctionalityVersion, gPCWQLFilter, gPCMachineExtensionNames, Description, CanonicalName, DistinguishedName | ForEach-Object -Process { #, Deleted -IncludeDeletedObjects #if ($_) { $DomainCN = ConvertFrom-DistinguishedName -DistinguishedName $_.DistinguishedName -ToDomainCN $Output = [ordered]@{ } <# $Search = -join ($DomainCN, $Output['Guid']) if ($GPOCache -and -not $Limited) { $Output['DisplayName'] = $GPOCache[$Search].DisplayName $Output['DomainName'] = $GPOCache[$Search].DomainName $Output['Owner'] = $GPOCache[$Search].Owner $Output['GpoStatus'] = $GPOCache[$Search].GpoStatus $Output['Description'] = $GPOCache[$Search].Description $Output['CreationTime'] = $GPOCache[$Search].CreationTime $Output['ModificationTime'] = $GPOCache[$Search].ModificationTime } #> $Output['DisplayName'] = $_.DisplayName $Output['DomainName'] = $DomainCN $Output['Description'] = $_.Description $Output['GUID'] = $_.Name -replace '{' -replace '}' $Output['Path'] = $_.gPCFileSysPath $Output['FunctionalityVersion'] = $_.gPCFunctionalityVersion $Output['Created'] = $_.Created $Output['Modified'] = $_.Modified $Output['GPOCanonicalName'] = $_.CanonicalName $Output['GPODomainDistinguishedName'] = ConvertFrom-DistinguishedName -DistinguishedName $_.DistinguishedName -ToDC $Output['GPODistinguishedName'] = $_.DistinguishedName [PSCustomObject] $Output <# CanonicalName : ad.evotec.xyz/System/Policies/{31B2F340-016D-11D2-945F-00C04FB984F9} Created : 20.05.2018 09:55:29 Description : DisplayName : Default Domain Policy DistinguishedName : CN={31B2F340-016D-11D2-945F-00C04FB984F9},CN=Policies,CN=System,DC=ad,DC=evotec,DC=xyz gPCFileSysPath : \\ad.evotec.xyz\sysvol\ad.evotec.xyz\Policies\{31B2F340-016D-11D2-945F-00C04FB984F9} gPCFunctionalityVersion : 2 gPCMachineExtensionNames : [{35378EAC-683F-11D2-A89A-00C04FBBCFA2}{53D6AB1B-2488-11D1-A28C-00C04FB94F17}][{827D319E-6EAC-11D2-A4EA-00C04F79F83A}{803E14A0-B4FB-11D0-A0D0-00A0C90F574B}][{B1BE8D72-6EAC-11D2-A4EA-00C04F79F83A}{53D6AB1B-2488-11D1-A28C-00C04FB94F17}] Modified : 26.04.2020 18:53:56 Name : {31B2F340-016D-11D2-945F-00C04FB984F9} ObjectClass : groupPolicyContainer ObjectGUID : 679a6dd9-30fb-438c-a35f-e5fe8167703e #> #} } } } 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 -Process { [PSCustomObject] @{ DisplayName = $_.GPODisplayName.'#cdata-section' DomainName = $_.GPODomain.'#cdata-section' Guid = $_.GPOGUid.'#cdata-section' -replace '{' -replace '}' DomainGuid = $_.GPODomainGuid.'#cdata-section' -replace '{' -replace '}' DomainController = $_.GPODomainController.'#cdata-section' BackupTime = [DateTime]::Parse($_.BackupTime.'#cdata-section') ID = $_.ID.'#cdata-section' -replace '{' -replace '}' Comment = $_.Comment.'#cdata-section' } } } else { Write-Warning "Get-GPOZaurrBackupInformation - No backup information available" } } } } End { } } function Get-GPOZaurrPermissionConsistency { [cmdletBinding()] param( [Parameter(ParameterSetName = 'GPOName')] [string] $GPOName, [Parameter(ParameterSetName = 'GPOGUID')] [alias('GUID', 'GPOID')][string] $GPOGuid, [Parameter(ParameterSetName = 'Type')][validateSet('Consistent', 'Inconsistent', 'All')][string[]] $Type = 'All', [alias('ForestName')][string] $Forest, [string[]] $ExcludeDomains, [alias('Domain', 'Domains')][string[]] $IncludeDomains, [System.Collections.IDictionary] $ExtendedForestInformation, [switch] $IncludeGPOObject ) Begin { $ForestInformation = Get-WinADForestDetails -Forest $Forest -IncludeDomains $IncludeDomains -ExcludeDomains $ExcludeDomains -ExtendedForestInformation $ExtendedForestInformation } 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 { try { $IsConsistent = $_.IsAclConsistent() $ErrorMessage = '' } catch { $ErrorMessage = $_.Exception.Message Write-Warning "Get-GPOZaurrPermissionConsistency - Failed to get consistency: $($_.Exception.Message)." $IsConsistent = 'Not available.' } $Object = @{ DisplayName = $_.DisplayName # : New Group Policy Object DomainName = $_.DomainName # : ad.evotec.xyz ACLConsistent = $IsConsistent Owner = $_.Owner # : EVOTEC\Enterprise Admins Id = $_.Id # : 8a7bc515-d7fd-4d1f-90b8-e47c15f89295 GpoStatus = $_.GpoStatus # : AllSettingsEnabled Description = $_.Description # : CreationTime = $_.CreationTime # : 04.03.2020 17:19:42 ModificationTime = $_.ModificationTime# : 06.05.2020 10:30:36 UserVersion = $_.UserVersion # : AD Version: 0, SysVol Version: 0 ComputerVersion = $_.ComputerVersion # : AD Version: 1, SysVol Version: 1 WmiFilter = $_.WmiFilter # : Error = $ErrorMessage } if ($IncludeGPOObject) { $Object['IncludeGPOObject'] = $_ } [PSCustomObject] $Object } } elseif ($GPOGuid) { Get-GPO -Guid $GPOGuid -Domain $Domain -Server $QueryServer -ErrorAction SilentlyContinue | ForEach-Object -Process { try { $IsConsistent = $_.IsAclConsistent() $ErrorMessage = '' } catch { $ErrorMessage = $_.Exception.Message Write-Warning "Get-GPOZaurrPermissionConsistency - Failed to get consistency: $($_.Exception.Message)." $IsConsistent = 'Not available.' } $Object = @{ DisplayName = $_.DisplayName # : New Group Policy Object DomainName = $_.DomainName # : ad.evotec.xyz ACLConsistent = $IsConsistent Owner = $_.Owner # : EVOTEC\Enterprise Admins Id = $_.Id # : 8a7bc515-d7fd-4d1f-90b8-e47c15f89295 GpoStatus = $_.GpoStatus # : AllSettingsEnabled Description = $_.Description # : CreationTime = $_.CreationTime # : 04.03.2020 17:19:42 ModificationTime = $_.ModificationTime# : 06.05.2020 10:30:36 UserVersion = $_.UserVersion # : AD Version: 0, SysVol Version: 0 ComputerVersion = $_.ComputerVersion # : AD Version: 1, SysVol Version: 1 WmiFilter = $_.WmiFilter # : Error = $ErrorMessage } if ($IncludeGPOObject) { $Object['IncludeGPOObject'] = $_ } [PSCustomObject] $Object } } else { Get-GPO -All -Domain $Domain -Server $QueryServer | ForEach-Object -Process { try { $IsConsistent = $_.IsAclConsistent() $ErrorMessage = '' } catch { $ErrorMessage = $_.Exception.Message Write-Warning "Get-GPOZaurrPermissionConsistency - Failed to get consistency: $($_.Exception.Message)." $IsConsistent = 'Not available.' } if ($Type -eq 'Consistent') { if (-not $IsConsistent) { return } } elseif ($Type -eq 'Inconsistent') { if ($IsConsistent -eq $true) { return } } $Object = @{ DisplayName = $_.DisplayName # : New Group Policy Object DomainName = $_.DomainName # : ad.evotec.xyz ACLConsistent = $IsConsistent Owner = $_.Owner # : EVOTEC\Enterprise Admins Id = $_.Id # : 8a7bc515-d7fd-4d1f-90b8-e47c15f89295 GpoStatus = $_.GpoStatus # : AllSettingsEnabled Description = $_.Description # : CreationTime = $_.CreationTime # : 04.03.2020 17:19:42 ModificationTime = $_.ModificationTime# : 06.05.2020 10:30:36 UserVersion = $_.UserVersion # : AD Version: 0, SysVol Version: 0 ComputerVersion = $_.ComputerVersion # : AD Version: 1, SysVol Version: 1 WmiFilter = $_.WmiFilter # : Error = $ErrorMessage } if ($IncludeGPOObject) { $Object['IncludeGPOObject'] = $_ } [PSCustomObject] $Object } } } } End { } } function Get-GPOZaurrLink { [cmdletbinding()] param( [parameter(ParameterSetName = 'ADObject', ValueFromPipeline, ValueFromPipelineByPropertyName, Mandatory)][Microsoft.ActiveDirectory.Management.ADObject[]] $ADObject, # weirdly enough site doesn't really work this way unless you give it 'CN=Configuration,DC=ad,DC=evotec,DC=xyz' as SearchBase [parameter(ParameterSetName = 'Filter')][string] $Filter = "(objectClass -eq 'organizationalUnit' -or objectClass -eq 'domainDNS' -or objectClass -eq 'site')", [parameter(ParameterSetName = 'Filter')][string] $SearchBase, [parameter(ParameterSetName = 'Filter')][Microsoft.ActiveDirectory.Management.ADSearchScope] $SearchScope, [parameter(ParameterSetName = 'Linked', Mandatory)][validateset('Root', 'DomainControllers', 'Site', 'Other')][string] $Linked, [parameter(ParameterSetName = 'Filter')] [parameter(ParameterSetName = 'ADObject')] [parameter(ParameterSetName = 'Linked')] [switch] $Limited, [parameter(ParameterSetName = 'Filter')] [parameter(ParameterSetName = 'ADObject')] [parameter(ParameterSetName = 'Linked')] [System.Collections.IDictionary] $GPOCache, [parameter(ParameterSetName = 'Filter')] [parameter(ParameterSetName = 'ADObject')] [parameter(ParameterSetName = 'Linked')] [alias('ForestName')][string] $Forest, [parameter(ParameterSetName = 'Filter')] [parameter(ParameterSetName = 'ADObject')] [parameter(ParameterSetName = 'Linked')] [string[]] $ExcludeDomains, [parameter(ParameterSetName = 'Filter')] [parameter(ParameterSetName = 'ADObject')] [parameter(ParameterSetName = 'Linked')] [alias('Domain', 'Domains')][string[]] $IncludeDomains, [parameter(ParameterSetName = 'Filter')] [parameter(ParameterSetName = 'ADObject')] [parameter(ParameterSetName = 'Linked')] [System.Collections.IDictionary] $ExtendedForestInformation ) Begin { $ForestInformation = Get-WinADForestDetails -Extended -Forest $Forest -IncludeDomains $IncludeDomains -ExcludeDomains $ExcludeDomains -ExtendedForestInformation $ExtendedForestInformation if (-not $GPOCache -and -not $Limited) { $GPOCache = @{ } foreach ($Domain in $ForestInformation.Domains) { $QueryServer = $ForestInformation['QueryServers'][$Domain]['HostName'][0] Get-GPO -All -DomainName $Domain -Server $QueryServer | ForEach-Object { $GPOCache["$Domain$($_.ID.Guid)"] = $_ } } } } Process { if (-not $ADObject) { if ($Linked) { foreach ($Domain in $ForestInformation.Domains) { $Splat = @{ #Filter = $Filter Properties = 'distinguishedName', 'gplink', 'CanonicalName' # Filter = "(objectClass -eq 'organizationalUnit' -or objectClass -eq 'domainDNS' -or objectClass -eq 'site')" Server = $ForestInformation['QueryServers'][$Domain]['HostName'][0] } if ($Linked -contains 'DomainControllers') { $SearchBase = $ForestInformation['DomainsExtended'][$Domain]['DomainControllersContainer'] #if ($SearchBase -notlike "*$DomainDistinguishedName") { # we check if SearchBase is part of domain distinugishname. If it isn't we skip # continue #} $Splat['Filter'] = "(objectClass -eq 'organizationalUnit')" $Splat['SearchBase'] = $SearchBase Get-ADObject @Splat | ForEach-Object -Process { Get-PrivGPOZaurrLink -Object $_ -Limited:$Limited.IsPresent -GPOCache $GPOCache } } if ($Linked -contains 'Root') { $SearchBase = $ForestInformation['DomainsExtended'][$Domain]['DistinguishedName'] #if ($SearchBase -notlike "*$DomainDistinguishedName") { # we check if SearchBase is part of domain distinugishname. If it isn't we skip # continue # } $Splat['Filter'] = "objectClass -eq 'domainDNS'" $Splat['SearchBase'] = $SearchBase Get-ADObject @Splat | ForEach-Object -Process { Get-PrivGPOZaurrLink -Object $_ -Limited:$Limited.IsPresent -GPOCache $GPOCache } } if ($Linked -contains 'Site') { # Sites are defined only in primary domain if ($ForestInformation['DomainsExtended'][$Domain]['DNSRoot'] -eq $ForestInformation['DomainsExtended'][$Domain]['Forest']) { $SearchBase = -join ("CN=Configuration,", $ForestInformation['DomainsExtended'][$Domain]['DistinguishedName']) # if ($SearchBase -notlike "*$DomainDistinguishedName") { # we check if SearchBase is part of domain distinugishname. If it isn't we skip #continue #} $Splat['Filter'] = "(objectClass -eq 'site')" $Splat['SearchBase'] = $SearchBase Get-ADObject @Splat | ForEach-Object -Process { Get-PrivGPOZaurrLink -Object $_ -Limited:$Limited.IsPresent -GPOCache $GPOCache } } } if ($Linked -contains 'Other') { $SearchBase = $ForestInformation['DomainsExtended'][$Domain]['DistinguishedName'] #if ($SearchBase -notlike "*$DomainDistinguishedName") { # we check if SearchBase is part of domain distinugishname. If it isn't we skip # continue #} $Splat['Filter'] = "(objectClass -eq 'organizationalUnit')" $Splat['SearchBase'] = $SearchBase Get-ADObject @Splat | ForEach-Object -Process { if ($_.DistinguishedName -eq $ForestInformation['DomainsExtended'][$Domain]['DistinguishedName']) { # other skips Domain Root } elseif ($_.DistinguishedName -eq $ForestInformation['DomainsExtended'][$Domain]['DomainControllersContainer']) { # other skips Domain Controllers } else { Get-PrivGPOZaurrLink -Object $_ -Limited:$Limited.IsPresent -GPOCache $GPOCache } } } } } else { foreach ($Domain in $ForestInformation.Domains) { $Splat = @{ Filter = $Filter Properties = 'distinguishedName', 'gplink', 'CanonicalName' Server = $ForestInformation['QueryServers'][$Domain]['HostName'][0] } if ($PSBoundParameters.ContainsKey('SearchBase')) { $DomainDistinguishedName = $ForestInformation['DomainsExtended'][$Domain]['DistinguishedName'] if ($SearchBase -notlike "*$DomainDistinguishedName") { # we check if SearchBase is part of domain distinugishname. If it isn't we skip continue } $Splat['SearchBase'] = $SearchBase } if ($PSBoundParameters.ContainsKey('SearchScope')) { $Splat['SearchScope'] = $SearchScope } Get-ADObject @Splat | ForEach-Object { Get-PrivGPOZaurrLink -Object $_ -Limited:$Limited.IsPresent -GPOCache $GPOCache } } } } else { foreach ($Object in $ADObject) { Get-PrivGPOZaurrLink -Object $Object -Limited:$Limited.IsPresent -GPOCache $GPOCache } } } End { } } function Get-GPOZaurrOwner { [cmdletbinding(DefaultParameterSetName = 'Default')] param( [Parameter(ParameterSetName = 'GPOName')][string] $GPOName, [Parameter(ParameterSetName = 'GPOGUID')][alias('GUID', 'GPOID')][string] $GPOGuid, [switch] $IncludeSysvol, [alias('ForestName')][string] $Forest, [string[]] $ExcludeDomains, [alias('Domain', 'Domains')][string[]] $IncludeDomains, [System.Collections.IDictionary] $ExtendedForestInformation, [System.Collections.IDictionary] $ADAdministrativeGroups ) Begin { $ForestInformation = Get-WinADForestDetails -Extended -Forest $Forest -IncludeDomains $IncludeDomains -ExcludeDomains $ExcludeDomains -ExtendedForestInformation $ExtendedForestInformation if (-not $ADAdministrativeGroups) { $ADAdministrativeGroups = Get-ADADministrativeGroups -Type DomainAdmins, EnterpriseAdmins -Forest $Forest -IncludeDomains $IncludeDomains -ExcludeDomains $ExcludeDomains -ExtendedForestInformation $ExtendedForestInformation } } Process { $getGPOZaurrADSplat = @{ Forest = $Forest IncludeDomains = $IncludeDomains ExcludeDomains = $ExcludeDomains ExtendedForestInformation = $ForestInformation } if ($GPOName) { $getGPOZaurrADSplat['GPOName'] = $GPOName } elseif ($GPOGuid) { $getGPOZaurrADSplat['GPOGUID'] = $GPOGuid } Get-GPOZaurrAD @getGPOZaurrADSplat | ForEach-Object -Process { Write-Verbose "Get-GPOZaurrOwner - Processing GPO: $($_.DisplayName) from domain: $($_.DomainName)" $ACL = Get-ADACLOwner -ADObject $_.GPODistinguishedName -Resolve -ADAdministrativeGroups $ADAdministrativeGroups $Object = [ordered] @{ DisplayName = $_.DisplayName DomainName = $_.DomainName GUID = $_.GUID DistinguishedName = $_.GPODistinguishedName Owner = $ACL.OwnerName OwnerSid = $ACL.OwnerSid OwnerType = $ACL.OwnerType } if ($IncludeSysvol) { $FileOwner = Get-FileOwner -JustPath -Path $_.Path -Resolve $Object['SysvolOwner'] = $FileOwner.OwnerName $Object['SysvolSid'] = $FileOwner.OwnerSid $Object['SysvolType'] = $FileOwner.OwnerType } [PSCUstomObject] $Object } } 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 } [Array] $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, [string[]] $Principal, [validateset('DistinguishedName', 'Name', 'Sid')][string] $PrincipalType = 'Sid', [validateSet('Unknown', 'NotWellKnown', 'NotWellKnownAdministrative', 'NotAdministrative', 'Administrative', '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) { $getGPOSplat = @{ Name = $GPOName Domain = $Domain Server = $QueryServer ErrorAction = 'SilentlyContinue' } } elseif ($GPOGuid) { $getGPOSplat = @{ Guid = $GPOGuid Domain = $Domain Server = $QueryServer ErrorAction = 'SilentlyContinue' } } else { $getGPOSplat = @{ All = $true Domain = $Domain Server = $QueryServer ErrorAction = 'SilentlyContinue' } } Get-GPO @getGPOSplat | ForEach-Object -Process { $getPrivPermissionSplat = @{ Principal = $Principal PrincipalType = $PrincipalType Accounts = $Accounts Type = $Type GPO = $_ SkipWellKnown = $SkipWellKnown.IsPresent SkipAdministrative = $SkipAdministrative.IsPresent IncludeOwner = $IncludeOwner.IsPresent IncludeGPOObject = $IncludeGPOObject.IsPresent IncludePermissionType = $IncludePermissionType ExcludePermissionType = $ExcludePermissionType ADAdministrativeGroups = $ADAdministrativeGroups } Get-PrivPermission @getPrivPermissionSplat } } } 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 Invoke-GPOZaurrPermission { [cmdletBinding(SupportsShouldProcess)] param( [Parameter(ParameterSetName = 'GPOGUID')] [Parameter(ParameterSetName = 'GPOName')] [parameter(ParameterSetName = 'Filter')] [parameter(ParameterSetName = 'ADObject')] [parameter(ParameterSetName = 'Linked')] [parameter(Position = 0)] [scriptblock] $PermissionRules, [Parameter(ParameterSetName = 'GPOName')][string] $GPOName, [Parameter(ParameterSetName = 'GPOGUID')][alias('GUID', 'GPOID')][string] $GPOGuid, [parameter(ParameterSetName = 'Linked', Mandatory)][validateset('Root', 'DomainControllers', 'Site', 'Other')][string] $Linked, [parameter(ParameterSetName = 'ADObject', ValueFromPipeline, ValueFromPipelineByPropertyName, Mandatory)][Microsoft.ActiveDirectory.Management.ADObject[]] $ADObject, [parameter(ParameterSetName = 'Filter')][string] $Filter = "(objectClass -eq 'organizationalUnit' -or objectClass -eq 'domainDNS' -or objectClass -eq 'site')", [parameter(ParameterSetName = 'Filter')][string] $SearchBase, [parameter(ParameterSetName = 'Filter')][Microsoft.ActiveDirectory.Management.ADSearchScope] $SearchScope, [Parameter(ParameterSetName = 'GPOGUID')] [Parameter(ParameterSetName = 'GPOName')] [parameter(ParameterSetName = 'Filter')] [parameter(ParameterSetName = 'ADObject')] [parameter(ParameterSetName = 'Linked')] [validateSet('Unknown', 'NotWellKnown', 'NotWellKnownAdministrative', 'NotAdministrative', 'All')][string[]] $Type, [Parameter(ParameterSetName = 'GPOGUID')] [Parameter(ParameterSetName = 'GPOName')] [parameter(ParameterSetName = 'Filter')] [parameter(ParameterSetName = 'ADObject')] [parameter(ParameterSetName = 'Linked')] [Array] $ApprovedGroups, [Parameter(ParameterSetName = 'GPOGUID')] [Parameter(ParameterSetName = 'GPOName')] [parameter(ParameterSetName = 'Filter')] [parameter(ParameterSetName = 'ADObject')] [parameter(ParameterSetName = 'Linked')] [alias('Principal')][Array] $Trustee, [Parameter(ParameterSetName = 'GPOGUID')] [Parameter(ParameterSetName = 'GPOName')] [parameter(ParameterSetName = 'Filter')] [parameter(ParameterSetName = 'ADObject')] [parameter(ParameterSetName = 'Linked')] [Microsoft.GroupPolicy.GPPermissionType] $TrusteePermissionType, [Parameter(ParameterSetName = 'GPOGUID')] [Parameter(ParameterSetName = 'GPOName')] [parameter(ParameterSetName = 'Filter')] [parameter(ParameterSetName = 'ADObject')] [parameter(ParameterSetName = 'Linked')] [alias('PrincipalType')][validateset('DistinguishedName', 'Name', 'Sid')][string] $TrusteeType = 'DistinguishedName', [Parameter(ParameterSetName = 'GPOGUID')] [Parameter(ParameterSetName = 'GPOName')] [parameter(ParameterSetName = 'Filter')] [parameter(ParameterSetName = 'ADObject')] [parameter(ParameterSetName = 'Linked')] [System.Collections.IDictionary] $GPOCache, [Parameter(ParameterSetName = 'GPOGUID')] [Parameter(ParameterSetName = 'GPOName')] [parameter(ParameterSetName = 'Filter')] [parameter(ParameterSetName = 'ADObject')] [parameter(ParameterSetName = 'Linked')] [alias('ForestName')][string] $Forest, [Parameter(ParameterSetName = 'GPOGUID')] [Parameter(ParameterSetName = 'GPOName')] [parameter(ParameterSetName = 'Filter')] [parameter(ParameterSetName = 'ADObject')] [parameter(ParameterSetName = 'Linked')] [string[]] $ExcludeDomains, [Parameter(ParameterSetName = 'GPOGUID')] [Parameter(ParameterSetName = 'GPOName')] [parameter(ParameterSetName = 'Filter')] [parameter(ParameterSetName = 'ADObject')] [parameter(ParameterSetName = 'Linked')] [alias('Domain', 'Domains')][string[]] $IncludeDomains, [Parameter(ParameterSetName = 'GPOGUID')] [Parameter(ParameterSetName = 'GPOName')] [parameter(ParameterSetName = 'Filter')] [parameter(ParameterSetName = 'ADObject')] [parameter(ParameterSetName = 'Linked')] [System.Collections.IDictionary] $ExtendedForestInformation ) Begin { $ADAdministrativeGroups = Get-ADADministrativeGroups -Type DomainAdmins, EnterpriseAdmins -Forest $Forest -IncludeDomains $IncludeDomains -ExcludeDomains $ExcludeDomains -ExtendedForestInformation $ExtendedForestInformation <# $Script:Actions = @{ GpoApply = @{ Remove = @{ NotAdministrative = $false NotWellKnownAdministrative = $false } Add = @{ Administrative = $false WellKnownAdministrative = $false } } GpoRead = @{ Remove = @{ NotAdministrative = $false NotWellKnownAdministrative = $false } Add = @{ Administrative = $false WellKnownAdministrative = $false } } GpoCustom = @{ Remove = @{ NotAdministrative = $false NotWellKnownAdministrative = $false } Add = @{ Administrative = $false WellKnownAdministrative = $false } } GpoEditDeleteModifySecurity = @{ Remove = @{ NotAdministrative = $false NotWellKnownAdministrative = $false } Add = @{ Administrative = $false WellKnownAdministrative = $false } } GpoEdit = @{ Remove = @{ NotAdministrative = $false NotWellKnownAdministrative = $false } Add = @{ Administrative = $false WellKnownAdministrative = $false } } } #> } Process { if ($PermissionRules) { $Rules = & $PermissionRules <# foreach ($Rule in $Rules) { #$Actions["$Rule."] if ($Rule.Action -eq 'Remove' -and $Rule.Type -contains 'NotWellKnownAdministrative') { #$Actions.NotWellKnownAdministrative = $true } if ($Rule.Action -eq 'Remove' -and $Rule.Type -contains 'NotAdministrative') { #$Actions.Remove.NotAdministrative = $true } } #> } if ($GPOName -or $GPOGuid) { } else { $Splat = @{ } if ($ADObject) { $Splat['ADObject'] = $ADObject } elseif ($Linked) { $Splat['Linked'] = $Linked } else { if ($Filter) { $Splat['Filter'] = $Filter } if ($SearchBase) { $Splat['SearchBase'] = $SearchBase } if ($SearchScope) { $Splat['SearchScope'] = $SearchScope } } Get-GPOZaurrLink @Splat | ForEach-Object -Process { $GPO = $_ foreach ($Rule in $Rules) { if ($Rule.Action -eq 'Owner') { if ($Rule.Type -eq 'Administrative') { $AdministrativeGroup = $ADAdministrativeGroups['ByNetBIOS']["$($GPO.Owner)"] if (-not $AdministrativeGroup) { $DefaultPrincipal = $ADAdministrativeGroups["$($GPO.DomainName)"]['DomainAdmins'] Write-Verbose "Set-GPOZaurrOwner - Changing GPO: $($GPO.DisplayName) from domain: $($GPO.DomainName) from owner $($GPO.Owner) to $DefaultPrincipal" Set-ADACLOwner -ADObject $GPO.GPODistinguishedName -Principal $DefaultPrincipal -Verbose:$false -WhatIf:$WhatIfPreference } } elseif ($Rule.Type -eq 'Default') { Write-Verbose "Set-GPOZaurrOwner - Changing GPO: $($GPO.DisplayName) from domain: $($GPO.DomainName) from owner $($GPO.Owner) to $($Rule.Principal)" Set-ADACLOwner -ADObject $GPO.GPODistinguishedName -Principal $Rule.Principal -Verbose:$false -WhatIf:$WhatIfPreference } continue } if ($Rule.Action -eq 'Remove') { $GPOPermissions = Get-GPOZaurrPermission -GPOGuid $_.GUID -IncludePermissionType $Rule.IncludePermissionType -ExcludePermissionType $Rule.ExcludePermissionType -Type $Rule.Type -IncludeGPOObject foreach ($Permission in $GPOPermissions) { Remove-PrivPermission -Principal $Permission.Sid -PrincipalType Sid -GPOPermission $Permission -IncludePermissionType $Permission.Permission #-IncludeDomains $GPO.DomainName } continue } if ($Rule.Action -eq 'Add') { #$GPOPermissions = Get-GPOZaurrPermission -GPOGuid $_.GUID -IncludePermissionType $Rule.IncludePermissionType -ExcludePermissionType $Rule.ExcludePermissionType -Type 'All' -IncludeGPOObject # foreach ($Permission in $GPOPermissions) { Add-GPOZaurrPermission -GPOGuid $_.GUID -IncludeDomains $GPO.DomainName -Type $Rule.Type -PermissionType $Rule.IncludePermissionType -ADAdministrativeGroups $ADAdministrativeGroups # } } } } } } End { } } 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-GPOPermission { [cmdletBinding()] param( [validateSet('Unknown', 'NotWellKnown', 'NotWellKnownAdministrative', 'Administrative', 'NotAdministrative', 'All')][string[]] $Type, [Microsoft.GroupPolicy.GPPermissionType[]] $IncludePermissionType, [Microsoft.GroupPolicy.GPPermissionType[]] $ExcludePermissionType ) if ($Type) { @{ Action = 'Remove' Type = $Type IncludePermissionType = $IncludePermissionType ExcludePermissionType = $ExcludePermissionType } } <# foreach ($T in $Type) { foreach ($Permission in $IncludePermissionType) { if ($T -eq 'NotWellKnownAdministrative') { $Script:Actions[$Permission][$T] = $true } elseif ($T -eq 'NotAdministrative') { $Script:Actions[$Permission][$T] = $true } } } #> } <# function Find-GPOPermission { param( $GPOPermissions, [Microsoft.GroupPolicy.GPPermissionType[]] $IncludePermissionType, [bool] $NotAdministrative, [bool] $NotWellKnownAdministrative ) foreach ($Permission in $GPOPermissions) { if ($Permission.Permission -in $IncludePermissionType) { if ($NotAdministrative -and $NotWellKnownAdministrative) { $Permission } } } } #> 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 $BackupOK = $true } catch { Write-Warning "Remove-GPOZaurr - Backing up GPO $($_.DisplayName) from $($_.DomainName) failed: $($_.Exception.Message)" $BackupOK = $false } } if (($BackupRequired -and $BackupOK) -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 $BackupOK = $true } catch { Write-Warning "Remove-GPOZaurr - Backing up GPO $($_.DisplayName) from $($_.DomainName) failed: $($_.Exception.Message)" $BackupOK = $false } } if (($BackupRequired -and $BackupOK) -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, DefaultParameterSetName = 'Global')] param( [Parameter(ParameterSetName = 'GPOName', Mandatory)] [string] $GPOName, [Parameter(ParameterSetName = 'GPOGUID', Mandatory)] [alias('GUID', 'GPOID')][string] $GPOGuid, [string[]] $Principal, [validateset('DistinguishedName', 'Name', 'Sid')][string] $PrincipalType = 'Sid', [validateset('Unknown', 'NotAdministrative', 'Default')][string[]] $Type = 'Default', [alias('PermissionType')][Microsoft.GroupPolicy.GPPermissionType[]] $IncludePermissionType, [Microsoft.GroupPolicy.GPPermissionType[]] $ExcludePermissionType, [switch] $SkipWellKnown, [switch] $SkipAdministrative, [alias('ForestName')][string] $Forest, [string[]] $ExcludeDomains, [alias('Domain', 'Domains')][string[]] $IncludeDomains, [System.Collections.IDictionary] $ExtendedForestInformation, [int] $LimitProcessing ) Begin { $Count = 0 $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 "Remove-GPOZaurrPermission - Using SkipAdministrative or SkipWellKnown while looking for Unknown doesn't make sense as only Unknown will be displayed." } } } Process { if ($Type -contains 'Named' -and $Principal.Count -eq 0) { Write-Warning "Remove-GPOZaurrPermission - When using type Named you need to provide names to remove. Terminating." return } # $GPOPermission.GPOSecurity.RemoveTrustee($GPOPermission.Sid) #void RemoveTrustee(string trustee) #void RemoveTrustee(System.Security.Principal.IdentityReference identity) #$GPOPermission.GPOSecurity.Remove #void RemoveAt(int index) #void IList[GPPermission].RemoveAt(int index) #void IList.RemoveAt(int index) foreach ($Domain in $ForestInformation.Domains) { $QueryServer = $ForestInformation['QueryServers'][$Domain]['HostName'][0] if ($GPOName) { $getGPOSplat = @{ Name = $GPOName Domain = $Domain Server = $QueryServer ErrorAction = 'SilentlyContinue' } } elseif ($GPOGuid) { $getGPOSplat = @{ Guid = $GPOGuid Domain = $Domain Server = $QueryServer ErrorAction = 'SilentlyContinue' } } else { $getGPOSplat = @{ All = $true Domain = $Domain Server = $QueryServer ErrorAction = 'SilentlyContinue' } } Get-GPO @getGPOSplat | ForEach-Object -Process { $getPrivPermissionSplat = @{ Principal = $Principal PrincipalType = $PrincipalType Accounts = $Accounts Type = $Type GPO = $_ SkipWellKnown = $SkipWellKnown.IsPresent SkipAdministrative = $SkipAdministrative.IsPresent IncludeOwner = $false IncludeGPOObject = $true IncludePermissionType = $IncludePermissionType ExcludePermissionType = $ExcludePermissionType ADAdministrativeGroups = $ADAdministrativeGroups } [Array] $GPOPermissions = Get-PrivPermission @getPrivPermissionSplat if ($GPOPermissions.Count -gt 0) { foreach ($Permission in $GPOPermissions) { Remove-PrivPermission -Principal $Permission.Sid -PrincipalType Sid -GPOPermission $Permission -IncludePermissionType $Permission.Permission #-IncludeDomains $GPO.DomainName } $Count++ if ($Count -eq $LimitProcessing) { # skipping skips per removed permission not per gpo. break } } } } <# Get-GPOZaurrPermission @Splat | 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)")) { try { Write-Verbose "Remove-GPOZaurrPermission - Removing permission $($GPOPermission.Permission) for $($GPOPermission.Sid)" $GPOPermission.GPOSecurity.RemoveTrustee($GPOPermission.Sid) $GPOPermission.GPOObject.SetSecurityInfo($GPOPermission.GPOSecurity) #$GPOPermission.GPOSecurity.RemoveAt($GPOPermission.GPOSecurityPermissionItem) #$GPOPermission.GPOObject.SetSecurityInfo($GPOPermission.GPOSecurity) } catch { Write-Warning "Remove-GPOZaurrPermission - Removing permission $($GPOPermission.Permission) for $($GPOPermission.Sid) with error: $($_.Exception.Message)" } # 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 ($Type -contains 'NotAdministrative') { } if ($Type -contains 'Default') { Remove-PrivPermission -Principal $Principal -PrincipalType $PrincipalType -GPOPermission $GPOPermission -IncludePermissionType $IncludePermissionType } #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-GPOOwner { [cmdletBinding()] param( [validateset('Administrative', 'Default')][string] $Type = 'Default', [string] $Principal ) if ($Type -eq 'Default') { if ($Principal) { @{ Action = 'Owner' Type = 'Default' Principal = $Principal } } } elseif ($Type -eq 'Administrative') { @{ Action = 'Owner' Type = 'Administrative' Principal = '' } } } function Set-GPOZaurrOwner { [cmdletBinding(SupportsShouldProcess, DefaultParameterSetName = 'Type')] param( [Parameter(ParameterSetName = 'Type', Mandatory)] [validateset('Unknown', 'NotAdministrative', 'All')][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(ParameterSetName = 'Type')] [Parameter(ParameterSetName = 'Named')] [string] $Principal, [switch] $IncludeSysVol, [Parameter(ParameterSetName = 'Type')] [Parameter(ParameterSetName = 'Named')] [int] $LimitProcessing = [int32]::MaxValue ) Begin { Write-Verbose "Set-GPOZaurrOwner - Getting ADAdministrativeGroups" $ADAdministrativeGroups = Get-ADADministrativeGroups -Type DomainAdmins, EnterpriseAdmins -Forest $Forest -IncludeDomains $IncludeDomains -ExcludeDomains $ExcludeDomains -ExtendedForestInformation $ExtendedForestInformation Write-Verbose "Set-GPOZaurrOwner - Processing GPOs for Type $Type" } Process { $getGPOZaurrOwnerSplat = @{ IncludeSysvol = $IncludeSysVol Forest = $Forest IncludeDomains = $IncludeDomains ExcludeDomains = $ExcludeDomains ExtendedForestInformation = $ExtendedForestInformation ADAdministrativeGroups = $ADAdministrativeGroups Verbose = $VerbosePreference } if ($GPOName) { $getGPOZaurrOwnerSplat['GPOName'] = $GPOName } elseif ($GPOGuid) { $getGPOZaurrOwnerSplat['GPOGuid'] = $GPOGUiD } Get-GPOZaurrOwner @getGPOZaurrOwnerSplat | Where-Object { if ($Type -contains 'NotAdministrative' -and $Type -notcontains 'All') { if ($_.Owner) { $AdministrativeGroup = $ADAdministrativeGroups['ByNetBIOS']["$($_.Owner)"] if (-not $AdministrativeGroup) { $_ } } } elseif ($Type -contains 'Unknown' -and $Type -notcontains 'All') { if ($null -eq $_.Owner) { $_ } } else { $_ } } | Select-Object -First $LimitProcessing | ForEach-Object -Process { $GPO = $_ if ($Principal) { 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 -WhatIf:$WhatIfPreference } else { $DefaultPrincipal = $ADAdministrativeGroups["$($GPO.DomainName)"]['DomainAdmins'] Write-Verbose "Set-GPOZaurrOwner - Changing GPO: $($GPO.DisplayName) from domain: $($GPO.DomainName) from owner $($GPO.Owner)/$($GPO.OwnerSID) to $DefaultPrincipal" Set-ADACLOwner -ADObject $GPO.DistinguishedName -Principal $DefaultPrincipal -Verbose:$false -WhatIf:$WhatIfPreference } <# if ($Type -contains 'All') { # Regardless who is the owner it is overwritten if ($Principal) { Write-Verbose "Set-GPOZaurrOwner - Changing GPO: $($GPO.DisplayName) from domain: $($GPO.DomainName) from owner $($GPO.Owner)/$($GPO.OwnerSID) to $Principal" Set-ADACLOwner -ADObject $GPO.GPODistinguishedName -Principal $Principal -Verbose:$false -WhatIf:$WhatIfPreference } else { $DefaultPrincipal = $ADAdministrativeGroups["$($GPO.DomainName)"]['DomainAdmins'] Write-Verbose "Set-GPOZaurrOwner - Changing GPO: $($GPO.DisplayName) from domain: $($GPO.DomainName) from owner $($GPO.Owner)/$($GPO.OwnerSID) to $DefaultPrincipal" Set-ADACLOwner -ADObject $GPO.GPODistinguishedName -Principal $DefaultPrincipal -Verbose:$false -WhatIf:$WhatIfPreference } $Count++ if ($Count -eq $LimitProcessing) { break } } elseif ($Type -contains 'NotAdministrative' -and $Type -notcontains 'All') { if ($GPO.Owner) { $AdministrativeGroup = $ADAdministrativeGroups['ByNetBIOS']["$($GPO.Owner)"] if (-not $AdministrativeGroup) { if ($Principal) { Write-Verbose "Set-GPOZaurrOwner - Changing GPO: $($GPO.DisplayName) from domain: $($GPO.DomainName) from owner $($GPO.Owner)/$($GPO.OwnerSID) to $Principal" Set-ADACLOwner -ADObject $GPO.GPODistinguishedName -Principal $DefaultPrincipal -Verbose:$false -WhatIf:$WhatIfPreference } else { $DefaultPrincipal = $ADAdministrativeGroups["$($GPO.DomainName)"]['DomainAdmins'] Write-Verbose "Set-GPOZaurrOwner - Changing GPO: $($GPO.DisplayName) from domain: $($GPO.DomainName) from owner $($GPO.Owner)/$($GPO.OwnerSID) to $DefaultPrincipal" Set-ADACLOwner -ADObject $GPO.GPODistinguishedName -Principal $DefaultPrincipal -Verbose:$false -WhatIf:$WhatIfPreference } $Count++ if ($Count -eq $LimitProcessing) { return } } } } else ($Type -contains 'Unknown' -and $Type -notcontains 'All') { if ($null -eq $GPO.Owner) { if ($Principal) { Write-Verbose "Set-GPOZaurrOwner - Changing GPO: $($GPO.DisplayName) from domain: $($GPO.DomainName) from owner NULL/$($GPO.OwnerSID) to $Principal" Set-ADACLOwner -ADObject $GPO.GPODistinguishedName -Principal $Principal -Verbose:$false -WhatIf:$WhatIfPreference } else { $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.GPODistinguishedName -Principal $DefaultPrincipal -Verbose:$false -WhatIf:$WhatIfPreference } $Count++ if ($Count -eq $LimitProcessing) { break } } } else { $GPO = $_ if ($Principal) { Write-Verbose "Set-GPOZaurrOwner - Changing GPO: $($GPO.DisplayName) from domain: $($GPO.DomainName) from owner $($GPO.Owner)/$($GPO.OwnerSID) to $Principal" Set-ADACLOwner -ADObject $GPO.GPODistinguishedName -Principal $Principal -Verbose:$false -WhatIf:$WhatIfPreference } else { $DefaultPrincipal = $ADAdministrativeGroups["$($GPO.DomainName)"]['DomainAdmins'] Write-Verbose "Set-GPOZaurrOwner - Changing GPO: $($GPO.DisplayName) from domain: $($GPO.DomainName) from owner $($GPO.Owner)/$($GPO.OwnerSID) to $DefaultPrincipal" Set-ADACLOwner -ADObject $GPO.GPODistinguishedName -Principal $DefaultPrincipal -Verbose:$false -WhatIf:$WhatIfPreference } } #> } #> #} <# else { $getGPOZaurrOwnerSplat = @{ IncludeSysvol = $IncludeSysVol Forest = $Forest IncludeDomains = $IncludeDomains ExcludeDomains = $ExcludeDomains ExtendedForestInformation = $ExtendedForestInformation ADAdministrativeGroups = $ADAdministrativeGroups GPOName = $GPOName GPOGuid = $GPOGUiD } Get-GPOZaurrOwner @getGPOZaurrOwnerSplat $IncludeSysVol | ForEach-Object -Process { $GPO = $_ if ($Principal) { Write-Verbose "Set-GPOZaurrOwner - Changing GPO: $($GPO.DisplayName) from domain: $($GPO.DomainName) from owner $($GPO.Owner)/$($GPO.OwnerSID) to $Principal" Set-ADACLOwner -ADObject $GPO.GPODistinguishedName -Principal $Principal -Verbose:$false -WhatIf:$WhatIfPreference } else { $DefaultPrincipal = $ADAdministrativeGroups["$($GPO.DomainName)"]['DomainAdmins'] Write-Verbose "Set-GPOZaurrOwner - Changing GPO: $($GPO.DisplayName) from domain: $($GPO.DomainName) from owner $($GPO.Owner)/$($GPO.OwnerSID) to $DefaultPrincipal" Set-ADACLOwner -ADObject $GPO.GPODistinguishedName -Principal $DefaultPrincipal -Verbose:$false -WhatIf:$WhatIfPreference } $Count++ if ($Count -eq $LimitProcessing) { break } } } #> } End { } } Export-ModuleMember -Function @('Add-GPOPermission', 'Add-GPOZaurrPermission', 'Backup-GPOZaurr', 'Get-GPOZaurr', 'Get-GPOZaurrAD', 'Get-GPOZaurrBackupInformation', 'Get-GPOZaurrLink', 'Get-GPOZaurrOwner', 'Get-GPOZaurrPassword', 'Get-GPOZaurrPermission', 'Get-GPOZaurrPermissionConsistency', 'Get-GPOZaurrWMI', 'Invoke-GPOZaurrPermission', 'New-GPOZaurrWMI', 'Remove-GPOPermission', 'Remove-GPOZaurr', 'Remove-GPOZaurrPermission', 'Remove-GPOZaurrWMI', 'Restore-GPOZaurr', 'Save-GPOZaurrFiles', 'Set-GPOOwner', 'Set-GPOZaurrOwner') -Alias @() |