Added Get-SiteName to find the site a computer is a part of

Added -ComputerName parameter to Get-NetGPO to enumerate all GPOs a given computer has applied
Fixed bug in Find-GPOComputerAdmin and added site enumeration for GPO links
This commit is contained in:
Harmj0y 2016-03-15 15:13:32 -04:00
parent 13adf516d5
commit 26a0757612
1 changed files with 297 additions and 110 deletions

View File

@ -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)
@ -5549,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 ' ',''
@ -5783,6 +5783,9 @@ function Get-NetGPO {
[String]
$DisplayName,
[String]
$ComputerName,
[String]
$Domain,
@ -5806,6 +5809,79 @@ function Get-NetGPO {
process {
if ($GPOSearcher) {
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 {
if($DisplayName) {
$GPOSearcher.filter="(&(objectCategory=groupPolicyContainer)(displayname=$DisplayName))"
}
@ -5825,6 +5901,7 @@ function Get-NetGPO {
}
}
}
}
function New-GPOImmediateTask {
@ -5863,7 +5940,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
@ -6121,7 +6198,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
@ -6416,6 +6493,7 @@ function Find-GPOLocation {
}
ForEach ($TargetSid in $TargetObjects) {
$Object = Get-ADObject -SID $TargetSid -Domain $Domain -DomainController $DomainController $_ -PageSize $PageSize
$IsGroup = @('268435456','268435457','536870912','536870913') -contains $Object.samaccounttype
@ -6434,7 +6512,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
@ -6554,6 +6632,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
@ -6561,36 +6641,30 @@ 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($_))
}
}
}
}
else {
$TargetOUs = @($OUName)
}
Write-Verbose "Target OUs: $TargetOUs"
$TargetOUs | Where-Object {$_} | Foreach-Object {
$OU = $_
# 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 {
# and then get any GPO links
$_.gplink.split("][") | Foreach-Object {
# 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 {
}
} | ForEach-Object {
$GPOGroupArgs = @{
'Domain' = $Domain
'DomainController' = $DomainController
@ -6602,9 +6676,42 @@ function Find-GPOComputerAdmin {
# for each GPO link, get any locally set user/group SIDs
Get-NetGPOGroup @GPOGroupArgs
}
}
}
else {
$TargetOUs = @($OUName)
}
Write-Verbose "Target OUs: $TargetOUs"
$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 {
# and then get any GPO links
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
}
}
# for each found GPO group, resolve the SIDs of the members
$GPOgroups | Where-Object {$_} | Foreach-Object {
$GPOgroups | Where-Object {$_} | ForEach-Object {
$GPO = $_
if ($GPO.members) {
@ -6619,7 +6726,7 @@ function Find-GPOComputerAdmin {
} | 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 $_
@ -6628,7 +6735,6 @@ function Find-GPOComputerAdmin {
$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
@ -6640,7 +6746,7 @@ function Find-GPOComputerAdmin {
# 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
@ -6666,7 +6772,6 @@ function Find-GPOComputerAdmin {
$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
@ -6680,7 +6785,6 @@ function Find-GPOComputerAdmin {
}
}
}
}
function Get-DomainPolicy {
@ -6714,9 +6818,15 @@ function Get-DomainPolicy {
.EXAMPLE
PS C:\> Get-NetGPO
PS C:\> Get-DomainPolicy
Returns the GPOs in the current domain.
Returns the domain policy for the current domain.
.EXAMPLE
PS C:\> Get-DomainPolicy -Source DC -DomainController MASTER.testlab.local
Returns the policy for the MASTER.testlab.local domain controller.
#>
[CmdletBinding()]
@ -6770,25 +6880,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 {
@ -7685,7 +7795,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.
@ -7759,6 +7869,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
@ -9366,7 +9552,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
}
}
@ -9703,7 +9889,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
}
}
@ -11969,7 +12155,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
@ -12141,8 +12327,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])),