Skip to content

Commit b6306a0

Browse files
committed
Small bug fix in Find-GPOLocation when enumerating all relationships
Moved GPOType check to Get-NetGPOGroup Expanded comments and help for GPO location cmdlets
1 parent da86d76 commit b6306a0

File tree

1 file changed

+79
-29
lines changed

1 file changed

+79
-29
lines changed

Recon/PowerView.ps1

Lines changed: 79 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -6590,6 +6590,20 @@ function Get-NetGPOGroup {
65906590
65916591
Returns all GPOs in a domain that set "Restricted Groups" or use groups.xml on on target machines.
65926592
6593+
Author: @harmj0y
6594+
License: BSD 3-Clause
6595+
Required Dependencies: Get-NetGPO, Get-GptTmpl, Get-GroupsXML, Convert-NameToSid, Convert-SidToName
6596+
Optional Dependencies: None
6597+
6598+
.DESCRIPTION
6599+
6600+
First enumerates all GPOs in the current/target domain using Get-NetGPO with passed
6601+
arguments, and for each GPO checks if 'Restricted Groups' are set with GptTmpl.inf or
6602+
group membership is set through Group Policy Preferences groups.xml files. For any
6603+
GptTmpl.inf files found, the file is parsed with Get-GptTmpl and any 'Group Membership'
6604+
section data is processed if present. Any found Groups.xml files are parsed with
6605+
Get-GroupsXML and those memberships are returned as well.
6606+
65936607
.PARAMETER GPOname
65946608
65956609
The GPO name to query for, wildcards accepted.
@@ -6628,6 +6642,10 @@ function Get-NetGPOGroup {
66286642
PS C:\> Get-NetGPOGroup
66296643
66306644
Returns all local groups set by GPO along with their members and memberof.
6645+
6646+
.LINK
6647+
6648+
https://morgansimonsenblog.azurewebsites.net/tag/groups/
66316649
#>
66326650

66336651
[CmdletBinding()]
@@ -6683,13 +6701,14 @@ function Get-NetGPOGroup {
66836701
ForEach ($Membership in $Inf.'Group Membership'.GetEnumerator()) {
66846702
$Group, $Relation = $Membership.Key.Split('__', $Option) | ForEach-Object {$_.Trim()}
66856703

6704+
# extract out ALL members
66866705
$MembershipValue = $Membership.Value.Split(',') | ForEach-Object { $_.Trim('*') } | Where-Object {$_}
66876706
if($MembershipValue -isnot [System.Array]) { $MembershipValue = @($MembershipValue) }
66886707

66896708
if($ResolveMemberSIDs) {
6709+
# if the resulting member is username and not a SID, attempt to resolve it
66906710
$GroupMembers = @()
66916711
ForEach($Member in $MembershipValue) {
6692-
Write-Verbose "Member: $Member"
66936712
if($Member -notmatch '^S-1-.*') {
66946713
$MemberSID = Convert-NameToSid -ObjectName $Member | Select-Object -ExpandProperty SID
66956714
if($MemberSID) {
@@ -6714,7 +6733,7 @@ function Get-NetGPOGroup {
67146733

67156734
ForEach ($Membership in $Memberships.GetEnumerator()) {
67166735
if($Membership.Key -match '^\*') {
6717-
# if the SID is already resolved, try to resolve SID to a name
6736+
# if the SID is already resolved (i.e. begins with *) try to resolve SID to a name
67186737
$GroupSID = $Membership.Key.Trim('*')
67196738
$GroupName = Convert-SidToName -SID $GroupSID
67206739
}
@@ -6739,6 +6758,7 @@ function Get-NetGPOGroup {
67396758
$GPOGroup | Add-Member Noteproperty 'GPODisplayName' $GPODisplayName
67406759
$GPOGroup | Add-Member Noteproperty 'GPOName' $GPOName
67416760
$GPOGroup | Add-Member Noteproperty 'GPOPath' $GPOPath
6761+
$GPOGroup | Add-Member Noteproperty 'GPOType' 'RestrictedGroups'
67426762
$GPOGroup | Add-Member Noteproperty 'Filters' $Null
67436763
$GPOGroup | Add-Member Noteproperty 'GroupName' $GroupName
67446764
$GPOGroup | Add-Member Noteproperty 'GroupSID' $GroupSID
@@ -6758,6 +6778,7 @@ function Get-NetGPOGroup {
67586778
$GroupMembers = @()
67596779
ForEach($Member in $_.GroupMembers) {
67606780
if($Member -notmatch '^S-1-.*') {
6781+
# if the resulting member is username and not a SID, attempt to resolve it
67616782
$MemberSID = Convert-NameToSid -ObjectName $Member | Select-Object -ExpandProperty SID
67626783
if($MemberSID) {
67636784
$GroupMembers += $MemberSID
@@ -6775,6 +6796,7 @@ function Get-NetGPOGroup {
67756796

67766797
$_ | Add-Member Noteproperty 'GPODisplayName' $GPODisplayName
67776798
$_ | Add-Member Noteproperty 'GPOName' $GPOName
6799+
$_ | Add-Member Noteproperty 'GPOType' 'GroupPolicyPreferences'
67786800
$_
67796801
}
67806802
}
@@ -6784,10 +6806,19 @@ function Get-NetGPOGroup {
67846806
function Find-GPOLocation {
67856807
<#
67866808
.SYNOPSIS
6809+
6810+
Enumerates the machines where a specific user/group is a member of a specific
6811+
local group, all through GPO correlation.
67876812
6788-
Takes a user/group name and optional domain, and determines
6789-
the computers in the domain the user/group has local admin
6790-
(or RDP) rights to.
6813+
Author: @harmj0y
6814+
License: BSD 3-Clause
6815+
Required Dependencies: Get-NetUser, Get-NetGroup, Get-NetGPOGroup, Get-NetOU, Get-NetComputer, Get-ADObject, Get-NetSite
6816+
Optional Dependencies: None
6817+
6818+
.DESCRIPTION
6819+
6820+
Takes a user/group name and optional domain, and determines the computers in the domain
6821+
the user/group has local admin (or RDP) rights to.
67916822
67926823
It does this by:
67936824
1. resolving the user/group to its proper SID
@@ -6800,6 +6831,9 @@ function Find-GPOLocation {
68006831
5. enumerating all OUs and sites and applicable GPO GUIs are
68016832
applied to through gplink enumerating
68026833
6. querying for all computers under the given OUs or sites
6834+
6835+
If no user/group is specified, all user/group -> machine mappings discovered through
6836+
GPO relationships are returned.
68036837
68046838
.PARAMETER UserName
68056839
@@ -6831,6 +6865,13 @@ function Find-GPOLocation {
68316865
68326866
The PageSize to set for the LDAP searcher object.
68336867
6868+
.EXAMPLE
6869+
6870+
PS C:\> Find-GPOLocation
6871+
6872+
Find all user/group -> machine relationships where the user/group is a member
6873+
of the local administrators group on target machines.
6874+
68346875
.EXAMPLE
68356876
68366877
PS C:\> Find-GPOLocation -UserName dfm
@@ -6878,11 +6919,11 @@ function Find-GPOLocation {
68786919
)
68796920

68806921
if($UserName) {
6881-
6922+
# if a group name is specified, get that user object so we can extract the target SID
68826923
$User = Get-NetUser -UserName $UserName -Domain $Domain -DomainController $DomainController -PageSize $PageSize
68836924
$UserSid = $User.objectsid
68846925

6885-
if(!$UserSid) {
6926+
if(-not $UserSid) {
68866927
Throw "User '$UserName' not found!"
68876928
}
68886929

@@ -6891,11 +6932,11 @@ function Find-GPOLocation {
68916932
$TargetObject = $UserSid
68926933
}
68936934
elseif($GroupName) {
6894-
6935+
# if a group name is specified, get that group object so we can extract the target SID
68956936
$Group = Get-NetGroup -GroupName $GroupName -Domain $Domain -DomainController $DomainController -FullData -PageSize $PageSize
68966937
$GroupSid = $Group.objectsid
68976938

6898-
if(!$GroupSid) {
6939+
if(-not $GroupSid) {
68996940
Throw "Group '$GroupName' not found!"
69006941
}
69016942

@@ -6907,6 +6948,7 @@ function Find-GPOLocation {
69076948
$TargetSIDs = @('*')
69086949
}
69096950

6951+
# figure out what the SID is of the target local group we're checking for membership in
69106952
if($LocalGroup -like "*Admin*") {
69116953
$TargetLocalSID = 'S-1-5-32-544'
69126954
}
@@ -6920,8 +6962,9 @@ function Find-GPOLocation {
69206962
throw "LocalGroup must be 'Administrators', 'RDP', or a 'S-1-5-X' SID format."
69216963
}
69226964

6965+
# if we're not listing all relationships, use the tokenGroups approach from Get-NetGroup to
6966+
# get all effective security SIDs this object is a part of
69236967
if($TargetSIDs[0] -and ($TargetSIDs[0] -ne '*')) {
6924-
# use the tokenGroups approach from Get-NetGroup to get all effective security SIDs this object is a part of
69256968
$TargetSIDs += Get-NetGroup -Domain $Domain -DomainController $DomainController -PageSize $PageSize -UserName $ObjectSamAccountName -RawSids
69266969
}
69276970

@@ -6940,6 +6983,7 @@ function Find-GPOLocation {
69406983
'PageSize' = $PageSize
69416984
}
69426985

6986+
# enumerate all GPO group mappings for the target domain
69436987
$GPOgroups = Get-NetGPOGroup @GPOGroupArgs | ForEach-Object {
69446988

69456989
$GPOgroup = $_
@@ -6960,26 +7004,24 @@ function Find-GPOLocation {
69607004
$GPOname = $_.GPODisplayName
69617005
$GPOguid = $_.GPOName
69627006
$GPOPath = $_.GPOPath
7007+
$GPOType = $_.GPOType
69637008
$GPOMembers = $_.GroupMembers
69647009
$Filters = $_.Filters
69657010

69667011
if(-not $TargetObject) {
69677012
# if the * wildcard was used, set the ObjectDistName as the GPO member SID set
6968-
$TargetObject = $GPOMembers
6969-
}
6970-
6971-
if($GPOName -match 'Groups.xml') {
6972-
$GPOType = 'GroupPolicyPreferences'
7013+
# so all relationship mappings are output
7014+
$TargetObjectSIDs = $GPOMembers
69737015
}
69747016
else {
6975-
$GPOType = 'RestrictedGroups'
7017+
$TargetObjectSIDs = $TargetObject
69767018
}
69777019

69787020
# find any OUs that have this GUID applied and then retrieve any computers from the OU
69797021
Get-NetOU -Domain $Domain -DomainController $DomainController -GUID $GPOguid -FullData -PageSize $PageSize | ForEach-Object {
69807022
if($Filters) {
69817023
# filter for computer name/org unit if a filter is specified
6982-
# TODO: handle other filters (i.e. OU filters?)
7024+
# TODO: handle other filters (i.e. OU filters?) again, I hate you GPP...
69837025
$OUComputers = Get-NetComputer -Domain $Domain -DomainController $DomainController -Credential $Credential -ADSpath $_.ADSpath -FullData -PageSize $PageSize | Where-Object {
69847026
$_.adspath -match ($Filters.Value)
69857027
} | ForEach-Object { $_.dnshostname }
@@ -6990,7 +7032,7 @@ function Find-GPOLocation {
69907032

69917033
if($OUComputers -isnot [System.Array]) {$OUComputers = @($OUComputers)}
69927034

6993-
ForEach ($TargetSid in $TargetObject) {
7035+
ForEach ($TargetSid in $TargetObjectSIDs) {
69947036

69957037
$Object = Get-ADObject -SID $TargetSid -Domain $Domain -DomainController $DomainController $_ -PageSize $PageSize
69967038

@@ -7014,7 +7056,7 @@ function Find-GPOLocation {
70147056
# find any sites that have this GUID applied
70157057
Get-NetSite -Domain $Domain -DomainController $DomainController -GUID $GPOguid -PageSize $PageSize -FullData | ForEach-Object {
70167058

7017-
ForEach ($TargetSid in $TargetObject) {
7059+
ForEach ($TargetSid in $TargetObjectSIDs) {
70187060
$Object = Get-ADObject -SID $TargetSid -Domain $Domain -DomainController $DomainController $_ -PageSize $PageSize
70197061

70207062
$IsGroup = @('268435456','268435457','536870912','536870913') -contains $Object.samaccounttype
@@ -7041,8 +7083,23 @@ function Find-GPOComputerAdmin {
70417083
<#
70427084
.SYNOPSIS
70437085
7044-
Takes a computer (or GPO) object and determines what users/groups have
7045-
administrative access over it.
7086+
Takes a computer (or GPO) object and determines what users/groups are in the specified
7087+
local group for the machine.
7088+
7089+
Author: @harmj0y
7090+
License: BSD 3-Clause
7091+
Required Dependencies: Get-NetComputer, Get-SiteName, Get-NetSite, Get-NetGPOGroup, Get-ADObject, Get-NetGroupMember, Convert-SidToName
7092+
Optional Dependencies: None
7093+
7094+
.DESCRIPTION
7095+
7096+
If a -ComputerName is specified, retrieve the complete computer object, attempt to
7097+
determine the OU the computer is a part of. Then resolve the computer's site name with
7098+
Get-SiteName and retrieve all sites object Get-NetSite. For those results, attempt to
7099+
enumerate all linked GPOs and associated local group settings with Get-NetGPOGroup. For
7100+
each resulting GPO group, resolve the resulting user/group name to a full AD object and
7101+
return the results. This will return the domain objects that are members of the specified
7102+
-LocalGroup for the given computer.
70467103
70477104
Inverse of Find-GPOLocation.
70487105
@@ -7211,13 +7268,6 @@ function Find-GPOComputerAdmin {
72117268
$GPOgroups | Sort-Object -Property GPOName -Unique | ForEach-Object {
72127269
$GPOGroup = $_
72137270

7214-
if($GPOGroup.GPOPath -match 'Groups.xml') {
7215-
$GPOType = 'GroupPolicyPreferences'
7216-
}
7217-
else {
7218-
$GPOType = 'RestrictedGroups'
7219-
}
7220-
72217271
$GPOGroup.GroupMembers | ForEach-Object {
72227272

72237273
# resolve this SID to a domain object
@@ -7234,7 +7284,7 @@ function Find-GPOComputerAdmin {
72347284
$GPOComputerAdmin | Add-Member Noteproperty 'GPODisplayName' $GPOGroup.GPODisplayName
72357285
$GPOComputerAdmin | Add-Member Noteproperty 'GPOGuid' $GPOGroup.GPOName
72367286
$GPOComputerAdmin | Add-Member Noteproperty 'GPOPath' $GPOGroup.GPOPath
7237-
$GPOComputerAdmin | Add-Member Noteproperty 'GPOType' $GPOType
7287+
$GPOComputerAdmin | Add-Member Noteproperty 'GPOType' $GPOType.GPOType
72387288
$GPOComputerAdmin
72397289

72407290
# if we're recursing and the current result object is a group

0 commit comments

Comments
 (0)