Skip to main content

Enumerating Hosts and Identifying the Domain Controllers

Fingerprinting Domain Controllers

PORT     STATE SERVICE
53/tcp   open  domain
88/tcp   open  kerberos-sec
135/tcp  open  msrpc
139/tcp  open  netbios-ssn
389/tcp  open  ldap
445/tcp  open  microsoft-ds
464/tcp  open  kpasswd5
593/tcp  open  http-rpc-epmap
636/tcp  open  ldapssl
3268/tcp open  globalcatLDAP
3269/tcp open  globalcatLDAPssl

Typical port signature of a domain controller (e.g. DNS, Kerberos, LDAP)


Host Discovery

Internal

ARP-Scan

Since this is an internal assessment, Kali is on the same LAN segment as the target(s) and ICMP is not needed to enumerate. ARP does not flow over VPN connections, as ARP is a layer 2 protocol and most VPNs operate at layer 3.

sudo arp-scan -d 10.10.10.0/24

Broadcast ARP discover requests on 10.10.10.0/24

nmap -n -sn 10.10.10.0/24

Functionally doing the same thing as arp-scan above

NetExec

You can spray some unauthenticated SMB requests around a network to discover hosts. This will reveal the hosts' NetBIOS names, from which you may able to identify domain controllers and servers.

This will only work on hosts where SMB is enabled.

nxc smb 10.10.10.0/24

Send unauthenticated SMB requests to 10.10.10.0/24

External

Ping Sweep on Target

Not the most reliable, as ICMP is disabled by default on Windows hosts.

Linux
ip="10.80.80.0"; cidr=24; IFS=. read -r i1 i2 i3 i4 <<< "$ip"; raw=$(( (1 << (32 - cidr)) - 2 )); base_ip=$(( (i1<<24) + (i2<<16) + (i3<<8) + i4 )); network=$(( base_ip & (0xFFFFFFFF << (32 - cidr)) )); for i in $(seq 1 $raw); do ip_calc=$((network + i)); printf "%d.%d.%d.%d\n" $(( (ip_calc >> 24) & 255 )) $(( (ip_calc >> 16) & 255 )) $(( (ip_calc >> 8) & 255 )) $(( ip_calc & 255 )); done | awk '{ system("ping -c 1 -w 1 " $1 " | grep \"bytes from\" &"); }' > ping_sweep.txt

Awk ICMP sweep (as documented here), output to ping_sweep.txt

PowerShell
1..254 | % { try { (ping -n 1 -w 1 10.10.10.$_ | select-string 'reply from').ToString().Split(' ')[2] -replace ':' } catch {} }

PowerShell ICMP sweep

NetExec

Again, only effective as long as SMB is enabled on the target.

# Via proxy host
proxychains -q nxc smb 10.10.10.0/24

fping

fping -ag 10.10.10.0/24

If pivoting through ligolo-ng, then ICMP is supported, would not work on SOCKS -- e.g. chisel or ssh

Nmap

SOCKS

sudo proxychains -q nmap -Pn -sT -T4 --top-ports 100 -oN discovered_hosts.txt 10.10.10.0/24

Scan via SOCKS proxy for top 100 ports on 10.10.10.0/24 as a means of finding live hosts

Tunnel

sudo nmap -sn -oN discovered-hosts.txt 10.10.10.0/24

Using a tunnel such as ligolo-ng supports ICMP host discovery

Transferred Tools

Could transfer tools internally to further enumerate hosts


Port Scans

Now that you've enumerated live hosts, save any hostnames or IP addresses that you've found to a file -- for example, targets.txt -- and feed this file into tooling for convenience.

In both scenarios below -- internal and external -- the scan output should include the SMB signing requirements for the target(s). Make a note of this for SMB relaying where SMB signing is not required.

Internal

Nmap on the Target

sudo nmap -Pn -p- -T4 -sC -sV -oN nmap-scan.txt -iL targets.txt

Scan all ports on targets.txt list and save output in nmap-scan.txt

Linux Binaries

seq 1 65535 | awk '{ target="10.80.80.2"; port = $1; if (system("nc -nz " target " " port) == 0) { print "Port " port " is open"} ; }' > awk_scan.txt &

Awk port scan (as documented here), output to awk_scan.txt

PowerShell

https://github.com/0xBEN/PSToolbox/blob/master/Public/ps1/Test-TcpPort.ps1

External

You also have the option of transferring a statically compiled nmap binary to a target internally and running from there; in which case, see the "Internal" port scan notes just above.

SOCKS

sudo proxychains -q nmap -Pn -sT -sC -sV -T4 --top-ports 1000 -oN nmap-scan.txt -iL targets.txt

If pivoting through chisel or ssh SOCKS proxies, must use -sT and recommend using --top-ports, as TCP connect scans are notoriously slow

Tunnel

sudo nmap -Pn -p- -T4 -sC -sV -oN nmap-scan.txt -iL targets.txt

If pivoting through a layer 3 tunnel like ligolo-ng will typically perform better, but may still have some overhead as opposed to running internally


Identify the Root Domain

Now that you've run your port scan on the targets.txt list, refer to your nmap-scan.txt output and compare that with the information above on fingerprinting the Domain Controller.

Once you've identified the Domain Controller, it's time to establish the root domain of the environment.

LDAP DSE

The root DSE is the entry at the top of the LDAP server directory information tree. All the namingcontexts (suffixes) in the LDAP server are directly below the root DSE. The root DSE contains information about the LDAP server, including the namingcontexts that are configured and the capabilities of the server.

-- https://www.ibm.com/docs/en/zos/2.1.0?topic=considerations-root-dse

Internal

sudo nmap -Pn -T4 -p 389,636 --script ldap-rootdse 10.10.10.2 | grep dnsHostName | sort -u

Assumes 10.10.10.2 is the DC based on port enumeration

External

SOCKS

sudo proxychains -q nmap -Pn -T4 -sT -p 389,636 --script ldap-rootdse 10.10.10.2 | grep dnsHostName | sort -u

Assumes 10.10.10.2 is the DC based on port enumeration. Scan via SOCKS proxy -- e.g. chisel or ssh

Tunnel

sudo nmap -Pn -T4 -p 389,636 --script ldap-rootdse 10.10.10.2 | grep dnsHostName | sort -u

Functionally the same as above, but assumes you're pivoting via tunnel -- e.g. ligolo-ng

Add DC to Hosts File

echo -e '10.10.10.2\t\tdc01.ad.lab ad.lab' | sudo tee -a /etc/hosts