Enumerate directory objects with native, LDAP and PowerView approaches
Needs: Correct search base and authentication transport; object/attribute visibility and compatible local utilities
Windows commands
REM Baseline
net user /domain
net user USER /domain
net group /domain
net group "Domain Admins" /domain
net group "GROUP" /domain
net accounts /domain
nltest /domain_trusts /all_trusts
net view /domain
net view \\DC_HOST
RSAT ActiveDirectory module, only when installed
# RSAT ActiveDirectory module, only when installed
Get-Command -Module ActiveDirectory
Get-ADDomain
Get-ADForest
Get-ADDomainController -Filter *
Get-ADUser -Filter * -Properties Enabled,Description,MemberOf,ServicePrincipalName,UserPrincipalName,PasswordLastSet,LastLogonDate,AdminCount
Get-ADGroup -Filter * -Properties GroupScope,GroupCategory,Members,Description
Get-ADGroupMember -Identity 'GROUP' -Recursive
Get-ADComputer -Filter * -Properties DNSHostName,OperatingSystem,OperatingSystemVersion,ServicePrincipalName,TrustedForDelegation,LastLogonDate
Get-ADTrust -Filter *
RSAT ActiveDirectory module, only when installed
Get-AD*cmdlets require the RSAT ActiveDirectory module. Its absence on a client is normal; use ADSI, LDAP, PowerView or an off-domain client.
For automatic, explicitly scoped inventory, run the AD surface helpers with an explicit DC/domain. Collection runs by default, prints a bounded findings summary and saves a unique private evidence directory;
-Previewdisplays checks without connecting. The helper preserves query failures, candidate clues, account-context limits and linked manual-validation handoffs without requesting roast material or changing directory objects.
For repeated queries, define LDAPSearch once inline, then use its purpose-labelled calls. The transparent one-off procedure below remains useful when no helper is loaded.
# RSAT ActiveDirectory module, only when installed
$root = [ADSI]'LDAP://RootDSE'
$base = [ADSI]("LDAP://" + $root.defaultNamingContext)
$searcher = New-Object System.DirectoryServices.DirectorySearcher($base)
$searcher.PageSize = 1000
$searcher.PropertiesToLoad.AddRange(@('samaccountname','userprincipalname','objectsid','memberof','serviceprincipalname','description','useraccountcontrol','pwdlastset','lastlogontimestamp'))
$searcher.Filter = '(&(objectCategory=person)(objectClass=user))'
$searcher.FindAll() | ForEach-Object { $_.Properties }
Change only the filter and requested attributes for another object class
# Change only the filter and requested attributes for another object class
# Groups
$searcher.Filter = '(objectCategory=group)'
$searcher.PropertiesToLoad.Clear()
$searcher.PropertiesToLoad.AddRange(@('samaccountname','objectsid','member','grouptype','description'))
$searcher.FindAll() | ForEach-Object { $_.Properties }
# Computers
$searcher.Filter = '(objectCategory=computer)'
$searcher.PropertiesToLoad.Clear()
$searcher.PropertiesToLoad.AddRange(@('dnshostname','operatingsystem','operatingsystemversion','serviceprincipalname','useraccountcontrol','lastlogontimestamp'))
$searcher.FindAll() | ForEach-Object { $_.Properties }
Discover the naming context
# Discover the naming context
ldapsearch -x -LLL -H ldap://DC_HOST:389 -s base -b '' \
defaultNamingContext configurationNamingContext rootDomainNamingContext dnsHostName
# Users, groups and computers
ldapsearch -x -LLL -H ldap://DC_HOST:389 -D 'USER@DOMAIN' -W \
-E pr=1000/noprompt -b 'DC=DOMAIN,DC=TLD' \
'(&(objectCategory=person)(objectClass=user))' \
sAMAccountName userPrincipalName objectSid userAccountControl memberOf description servicePrincipalName pwdLastSet lastLogonTimestamp adminCount
# Users, groups and computers
ldapsearch -x -LLL -H ldap://DC_HOST:389 -D 'USER@DOMAIN' -W \
-E pr=1000/noprompt -b 'DC=DOMAIN,DC=TLD' \
'(objectCategory=group)' sAMAccountName objectSid member groupType description
# Users, groups and computers
ldapsearch -x -LLL -H ldap://DC_HOST:389 -D 'USER@DOMAIN' -W \
-E pr=1000/noprompt -b 'DC=DOMAIN,DC=TLD' \
'(objectCategory=computer)' dNSHostName operatingSystem operatingSystemVersion servicePrincipalName userAccountControl lastLogonTimestamp
# SPNs, trusts and GPO/OU context
# SPN-bearing accounts: mapping only; do not request tickets in this block.
ldapsearch -x -LLL -H ldap://DC_HOST:389 -D 'USER@DOMAIN' -W \
-E pr=1000/noprompt -b 'DC=DOMAIN,DC=TLD' \
'(&(objectCategory=person)(objectClass=user)(servicePrincipalName=*))' \
sAMAccountName servicePrincipalName memberOf userAccountControl pwdLastSet
# SPNs, trusts and GPO/OU context
# Trusted-domain objects
ldapsearch -x -LLL -H ldap://DC_HOST:389 -D 'USER@DOMAIN' -W \
-b 'DC=DOMAIN,DC=TLD' '(objectClass=trustedDomain)' \
cn securityIdentifier trustDirection trustType trustAttributes
# SPNs, trusts and GPO/OU context
# OUs and GPO containers; correlate links before inferring host effect.
ldapsearch -x -LLL -H ldap://DC_HOST:389 -D 'USER@DOMAIN' -W \
-E pr=1000/noprompt -b 'DC=DOMAIN,DC=TLD' \
'(|(objectClass=organizationalUnit)(objectClass=groupPolicyContainer))' \
distinguishedName displayName name gPLink gPOptions
LDAP failure router
Result Interpretation Next action Invalid credentials (49)Bind identity/secret/context failed; subcodes may refine the cause Recheck UPN vs DOMAIN\USER, account state and exact secret; do not infer authorizationStrong(er) authentication required/ confidentiality requiredServer policy rejects that bind/transport Use the permitted LDAPS/StartTLS or Kerberos/SASL path; do not disable protections Size limit exceededor suspiciously round countSearch is incomplete Add paged results and narrow the base/filter Referral/partial results Search crossed a naming-context boundary Query the referred domain/partition or compatible Global Catalog deliberately Bind succeeds, search empty Wrong base/filter, ACL filtering or genuinely no matches Verify RootDSE base, test a known object and request fewer attributes Works by IP, Kerberos fails Route exists but name/SPN/DNS/time path is wrong Use DC FQDN, AD DNS, correct realm and synchronized time
# LDAP failure router
Import-Module .\PowerView.ps1
Get-Command -Module PowerView
Get-Domain
Get-DomainController
Get-DomainTrust
Get-DomainUser | Select-Object samaccountname,userprincipalname,description,memberof,serviceprincipalname
Get-DomainGroup
Get-DomainGroupMember -Identity 'GROUP' -Recurse
Get-DomainComputer | Select-Object dnshostname,operatingsystem,operatingsystemversion
Get-DomainUser -SPN | Select-Object samaccountname,serviceprincipalname,memberof
LDAP failure router
# LDAP failure router
NEW PASSWORD/HASH/KEY/TICKET
-> VERIFY TYPE, CLIENT, REALM, VALIDITY
-> AUTHENTICATE THROUGH ONE COMPATIBLE SERVICE
-> CONFIRM IDENTITY
-> REPEAT GROUP/ACL/SHARE/HOST/SESSION/ROUTE MAPPING
Verify → Retain object identifiers, group relationships and actual visibility; distinguish directory facts from inferred execution access.
If it fails → Missing RSAT/PowerView does not block built-in ADSI or LDAP. Signing/TLS policy requires a compatible authenticated transport. More detail ↓
Explanation & examples
Enumerate directory objects with native, LDAP and PowerView approaches
- USE WHEN
- A directory bind or domain-joined identity can read relevant objects
- STARTING ACCESS
- A known domain identity or a directory endpoint that permits the selected anonymous query
- RESULT
- User, group, computer, trust and policy relationships for attack-path hypotheses
Recognize the clue
Use the available built-in/LDAP interface from the verified domain context; inspect one useful user/group before broad graph assumptions.
net user USER /domain
net group "GROUP" /domain
Account: USER
Global group memberships: GROUP
Group members: CONTROLLED_USERMeans: Account/group membership supplies a relationship to investigate; nested membership and effective destination rights remain separate.
Confirm: Verify object SID/type, nesting and the exact right granted to that principal.
- After validation
- The membership resolves to a currently effective object/service right: follow that route.
- Ruled out in this context
- The same-named group belongs to another domain or grants no intended right: reject the assumed relationship.
- Still inconclusive
- Partial visibility or nesting not yet expanded leaves effective membership unresolved.
Troubleshooting: Missing RSAT/PowerView does not block built-in ADSI or LDAP. Signing/TLS policy requires a compatible authenticated transport.
Additional prerequisite checks
net user /domain
net group /domain
These commands are broadly available but provide partial views. Expand interesting users and groups individually, trace nested groups rather than assuming memberOf is complete, and retain SIDs when names can collide across domains.
RSAT ActiveDirectory module, only when installed
Get-AD* cmdlets require the RSAT ActiveDirectory module. Its absence on a client is normal; use ADSI, LDAP, PowerView or an off-domain client.
For automatic, explicitly scoped inventory, run the AD surface helpers with an explicit DC/domain. Collection runs by default, prints a bounded findings summary and saves a unique private evidence directory; -Preview displays checks without connecting. The helper preserves query failures, candidate clues, account-context limits and linked manual-validation handoffs without requesting roast material or changing directory objects.
For repeated queries, define LDAPSearch once inline, then use its purpose-labelled calls. The transparent one-off procedure below remains useful when no helper is loaded.
Change only the filter and requested attributes for another object class:
PageSize = 1000asks for paged results; without paging, the server's result-size limit can silently produce an incomplete inventory. LDAP filters are data selection, not proof of access or exploitability.
Discover the naming context
Users, groups and computers
SPNs, trusts and GPO/OU context
LDAP failure router
| Result | Interpretation | Next action |
|---|---|---|
Invalid credentials (49) | Bind identity/secret/context failed; subcodes may refine the cause | Recheck UPN vs DOMAIN\USER, account state and exact secret; do not infer authorization |
Strong(er) authentication required / confidentiality required | Server policy rejects that bind/transport | Use the permitted LDAPS/StartTLS or Kerberos/SASL path; do not disable protections |
Size limit exceeded or suspiciously round count | Search is incomplete | Add paged results and narrow the base/filter |
| Referral/partial results | Search crossed a naming-context boundary | Query the referred domain/partition or compatible Global Catalog deliberately |
| Bind succeeds, search empty | Wrong base/filter, ACL filtering or genuinely no matches | Verify RootDSE base, test a known object and request fewer attributes |
| Works by IP, Kerberos fails | Route exists but name/SPN/DNS/time path is wrong | Use DC FQDN, AD DNS, correct realm and synchronized time |
The original PowerSploit repository is archived. Course examples and forks may use legacy aliases such as Get-NetUser, Get-NetGroup, Get-NetComputer or Get-NetDomainTrust. Inspect Get-Command/Get-Help for the exact copy present rather than mixing generations.
Do not overwrite the old state. Record which source produced the material and which protocol accepted it.
Why it works
Tools expose the same directory through different interfaces. Group nesting, object types, primary groups and protected attributes affect how relationships translate into effective rights.
Worked example · hypothetical
Observation: a group appears to grant useful access. Test: enumerate its membership and nesting with the available native/LDAP method. Illustrative output: the controlled user is included through another group. Interpretation: validate the resulting destination/object right.
New identity, privilege, host or route? Re-enumerate → All topic tasks →