AD Cheatsheet: Enumeration & Fundamentals
This is the first post in a practical Active Directory cheatsheet series aimed at penetration testers and red teamers. The series covers the full attack lifecycle from initial enumeration through domain compromise. Every command is ready to copy and adapt to your engagement. This post focuses on the reconnaissance and enumeration phase -- the foundation for every successful AD attack path.
1. Initial Enumeration
DNS Reconnaissance
DNS is one of the most reliable ways to identify domain controllers and map the AD environment.
# Identify the domain controller via DNS SRV records
nslookup -type=SRV _ldap._tcp.dc._msdcs.domain.local <DC_IP>
# Zone transfer attempt (rarely works, always worth trying)
dig axfr domain.local @<DC_IP>
# Reverse lookup to identify hostnames
dig -x <IP> @<DC_IP>
# Enumerate all DNS records
dnsenum --dnsserver <DC_IP> --enum domain.local
Nmap Scanning
# Fast port scan - top ports
nmap -sC -sV -T4 --top-ports 1000 <TARGET_IP> -oN nmap_initial.txt
# Full port scan
nmap -p- -T4 <TARGET_IP> -oN nmap_allports.txt
# Targeted AD services scan
nmap -p 53,88,135,139,389,445,464,593,636,3268,3269,5985,5986,9389 -sC -sV <TARGET_IP> -oN nmap_ad.txt
Tip: Port 88 (Kerberos) is the strongest indicator of a domain controller. Port 5985 (WinRM) means you can get a shell with valid credentials via evil-winrm.
Ping Sweep
# Discover live hosts on the subnet
nmap -sn 10.10.10.0/24 -oG live_hosts.txt
# Using fping (faster)
fping -asgq 10.10.10.0/24
Passive Network Capture
# Capture traffic to identify protocols and hosts
sudo tcpdump -i tun0 -w capture.pcap
# Responder in analyze mode (passive - no poisoning)
sudo responder -I tun0 -A
Tip: Running Responder in analyze mode (
-A) lets you see LLMNR/NBT-NS/mDNS queries without poisoning. Useful for mapping services and identifying targets before going active.
2. SMB Enumeration
SMB is almost always open on Windows hosts and frequently allows unauthenticated enumeration.
Null Session Testing
# Test null session with smbclient
smbclient -N -L //<TARGET_IP>/
# Test null session with netexec
nxc smb <TARGET_IP> -u '' -p ''
nxc smb <TARGET_IP> -u 'guest' -p ''
# List shares with access
nxc smb <TARGET_IP> -u '' -p '' --shares
nxc smb <TARGET_IP> -u 'guest' -p '' --shares
SMB Share Enumeration
# List and access shares
smbclient -N //<TARGET_IP>/<SHARE>
smbclient //<TARGET_IP>/<SHARE> -U '<DOMAIN>/<USER>%<PASS>'
# Recursive download of a share
smbclient //<TARGET_IP>/<SHARE> -U '<DOMAIN>/<USER>%<PASS>' -c 'recurse ON; prompt OFF; mget *'
# Spider shares for interesting files
nxc smb <TARGET_IP> -u <USER> -p <PASS> -M spider_plus
RPC Enumeration
# Connect with null session
rpcclient -U '' -N <TARGET_IP>
# Useful rpcclient commands once connected:
# enumdomusers - list all domain users
# enumdomgroups - list all domain groups
# querygroupmem <RID> - list group members
# queryuser <RID> - get user details
# getdompwinfo - get password policy
# enumprinters - list printers (can leak info)
# lsaenumsid - enumerate SIDs
enum4linux-ng
# Full enumeration (null session)
enum4linux-ng -A <TARGET_IP>
# With credentials
enum4linux-ng -A <TARGET_IP> -u <USER> -p <PASS>
Tip: enum4linux-ng is the modern rewrite. It outputs cleaner results and supports JSON output with
-oJ.
3. LDAP Enumeration
LDAP (port 389/636) is the backbone of AD. Many domains allow anonymous or authenticated LDAP queries.
ldapsearch
# Anonymous bind - get base naming context
ldapsearch -x -H ldap://<DC_IP> -s base namingcontexts
# Anonymous bind - dump everything (if allowed)
ldapsearch -x -H ldap://<DC_IP> -b "DC=domain,DC=local"
# Authenticated - all users
ldapsearch -x -H ldap://<DC_IP> -D '<DOMAIN>\<USER>' -w '<PASS>' \
-b "DC=domain,DC=local" "(objectClass=user)" sAMAccountName userPrincipalName memberOf
# Find users with SPNs (Kerberoastable)
ldapsearch -x -H ldap://<DC_IP> -D '<DOMAIN>\<USER>' -w '<PASS>' \
-b "DC=domain,DC=local" "(&(objectClass=user)(servicePrincipalName=*))" sAMAccountName servicePrincipalName
# Find accounts with no preauth (AS-REP Roastable)
ldapsearch -x -H ldap://<DC_IP> -D '<DOMAIN>\<USER>' -w '<PASS>' \
-b "DC=domain,DC=local" "(userAccountControl:1.2.840.113556.1.4.803:=4194304)" sAMAccountName
# Find domain admins
ldapsearch -x -H ldap://<DC_IP> -D '<DOMAIN>\<USER>' -w '<PASS>' \
-b "DC=domain,DC=local" "(memberOf=CN=Domain Admins,CN=Users,DC=domain,DC=local)" sAMAccountName
windapsearch
# Enumerate users
windapsearch -d <DOMAIN> --dc <DC_IP> -u <USER>@<DOMAIN> -p <PASS> --users
# Enumerate groups
windapsearch -d <DOMAIN> --dc <DC_IP> -u <USER>@<DOMAIN> -p <PASS> --groups
# Enumerate computers
windapsearch -d <DOMAIN> --dc <DC_IP> -u <USER>@<DOMAIN> -p <PASS> --computers
# Find privileged users
windapsearch -d <DOMAIN> --dc <DC_IP> -u <USER>@<DOMAIN> -p <PASS> --privileged-users
4. Password Policy Discovery
Knowing the password policy is critical before any spraying attempt to avoid lockouts.
From Linux
# netexec - quickest method
nxc smb <DC_IP> -u <USER> -p <PASS> --pass-pol
# rpcclient
rpcclient -U '<DOMAIN>/<USER>%<PASS>' <DC_IP> -c 'getdompwinfo'
# enum4linux-ng
enum4linux-ng -P <DC_IP> -u <USER> -p <PASS>
# LDAP - fine-grained password policies
ldapsearch -x -H ldap://<DC_IP> -D '<DOMAIN>\<USER>' -w '<PASS>' \
-b "DC=domain,DC=local" "(objectClass=msDS-PasswordSettings)"
From Windows
# Built-in
net accounts /domain
# PowerView
Import-Module .\PowerView.ps1
Get-DomainPolicy | Select-Object -ExpandProperty SystemAccess
| Policy Attribute | What to Look For |
|---|---|
| Minimum password length | Short = easier to spray |
| Account lockout threshold | 0 = no lockout (spray freely) |
| Lockout duration | How long until reset |
| Lockout observation window | Time between failed attempts |
| Password complexity | Required or not |
Tip: If the lockout threshold is 0, there is no account lockout policy and you can spray without fear. If it is 3-5, be very careful with timing. Always check this FIRST.
5. User Enumeration
From Linux
# enum4linux-ng
enum4linux-ng -U <TARGET_IP> -u <USER> -p <PASS>
# rpcclient - enumerate users
rpcclient -U '<DOMAIN>/<USER>%<PASS>' <DC_IP> -c 'enumdomusers'
# rpcclient - query specific user
rpcclient -U '<DOMAIN>/<USER>%<PASS>' <DC_IP> -c 'queryuser <USERNAME>'
# LDAP - all users with details
ldapsearch -x -H ldap://<DC_IP> -D '<DOMAIN>\<USER>' -w '<PASS>' \
-b "DC=domain,DC=local" "(objectClass=user)" sAMAccountName description memberOf \
userAccountControl lastLogon
# netexec - list users
nxc smb <DC_IP> -u <USER> -p <PASS> --users
# netexec - list logged-on users (requires admin)
nxc smb <TARGET_IP> -u <USER> -p <PASS> --loggedon-users
# Kerbrute - enumerate valid usernames without credentials
kerbrute userenum usernames.txt --dc <DC_IP> -d <DOMAIN>
From Windows
# PowerView
Import-Module .\PowerView.ps1
Get-DomainUser | Select-Object samaccountname, description, memberof, lastlogon
Get-DomainUser -SPN | Select-Object samaccountname, serviceprincipalname
# Native
net user /domain
Tip: Always check the
descriptionfield. Administrators frequently store passwords or hints in user descriptions.
6. Group & Computer Enumeration
Group Enumeration
# rpcclient
rpcclient -U '<DOMAIN>/<USER>%<PASS>' <DC_IP> -c 'enumdomgroups'
# rpcclient - members of a specific group (by RID)
rpcclient -U '<DOMAIN>/<USER>%<PASS>' <DC_IP> -c 'querygroupmem <GROUP_RID>'
# netexec
nxc smb <DC_IP> -u <USER> -p <PASS> --groups
# LDAP - all groups
ldapsearch -x -H ldap://<DC_IP> -D '<DOMAIN>\<USER>' -w '<PASS>' \
-b "DC=domain,DC=local" "(objectClass=group)" cn member
# LDAP - Domain Admins members
ldapsearch -x -H ldap://<DC_IP> -D '<DOMAIN>\<USER>' -w '<PASS>' \
-b "CN=Domain Admins,CN=Users,DC=domain,DC=local" member
# PowerView
Import-Module .\PowerView.ps1
Get-DomainGroup | Select-Object cn, description
Get-DomainGroupMember -Identity "Domain Admins"
Get-DomainGroupMember -Identity "Remote Desktop Users"
Get-DomainGroupMember -Identity "Remote Management Users"
Computer Enumeration
# netexec - discover hosts
nxc smb <SUBNET>/24
# LDAP - all computers
ldapsearch -x -H ldap://<DC_IP> -D '<DOMAIN>\<USER>' -w '<PASS>' \
-b "DC=domain,DC=local" "(objectClass=computer)" cn operatingSystem dNSHostName
# PowerView
Get-DomainComputer | Select-Object name, operatingsystem, dnshostname
Get-DomainComputer -Unconstrained | Select-Object name
Get-DomainComputer -TrustedToAuth | Select-Object name, msds-allowedtodelegateto
| Group to Check | Why |
|---|---|
| Domain Admins | Full domain control |
| Enterprise Admins | Forest-level control |
| Remote Desktop Users | RDP access to hosts |
| Remote Management Users | WinRM access |
| Backup Operators | Can DCSync via backup privileges |
| Server Operators | Can modify services on DCs |
| Account Operators | Can create/modify non-admin accounts |
| DnsAdmins | DLL injection on DNS service (DC) |
7. Security Controls Enumeration
Understanding what defenses are in place helps you choose the right tools and avoid detection.
Windows Defender
# Check Defender status
Get-MpComputerStatus | Select-Object AntivirusEnabled, RealTimeProtectionEnabled, AMServiceEnabled
# Check exclusion paths (gold for dropping tools)
Get-MpPreference | Select-Object -ExpandProperty ExclusionPath
# Check if tamper protection is on
Get-MpComputerStatus | Select-Object IsTamperProtected
AppLocker
# Check AppLocker policy
Get-AppLockerPolicy -Effective | Select-Object -ExpandProperty RuleCollections
# Common bypass directories
# C:\Windows\Tasks\
# C:\Windows\Temp\
# C:\Windows\System32\spool\drivers\color\
LAPS (Local Administrator Password Solution)
# Check if LAPS is deployed (from Linux)
nxc smb <DC_IP> -u <USER> -p <PASS> -M laps
# netexec - read LAPS password (requires ReadLAPSPassword permission)
nxc ldap <DC_IP> -u <USER> -p <PASS> --module laps
# Check if LAPS module exists
Get-Command Get-LapsADPassword -ErrorAction SilentlyContinue
# Read LAPS password (if permitted)
Get-LapsADPassword -Identity <COMPUTER> -AsPlainText
PowerShell Language Mode
# Check current language mode
$ExecutionContext.SessionState.LanguageMode
# FullLanguage = unrestricted
# ConstrainedLanguage = limited (.NET restricted, no Add-Type)
Tip: In Constrained Language Mode, most offensive PowerShell tools will not work. Pivot to compiled binaries (SharpHound, Rubeus, Certify) or use AMSI bypass techniques if possible.
8. BloodHound Collection
BloodHound visualizes AD relationships and finds attack paths that are nearly impossible to spot manually.
From Linux (bloodhound-python)
# Standard collection
bloodhound-python -u <USER> -p <PASS> -d <DOMAIN> -dc <DC_FQDN> -c all
# With specific nameserver
bloodhound-python -u <USER> -p <PASS> -d <DOMAIN> -dc <DC_FQDN> -c all -ns <DC_IP>
# With NTLM hash
bloodhound-python -u <USER> --hashes :<NTHASH> -d <DOMAIN> -dc <DC_FQDN> -c all
From Windows (SharpHound)
# SharpHound - full collection
.\SharpHound.exe -c All
# SharpHound - with specific domain and stealth options
.\SharpHound.exe -c All -d <DOMAIN> --stealth
# PowerShell version
Import-Module .\SharpHound.ps1
Invoke-BloodHound -CollectionMethod All -OutputDirectory C:\Temp\
Key Queries to Run in BloodHound
| Query | Purpose |
|---|---|
| Shortest Path to Domain Admins | Primary attack path |
| Find Kerberoastable Users | Accounts with SPNs to crack |
| Find AS-REP Roastable Users | No preauth accounts |
| Shortest Path from Owned Principals | Paths from your current access |
| Find Computers with Unconstrained Delegation | Delegation abuse targets |
| List all GPOs | Policy-based lateral movement |
Tip: After importing data, mark your owned users and computers in BloodHound. Then use "Shortest Path from Owned Principals" to find the optimal attack chain.
9. Basic Windows Net Commands
Quick reference for built-in Windows commands that work without importing any modules.
| Command | Purpose |
|---|---|
net user /domain | List all domain users |
net user <USER> /domain | Details on a specific user |
net group /domain | List all domain groups |
net group "Domain Admins" /domain | List Domain Admins |
net group "Remote Desktop Users" /domain | List RDP users |
net accounts /domain | Password policy |
net share | List local shares |
net localgroup Administrators | Local admin group members |
net view /domain | List computers in the domain |
nltest /dclist:<DOMAIN> | List domain controllers |
nltest /domain_trusts | List domain trusts |
whoami /all | Current user, groups, and privileges |
systeminfo | OS version, hotfixes, domain info |
ipconfig /all | Network config including DNS server (usually DC) |
klist | List cached Kerberos tickets |
setspn -L <USER> | List SPNs for a user |
Tip: These commands work even in Constrained Language Mode and do not require admin privileges. They should be your first step after getting a shell on a domain-joined machine.
What's Next
The next post in this series covers Kerberos Attacks -- Kerberoasting, AS-REP Roasting, Golden/Silver Tickets, delegation abuse, and more.