aboutsummaryrefslogtreecommitdiff
path: root/Recon
diff options
context:
space:
mode:
Diffstat (limited to 'Recon')
-rw-r--r--Recon/PowerView.ps1608
1 files changed, 496 insertions, 112 deletions
diff --git a/Recon/PowerView.ps1 b/Recon/PowerView.ps1
index d95443f..c6ce1d2 100644
--- a/Recon/PowerView.ps1
+++ b/Recon/PowerView.ps1
@@ -749,7 +749,7 @@ filter Export-PowerViewCSV {
if (Test-Path -Path $OutFile) {
# hack to skip the first line of output if the file already exists
- $ObjectCSV | Foreach-Object { $Start=$True }{ if ($Start) {$Start=$False} else {$_} } | Out-File -Encoding 'ASCII' -Append -FilePath $OutFile
+ $ObjectCSV | ForEach-Object { $Start=$True }{ if ($Start) {$Start=$False} else {$_} } | Out-File -Encoding 'ASCII' -Append -FilePath $OutFile
}
else {
$ObjectCSV | Out-File -Encoding 'ASCII' -Append -FilePath $OutFile
@@ -2857,7 +2857,7 @@ function Get-ObjectAcl {
}
try {
- $Searcher.FindAll() | Where-Object {$_} | Foreach-Object {
+ $Searcher.FindAll() | Where-Object {$_} | ForEach-Object {
$Object = [adsi]($_.path)
if($Object.distinguishedname) {
@@ -2888,7 +2888,7 @@ function Get-ObjectAcl {
else {
$_
}
- } | Foreach-Object {
+ } | ForEach-Object {
if($GUIDs) {
# if we're resolving GUIDs, map them them to the resolved hash table
$AclProperties = @{}
@@ -3080,7 +3080,7 @@ function Add-ObjectAcl {
}
try {
- $Searcher.FindAll() | Where-Object {$_} | Foreach-Object {
+ $Searcher.FindAll() | Where-Object {$_} | ForEach-Object {
# adapted from 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
$TargetDN = $_.Properties.distinguishedname
@@ -4659,7 +4659,7 @@ function Get-NetGroup {
# cause the cache to calculate the token groups for the user
$UserDirectoryEntry.RefreshCache("tokenGroups")
- $UserDirectoryEntry.TokenGroups | Foreach-Object {
+ $UserDirectoryEntry.TokenGroups | ForEach-Object {
# convert the token group sid
$GroupSid = (New-Object System.Security.Principal.SecurityIdentifier($_,0)).Value
@@ -5085,7 +5085,7 @@ function Get-NetFileServer {
$TargetUsers -Match $_.samAccountName
}
else { $True }
- } | Foreach-Object {
+ } | ForEach-Object {
# split out every potential file server path
if($_.homedirectory) {
SplitPath($_.homedirectory)
@@ -5138,13 +5138,13 @@ function Get-DFSshare {
.EXAMPLE
PS C:\> Get-DFSshare
-
+
Returns all distributed file system shares for the current domain.
.EXAMPLE
PS C:\> Get-DFSshare -Domain test
-
+
Returns all distributed file system shares for the 'test' domain.
#>
@@ -5171,6 +5171,185 @@ function Get-DFSshare {
$Credential
)
+ function Parse-Pkt {
+ [CmdletBinding()]
+ param(
+ [byte[]]
+ $Pkt
+ )
+
+ $bin = $Pkt
+ $blob_version = [bitconverter]::ToUInt32($bin[0..3],0)
+ $blob_element_count = [bitconverter]::ToUInt32($bin[4..7],0)
+ #Write-Host "Element Count: " $blob_element_count
+ $offset = 8
+ #https://msdn.microsoft.com/en-us/library/cc227147.aspx
+ $object_list = @()
+ for($i=1; $i -le $blob_element_count; $i++){
+ $blob_name_size_start = $offset
+ $blob_name_size_end = $offset + 1
+ $blob_name_size = [bitconverter]::ToUInt16($bin[$blob_name_size_start..$blob_name_size_end],0)
+ #Write-Host "Blob name size: " $blob_name_size
+ $blob_name_start = $blob_name_size_end + 1
+ $blob_name_end = $blob_name_start + $blob_name_size - 1
+ $blob_name = [System.Text.Encoding]::Unicode.GetString($bin[$blob_name_start..$blob_name_end])
+ #Write-Host "Blob Name: " $blob_name
+ $blob_data_size_start = $blob_name_end + 1
+ $blob_data_size_end = $blob_data_size_start + 3
+ $blob_data_size = [bitconverter]::ToUInt32($bin[$blob_data_size_start..$blob_data_size_end],0)
+ #Write-Host "blob data size: " $blob_data_size
+ $blob_data_start = $blob_data_size_end + 1
+ $blob_data_end = $blob_data_start + $blob_data_size - 1
+ $blob_data = $bin[$blob_data_start..$blob_data_end]
+ switch -wildcard ($blob_name) {
+ "\siteroot" { }
+ "\domainroot*" {
+ # Parse DFSNamespaceRootOrLinkBlob object. Starts with variable length DFSRootOrLinkIDBlob which we parse first...
+ # DFSRootOrLinkIDBlob
+ $root_or_link_guid_start = 0
+ $root_or_link_guid_end = 15
+ $root_or_link_guid = [byte[]]$blob_data[$root_or_link_guid_start..$root_or_link_guid_end]
+ $guid = New-Object Guid(,$root_or_link_guid) # should match $guid_str
+ $prefix_size_start = $root_or_link_guid_end + 1
+ $prefix_size_end = $prefix_size_start + 1
+ $prefix_size = [bitconverter]::ToUInt16($blob_data[$prefix_size_start..$prefix_size_end],0)
+ $prefix_start = $prefix_size_end + 1
+ $prefix_end = $prefix_start + $prefix_size - 1
+ $prefix = [System.Text.Encoding]::Unicode.GetString($blob_data[$prefix_start..$prefix_end])
+ #write-host "Prefix: " $prefix
+ $short_prefix_size_start = $prefix_end + 1
+ $short_prefix_size_end = $short_prefix_size_start + 1
+ $short_prefix_size = [bitconverter]::ToUInt16($blob_data[$short_prefix_size_start..$short_prefix_size_end],0)
+ $short_prefix_start = $short_prefix_size_end + 1
+ $short_prefix_end = $short_prefix_start + $short_prefix_size - 1
+ $short_prefix = [System.Text.Encoding]::Unicode.GetString($blob_data[$short_prefix_start..$short_prefix_end])
+ #write-host "Short Prefix: " $short_prefix
+ $type_start = $short_prefix_end + 1
+ $type_end = $type_start + 3
+ $type = [bitconverter]::ToUInt32($blob_data[$type_start..$type_end],0)
+ #write-host $type
+ $state_start = $type_end + 1
+ $state_end = $state_start + 3
+ $state = [bitconverter]::ToUInt32($blob_data[$state_start..$state_end],0)
+ #write-host $state
+ $comment_size_start = $state_end + 1
+ $comment_size_end = $comment_size_start + 1
+ $comment_size = [bitconverter]::ToUInt16($blob_data[$comment_size_start..$comment_size_end],0)
+ $comment_start = $comment_size_end + 1
+ $comment_end = $comment_start + $comment_size - 1
+ if ($comment_size -gt 0) {
+ $comment = [System.Text.Encoding]::Unicode.GetString($blob_data[$comment_start..$comment_end])
+ #Write-Host $comment
+ }
+ $prefix_timestamp_start = $comment_end + 1
+ $prefix_timestamp_end = $prefix_timestamp_start + 7
+ # https://msdn.microsoft.com/en-us/library/cc230324.aspx FILETIME
+ $prefix_timestamp = $blob_data[$prefix_timestamp_start..$prefix_timestamp_end] #dword lowDateTime #dword highdatetime
+ $state_timestamp_start = $prefix_timestamp_end + 1
+ $state_timestamp_end = $state_timestamp_start + 7
+ $state_timestamp = $blob_data[$state_timestamp_start..$state_timestamp_end]
+ $comment_timestamp_start = $state_timestamp_end + 1
+ $comment_timestamp_end = $comment_timestamp_start + 7
+ $comment_timestamp = $blob_data[$comment_timestamp_start..$comment_timestamp_end]
+ $version_start = $comment_timestamp_end + 1
+ $version_end = $version_start + 3
+ $version = [bitconverter]::ToUInt32($blob_data[$version_start..$version_end],0)
+
+ #write-host $version
+ if ($version -ne 3)
+ {
+ #write-host "error"
+ }
+
+ # Parse rest of DFSNamespaceRootOrLinkBlob here
+ $dfs_targetlist_blob_size_start = $version_end + 1
+ $dfs_targetlist_blob_size_end = $dfs_targetlist_blob_size_start + 3
+ $dfs_targetlist_blob_size = [bitconverter]::ToUInt32($blob_data[$dfs_targetlist_blob_size_start..$dfs_targetlist_blob_size_end],0)
+ #write-host $dfs_targetlist_blob_size
+ $dfs_targetlist_blob_start = $dfs_targetlist_blob_size_end + 1
+ $dfs_targetlist_blob_end = $dfs_targetlist_blob_start + $dfs_targetlist_blob_size - 1
+ $dfs_targetlist_blob = $blob_data[$dfs_targetlist_blob_start..$dfs_targetlist_blob_end]
+ $reserved_blob_size_start = $dfs_targetlist_blob_end + 1
+ $reserved_blob_size_end = $reserved_blob_size_start + 3
+ $reserved_blob_size = [bitconverter]::ToUInt32($blob_data[$reserved_blob_size_start..$reserved_blob_size_end],0)
+ #write-host $reserved_blob_size
+ $reserved_blob_start = $reserved_blob_size_end + 1
+ $reserved_blob_end = $reserved_blob_start + $reserved_blob_size - 1
+ $reserved_blob = $blob_data[$reserved_blob_start..$reserved_blob_end]
+ $referral_ttl_start = $reserved_blob_end + 1
+ $referral_ttl_end = $referral_ttl_start + 3
+ $referral_ttl = [bitconverter]::ToUInt32($blob_data[$referral_ttl_start..$referral_ttl_end],0)
+
+ #Parse DFSTargetListBlob
+ $target_count_start = 0
+ $target_count_end = $target_count_start + 3
+ $target_count = [bitconverter]::ToUInt32($dfs_targetlist_blob[$target_count_start..$target_count_end],0)
+ $t_offset = $target_count_end + 1
+ #write-host $target_count
+
+ for($j=1; $j -le $target_count; $j++){
+ $target_entry_size_start = $t_offset
+ $target_entry_size_end = $target_entry_size_start + 3
+ $target_entry_size = [bitconverter]::ToUInt32($dfs_targetlist_blob[$target_entry_size_start..$target_entry_size_end],0)
+ #write-host $target_entry_size
+ $target_time_stamp_start = $target_entry_size_end + 1
+ $target_time_stamp_end = $target_time_stamp_start + 7
+ # FILETIME again or special if priority rank and priority class 0
+ $target_time_stamp = $dfs_targetlist_blob[$target_time_stamp_start..$target_time_stamp_end]
+ $target_state_start = $target_time_stamp_end + 1
+ $target_state_end = $target_state_start + 3
+ $target_state = [bitconverter]::ToUInt32($dfs_targetlist_blob[$target_state_start..$target_state_end],0)
+ #write-host $target_state
+ $target_type_start = $target_state_end + 1
+ $target_type_end = $target_type_start + 3
+ $target_type = [bitconverter]::ToUInt32($dfs_targetlist_blob[$target_type_start..$target_type_end],0)
+ #write-host $target_type
+ $server_name_size_start = $target_type_end + 1
+ $server_name_size_end = $server_name_size_start + 1
+ $server_name_size = [bitconverter]::ToUInt16($dfs_targetlist_blob[$server_name_size_start..$server_name_size_end],0)
+ #write-host $server_name_size
+ $server_name_start = $server_name_size_end + 1
+ $server_name_end = $server_name_start + $server_name_size - 1
+ $server_name = [System.Text.Encoding]::Unicode.GetString($dfs_targetlist_blob[$server_name_start..$server_name_end])
+ #write-host $server_name
+ $share_name_size_start = $server_name_end + 1
+ $share_name_size_end = $share_name_size_start + 1
+ $share_name_size = [bitconverter]::ToUInt16($dfs_targetlist_blob[$share_name_size_start..$share_name_size_end],0)
+ $share_name_start = $share_name_size_end + 1
+ $share_name_end = $share_name_start + $share_name_size - 1
+ $share_name = [System.Text.Encoding]::Unicode.GetString($dfs_targetlist_blob[$share_name_start..$share_name_end])
+ #write-host $share_name
+ $target_list += "\\$server_name\$share_name"
+ $t_offset = $share_name_end + 1
+ }
+ }
+ }
+ $offset = $blob_data_end + 1
+ $dfs_pkt_properties = @{
+ 'Name' = $blob_name
+ 'Prefix' = $prefix
+ 'TargetList' = $target_list
+ }
+ $object_list += New-Object -TypeName PSObject -Property $dfs_pkt_properties
+ $prefix = $null
+ $blob_name = $null
+ $target_list = $null
+ }
+
+ $servers = @()
+ $object_list | ForEach-Object {
+ #write-host $_.Name;
+ #write-host $_.TargetList
+ if ($_.TargetList) {
+ $_.TargetList | ForEach-Object {
+ $servers += $_.split("\")[2]
+ }
+ }
+ }
+
+ $servers
+ }
+
function Get-DFSshareV1 {
[CmdletBinding()]
param(
@@ -5183,7 +5362,7 @@ function Get-DFSshare {
[String]
$ADSpath,
- [ValidateRange(1,10000)]
+ [ValidateRange(1,10000)]
[Int]
$PageSize = 200,
@@ -5201,6 +5380,7 @@ function Get-DFSshare {
$DFSSearcher.FindAll() | Where-Object {$_} | ForEach-Object {
$Properties = $_.Properties
$RemoteNames = $Properties.remoteservername
+ $Pkt = $Properties.pkt
$DFSshares += $RemoteNames | ForEach-Object {
try {
@@ -5213,9 +5393,22 @@ function Get-DFSshare {
}
}
}
+
+ if($pkt -and $pkt[0]) {
+ Parse-Pkt $pkt[0] | ForEach-Object {
+ # If a folder doesn't have a redirection it will
+ # have a target like
+ # \\null\TestNameSpace\folder\.DFSFolderLink so we
+ # do actually want to match on "null" rather than
+ # $null
+ if ($_ -ne "null") {
+ New-Object -TypeName PSObject -Property @{'Name'=$Properties.name[0];'RemoteServerName'=$_}
+ }
+ }
+ }
}
catch {
- Write-Warning "Get-DFSshareV2 error : $_"
+ Write-Warning "Get-DFSshareV1 error : $_"
}
$DFSshares | Sort-Object -Property "RemoteServerName"
}
@@ -5276,7 +5469,7 @@ function Get-DFSshare {
}
$DFSshares = @()
-
+
if ( ($Version -eq "all") -or ($Version.endsWith("1")) ) {
$DFSshares += Get-DFSshareV1 -Domain $Domain -DomainController $DomainController -Credential $Credential -ADSpath $ADSpath -PageSize $PageSize
}
@@ -5284,7 +5477,7 @@ function Get-DFSshare {
$DFSshares += Get-DFSshareV2 -Domain $Domain -DomainController $DomainController -Credential $Credential -ADSpath $ADSpath -PageSize $PageSize
}
- $DFSshares | Sort-Object -Property "RemoteServerName"
+ $DFSshares | Sort-Object -Property ("RemoteServerName","Name") -Unique
}
@@ -5356,7 +5549,7 @@ function Get-GptTmpl {
try {
Write-Verbose "Parsing $GptTmplPath"
- Get-Content $GptTmplPath -ErrorAction Stop | Foreach-Object {
+ Get-Content $GptTmplPath -ErrorAction Stop | ForEach-Object {
if ($_ -match '\[') {
# this signifies that we're starting a new section
$SectionName = $_.trim('[]') -replace ' ',''
@@ -5553,6 +5746,10 @@ function Get-NetGPO {
The GPO display name to query for, wildcards accepted.
+ .PARAMETER ComputerName
+
+ Return all GPO objects applied to a given computer (FQDN).
+
.PARAMETER Domain
The domain to query for GPOs, defaults to the current domain.
@@ -5591,6 +5788,9 @@ function Get-NetGPO {
$DisplayName,
[String]
+ $ComputerName,
+
+ [String]
$Domain,
[String]
@@ -5613,21 +5813,95 @@ function Get-NetGPO {
process {
if ($GPOSearcher) {
- if($DisplayName) {
- $GPOSearcher.filter="(&(objectCategory=groupPolicyContainer)(displayname=$DisplayName))"
+
+ if($ComputerName) {
+ $GPONames = @()
+ $Computers = Get-NetComputer -ComputerName $ComputerName -Domain $Domain -DomainController $DomainController -FullData -PageSize $PageSize
+
+ if(!$Computers) {
+ throw "Computer $ComputerName in domain '$Domain' not found! Try a fully qualified host name"
+ }
+
+ # get the given computer's OU
+ $ComputerOUs = @()
+ ForEach($Computer in $Computers) {
+ # extract all OUs a computer is a part of
+ $DN = $Computer.distinguishedname
+
+ $ComputerOUs += $DN.split(",") | ForEach-Object {
+ if($_.startswith("OU=")) {
+ $DN.substring($DN.indexof($_))
+ }
+ }
+ }
+
+ Write-Verbose "ComputerOUs: $ComputerOUs"
+
+ # find all the GPOs linked to the computer's OU
+ ForEach($ComputerOU in $ComputerOUs) {
+ $GPONames += Get-NetOU -Domain $Domain -DomainController $DomainController -ADSpath $ComputerOU -FullData -PageSize $PageSize | ForEach-Object {
+ # get any GPO links
+ write-verbose "blah: $($_.name)"
+ $_.gplink.split("][") | ForEach-Object {
+ if ($_.startswith("LDAP")) {
+ $_.split(";")[0]
+ }
+ }
+ }
+ }
+
+ Write-Verbose "GPONames: $GPONames"
+
+ # find any GPOs linked to the site for the given computer
+ $ComputerSite = (Get-SiteName -ComputerName $ComputerName).SiteName
+ if($ComputerSite -and ($ComputerSite -ne 'ERROR')) {
+ $GPONames += Get-NetSite -SiteName $ComputerSite -FullData | ForEach-Object {
+ if($_.gplink) {
+ $_.gplink.split("][") | ForEach-Object {
+ if ($_.startswith("LDAP")) {
+ $_.split(";")[0]
+ }
+ }
+ }
+ }
+ }
+
+ $GPONames | Where-Object{$_ -and ($_ -ne '')} | ForEach-Object {
+
+ # use the gplink as an ADS path to enumerate all GPOs for the computer
+ $GPOSearcher = Get-DomainSearcher -Domain $Domain -DomainController $DomainController -Credential $Credential -ADSpath $_ -PageSize $PageSize
+ $GPOSearcher.filter="(&(objectCategory=groupPolicyContainer)(name=$GPOname))"
+
+ try {
+ $GPOSearcher.FindAll() | Where-Object {$_} | ForEach-Object {
+ $Out = Convert-LDAPProperty -Properties $_.Properties
+ $Out | Add-Member Noteproperty 'ComputerName' $ComputerName
+ $Out
+ }
+ }
+ catch {
+ Write-Warning $_
+ }
+ }
}
+
else {
- $GPOSearcher.filter="(&(objectCategory=groupPolicyContainer)(name=$GPOname))"
- }
+ if($DisplayName) {
+ $GPOSearcher.filter="(&(objectCategory=groupPolicyContainer)(displayname=$DisplayName))"
+ }
+ else {
+ $GPOSearcher.filter="(&(objectCategory=groupPolicyContainer)(name=$GPOname))"
+ }
- try {
- $GPOSearcher.FindAll() | Where-Object {$_} | ForEach-Object {
- # convert/process the LDAP fields for each result
- Convert-LDAPProperty -Properties $_.Properties
+ try {
+ $GPOSearcher.FindAll() | Where-Object {$_} | ForEach-Object {
+ # convert/process the LDAP fields for each result
+ Convert-LDAPProperty -Properties $_.Properties
+ }
+ }
+ catch {
+ Write-Warning $_
}
- }
- catch {
- Write-Warning $_
}
}
}
@@ -5670,7 +5944,7 @@ function New-GPOImmediateTask {
.PARAMETER GPODisplayName
- The GPO display name to to build the task for.
+ The GPO display name to build the task for.
.PARAMETER Domain
@@ -5928,7 +6202,7 @@ function Get-NetGPOGroup {
)
# get every GPO from the specified domain with restricted groups set
- Get-NetGPO -GPOName $GPOname -DisplayName $GPOname -Domain $Domain -DomainController $DomainController -ADSpath $ADSpath -PageSize $PageSize | Foreach-Object {
+ Get-NetGPO -GPOName $GPOname -DisplayName $GPOname -Domain $Domain -DomainController $DomainController -ADSpath $ADSpath -PageSize $PageSize | ForEach-Object {
$Memberof = $Null
$Members = $Null
@@ -6199,6 +6473,11 @@ function Find-GPOLocation {
$GPOguid = $_.GPOName
$GPOMembers = $_.Members
+ if(!$TargetObjects) {
+ # if the * wildcard was used, set the ObjectDistName as the GPO member sid set
+ $TargetObjects = $GPOMembers
+ }
+
if( -not $ProcessedGUIDs[$GPOguid] ) {
$GPOname = $_.GPODisplayName
$Filters = $_.Filters
@@ -6217,12 +6496,8 @@ function Find-GPOLocation {
$OUComputers = Get-NetComputer -Domain $Domain -DomainController $DomainController -Credential $Credential -ADSpath $_.ADSpath -PageSize $PageSize
}
- if(!$TargetObjects) {
- # if the * wildcard was used, set the ObjectDistName as the GPO member sid set
- $TargetObjects = $GPOMembers
- }
+ ForEach ($TargetSid in $TargetObjects) {
- ForEach ($TargetSid in $TargetObjects) {
$Object = Get-ADObject -SID $TargetSid -Domain $Domain -DomainController $DomainController $_ -PageSize $PageSize
$IsGroup = @('268435456','268435457','536870912','536870913') -contains $Object.samaccounttype
@@ -6241,7 +6516,7 @@ function Find-GPOLocation {
}
# find any sites that have this GUID applied
- Get-NetSite -Domain $Domain -DomainController $DomainController -GUID $GPOguid -PageSize $PageSize -FullData | Foreach-Object {
+ Get-NetSite -Domain $Domain -DomainController $DomainController -GUID $GPOguid -PageSize $PageSize -FullData | ForEach-Object {
ForEach ($TargetSid in $TargetObjects) {
$Object = Get-ADObject -SID $TargetSid -Domain $Domain -DomainController $DomainController $_ -PageSize $PageSize
@@ -6361,6 +6636,8 @@ function Find-GPOComputerAdmin {
Throw "-ComputerName or -OUName must be provided"
}
+ $GPOGroups = @()
+
if($ComputerName) {
$Computers = Get-NetComputer -ComputerName $ComputerName -Domain $Domain -DomainController $DomainController -FullData -PageSize $PageSize
@@ -6368,16 +6645,42 @@ function Find-GPOComputerAdmin {
throw "Computer $ComputerName in domain '$Domain' not found! Try a fully qualified host name"
}
+ $TargetOUs = @()
ForEach($Computer in $Computers) {
# extract all OUs a computer is a part of
$DN = $Computer.distinguishedname
- $TargetOUs = $DN.split(",") | Foreach-Object {
+ $TargetOUs += $DN.split(",") | ForEach-Object {
if($_.startswith("OU=")) {
$DN.substring($DN.indexof($_))
}
}
}
+
+ # enumerate any linked GPOs for the computer's site
+ $ComputerSite = (Get-SiteName -ComputerName $ComputerName).SiteName
+ if($ComputerSite -and ($ComputerSite -ne 'ERROR')) {
+ $GPOGroups += Get-NetSite -SiteName $ComputerSite -FullData | ForEach-Object {
+ if($_.gplink) {
+ $_.gplink.split("][") | ForEach-Object {
+ if ($_.startswith("LDAP")) {
+ $_.split(";")[0]
+ }
+ }
+ }
+ } | ForEach-Object {
+ $GPOGroupArgs = @{
+ 'Domain' = $Domain
+ 'DomainController' = $DomainController
+ 'ADSpath' = $_
+ 'UsePSDrive' = $UsePSDrive
+ 'PageSize' = $PageSize
+ }
+
+ # for each GPO link, get any locally set user/group SIDs
+ Get-NetGPOGroup @GPOGroupArgs
+ }
+ }
}
else {
$TargetOUs = @($OUName)
@@ -6385,19 +6688,19 @@ function Find-GPOComputerAdmin {
Write-Verbose "Target OUs: $TargetOUs"
- $TargetOUs | Where-Object {$_} | Foreach-Object {
-
- $OU = $_
+ $TargetOUs | Where-Object {$_} | ForEach-Object {
# for each OU the computer is a part of, get the full OU object
- $GPOgroups = Get-NetOU -Domain $Domain -DomainController $DomainController -ADSpath $_ -FullData -PageSize $PageSize | Foreach-Object {
+ $GPOgroups += Get-NetOU -Domain $Domain -DomainController $DomainController -ADSpath $_ -FullData -PageSize $PageSize | ForEach-Object {
# and then get any GPO links
- $_.gplink.split("][") | Foreach-Object {
- if ($_.startswith("LDAP")) {
- $_.split(";")[0]
+ if($_.gplink) {
+ $_.gplink.split("][") | ForEach-Object {
+ if ($_.startswith("LDAP")) {
+ $_.split(";")[0]
+ }
}
}
- } | Foreach-Object {
+ } | ForEach-Object {
$GPOGroupArgs = @{
'Domain' = $Domain
'DomainController' = $DomainController
@@ -6409,79 +6712,77 @@ function Find-GPOComputerAdmin {
# for each GPO link, get any locally set user/group SIDs
Get-NetGPOGroup @GPOGroupArgs
}
+ }
- # for each found GPO group, resolve the SIDs of the members
- $GPOgroups | Where-Object {$_} | Foreach-Object {
- $GPO = $_
+ # for each found GPO group, resolve the SIDs of the members
+ $GPOgroups | Where-Object {$_} | ForEach-Object {
+ $GPO = $_
- if ($GPO.members) {
- $GPO.members = $GPO.members | Where-Object {$_} | ForEach-Object {
- if($_ -match '^S-1-.*') {
- $_
- }
- else {
- # if there are any plain group names, try to resolve them to sids
- (Convert-NameToSid -ObjectName $_ -Domain $Domain).SID
- }
- } | Sort-Object -Unique
- }
+ if ($GPO.members) {
+ $GPO.members = $GPO.members | Where-Object {$_} | ForEach-Object {
+ if($_ -match '^S-1-.*') {
+ $_
+ }
+ else {
+ # if there are any plain group names, try to resolve them to sids
+ (Convert-NameToSid -ObjectName $_ -Domain $Domain).SID
+ }
+ } | Sort-Object -Unique
+ }
- $GPO.members | Foreach-Object {
+ $GPO.members | ForEach-Object {
- # resolve this SID to a domain object
- $Object = Get-ADObject -Domain $Domain -DomainController $DomainController -PageSize $PageSize -SID $_
+ # resolve this SID to a domain object
+ $Object = Get-ADObject -Domain $Domain -DomainController $DomainController -PageSize $PageSize -SID $_
- $IsGroup = @('268435456','268435457','536870912','536870913') -contains $Object.samaccounttype
+ $IsGroup = @('268435456','268435457','536870912','536870913') -contains $Object.samaccounttype
- $GPOComputerAdmin = New-Object PSObject
- $GPOComputerAdmin | Add-Member Noteproperty 'ComputerName' $ComputerName
- $GPOComputerAdmin | Add-Member Noteproperty 'OU' $OU
- $GPOComputerAdmin | Add-Member Noteproperty 'GPODisplayName' $GPO.GPODisplayName
- $GPOComputerAdmin | Add-Member Noteproperty 'GPOPath' $GPO.GPOPath
- $GPOComputerAdmin | Add-Member Noteproperty 'ObjectName' $Object.samaccountname
- $GPOComputerAdmin | Add-Member Noteproperty 'ObjectDN' $Object.distinguishedname
- $GPOComputerAdmin | Add-Member Noteproperty 'ObjectSID' $_
- $GPOComputerAdmin | Add-Member Noteproperty 'IsGroup' $IsGroup
- $GPOComputerAdmin
+ $GPOComputerAdmin = New-Object PSObject
+ $GPOComputerAdmin | Add-Member Noteproperty 'ComputerName' $ComputerName
+ $GPOComputerAdmin | Add-Member Noteproperty 'GPODisplayName' $GPO.GPODisplayName
+ $GPOComputerAdmin | Add-Member Noteproperty 'GPOPath' $GPO.GPOPath
+ $GPOComputerAdmin | Add-Member Noteproperty 'ObjectName' $Object.samaccountname
+ $GPOComputerAdmin | Add-Member Noteproperty 'ObjectDN' $Object.distinguishedname
+ $GPOComputerAdmin | Add-Member Noteproperty 'ObjectSID' $_
+ $GPOComputerAdmin | Add-Member Noteproperty 'IsGroup' $IsGroup
+ $GPOComputerAdmin
- # if we're recursing and the current result object is a group
- if($Recurse -and $GPOComputerAdmin.isGroup) {
+ # if we're recursing and the current result object is a group
+ if($Recurse -and $GPOComputerAdmin.isGroup) {
- Get-NetGroupMember -Domain $Domain -DomainController $DomainController -SID $_ -FullData -Recurse -PageSize $PageSize | Foreach-Object {
+ Get-NetGroupMember -Domain $Domain -DomainController $DomainController -SID $_ -FullData -Recurse -PageSize $PageSize | ForEach-Object {
- $MemberDN = $_.distinguishedName
+ $MemberDN = $_.distinguishedName
- # extract the FQDN from the Distinguished Name
- $MemberDomain = $MemberDN.subString($MemberDN.IndexOf("DC=")) -replace 'DC=','' -replace ',','.'
+ # extract the FQDN from the Distinguished Name
+ $MemberDomain = $MemberDN.subString($MemberDN.IndexOf("DC=")) -replace 'DC=','' -replace ',','.'
- $MemberIsGroup = @('268435456','268435457','536870912','536870913') -contains $_.samaccounttype
+ $MemberIsGroup = @('268435456','268435457','536870912','536870913') -contains $_.samaccounttype
- if ($_.samAccountName) {
- # forest users have the samAccountName set
- $MemberName = $_.samAccountName
+ if ($_.samAccountName) {
+ # forest users have the samAccountName set
+ $MemberName = $_.samAccountName
+ }
+ else {
+ # external trust users have a SID, so convert it
+ try {
+ $MemberName = Convert-SidToName $_.cn
}
- else {
- # external trust users have a SID, so convert it
- try {
- $MemberName = Convert-SidToName $_.cn
- }
- catch {
- # if there's a problem contacting the domain to resolve the SID
- $MemberName = $_.cn
- }
+ catch {
+ # if there's a problem contacting the domain to resolve the SID
+ $MemberName = $_.cn
}
-
- $GPOComputerAdmin = New-Object PSObject
- $GPOComputerAdmin | Add-Member Noteproperty 'ComputerName' $ComputerName
- $GPOComputerAdmin | Add-Member Noteproperty 'OU' $OU
- $GPOComputerAdmin | Add-Member Noteproperty 'GPODisplayName' $GPO.GPODisplayName
- $GPOComputerAdmin | Add-Member Noteproperty 'GPOPath' $GPO.GPOPath
- $GPOComputerAdmin | Add-Member Noteproperty 'ObjectName' $MemberName
- $GPOComputerAdmin | Add-Member Noteproperty 'ObjectDN' $MemberDN
- $GPOComputerAdmin | Add-Member Noteproperty 'ObjectSID' $_.objectsid
- $GPOComputerAdmin | Add-Member Noteproperty 'IsGroup' $MemberIsGroup
- $GPOComputerAdmin
}
+
+ $GPOComputerAdmin = New-Object PSObject
+ $GPOComputerAdmin | Add-Member Noteproperty 'ComputerName' $ComputerName
+ $GPOComputerAdmin | Add-Member Noteproperty 'GPODisplayName' $GPO.GPODisplayName
+ $GPOComputerAdmin | Add-Member Noteproperty 'GPOPath' $GPO.GPOPath
+ $GPOComputerAdmin | Add-Member Noteproperty 'ObjectName' $MemberName
+ $GPOComputerAdmin | Add-Member Noteproperty 'ObjectDN' $MemberDN
+ $GPOComputerAdmin | Add-Member Noteproperty 'ObjectSID' $_.objectsid
+ $GPOComputerAdmin | Add-Member Noteproperty 'IsGroup' $MemberIsGroup
+ $GPOComputerAdmin
}
}
}
@@ -6521,9 +6822,15 @@ function Get-DomainPolicy {
.EXAMPLE
- PS C:\> Get-NetGPO
+ PS C:\> Get-DomainPolicy
+
+ Returns the domain policy for the current domain.
+
+ .EXAMPLE
- Returns the GPOs in the current domain.
+ PS C:\> Get-DomainPolicy -Source DC -DomainController MASTER.testlab.local
+
+ Returns the policy for the MASTER.testlab.local domain controller.
#>
[CmdletBinding()]
@@ -6577,25 +6884,25 @@ function Get-DomainPolicy {
}
# parse the GptTmpl.inf
- Get-GptTmpl @ParseArgs | Foreach-Object {
+ Get-GptTmpl @ParseArgs | ForEach-Object {
if($ResolveSids) {
# if we're resolving sids in PrivilegeRights to names
$Policy = New-Object PSObject
- $_.psobject.properties | Foreach-Object {
+ $_.psobject.properties | ForEach-Object {
if( $_.Name -eq 'PrivilegeRights') {
$PrivilegeRights = New-Object PSObject
# for every nested SID member of PrivilegeRights, try to
# unpack everything and resolve the SIDs as appropriate
- $_.Value.psobject.properties | Foreach-Object {
+ $_.Value.psobject.properties | ForEach-Object {
- $Sids = $_.Value | Foreach-Object {
+ $Sids = $_.Value | ForEach-Object {
try {
if($_ -isnot [System.Array]) {
Convert-SidToName $_
}
else {
- $_ | Foreach-Object { Convert-SidToName $_ }
+ $_ | ForEach-Object { Convert-SidToName $_ }
}
}
catch {
@@ -6707,7 +7014,7 @@ function Get-NetLocalGroup {
[Parameter(ParameterSetName = 'WinNT', Position=0, ValueFromPipeline=$True)]
[Alias('HostName')]
[String[]]
- $ComputerName = 'localhost',
+ $ComputerName = "$($env:COMPUTERNAMECOMPUTERNAME)",
[Parameter(ParameterSetName = 'WinNT')]
[Parameter(ParameterSetName = 'API')]
@@ -7492,7 +7799,7 @@ filter Invoke-CheckLocalAdminAccess {
<#
.SYNOPSIS
- This function will use the OpenSCManagerW Win32API call to to establish
+ This function will use the OpenSCManagerW Win32API call to establish
a handle to the remote host. If this succeeds, the current user context
has local administrator acess to the target.
@@ -7566,6 +7873,82 @@ filter Invoke-CheckLocalAdminAccess {
}
+filter Get-SiteName {
+<#
+ .SYNOPSIS
+
+ This function will use the DsGetSiteName Win32API call to look up the
+ name of the site where a specified computer resides.
+
+ .PARAMETER ComputerName
+
+ The hostname to look the site up for, default to localhost.
+
+ .EXAMPLE
+
+ PS C:\> Get-SiteName -ComputerName WINDOWS1
+
+ Returns the site for WINDOWS1.testlab.local.
+
+ .EXAMPLE
+
+ PS C:\> Get-NetComputer | Invoke-CheckLocalAdminAccess
+
+ Returns the sites for every machine in AD.
+#>
+ [CmdletBinding()]
+ param(
+ [Parameter(ValueFromPipeline=$True)]
+ [Alias('HostName')]
+ [Object[]]
+ [ValidateNotNullOrEmpty()]
+ $ComputerName = $Env:ComputerName
+ )
+
+ # extract the computer name from whatever object was passed on the pipeline
+ $Computer = $ComputerName | Get-NameField
+
+ # if we get an IP address, try to resolve the IP to a hostname
+ if($Computer -match '^(?:[0-9]{1,3}\.){3}[0-9]{1,3}$') {
+ $IPAddress = $Computer
+ $Computer = [System.Net.Dns]::GetHostByAddress($Computer)
+ }
+ else {
+ $IPAddress = @(Get-IPAddress -ComputerName $Computer)[0].IPAddress
+ }
+
+ $PtrInfo = [IntPtr]::Zero
+
+ $Result = $Netapi32::DsGetSiteName($Computer, [ref]$PtrInfo)
+ Write-Debug "Get-SiteName result for $Computer : $Result"
+
+ $ComputerSite = New-Object PSObject
+ $ComputerSite | Add-Member Noteproperty 'ComputerName' $Computer
+ $ComputerSite | Add-Member Noteproperty 'IPAddress' $IPAddress
+
+ if ($Result -eq 0) {
+ $Sitename = [System.Runtime.InteropServices.Marshal]::PtrToStringAuto($PtrInfo)
+ $ComputerSite | Add-Member Noteproperty 'SiteName' $Sitename
+ }
+ elseif($Result -eq 1210) {
+ Write-Verbose "Computername '$Computer' is not in a valid form."
+ $ComputerSite | Add-Member Noteproperty 'SiteName' 'ERROR'
+ }
+ elseif($Result -eq 1919) {
+ Write-Verbose "Computer '$Computer' is not in a site"
+
+ $ComputerSite | Add-Member Noteproperty 'SiteName' $Null
+ }
+ else {
+ Write-Verbose "Error"
+ $ComputerSite | Add-Member Noteproperty 'SiteName' 'ERROR'
+ }
+
+ $Null = $Netapi32::NetApiBufferFree($PtrInfo)
+ $ComputerSite
+}
+
+
filter Get-LastLoggedOn {
<#
.SYNOPSIS
@@ -9173,7 +9556,7 @@ function Invoke-ProcessHunter {
else {
ForEach ($Domain in $TargetDomains) {
Write-Verbose "[*] Querying domain $Domain for users of group '$GroupName'"
- $TargetUsers += Get-NetGroupMember -GroupName $GroupName -Domain $Domain -DomainController $DomainController -Credential $Credential| Foreach-Object {
+ $TargetUsers += Get-NetGroupMember -GroupName $GroupName -Domain $Domain -DomainController $DomainController -Credential $Credential| ForEach-Object {
$_.MemberName
}
}
@@ -9510,7 +9893,7 @@ function Invoke-EventHunter {
else {
ForEach ($Domain in $TargetDomains) {
Write-Verbose "[*] Querying domain $Domain for users of group '$GroupName'"
- $TargetUsers += Get-NetGroupMember -GroupName $GroupName -Domain $Domain -DomainController $DomainController -Credential $Credential | Foreach-Object {
+ $TargetUsers += Get-NetGroupMember -GroupName $GroupName -Domain $Domain -DomainController $DomainController -Credential $Credential | ForEach-Object {
$_.MemberName
}
}
@@ -11776,7 +12159,7 @@ function Find-ManagedSecurityGroups {
#>
# Go through the list of security groups on the domain and identify those who have a manager
- Get-NetGroup -FullData -Filter '(&(managedBy=*)(groupType:1.2.840.113556.1.4.803:=2147483648))' | Select-Object -Unique distinguishedName,managedBy,cn | Foreach-Object {
+ Get-NetGroup -FullData -Filter '(&(managedBy=*)(groupType:1.2.840.113556.1.4.803:=2147483648))' | Select-Object -Unique distinguishedName,managedBy,cn | ForEach-Object {
# Retrieve the object that the managedBy DN refers to
$group_manager = Get-ADObject -ADSPath $_.managedBy | Select-Object cn,distinguishedname,name,samaccounttype,samaccountname
@@ -11948,8 +12331,9 @@ $FunctionDefinitions = @(
(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 NetLocalGroupGetMembers ([Int]) @([String], [String], [Int], [IntPtr].MakeByRefType(), [Int], [Int32].MakeByRefType(), [Int32].MakeByRefType(), [Int32].MakeByRefType())),
- (func advapi32 ConvertSidToStringSid ([Int]) @([IntPtr], [String].MakeByRefType())),
+ (func netapi32 DsGetSiteName ([Int]) @([String], [IntPtr].MakeByRefType())),
(func netapi32 NetApiBufferFree ([Int]) @([IntPtr])),
+ (func advapi32 ConvertSidToStringSid ([Int]) @([IntPtr], [String].MakeByRefType())),
(func advapi32 OpenSCManagerW ([IntPtr]) @([String], [String], [Int])),
(func advapi32 CloseServiceHandle ([Int]) @([IntPtr])),
(func wtsapi32 WTSOpenServerEx ([IntPtr]) @([String])),