Skip to content
HackIndex logo

HackIndex

AD Domain and DC Discovery

4 min read Jun 9, 2026

The first goal on an AD engagement is identifying the domain name, finding domain controllers, and mapping the network topology — all before you have any credentials. DCs expose several distinctive ports (88, 389, 445, 3268) and respond to DNS queries that reveal the domain structure.

Identify domain controllers from the network

Domain controllers run Kerberos (88), LDAP (389/636), Global Catalog (3268/3269), and SMB (445). A targeted port scan finds them quickly. nxc also labels hosts as (PDC) or (DC) in SMB output.

┌──(kali㉿kali)-[~]
└─$ # Quick DC fingerprint — ports that only DCs run
┌──(kali㉿kali)-[~]
└─$ nmap -p 88,389,445,3268 $TARGET_SUBNET/24 --open -oG - | grep 'open'
 
┌──(kali㉿kali)-[~]
└─$ # Full DC port set
┌──(kali㉿kali)-[~]
└─$ nmap -p 53,88,135,139,389,445,464,636,3268,3269,5985 $TARGET_SUBNET/24 --open
 
┌──(kali㉿kali)-[~]
└─$ # nxc sweep — flags domain controllers explicitly
┌──(kali㉿kali)-[~]
└─$ nxc smb $TARGET_SUBNET/24
 
┌──(kali㉿kali)-[~]
└─$ # nxc — list only DCs
┌──(kali㉿kali)-[~]
└─$ nxc smb $TARGET_SUBNET/24 | grep 'DC'
SMB  10.10.10.10  445  DC01  [*] Windows Server 2019 x64 (name:DC01) (domain:corp.local) (signing:True) (SMBv1:False) (DC) (PDC)
SMB  10.10.10.11  445  DC02  [*] Windows Server 2019 x64 (name:DC02) (domain:corp.local) (signing:True) (SMBv1:False) (DC)

DNS-based domain discovery

AD registers SRV records in DNS. Querying _ldap._tcp and _kerberos._tcp SRV records reveals all DCs and the domain name without touching any AD-specific port.

┌──(kali㉿kali)-[~]
└─$ # Discover domain name and DC from DNS
┌──(kali㉿kali)-[~]
└─$ nslookup -type=SRV _ldap._tcp $TARGET_IP
┌──(kali㉿kali)-[~]
└─$ nslookup -type=SRV _kerberos._tcp $TARGET_IP
 
┌──(kali㉿kali)-[~]
└─$ # dig equivalent
┌──(kali㉿kali)-[~]
└─$ dig SRV _ldap._tcp.corp.local @$TARGET_IP
┌──(kali㉿kali)-[~]
└─$ dig SRV _kerberos._tcp.corp.local @$TARGET_IP
┌──(kali㉿kali)-[~]
└─$ dig SRV _gc._tcp.corp.local @$TARGET_IP
 
┌──(kali㉿kali)-[~]
└─$ # Enumerate all _msdcs records (DC locator)
┌──(kali㉿kali)-[~]
└─$ dig any _msdcs.corp.local @$TARGET_IP
 
┌──(kali㉿kali)-[~]
└─$ # Reverse lookup DC IP to get hostname
┌──(kali㉿kali)-[~]
└─$ nslookup $TARGET_IP $TARGET_IP
_ldap._tcp.corp.local  600  IN  SRV  0 100 389 dc01.corp.local.
_kerberos._tcp.corp.local  600  IN  SRV  0 100 88 dc01.corp.local.

LDAP anonymous info — no credentials needed

LDAP exposes the rootDSE object anonymously on every DC. This returns the domain naming context, forest name, DC hostname, and domain functional level without any authentication.

┌──(kali㉿kali)-[~]
└─$ # Dump rootDSE — no credentials
┌──(kali㉿kali)-[~]
└─$ ldapsearch -x -H ldap://$TARGET_IP -b '' -s base
 
┌──(kali㉿kali)-[~]
└─$ # Key attributes: defaultNamingContext, rootDomainNamingContext, ldapServiceName
┌──(kali㉿kali)-[~]
└─$ ldapsearch -x -H ldap://$TARGET_IP -b '' -s base '(objectClass=*)' defaultNamingContext rootDomainNamingContext ldapServiceName dnsHostName domainFunctionality
 
┌──(kali㉿kali)-[~]
└─$ # nxc
┌──(kali㉿kali)-[~]
└─$ nxc ldap $TARGET_IP
defaultNamingContext: DC=corp,DC=local
rootDomainNamingContext: DC=corp,DC=local
ldapServiceName: corp.local:[email protected]
dnsHostName: dc01.corp.local
domainFunctionality: 7

Authenticated enumeration — domain info with credentials

Once you have any valid credential (even a low-privilege user), extract the domain SID, list all DCs, and get the full forest structure.

┌──(kali㉿kali)-[~]
└─$ # Domain SID — required for ticket forging
┌──(kali㉿kali)-[~]
└─$ nxc ldap $TARGET_IP -u $USER -p $PASSWORD --get-sid
 
┌──(kali㉿kali)-[~]
└─$ # List all domain controllers
┌──(kali㉿kali)-[~]
└─$ nxc ldap $TARGET_IP -u $USER -p $PASSWORD --dc-list
 
┌──(kali㉿kali)-[~]
└─$ # BloodyAD — domain info
┌──(kali㉿kali)-[~]
└─$ bloodyAD -d $DOMAIN -u $USER -p $PASSWORD --host $TARGET_IP get domain
 
┌──(kali㉿kali)-[~]
└─$ # All DC computer objects
┌──(kali㉿kali)-[~]
└─$ bloodyAD -d $DOMAIN -u $USER -p $PASSWORD --host $TARGET_IP get search \
--filter '(&(objectClass=computer)(userAccountControl:1.2.840.113556.1.4.803:=8192))' \
--attr dNSHostName operatingSystem operatingSystemVersion whenCreated
 
┌──(kali㉿kali)-[~]
└─$ # Domain trusts
┌──(kali㉿kali)-[~]
└─$ bloodyAD -d $DOMAIN -u $USER -p $PASSWORD --host $TARGET_IP get trusts
 
┌──(kali㉿kali)-[~]
└─$ # nxc — enumerate trusts
┌──(kali㉿kali)-[~]
└─$ nxc ldap $TARGET_IP -u $USER -p $PASSWORD --trusted-for-delegation
SMB  10.10.10.10  445  DC01  Domain SID: S-1-5-21-1234567890-0987654321-1122334455
LDAP  10.10.10.10  389  DC01  dc01.corp.local - Windows Server 2019 (PDC)
LDAP  10.10.10.10  389  DC01  dc02.corp.local - Windows Server 2019
┌──(kali㉿kali)-[~]
└─$ # Domain info via RPC (null session may work)
┌──(kali㉿kali)-[~]
└─$ rpcclient -U "" -N $TARGET_IP -c "lsaquery"
┌──(kali㉿kali)-[~]
└─$ rpcclient -U "$USER%$PASSWORD" $TARGET_IP -c "lsaquery"
 
┌──(kali㉿kali)-[~]
└─$ # List DCs
┌──(kali㉿kali)-[~]
└─$ rpcclient -U "$USER%$PASSWORD" $TARGET_IP -c "dsr_getdcname $DOMAIN"
 
┌──(kali㉿kali)-[~]
└─$ # Domain users count
┌──(kali㉿kali)-[~]
└─$ rpcclient -U "$USER%$PASSWORD" $TARGET_IP -c "querydominfo"

With domain name, DC IPs, and domain SID in hand, proceed to AD Object Enumeration for users, groups, and computers, and BloodHound Collection to map attack paths.

References