mirror of
https://github.com/EvotecIT/GPOZaurr.git
synced 2026-07-26 11:49:17 +00:00
391 lines
21 KiB
PowerShell
391 lines
21 KiB
PowerShell
function Get-GPOZaurrFiles {
|
|
<#
|
|
.SYNOPSIS
|
|
Retrieves information about Group Policy Objects (GPOs) stored in SYSVOL and NETLOGON folders.
|
|
|
|
.DESCRIPTION
|
|
This function retrieves information about GPOs stored in SYSVOL and NETLOGON folders of specified domains. It can filter by type of files and hash algorithms used for verification.
|
|
|
|
.PARAMETER Type
|
|
Specifies the type of files to retrieve. Valid values are 'All', 'Netlogon', and 'Sysvol'.
|
|
|
|
.PARAMETER HashAlgorithm
|
|
Specifies the hash algorithm to use for file verification. Valid values are 'None', 'MACTripleDES', 'MD5', 'RIPEMD160', 'SHA1', 'SHA256', 'SHA384', 'SHA512'.
|
|
|
|
.PARAMETER Signature
|
|
Indicates whether to include file signatures for verification.
|
|
|
|
.PARAMETER AsHashTable
|
|
Indicates whether to return the results as a hashtable.
|
|
|
|
.PARAMETER Extended
|
|
Indicates whether to include extended information about the forest.
|
|
|
|
.PARAMETER ExtendedMetaData
|
|
Indicates whether to include extended metadata information.
|
|
|
|
.PARAMETER Forest
|
|
Specifies the forest name to retrieve GPO information from.
|
|
|
|
.PARAMETER ExcludeDomains
|
|
Specifies an array of domains to exclude from the search.
|
|
|
|
.PARAMETER IncludeDomains
|
|
Specifies an array of domains to include in the search.
|
|
|
|
.PARAMETER ExtendedForestInformation
|
|
Specifies additional forest information to include.
|
|
|
|
.EXAMPLE
|
|
Get-GPOZaurrFiles -Type 'All' -HashAlgorithm 'SHA256' -Signature
|
|
Retrieves all files from SYSVOL and NETLOGON folders with SHA256 hash algorithm and includes file signatures.
|
|
|
|
.EXAMPLE
|
|
Get-GPOZaurrFiles -Type 'Sysvol' -HashAlgorithm 'MD5' -AsHashTable
|
|
Retrieves only SYSVOL files with MD5 hash algorithm and returns the results as a hashtable.
|
|
#>
|
|
[cmdletbinding()]
|
|
param(
|
|
[ValidateSet('All', 'Netlogon', 'Sysvol')][string[]] $Type = 'All',
|
|
[ValidateSet('None', 'MACTripleDES', 'MD5', 'RIPEMD160', 'SHA1', 'SHA256', 'SHA384', 'SHA512')][string] $HashAlgorithm = 'None',
|
|
[switch] $Signature,
|
|
[switch] $AsHashTable,
|
|
[switch] $Extended,
|
|
[switch] $ExtendedMetaData,
|
|
[alias('ForestName')][string] $Forest,
|
|
[string[]] $ExcludeDomains,
|
|
[alias('Domain', 'Domains')][string[]] $IncludeDomains,
|
|
[System.Collections.IDictionary] $ExtendedForestInformation
|
|
)
|
|
$GPOCache = @{}
|
|
$ForestInformation = Get-WinADForestDetails -Extended -Forest $Forest -IncludeDomains $IncludeDomains -ExcludeDomains $ExcludeDomains -ExtendedForestInformation $ExtendedForestInformation
|
|
$GPOList = Get-GPOZaurrAD -ExtendedForestInformation $ForestInformation
|
|
foreach ($GPO in $GPOList) {
|
|
if (-not $GPOCache[$GPO.DomainName]) {
|
|
$GPOCache[$GPO.DomainName] = @{}
|
|
}
|
|
$GPOCache[$($GPO.DomainName)][($GPO.GUID)] = $GPO
|
|
}
|
|
foreach ($Domain in $ForestInformation.Domains) {
|
|
$Path = @(
|
|
if ($Type -contains 'All') {
|
|
"\\$Domain\SYSVOL\$Domain"
|
|
}
|
|
if ($Type -contains 'Sysvol') {
|
|
"\\$Domain\SYSVOL\$Domain\policies"
|
|
}
|
|
if ($Type -contains 'NetLogon') {
|
|
"\\$Domain\NETLOGON"
|
|
}
|
|
)
|
|
# Order does matter
|
|
$Folders = [ordered] @{
|
|
"\\$Domain\SYSVOL\$Domain\policies\PolicyDefinitions" = @{
|
|
Name = 'SYSVOL PolicyDefinitions'
|
|
}
|
|
"\\$Domain\SYSVOL\$Domain\policies" = @{
|
|
Name = 'SYSVOL Policies'
|
|
}
|
|
"\\$Domain\SYSVOL\$Domain\scripts" = @{
|
|
Name = 'NETLOGON Scripts'
|
|
}
|
|
"\\$Domain\SYSVOL\$Domain\StarterGPOs" = @{
|
|
Name = 'SYSVOL GPO Starters'
|
|
}
|
|
"\\$Domain\NETLOGON" = @{
|
|
Name = 'NETLOGON Scripts'
|
|
}
|
|
"\\$Domain\SYSVOL\$Domain\DfsrPrivate" = @{
|
|
Name = 'DfsrPrivate'
|
|
}
|
|
"\\$Domain\SYSVOL\$Domain" = @{
|
|
Name = 'SYSVOL Root'
|
|
}
|
|
}
|
|
Get-ChildItem -Path $Path -ErrorAction SilentlyContinue -Recurse -ErrorVariable err -File -Force | ForEach-Object {
|
|
# Lets reset values just to be sure those are empty
|
|
$GPO = $null
|
|
$BelongsToGPO = $false
|
|
$GPODisplayName = $null
|
|
$SuggestedAction = $null
|
|
$SuggestedActionComment = $null
|
|
$FileType = foreach ($Key in $Folders.Keys) {
|
|
if ($_.FullName -like "$Key*") {
|
|
$Folders[$Key]
|
|
break
|
|
}
|
|
}
|
|
if ($FileType.Name -eq 'SYSVOL Policies') {
|
|
$FoundGUID = $_.FullName -match '[\da-zA-Z]{8}-([\da-zA-Z]{4}-){3}[\da-zA-Z]{12}'
|
|
if ($FoundGUID) {
|
|
$GPO = $GPOCache[$Domain][$matches[0]]
|
|
if ($GPO) {
|
|
$BelongsToGPO = $true
|
|
$GPODisplayName = $GPO.DisplayName
|
|
}
|
|
}
|
|
$Correct = @(
|
|
[System.IO.Path]::Combine($GPO.Path, 'GPT.INI')
|
|
[System.IO.Path]::Combine($GPO.Path, 'GPO.cmt')
|
|
[System.IO.Path]::Combine($GPO.Path, 'Group Policy', 'GPE.ini')
|
|
foreach ($TypeM in @('Machine', 'User')) {
|
|
[System.IO.Path]::Combine($GPO.Path, $TypeM, 'Registry.pol')
|
|
[System.IO.Path]::Combine($GPO.Path, $TypeM, 'comment.cmtx')
|
|
[System.IO.Path]::Combine($GPO.Path, $TypeM, 'Preferences\Registry\Registry.xml')
|
|
[System.IO.Path]::Combine($GPO.Path, $TypeM, 'Preferences\Printers\Printers.xml')
|
|
[System.IO.Path]::Combine($GPO.Path, $TypeM, 'Preferences\ScheduledTasks\ScheduledTasks.xml')
|
|
[System.IO.Path]::Combine($GPO.Path, $TypeM, 'Preferences\Services\Services.xml')
|
|
[System.IO.Path]::Combine($GPO.Path, $TypeM, 'Preferences\Groups\Groups.xml')
|
|
[System.IO.Path]::Combine($GPO.Path, $TypeM, 'Preferences\RegionalOptions\RegionalOptions.xml')
|
|
[System.IO.Path]::Combine($GPO.Path, $TypeM, 'Preferences\FolderOptions\FolderOptions.xml')
|
|
[System.IO.Path]::Combine($GPO.Path, $TypeM, 'Preferences\Drives\Drives.xml')
|
|
[System.IO.Path]::Combine($GPO.Path, $TypeM, 'Preferences\InternetSettings\InternetSettings.xml')
|
|
[System.IO.Path]::Combine($GPO.Path, $TypeM, 'Preferences\Folders\Folders.xml')
|
|
[System.IO.Path]::Combine($GPO.Path, $TypeM, 'Preferences\PowerOptions\PowerOptions.xml')
|
|
[System.IO.Path]::Combine($GPO.Path, $TypeM, 'Preferences\Shortcuts\Shortcuts.xml')
|
|
[System.IO.Path]::Combine($GPO.Path, $TypeM, 'Preferences\Files\Files.xml')
|
|
[System.IO.Path]::Combine($GPO.Path, $TypeM, 'Preferences\EnvironmentVariables\EnvironmentVariables.xml')
|
|
[System.IO.Path]::Combine($GPO.Path, $TypeM, 'Preferences\NetworkOptions\NetworkOptions.xml')
|
|
[System.IO.Path]::Combine($GPO.Path, $TypeM, 'Preferences\DataSources\DataSources.xml')
|
|
[System.IO.Path]::Combine($GPO.Path, $TypeM, 'Preferences\NetworkShares\NetworkShares.xml')
|
|
[System.IO.Path]::Combine($GPO.Path, $TypeM, 'Preferences\StartMenuTaskbar\StartMenuTaskbar.xml')
|
|
[System.IO.Path]::Combine($GPO.Path, $TypeM, 'Applications\Microsoft\TBLayout.xml')
|
|
[System.IO.Path]::Combine($GPO.Path, $TypeM, 'Applications\Microsoft\DefaultApps.xml')
|
|
[System.IO.Path]::Combine($GPO.Path, $TypeM, 'Applications\ADE.CFG')
|
|
[System.IO.Path]::Combine($GPO.Path, $TypeM, 'Scripts\scripts.ini')
|
|
[System.IO.Path]::Combine($GPO.Path, $TypeM, 'Scripts\psscripts.ini')
|
|
[System.IO.Path]::Combine($GPO.Path, $TypeM, 'Documents & Settings\fdeploy.ini')
|
|
[System.IO.Path]::Combine($GPO.Path, $TypeM, 'Documents & Settings\fdeploy1.ini')
|
|
[System.IO.Path]::Combine($GPO.Path, $TypeM, 'Documents & Settings\fdeploy2.ini')
|
|
if ($_.Extension -eq '.aas') {
|
|
[System.IO.Path]::Combine($GPO.Path, $TypeM, 'Applications', $_.Name)
|
|
}
|
|
}
|
|
[System.IO.Path]::Combine($GPO.Path, 'Machine\Microsoft\Windows NT\SecEdit\GptTmpl.inf')
|
|
[System.IO.Path]::Combine($GPO.Path, 'Machine\Microsoft\Windows NT\Audit\audit.csv')
|
|
)
|
|
if ($GPO) {
|
|
if ($_.FullName -in $Correct) {
|
|
$SuggestedAction = 'Skip assesment'
|
|
$SuggestedActionComment = 'Correctly placed in SYSVOL'
|
|
} elseif ($_.FullName -like '*_NTFRS_*') {
|
|
$SuggestedAction = 'Consider deleting'
|
|
$SuggestedActionComment = 'Most likely replication error'
|
|
} elseif ($_.Extension -eq '.adm') {
|
|
$SuggestedAction = 'Consider deleting'
|
|
$SuggestedActionComment = 'Most likely legacy ADM files'
|
|
} elseif ($_.Name -eq 'Thumbs.db') {
|
|
$SuggestedAction = 'Consider deleting'
|
|
$SuggestedActionComment = 'Most likely database files to store image thumbnails on Windows systems.'
|
|
}
|
|
if (-not $SuggestedAction) {
|
|
$FullPathAdmFiles = [System.IO.Path]::Combine($GPO.Path, 'Adm\admfiles.ini')
|
|
if ($_.FullName -eq $FullPathAdmFiles) {
|
|
$SuggestedAction = 'Consider deleting'
|
|
$SuggestedActionComment = 'Most likely legacy ADM files settings file'
|
|
}
|
|
}
|
|
if (-not $SuggestedAction) {
|
|
foreach ($Ext in @('*old*', '*bak*', '*bck', '.new')) {
|
|
if ($_.Extension -like $Ext) {
|
|
$SuggestedAction = 'Consider deleting'
|
|
$SuggestedActionComment = 'Most likely backup files'
|
|
break
|
|
}
|
|
}
|
|
}
|
|
if (-not $SuggestedAction) {
|
|
<#
|
|
$IEAK = @(
|
|
'microsoft\IEAK\install.ins'
|
|
'MICROSOFT\IEAK\BRANDING\cs\connect.ras'
|
|
'microsoft\IEAK\BRANDING\cs\connect.set'
|
|
'microsoft\IEAK\BRANDING\cs\cs.dat'
|
|
'microsoft\IEAK\BRANDING\ADM\inetcorp.iem'
|
|
'microsoft\IEAK\BRANDING\ADM\inetcorp.inf'
|
|
'microsoft\IEAK\install.ins'
|
|
'microsoft\IEAK\BRANDING\favs\Outlook.ico'
|
|
'microsoft\IEAK\BRANDING\favs\Bio.ico'
|
|
'MICROSOFT\IEAK\BRANDING\favs\$fi380.ico'
|
|
'microsoft\IEAK\BRANDING\PROGRAMS\programs.inf'
|
|
'MICROSOFT\IEAK\BRANDING\RATINGS\ratings.inf'
|
|
'MICROSOFT\IEAK\BRANDING\RATINGS\ratrsop.inf'
|
|
'microsoft\IEAK\BRANDING\ZONES\seczones.inf'
|
|
'microsoft\IEAK\BRANDING\ZONES\seczrsop.inf'
|
|
'microsoft\IEAK\BRANDING\ZONES\seczrsop.inf'
|
|
)
|
|
#>
|
|
if ($_.FullName -like '*microsoft\IEAK*') {
|
|
# https://docs.microsoft.com/en-us/internet-explorer/ie11-deploy-guide/missing-internet-explorer-maintenance-settings-for-ie11#:~:text=The%20Internet%20Explorer%20Maintenance%20(IEM,Internet%20Explorer%2010%20or%20newer.
|
|
$SuggestedAction = 'GPO requires cleanup'
|
|
$SuggestedActionComment = 'Internet Explorer Maintenance (IEM) is deprecated for IE 11'
|
|
}
|
|
}
|
|
} else {
|
|
<#
|
|
$FullPathAdmFiles = [System.IO.Path]::Combine($GPO.Path, 'Adm\admfiles.ini')
|
|
if ($_.FullName -in $Correct) {
|
|
$SuggestedAction = 'Consider deleting'
|
|
$SuggestedActionComment = 'Most likely orphaned SYSVOL GPO'
|
|
} elseif ($_.Extension -eq '.adm') {
|
|
$SuggestedAction = 'Consider deleting'
|
|
$SuggestedActionComment = 'Most likely orphaned SYSVOL GPO (legacy ADM files)'
|
|
} elseif ($_.FullName -eq $FullPathAdmFiles) {
|
|
$SuggestedAction = 'Consider deleting'
|
|
$SuggestedActionComment = 'Most likely orphaned SYSVOL GPO (legacy ADM files)'
|
|
}
|
|
#>
|
|
$SuggestedAction = 'Consider deleting'
|
|
$SuggestedActionComment = 'Most likely orphaned SYSVOL GPO'
|
|
}
|
|
} elseif ($FileType.Name -eq 'NETLOGON Scripts') {
|
|
foreach ($Ext in @('*old*', '*bak*', '*bck', '.new')) {
|
|
if ($_.Extension -like $Ext) {
|
|
$SuggestedAction = 'Consider deleting'
|
|
$SuggestedActionComment = 'Most likely backup files'
|
|
break
|
|
}
|
|
}
|
|
if (-not $SuggestedAction) {
|
|
# We didn't find it in earlier check, lets go deeper
|
|
if ($_.Extension.Length -gt 6 -and $_.Extension -notin @('.config', '.sites', '.ipsec')) {
|
|
$SuggestedAction = 'Consider deleting'
|
|
$SuggestedActionComment = 'Extension longer then 5 chars'
|
|
} elseif ($_.Extension -eq '') {
|
|
$SuggestedAction = 'Consider deleting'
|
|
$SuggestedActionComment = 'No extension'
|
|
}
|
|
}
|
|
if (-not $SuggestedAction) {
|
|
foreach ($Name in @('*old*', '*bak*', '*bck*', '*Copy', '*backup*')) {
|
|
if ($_.BaseName -like $Name) {
|
|
$SuggestedAction = 'Consider deleting'
|
|
$SuggestedActionComment = "FileName contains backup related names ($Name)"
|
|
break
|
|
}
|
|
}
|
|
}
|
|
if (-not $SuggestedAction) {
|
|
if ($_.Name -eq 'Thumbs.db') {
|
|
$SuggestedAction = 'Consider deleting'
|
|
$SuggestedActionComment = 'Most likely database files to store image thumbnails on Windows systems.'
|
|
}
|
|
}
|
|
if (-not $SuggestedAction) {
|
|
foreach ($FullName in @('*backup*', '*Delete*', '*Obsoleet*', '*Obsolete*', '*Archive*')) {
|
|
if ($_.FullName -like $FullName) {
|
|
$SuggestedAction = 'Consider deleting'
|
|
$SuggestedActionComment = "Fullname contains backup related names ($FullName)"
|
|
break
|
|
}
|
|
}
|
|
}
|
|
if (-not $SuggestedAction) {
|
|
# We replace all letters leaving only numbers
|
|
# We want to find if there is a date possibly
|
|
$StrippedNumbers = $_.Name -replace "[^0-9]" , ''
|
|
if ($StrippedNumbers.Length -gt 5) {
|
|
$SuggestedAction = 'Consider deleting'
|
|
$SuggestedActionComment = 'FileName contains over 5 numbers (date?)'
|
|
}
|
|
}
|
|
} elseif ($FileType.Name -eq 'SYSVOL PolicyDefinitions') {
|
|
if ($_.Extension -in @('.admx', '.adml')) {
|
|
$SuggestedAction = 'Skip assesment'
|
|
$SuggestedActionComment = 'Most likely ADMX templates'
|
|
}
|
|
} elseif ($FileType.Name -eq 'SYSVOL GPO Starters') {
|
|
$FoundGUID = $_.FullName -match '[\da-zA-Z]{8}-([\da-zA-Z]{4}-){3}[\da-zA-Z]{12}'
|
|
if ($FoundGUID) {
|
|
$GUID = $matches[0]
|
|
$TemporaryStarterPath = "\\$Domain\SYSVOL\$Domain\StarterGPOs\{$GUID}"
|
|
$Correct = @(
|
|
[System.IO.Path]::Combine($TemporaryStarterPath, 'StarterGPO.tmplx')
|
|
[System.IO.Path]::Combine($TemporaryStarterPath, 'en-US', 'StarterGPO.tmpll')
|
|
foreach ($TypeM in @('Machine', 'User')) {
|
|
[System.IO.Path]::Combine($TemporaryStarterPath, $TypeM, 'Registry.pol')
|
|
[System.IO.Path]::Combine($TemporaryStarterPath, $TypeM, 'comment.cmtx')
|
|
}
|
|
)
|
|
if ($_.FullName -in $Correct) {
|
|
$SuggestedAction = 'Skip assesment'
|
|
$SuggestedActionComment = 'Correctly placed in SYSVOL'
|
|
}
|
|
}
|
|
} else {
|
|
|
|
}
|
|
if (-not $SuggestedAction) {
|
|
$SuggestedAction = 'Requires verification'
|
|
$SuggestedActionComment = 'Not able to auto asses'
|
|
}
|
|
if (-not $ExtendedMetaData) {
|
|
$MetaData = [ordered] @{
|
|
LocationType = $FileType.Name
|
|
FullName = $_.FullName
|
|
#Name = $_.Name
|
|
Extension = $_.Extension
|
|
SuggestedAction = $SuggestedAction
|
|
SuggestedActionComment = $SuggestedActionComment
|
|
BelongsToGPO = $BelongsToGPO
|
|
GPODisplayName = $GPODisplayName
|
|
SizeMB = [math]::Round(($_.Length / 1MB), 2)
|
|
Size = $_.Length
|
|
Attributes = $_.Attributes
|
|
CreationTime = $_.CreationTime
|
|
LastAccessTime = $_.LastAccessTime
|
|
LastWriteTime = $_.LastWriteTime
|
|
}
|
|
} else {
|
|
$MetaData = Get-FileMetaData -File $_ -AsHashTable
|
|
$MetaData['SuggestedAction'] = $SuggestedAction
|
|
$MetaData['SuggestedActionComment'] = $SuggestedActionComment
|
|
$MetaData['BelongsToGPO'] = $BelongsToGPO
|
|
$MetaData['GPODisplayName'] = $GPODisplayName
|
|
$MetaData['SizeMB'] = [math]::Round(($_.Length / 1MB), 2)
|
|
$MetaData['Size'] = $_.Length
|
|
}
|
|
if ($Signature) {
|
|
try {
|
|
$DigitalSignature = Get-AuthenticodeSignature -FilePath $_.Fullname -ErrorAction Stop
|
|
} catch {
|
|
Write-Warning "Get-GPOZaurrFiles - Error when reading signature: $($_.Exception.Message)"
|
|
}
|
|
if ($DigitalSignature) {
|
|
$MetaData['SignatureStatus'] = $DigitalSignature.Status
|
|
$MetaData['IsOSBinary'] = $DigitalSignature.IsOSBinary
|
|
$MetaData['SignatureCertificateSubject'] = $DigitalSignature.SignerCertificate.Subject
|
|
if ($Extended) {
|
|
$MetaData['SignatureCertificateIssuer'] = $DigitalSignature.SignerCertificate.Issuer
|
|
$MetaData['SignatureCertificateSerialNumber'] = $DigitalSignature.SignerCertificate.SerialNumber
|
|
$MetaData['SignatureCertificateNotBefore'] = $DigitalSignature.SignerCertificate.NotBefore
|
|
$MetaData['SignatureCertificateNotAfter'] = $DigitalSignature.SignerCertificate.NotAfter
|
|
$MetaData['SignatureCertificateThumbprint'] = $DigitalSignature.SignerCertificate.Thumbprint
|
|
}
|
|
} else {
|
|
$MetaData['SignatureStatus'] = 'Not available'
|
|
$MetaData['IsOSBinary'] = $null
|
|
$MetaData['SignatureCertificateSubject'] = $null
|
|
if ($Extended) {
|
|
$MetaData['SignatureCertificateIssuer'] = $null
|
|
$MetaData['SignatureCertificateSerialNumber'] = $null
|
|
$MetaData['SignatureCertificateNotBefore'] = $null
|
|
$MetaData['SignatureCertificateNotAfter'] = $null
|
|
$MetaData['SignatureCertificateThumbprint'] = $null
|
|
}
|
|
}
|
|
}
|
|
if ($HashAlgorithm -ne 'None') {
|
|
$MetaData['ChecksumSHA256'] = (Get-FileHash -LiteralPath $_.FullName -Algorithm $HashAlgorithm).Hash
|
|
}
|
|
if ($AsHashTable) {
|
|
$MetaData
|
|
} else {
|
|
[PSCustomObject] $MetaData
|
|
}
|
|
}
|
|
foreach ($e in $err) {
|
|
Write-Warning "Get-GPOZaurrFiles - $($e.Exception.Message) ($($e.CategoryInfo.Reason))"
|
|
}
|
|
}
|
|
} |