12 min read

Reconnaissance

Active Discovery

Active discovery is the first phase that sends packets to hosts nobody invited you to touch. Its job is narrow on purpose: turn the addresses you learned passively into a list of live hosts and the protocol that identifies each one, so the scan that follows has targets instead of guesses.

Warning

Active scanning generates logs and may trigger security alerts. Coordinate with the client on acceptable scanning windows and intensity levels before the first packet, and agree in writing which segments are out of scope — a discovery sweep crosses a firewall boundary more often than an exploitation attempt does. Ask who owns each range you are about to sweep: a segment can sit behind the client's firewall and still be managed by a service provider whose authorisation the client cannot give you.

Host Discovery

Use more than one discovery method and reconcile the answers. Each method fails in a different way, and the set of hosts that respond to ARP but not to ICMP is not an edge case — it is the normal state of a hardened Windows estate, where the host firewall drops echo requests while the machine is perfectly alive.

ARP Scanning (Layer 2)

On the local segment ARP is the only reliable discovery method: a host cannot ignore an ARP request without losing its own connectivity, and the reply proves the machine exists rather than that a firewall rule allows probing. An ARP sweep also returns MAC addresses, which give you the vendor before you open a port. It does not cross a router, so run it once per segment and treat the results as authoritative for that segment only.

arp-scan.sh
# ARP scan - fastest for local subnet (Layer 2)
sudo arp-scan -l -I eth0

# Specify range
sudo arp-scan -I eth0 10.0.0.0/24

# Multiple subnets
sudo arp-scan -I eth0 10.0.0.0/24 10.0.1.0/24

# Netdiscover active mode
sudo netdiscover -i eth0 -r 10.0.0.0/24

ICMP Discovery

A ping sweep is the fastest way to cover a routed range and the easiest to be wrong about. Hosts that do not answer -sn are "down" only in the sense that they did not answer; Windows Firewall blocks inbound echo by default on the public and domain profiles, so expect the majority of workstations to be missing from the results. fping -a is worth preferring on large ranges because it keeps state per host and finishes in seconds, and the timestamped variant gives you a timeline you can compare against a later sweep.

ping-sweep.sh
# Ping sweep with nmap
nmap -sn 10.0.0.0/24

# Faster ping sweep (no DNS resolution)
nmap -sn -n 10.0.0.0/24

# Using fping (faster for large ranges)
fping -a -g 10.0.0.0/24 2>/dev/null

# With timestamps
fping -a -g 10.0.0.0/24 2>/dev/null | while read ip; do
  echo "$(date +%H:%M:%S) - $ip"
done

TCP/UDP Discovery

When ICMP is filtered, ask a service instead. A SYN to a closed port still returns a RST from a live host, which is why -PS finds machines that -sn alone misses; -PA catches hosts that drop SYNs but answer ACKs; -PU on 53 or 161 reaches hosts that filter all TCP. Combine them in one pass rather than three, and treat a host that appears in none of the three as genuinely absent — or as being filtered by an inline device, which is itself worth reporting.

tcp-udp-discovery.sh
# TCP SYN discovery (when ICMP blocked)
nmap -sn -PS22,80,443,445 10.0.0.0/24

# TCP ACK discovery
nmap -sn -PA80,443 10.0.0.0/24

# UDP discovery
nmap -sn -PU53,161 10.0.0.0/24

# Combined discovery
nmap -sn -PS22,80,443,445 -PA80,443 -PU53,161 10.0.0.0/24

# Using masscan for speed
sudo masscan 10.0.0.0/24 -p22,80,443,445 --rate=1000

Port Scanning

Port scanning, service and version detection, NSE scripts and vulnerability scanning are owned by the Scanning page, where the workflow, timing templates and output formats are covered in one place. The division of labour is deliberate: this page answers "which hosts exist and what identifies them", that page answers "what is listening on them and how is it configured". Do not spend the discovery phase on a full -p- sweep — you will generate the engagement's loudest traffic before you know which addresses deserve it.

SMB Discovery

An unauthenticated SMB sweep is the single highest-value discovery step on a Windows network, because the protocol answers with more than "open": each responding host returns its NetBIOS name, domain, OS build, SMB dialect and signing state. Read the output column by column. The host line tells you which domain the machine belongs to and therefore whether a trust boundary is in play; SMBv1: True is a legacy finding; and signing status is the input to the relay work on the Relay Attacks page, which is why --gen-relay-list is worth running even at this stage. Hosts that answer on 445 but return STATUS_NOT_SUPPORTED are usually appliances or NAS devices with their own bugs, and they are easy to pick out because the OS field is blank.

smb-discovery.sh
# Identify SMB hosts
nmap -p 445 --open 10.0.0.0/24

# nxc SMB scan
nxc smb 10.0.0.0/24

# Identify domain controllers
nxc smb 10.0.0.0/24 | grep -i "domain"

# Generate relay target list (SMB signing disabled)
nxc smb 10.0.0.0/24 --gen-relay-list relay_targets.txt

# Enumerate shares (null session)
nxc smb 10.0.0.0/24 --shares

Danger

Use the account the client issued, not one you found. An unauthenticated SMB sweep is read-only and low risk; nxc smb 10.0.0.0/24 with a real credential is an authenticated action that lands a 4624 on every host in the range and, on a locked-out estate, can take real staff offline through the account you borrowed. A credential recovered during the engagement is not an authorisation to use it estate-wide — clear it with the client first, and keep the sweep to the subnets in the signed scope.

Domain Controller Discovery

You do not need credentials to find the DCs, and you should find all of them before you touch LDAP: the domain's SRV records list every DC in the site, and the PDC emulator record names the one that holds the account-lockout authority. DNS is the cheapest source and the one least likely to alert. The port signature — 88, 389, 636, 3268, 3269 open together — is the confirmation, and ldap-rootdse returns defaultNamingContext, which is the base DN every query on the next page needs. Full DC enumeration and per-DC role analysis belong to the Scanning page; this section gives you the list to feed it.

dc-discovery.sh
# DNS-based DC discovery
nslookup -type=SRV _ldap._tcp.dc._msdcs.DOMAIN.COM
nslookup -type=SRV _kerberos._tcp.DOMAIN.COM
nslookup -type=SRV _gc._tcp.DOMAIN.COM

# Find PDC
nslookup -type=SRV _ldap._tcp.pdc._msdcs.DOMAIN.COM

# LDAP banner grab (returns defaultNamingContext)
nmap -p 389 --script ldap-rootdse 10.0.0.1

Service-Specific Discovery

Once you have live hosts, classify them by the port that identifies their role rather than scanning everything: 1433, 1434, 3306, 5432, 1521 and 27017 mark database servers; 80, 443, 8080 and 8443 mark web front ends and internal applications; 3389, 22, 5985 and 5900 mark remote access paths, which are the lateral-movement candidates; 161, 9100, 515 and 631 mark network devices and printers, which are usually the least patched things on the network. Scan only the ports that would change your plan — a full port sweep of a /24 at this stage produces a lot of alerting for a list you will re-derive during scanning anyway. The commands and timing guidance for each service family live on the Scanning page; enumeration of the services themselves is on Database Enumeration and SMB Enumeration.

Scan Optimization

The two-tool pipeline exists because the tools fail differently. Masscan is stateless and asynchronous, so it can cover a /16 in minutes and will also miss hosts behind a rate limiter or a load balancer; nmap is slower because it tracks state and retransmits, which is what makes its results trustworthy. Use masscan to find the open ports, then nmap to confirm the ones that matter. Keep --rate conservative on a production network: a high rate is the fastest way to saturate a WAN link or to have the client's IPS drop your source address mid-engagement.

masscan-then-nmap.sh
# Masscan for speed (then nmap for accuracy)
# Phase 1: Fast discovery
sudo masscan 10.0.0.0/16 -p 21,22,23,25,53,80,88,110,135,139,143,389,443,445,636,1433,3306,3389,5432,8080 --rate=10000 -oG masscan_results.txt

# Phase 2: Parse masscan output
grep "Ports:" masscan_results.txt | awk '{print $4}' | cut -d'/' -f1 | sort -u > ports.txt
grep "Ports:" masscan_results.txt | awk '{print $2}' | sort -u > hosts.txt

# Phase 3: Detailed nmap scan
nmap -sV -sC -iL hosts.txt -p $(cat ports.txt | tr '\n' ',') -oA detailed_scan

What the Defender Sees

Discovery is the phase where the blue team is most likely to notice you, and the honest framing is that a sweep which produces no alerts may mean the estate has no network monitoring rather than that your technique was quiet. What each method leaves behind:

  • ARP and ICMP sweeps: nothing in host logs. Visible only in NetFlow, switch port statistics or an IDS tuned for scan patterns — which is why the network team's detection coverage is worth asking about before the first sweep.
  • SMB sweep: a 4625 on every host where the credential failed, and a burst of 445 connections from one source. This is the noisiest discovery method and the most useful, so run it once with a deliberate credential rather than repeatedly with guesses.
  • DNS SRV lookups: standard queries in the DNS server log, indistinguishable from a workstation locating a DC. The quietest DC discovery available.
  • Port scans: firewall and IDS records for every SYN; a horizontal scan of one port across a subnet is the classic signature. Rate is the variable you control.

Quick Reference

Target Ports Tool/Command
Domain Controllers 88, 389, 636, 3268 nmap, nxc
File Servers 445, 139, 2049 smbclient, nxc
Databases 1433, 3306, 5432, 1521 nmap scripts
Web Servers 80, 443, 8080, 8443 eyewitness, aquatone
Remote Access 22, 3389, 5985, 5900 nmap, nxc

Evidence Collection

Discovery evidence is an inventory plus the method that produced each entry, because every later phase inherits it.

Live host list: Addresses that answered, per method (ARP, ICMP, SYN, ACK, UDP), with the sweep command and timestamp. A host found only by ARP and not by ICMP is a fact worth recording, not a discrepancy to hide.

SMB host table: The nxc smb output per host: name, domain, OS build, SMB dialect, signing state. That one table feeds the relay work and the patch-level analysis later.

Relay candidate list: The --gen-relay-list output as a file, with the date. Signing state changes with builds and policy, so the list is only valid for the run that produced it.

DC and GC confirmation: The SRV query and the port combination that confirmed each DC, plus defaultNamingContext from ldap-rootdse — the base DN every later query needs.

Role classification: Which hosts carry database, web, remote-access and print ports, and therefore which ones the enumeration phase should open with.

False Positive Identification

  • No ICMP reply is not a dead host: Windows Firewall blocks echo on the domain and public profiles by default. Reconcile every sweep against ARP and SMB before reporting a host as absent.
  • Masscan false negatives: A rate limiter, load balancer or IPS drop makes a fast scan miss live services. Confirm anything that matters with nmap, and treat a masscan-only result as provisional.
  • An appliance on 445: A NAS or print appliance answering SMB with a blank OS field and STATUS_NOT_SUPPORTED is not a Windows host and will not follow Windows behaviour. Classify it before planning around it.
  • A DC signature without LDAP: Ports 88/389/636 open together on a member server running a relay is rare but possible. Confirm with ldap-rootdse before calling a host a domain controller.

Testing Checklist

Discovery is where a wrong answer is cheapest to catch: every host you miss here becomes a host you report as absent.

Confirm the sweep is complete

  • ☐ An ARP sweep finds hosts that ICMP and SYN miss - reconcile the three lists and explain every address found by only one method.
  • ☐ The SMB sweep returns name, domain and signing state per host; anything answering 445 with a blank OS string is classified before it is counted.
  • ☐ --gen-relay-list output is written to a dated file and regenerated for each run - signing state changes with builds and policy.
  • ☐ Port scanning runs from the position you will exploit from, because a rule between segments changes the answer.

Confirm the discovery facts

  • ☐ The SRV query for _ldap._tcp.dc._msdcs returns every DC the client expects, including site-specific records.
  • ☐ ldap-rootdse returns defaultNamingContext and domainFunctionality without credentials - that is the base DN later phases need.
  • ☐ Masscan results are confirmed with nmap before any port is reported; a fast scan's misses are not absences.
  • ☐ Any host written off as dead was tested with ARP and SMB, not ICMP alone.

Remediation & Defense

Discovery is hard to prevent and easy to detect; the useful controls are the ones that shorten the inventory an attacker can build.

Shrink the answer surface

  • • Require SMB signing, so an unsigned host cannot become a relay target
  • • Keep host firewalls on for every profile, and block SMB and RPC between workstation VLANs
  • • Remove unused services — Telnet, TFTP, SNMP v1/v2c, JetDirect — from servers and printers

Detect the sweeps

  • • Baseline NetFlow per subnet and alert on one source touching many hosts on one port
  • • Alert on a burst of 4625 across many hosts, and on anonymous SMB logons
  • • Log DNS SRV queries at the DCs so DC discovery is at least recorded