Files
GPOZaurr/Public/Get-GPOZaurrFiles.ps1
T
Przemyslaw Klys 7b4d31781c Add size
2024-10-17 19:34:45 +02:00

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))"
}
}
}