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 AttributeWhat to Look For
Minimum password lengthShort = easier to spray
Account lockout threshold0 = no lockout (spray freely)
Lockout durationHow long until reset
Lockout observation windowTime between failed attempts
Password complexityRequired 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 description field. 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 CheckWhy
Domain AdminsFull domain control
Enterprise AdminsForest-level control
Remote Desktop UsersRDP access to hosts
Remote Management UsersWinRM access
Backup OperatorsCan DCSync via backup privileges
Server OperatorsCan modify services on DCs
Account OperatorsCan create/modify non-admin accounts
DnsAdminsDLL 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

QueryPurpose
Shortest Path to Domain AdminsPrimary attack path
Find Kerberoastable UsersAccounts with SPNs to crack
Find AS-REP Roastable UsersNo preauth accounts
Shortest Path from Owned PrincipalsPaths from your current access
Find Computers with Unconstrained DelegationDelegation abuse targets
List all GPOsPolicy-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.

CommandPurpose
net user /domainList all domain users
net user <USER> /domainDetails on a specific user
net group /domainList all domain groups
net group "Domain Admins" /domainList Domain Admins
net group "Remote Desktop Users" /domainList RDP users
net accounts /domainPassword policy
net shareList local shares
net localgroup AdministratorsLocal admin group members
net view /domainList computers in the domain
nltest /dclist:<DOMAIN>List domain controllers
nltest /domain_trustsList domain trusts
whoami /allCurrent user, groups, and privileges
systeminfoOS version, hotfixes, domain info
ipconfig /allNetwork config including DNS server (usually DC)
klistList 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.