diff --git a/Examples/Example-40-ShowGPO01.ps1 b/Examples/Example-40-ShowGPO01.ps1 index 0848b61..c2aa181 100644 --- a/Examples/Example-40-ShowGPO01.ps1 +++ b/Examples/Example-40-ShowGPO01.ps1 @@ -1,3 +1,3 @@ Import-Module "$PSScriptRoot\..\GPoZaurr.psd1" -Force -Invoke-GPOZaurr -FilePath $PSScriptRoot\Reports\GPOZaurr.html \ No newline at end of file +Invoke-GPOZaurr -FilePath $PSScriptRoot\Reports\GPOZaurr.html -Type GPOPassword \ No newline at end of file diff --git a/Examples/Example-42-FindPassword.ps1 b/Examples/Example-42-FindPassword.ps1 new file mode 100644 index 0000000..1cf0274 --- /dev/null +++ b/Examples/Example-42-FindPassword.ps1 @@ -0,0 +1,3 @@ +Import-Module "$PSScriptRoot\..\GPoZaurr.psd1" -Force + +Get-GPOZaurrPassword -GPOPath 'C:\Users\przemyslaw.klys\Desktop\GPOExport_2020.10.12' diff --git a/GPOZaurr.psd1 b/GPOZaurr.psd1 index f9e2866..6ad49cc 100644 --- a/GPOZaurr.psd1 +++ b/GPOZaurr.psd1 @@ -8,7 +8,7 @@ Description = 'Group Policy Eater is a PowerShell module that aims to gather information about Group Policies but also allows fixing issues that you may find in them.' FunctionsToExport = @('Add-GPOPermission', 'Add-GPOZaurrPermission', 'Backup-GPOZaurr', 'Clear-GPOZaurrSysvolDFSR', 'ConvertFrom-CSExtension', 'Find-CSExtension', 'Get-GPOZaurr', 'Get-GPOZaurrAD', 'Get-GPOZaurrBackupInformation', 'Get-GPOZaurrBroken', 'Get-GPOZaurrDictionary', 'Get-GPOZaurrDuplicateObject', 'Get-GPOZaurrFiles', 'Get-GPOZaurrFilesPolicyDefinition', 'Get-GPOZaurrFolders', 'Get-GPOZaurrInheritance', 'Get-GPOZaurrLegacyFiles', 'Get-GPOZaurrLink', 'Get-GPOZaurrLinkSummary', 'Get-GPOZaurrNetLogon', 'Get-GPOZaurrOwner', 'Get-GPOZaurrPassword', 'Get-GPOZaurrPermission', 'Get-GPOZaurrPermissionConsistency', 'Get-GPOZaurrPermissionRoot', 'Get-GPOZaurrPermissionSummary', 'Get-GPOZaurrSysvolDFSR', 'Get-GPOZaurrWMI', 'Invoke-GPOZaurr', 'Invoke-GPOZaurrContent', 'Invoke-GPOZaurrPermission', 'Invoke-GPOZaurrSupport', 'New-GPOZaurrWMI', 'Remove-GPOPermission', 'Remove-GPOZaurr', 'Remove-GPOZaurrBroken', 'Remove-GPOZaurrDuplicateObject', 'Remove-GPOZaurrFolders', 'Remove-GPOZaurrLegacyFiles', 'Remove-GPOZaurrPermission', 'Remove-GPOZaurrWMI', 'Repair-GPOZaurrNetLogonOwner', 'Repair-GPOZaurrPermissionConsistency', 'Restore-GPOZaurr', 'Save-GPOZaurrFiles', 'Set-GPOOwner', 'Set-GPOZaurrOwner') GUID = 'f7d4c9e4-0298-4f51-ad77-e8e3febebbde' - ModuleVersion = '0.0.72' + ModuleVersion = '0.0.73' PowerShellVersion = '5.1' PrivateData = @{ PSData = @{ diff --git a/Private/Find-GPOPassword.ps1 b/Private/Find-GPOPassword.ps1 new file mode 100644 index 0000000..a4cb9ab --- /dev/null +++ b/Private/Find-GPOPassword.ps1 @@ -0,0 +1,37 @@ +function Find-GPOPassword { + [cmdletBinding()] + param( + [string] $Path + ) + #Convert XML in a String file + [string]$XMLString = Get-Content -LiteralPath $Path + #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 = '' + } + } + $Password +} \ No newline at end of file diff --git a/Public/Get-GPOZaurrPassword.ps1 b/Public/Get-GPOZaurrPassword.ps1 index 3e1902e..c592d34 100644 --- a/Public/Get-GPOZaurrPassword.ps1 +++ b/Public/Get-GPOZaurrPassword.ps1 @@ -1,4 +1,35 @@ function Get-GPOZaurrPassword { + <# + .SYNOPSIS + Tries to find CPassword in Group Policies or given path and translate it to readable value + + .DESCRIPTION + Tries to find CPassword in Group Policies or given path and translate it to readable value + + .PARAMETER Forest + Specify forest name. By default current forest is used + + .PARAMETER ExcludeDomains + Exclude Domain or Domains + + .PARAMETER IncludeDomains + Include only certain Domain or Domains + + .PARAMETER ExtendedForestInformation + Ability to provide extended forest information in advanced scenarios + + .PARAMETER GPOPath + Path where Group Policy content is located or where backup is located + + .EXAMPLE + Get-GPOZaurrPassword -GPOPath 'C:\Users\przemyslaw.klys\Desktop\GPOExport_2020.10.12' + + .EXAMPLE + Get-GPOZaurrPassword + + .NOTES + General notes + #> [cmdletBinding()] param( [alias('ForestName')][string] $Forest, @@ -7,115 +38,65 @@ [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 ($GPOPath) { + foreach ($Path in $GPOPath) { + $Items = Get-ChildItem -LiteralPath $Path -Recurse -Filter *.xml -ErrorAction SilentlyContinue -ErrorVariable err + $Output = foreach ($XMLFileName in $Items) { + $Password = Find-GPOPassword -Path $XMLFileName.FullName if ($Password) { - $PasswordStatus = $true - } else { - $PasswordStatus = $false + if ($XMLFileName.FullName -match '{\w{8}-\w{4}-\w{4}-\w{4}-\w{12}}') { + $GPOGUID = $matches[0] + } + [PSCustomObject] @{ + RootPath = $Path + PasswordFile = $XMLFileName.FullName + GUID = $GPOGUID + Password = $Password + } } - - [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 { + } + } + } else { + $ForestInformation = Get-WinADForestDetails -Forest $Forest -IncludeDomains $IncludeDomains -ExcludeDomains $ExcludeDomains -ExtendedForestInformation $ExtendedForestInformation + foreach ($Domain in $ForestInformation.Domains) { + $Path = -join ('\\', $Domain, '\SYSVOL\', $Domain, '\Policies') + #Extract the all XML files in the Folder + $Items = Get-ChildItem -LiteralPath $Path -Recurse -Filter *.xml -ErrorAction SilentlyContinue -ErrorVariable err + $Output = foreach ($XMLFileName in $Items) { + $Password = Find-GPOPassword -Path $XMLFileName.FullName + if ($Password) { + # match regex + if ($XMLFileName.FullName -match '{\w{8}-\w{4}-\w{4}-\w{4}-\w{12}}') { + $GPOGUID = $matches[0] + $GPO = Get-GPOZaurrAD -GPOGuid $GPOGUID -IncludeDomains $Domain [PSCustomObject] @{ - 'User' = $_.trustee.name.'#Text' - 'Permission Type' = $_.type.PermissionType - 'Inherited' = $_.Inherited - 'Permissions' = $_.Standard.GPOGroupedAccessEnum + DisplayName = $GPO.DisplayName + DomainName = $GPO.DomainName + GUID = $GPO.GUID + PasswordFile = $XMLFileName.FullName + Password = $Password + Created = $GPO.Created + Modified = $GPO.Modified + Description = $GPO.Description + } + } else { + [PSCustomObject] @{ + DisplayName = '' + DomainName = '' + GUID = '' + PasswordFile = $XMLFileName.FullName + Password = $Password + Created = '' + Modified = '' + Description = '' } } - } - #Write-Host "I find a Password [ " $Password " ] The GPO named:" $GPODetail" and th file is:" $XMLFileName - - } #if($XMLContent.Contains("cpassword") + } + foreach ($e in $err) { + Write-Warning "Get-GPOZaurrPassword - $($e.Exception.Message) ($($e.CategoryInfo.Reason))" + } + $Output } - $Output } } \ No newline at end of file