Y3llowDuck
Active Directory Enumeration Red Team OSCP Unauthenticated

Finding the Domain Controller
Without Credentials

Y3llowDuck | Active Directory Series · ~8 min read

You just landed on a box. Internal network. No domain creds. Maybe you got a local admin via some juicy vuln, maybe you're just sitting on the network with a rogue device. Either way, one of your first questions is the same every time: where is the Domain Controller?

You can't do much in an AD environment without knowing that. Kerberoasting, AS-REP roasting, BloodHound collection, pass-the-hash pivoting. All of it starts from knowing what the DC is and what domain you're in. So this post is about exactly that. Finding the DC before you even have a single valid credential.

I'm covering five methods. Some you'll use from your attacker machine on Linux, some work from a Windows box. But none needs a valid AD Domain credential.

01 — nmap fingerprinting

Method 1 — Nmap Port Fingerprinting

This is my favorite one. A Domain Controller has a very recognizable port profile. It's not like a regular Windows workstation or even a member server. The combination of services it has to run — DNS, Kerberos, LDAP, RPC, SMB — creates a signature that's hard to miss once you know what to look for.

Here's what you're typically going to see open on a DC:

Port Protocol Service Why it matters
53TCP/UDPDNSDCs are typically DNS servers for the domain
88TCP/UDPKerberosDC-only — strongest single indicator
135TCPRPC Endpoint MapperWindows standard, but present on DCs
389TCP/UDPLDAPAD LDAP — DC exclusive
445TCPSMBPresent everywhere but needed on DC
464TCP/UDPKerberos kpasswdPassword change service — DC only
636TCPLDAPSLDAP over TLS
3268TCPGlobal Catalog LDAPDC only, forest-wide queries
3269TCPGlobal Catalog LDAPSDC only, encrypted

Port 88 is your biggest tell. Kerberos only runs on Domain Controllers. If you see 88 open, you found a DC. Period. But to be thorough, do a targeted scan for the full combo:

kali — nmap DC fingerprint
$ sudo nmap -Pn -T4 -p 53,88,135,389,445,464,636,3268,3269 192.168.115.0/24 Starting Nmap 7.94 ( https://nmap.org ) Nmap scan report for 192.168.115.120 Host is up (0.0021s latency). PORT STATE SERVICE 53/tcp open domain 88/tcp open kerberos-sec 135/tcp open msrpc 389/tcp open ldap 445/tcp open microsoft-ds 464/tcp open kpasswd5 636/tcp open ldapssl 3268/tcp open globalcatLDAP 3269/tcp open globalcatLDAPssl

That output basically screams DC. But if you want confirmation along with actual domain info — hostname, domain name, forest name — take it one step further with the ldap-rootdse NSE script. This one queries the LDAP Root DSE, which is publicly accessible with no authentication required by default.

kali — ldap-rootdse
$ sudo nmap -Pn -T4 -p 389 --script ldap-rootdse 192.168.115.120 PORT STATE SERVICE 389/tcp open ldap | ldap-rootdse: | dnsHostName: dc01.contoso.com | defaultNamingContext: DC=contoso,DC=com | domainControllerFunctionality: 7 (Windows Server 2016+) | serverName: CN=DC01,CN=Servers,CN=Default-First-Site...

Right there. Hostname, domain name, even the functional level. Zero authentication. And if you want just the hostname fast without parsing the whole output:

kali — quick hostname grab
$ sudo nmap -Pn -T4 -p 389,636 --script ldap-rootdse 192.168.115.120 | grep dnsHostName | dnsHostName: dc01.contoso.com
● note
The Root DSE is queryable without credentials because it's designed that way. Microsoft's spec says it has to be accessible for clients to discover the AD structure. Useful for them. Useful for us.
02 — dns srv records

Method 2 — DNS SRV Records via nslookup

Active Directory relies heavily on DNS SRV records to help clients find services. Back in 2003, when I was working for HP, my former boss used to say that 99.99% of Active Directory problems were due to DNS. He was exaggerating a bit, but there was a lot of truth in his words.

When a machine needs to locate a Domain Controller, it queries DNS for specific SRV records. We can do exactly the same thing manually with nslookup. No creds, no domain membership required.

The key record is _ldap._tcp.dc._msdcs.<domain>. That's the record Windows clients use to find DCs. If you already have a domain name — maybe you grabbed it from NBNS traffic, or someone told you the environment name, or you got it from the nmap scan above — you can query it directly:

Windows — nslookup SRV query
PS C:\Users\chepe> nslookup -type=SRV _ldap._tcp.dc._msdcs.contoso.com DNS request timed out. timeout was 2 seconds. Server: UnKnown Address: 192.168.115.120 _ldap._tcp.dc._msdcs.contoso.com SRV service location: priority = 0 weight = 100 port = 389 svr hostname = dc01.contoso.com dc01.contoso.com internet address = 192.168.115.120

That's the output from the screenshot. Notice the DNS server itself is 192.168.115.120 — which is the same IP the SRV record resolves to. The DC is also the DNS server. Very common in AD environments, especially smaller ones. One query confirmed both the hostname and the IP.

The "DNS request timed out" at the top looks scary but it's not. That just means the reverse lookup for the DNS server's name didn't resolve. The actual query worked fine. You still got your answer.

You can also run this same query from Linux with dig:

kali — dig SRV query
$ dig SRV _ldap._tcp.dc._msdcs.contoso.com @192.168.115.120 ;; ANSWER SECTION: _ldap._tcp.dc._msdcs.contoso.com. 600 IN SRV 0 100 389 dc01.contoso.com. ;; ADDITIONAL SECTION: dc01.contoso.com. 1200 IN A 192.168.115.120

Same result. Hostname and IP, no creds.

⚠ heads up
This works when you already know the domain name. If you don't, pair it with Method 1 first to grab the domain from the LDAP Root DSE, then come back here to confirm with SRV records.
03 — nltest

Method 3 — nltest from a Windows Foothold

This one is for when you're already on a Windows machine but do not have valid domain credentials yet. And one of the coolest things is that you do not have to upload or install anything. nltest is a built-in Windows tool.

The /dclist flag tries to enumerate DCs for a given domain by binding to the Netlogon service on a DC. Here's the thing though — look at what happens when you're not on a domain joined machine:

Windows — nltest /dclist
PS C:\Users\chepe> nltest /dclist:contoso.com Get list of DCs in domain 'contoso.com' from '\\dc01.contoso.com'. You don't have access to DsBind to contoso.com (\\dc01.contoso.com) (Trying NetSe I_NetGetDCList failed: Status = 6118 0x17e6 ERROR_NO_BROWSER_SERVERS_FOUND

The error is misleading. ERROR_NO_BROWSER_SERVERS_FOUND sounds like it found nothing but look at the first line: "Get list of DCs in domain 'contoso.com' from '\\dc01.contoso.com'". It already told you the DC hostname before failing. The failure happens because we don't have credentials to actually bind and pull the full list. But the reconnaissance value is already there in line one.

If you want a cleaner approach from a Windows foothold, use /dsgetdc instead:

Windows — nltest /dsgetdc
PS C:\Users\chepe> nltest /dsgetdc:contoso.com DC: \\dc01.contoso.com Address: \\192.168.115.120 Dom Guid: <guid> Dom Name: contoso.com Forest Name: contoso.com Dc Site Name: Default-First-Site-Name Our Site Name: Default-First-Site-Name Flags: PDC GC DS LDAP KDC TIMESERV WRITABLE DNS_FOREST CLOSE_SITE

That one works without domain membership. It queries DNS for the SRV records under the hood; same thing as Method 2 but wrapped in a Windows tool. The Flags field is gold. PDC means this is the Primary DC. GC means it's a Global Catalog server. KDC confirms Kerberos. You're looking at the full profile of the DC from a single unauthenticated call.

04 — netexec

Method 4 — NetExec

I always joke and say that NetExec is better than bread and butter. I do not see myself doing an AD engagement without it. It is so powerful and versatile but easy to use.

SMB is present on all Windows boxes including servers. I have never seen a box with that port or service blocked. Windows may work without it but will cause a lot of headaches and some services may not work properly. So we can take advantage of that and use nxc to scan the network and fingerprint assets, including DCs. No credentials needed for this, just find the right subnet:

kali — nxc subnet sweep
$ nxc smb 192.168.115.0/24 SMB 192.168.115.105 445 WS01 [*] Windows 11 Build 22631 (name:WS01) (domain:contoso.com) (signing:False) (SMBv1:False) SMB 192.168.115.120 445 DC01 [*] Windows Server 2022 Build 20348 (name:DC01) (domain:contoso.com) (signing:True) (SMBv1:False)

That single line for DC01 gives you the hostname, domain name, OS version, and SMB signing status — all from an unauthenticated probe. The signing:True on the DC is expected and actually another indicator. DCs enforce SMB signing by default. Workstations typically don't.

You'll notice I'm not passing -u or -p here at all. nxc doesn't require credentials to enumerate hosts at this level. It's just sending an SMB negotiation and reading the response banner. Completely unauthenticated.

If you want to go one step further and attempt a null session to see what comes back:

kali — nxc null session
$ nxc smb 192.168.115.120 -u '' -p '' SMB 192.168.115.120 445 DC01 [*] Windows Server 2022 Build 20348 (name:DC01) (domain:contoso.com) (signing:True) (SMBv1:False) SMB 192.168.115.120 445 DC01 [-] contoso.com\: STATUS_ACCESS_DENIED

The STATUS_ACCESS_DENIED on null sessions is the expected response on hardened modern DCs and that's fine. The host enumeration line above it already gave you what you need. Null sessions being blocked doesn't stop you from reading the banner.

⚠ tip
The subnet sweep with no creds is the fastest way to map the whole environment at once. You'll see every Windows host that responds on 445, their hostnames, domain membership, and OS version in one shot. Run this early.
05 — ldapsearch

Method 5 — ldapsearch Anonymous Bind

If nmap isn't available or you want a more targeted approach, ldapsearch can query the LDAP Root DSE directly with an anonymous bind. By default, Active Directory allows unauthenticated clients to read the Root DSE — Microsoft's own spec requires this so that clients can discover the AD structure before authenticating.

The command for a Root DSE query looks like this:

kali — ldapsearch root DSE
$ ldapsearch -x -H ldap://192.168.115.120 -s base -b "" "(objectClass=*)" dn: objectClass: top currentTime: 20250604120000.0Z subschemaSubentry: CN=Aggregate,CN=Schema,CN=Configuration,DC=contoso,DC=com dsServiceName: CN=NTDS Settings,CN=DC01,CN=Servers,CN=Default-First-Site,... namingContexts: DC=contoso,DC=com namingContexts: CN=Configuration,DC=contoso,DC=com namingContexts: DC=DomainDnsZones,DC=contoso,DC=com namingContexts: DC=ForestDnsZones,DC=contoso,DC=com defaultNamingContext: DC=contoso,DC=com dnsHostName: dc01.contoso.com domainControllerFunctionality: 7

Flag breakdown: -x tells ldapsearch to use simple authentication instead of SASL. -H is the URI of the target. -s base restricts the search scope to the base entry only, so you're only pulling the Root DSE and not trying to walk the whole directory. -b "" sets an empty base DN which is how you target the Root DSE specifically.

The output gives you the domain naming context, the DC hostname via dnsHostName, and the domainControllerFunctionality value which maps to the Windows Server version. Value 7 means Windows Server 2016 or newer.

This is essentially the same query the nmap ldap-rootdse script runs under the hood — just without nmap in the picture. Good to know when you're working in a constrained environment or pivoting through a tunnel where you'd rather keep it to a single clean LDAP connection instead of a full port scan.

● note
If ldapsearch returns ldap_bind: Inappropriate authentication (48) it means anonymous binds are disabled on that server. That's less common on Windows AD but it does happen. Fall back to Method 1 or 4 in that case since those don't rely on an LDAP bind at all.
06 — wrap-up

Putting It Together

In real life, during an Active Directory pentest or CTF, we want to combine as many of these as we can. I usually run nxc to sweep the network, map every Windows host in one shot and immediately spot the DC by hostname convention and signing status. Then I can hit that box with either the nmap ldap-rootdse script or ldapsearch to pull the full domain info. Or if I am already on a Windows box, I take advantage of nltest or nslookup.

Five minutes later and you have the DC hostname, IP, domain name, forest name, and OS version, all without a single credential.

Now you can go after null session SMB, anonymous LDAP binds deeper into the directory, AS-REP roasting against accounts that don't require preauth. But that's a different post.

● takeaway
This workflow is relevant for OSCP, OSEP, and any internal pentest or red team engagement. The recon phase before you have creds is where a lot of people rush. Don't rush it. Understanding the environment first makes everything after it faster.