Param ( [switch]$Decrypt ) # Find-GPOPasswords.ps1 # This script is for educational purposes only and is not to be used in a production environment. # #Function that decodes and decrypts password # From http://obscuresecurity.blogspot.com/2013/07/get-gpppassword.html function Get-DecryptedCpassword { Param ( [string] $Cpassword ) try { #Append appropriate padding based on string length $Mod = ($Cpassword.length % 4) if ($Mod -ne 0) {$Cpassword += ('=' * (4 - $Mod))} $Base64Decoded = [Convert]::FromBase64String($Cpassword) #Create a new AES .NET Crypto Object $AesObject = New-Object System.Security.Cryptography.AesCryptoServiceProvider [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) #Set IV to all nulls to prevent dynamic generation of IV value $AesIV = New-Object Byte[]($AesObject.IV.Length) $AesObject.IV = $AesIV $AesObject.Key = $AesKey $DecryptorObject = $AesObject.CreateDecryptor() [Byte[]] $OutBlock = $DecryptorObject.TransformFinalBlock($Base64Decoded, 0, $Base64Decoded.length) return [System.Text.UnicodeEncoding]::Unicode.GetString($OutBlock) } catch {Write-Error $Error[0]} } $DomainDNS = [System.DirectoryServices.ActiveDirectory.Domain]::GetComputerDomain().Name #Get AD Domain (lightweight & fast method) $TimeVal = get-date -uformat "%Y-%m-%d-%H-%M" $LogDir = "C:\temp\Logs\" #Standard location for script logs IF (!(Test-Path $LogDir)) {new-item -type Directory -path $LogDir} import-module ActiveDirectory import-module grouppolicy get-help get-gpo -full $ADForestInfo = Get-ADForest $ADForestInfoDomains = $ADForestInfo.Domains ForEach ($DomainDNS in $ADForestInfoDomains) { ## OPEN ForEach ($DomainDNS in $ADForestInfoDomains) #$DomainDNS = "child.domain.com" $GPPDataReportFileName = "GPPDataReport-$DomainDNS-$TimeVal.csv" $GPPDataReportFile = $LogDir + $GPPDataReportFileName # Discover GPO XML Files $DomainGPOLocation = "\\$DomainDNS\SYSVOL\$DomainDNS\Policies" Write-Output "Scanning $DomainDNS for Group Policy Preference XML Files... `r " [array]$GPPXMLFiles = Get-ChildItem $DomainGPOLocation -Recurse -Force | Where { $_.Name -like "*.xml" } | Foreach-Object -process { $_.FullName } [int]$GPPXMLFilesCount = $GPPXMLFiles.Count Write-Output "Discovered $GPPXMLFilesCount Group Policy Preference XML Files in $DomainDNS `r " # Parse GPO XML Files for Passwords IF ($AllGPPData) { Clear-Variable AllGPPData } IF ($GPPPwdFiles) { Clear-Variable GPPPwdFiles } $AllGPPData = New-Object -TypeName PSObject IF ($GPPXMLFilesCount -ge 1) { ## OPEN IF ($GPPXMLFilesCount -ge 1) Write-Output "Checking GPP XML Files for encrypted passwords `r " ForEach ($GPPXMLFilesItem in $GPPXMLFiles) { ## OPEN ForEach ($GPPXMLFilesItem in $GPPXMLFiles) IF ($GPODisplayName) { Clear-Variable GPODisplayName } IF ($Type) { Clear-Variable Type } IF ($UserID) { Clear-Variable UserID } IF ($cPassword) { Clear-Variable cPassword } IF ($DriveLetter) { Clear-Variable DriveLetter } IF ($ServerSharePath) { Clear-Variable ServerSharePath } IF ($DataSourceName) { Clear-Variable DataSourceName } IF ($ServiceName) { Clear-Variable ServiceName } IF ($Password) { Clear-Variable Password } [string]$GPPXMLFileContent = Get-Content $GPPXMLFilesItem IF ($GPPXMLFileContent -like "*cpassword*") { ## OPEN IF ($Filecontent -like "*cpassword*") Write-Verbose "Encrypted password field discovered in GPO $GPODisplayName ($GPPXMLFilesItem) `r " $PolicyGUID1 = $GPPXMLFilesItem -split("{") $PolicyGUID2 = $PolicyGUID1 -split("}") $PolicyGUID = $PolicyGUID2[1] $GPOInfo = Get-GPO -GUID $PolicyGUID -Domain $DomainDNS $GPODisplayName = $GPOInfo.DisplayName [xml]$GPPXMLFileContentXML = Get-Content $GPPXMLFilesItem IF ($GPPXMLFileContentXML.ScheduledTasks.Task) { ## OPEN IF ($GPPXMLFileContentXML.ScheduledTasks.Task) $Type = 'ScheduledTask' $UserID = $GPPXMLFileContentXML.ScheduledTasks.Task.Properties.RunAs $cPassword = $GPPXMLFileContentXML.ScheduledTasks.Task.Properties.cPassword } ## CLOSE IF ($GPPXMLFileContentXML.ScheduledTasks.Task) IF ($GPPXMLFileContentXML.ScheduledTasks.TaskV2) { ## OPEN IF ($GPPXMLFileContentXML.ScheduledTasks.TaskV2) $Type = 'ScheduledTask' $UserID = $GPPXMLFileContentXML.ScheduledTasks.TaskV2.Properties.RunAs $cPassword = $GPPXMLFileContentXML.ScheduledTasks.TaskV2.Properties.cPassword } ## CLOSE IF ($GPPXMLFileContentXML.ScheduledTasks.TaskV2) IF ($GPPXMLFileContentXML.NTServices) { ## OPEN IF ($GPPXMLFileContentXML.Services) $Type = 'Services' $ServiceName = $GPPXMLFileContentXML.NTServices.NTService.Name $UserID = $GPPXMLFileContentXML.NTServices.NTService.Properties.accountName $cPassword = $GPPXMLFileContentXML.NTServices.NTService.Properties.cPassword } ## CLOSE IF ($GPPXMLFileContentXML.Services) IF ($GPPXMLFileContentXML.Groups) { ## OPEN IF ($GPPXMLFileContentXML.Groups) $Type = 'Groups' $GPPXMLUsers = $GPPXMLFileContentXML.Groups.User ForEach ($GPPXMLUsersItem in $GPPXMLUsers) { ## OPEN ForEach ($GPPXMLUsersItem in $GPPXMLUsers) $UserID = $GPPXMLUsersItem.Name $cPassword = $GPPXMLUsersItem.Properties.cPassword } ## CLOSE ForEach ($GPPXMLUsersItem in $GPPXMLUsers) } ## CLOSE IF ($GPPXMLFileContentXML.Groups) IF ($GPPXMLFileContentXML.DataSources) { ## OPEN IF ($GPPXMLFileContentXML.DataSources) $Type = 'DataSources' $DataSourceName = $GPPXMLFileContentXML.DataSources.DataSource.Name $UserID = $GPPXMLFileContentXML.DataSources.DataSource.Properties.userName $cPassword = $GPPXMLFileContentXML.DataSources.DataSource.Properties.cPassword } ## CLOSE IF ($GPPXMLFileContentXML.DataSources) IF ($GPPXMLFileContentXML.Drives) { ## OPEN IF ($GPPXMLFileContentXML.Drives) $Type = 'Drives' $DriveLetter = $GPPXMLFileContentXML.Drives.Drive.Name $ServerSharePath = $GPPXMLFileContentXML.Drives.Drive.Properties.Path $UserID = $GPPXMLFileContentXML.Drives.Drive.Properties.userName $cPassword = $GPPXMLFileContentXML.Drives.Drive.Properties.cPassword } ## CLOSE IF ($GPPXMLFileContentXML.Drives) $GPPData = New-Object -TypeName PSObject $GPPData | Add-Member -MemberType NoteProperty -Name GPOName -Value $GPODisplayName $GPPData | Add-Member -MemberType NoteProperty -Name Type -Value $Type $GPPData | Add-Member -MemberType NoteProperty -Name UserID -Value $UserID $GPPData | Add-Member -MemberType NoteProperty -Name EncryptedPassword -Value $cPassword IF ($Decrypt -eq $True){ IF ($cPassword) { $Password = Get-DecryptedCpassword $Cpassword ; $GPPData | Add-Member -MemberType NoteProperty -Name Password -Value $Password } } $GPPData | Add-Member -MemberType NoteProperty -Name DriveLetter -Value $DriveLetter $GPPData | Add-Member -MemberType NoteProperty -Name ServerSharePath -Value $ServerSharePath $GPPData | Add-Member -MemberType NoteProperty -Name DataSourceName -Value $DataSourceName $GPPData | Add-Member -MemberType NoteProperty -Name ServiceName -Value $ServiceName $GPPData | Add-Member -MemberType NoteProperty -Name GPOXMLFile -Value $GPPXMLFilesItem [array]$AllGPPData += $GPPData } ## CLOSE IF ($Filecontent -like "*cpassword*") ELSE { Write-Verbose "No encrypted password found in GPO $GPODisplayName ($GPPXMLFilesItem)`r " } } ## CLOSE ForEach ($GPPXMLFilesItem in $GPPXMLFiles) [int]$GPPPwdFilesCount = $GPPPwdFiles.Count Write-Output "$GPPPwdFilesCount out of $GPPXMLFilesCount Group Policy Preference XML Files contain an encrypted password in $DomainDNS `r " $AllGPPData | Select GPOName,UserID,EncryptedPassword,Password | Format-Table -AutoSize Write-Output "Saving report data to: $GPPDataReportFile `r " $AllGPPData | Select GPOName,UserID,EncryptedPassword,Password,DriveLetter,ServerSharePath,DataSourceName,ServiceName,GPOXMLFile | Export-CSV $GPPDataReportFile -NoTypeInformation } ## CLOSE IF ($GPPXMLFilesCount -ge 1) ELSE { Write-Output "There were no XML files found in $DomainDNS `r " } } ## CLOSE ForEach ($DomainDNS in $ADForestInfoDomains)