Workflow: Network Reconnaissance
Phase 1 of the engagement. Goal: inventory reachable hosts, protocols, and services within the authorized scope, producing a target list that downstream workflows consume.
Preconditions
- Written scope defines CIDRs, excluded ranges, and time window
- Source IP is on the engagement allowlist if one exists
- A working directory exists:
loot/<engagement>/recon/
Inputs
scope.txt— list of CIDRs / hostnames in scopeexcluded.txt— hosts/ranges to skip
Outputs
live.txt— responsive hostsservices.gnmap/services.xml— nmap service inventorysmb.csv,ldap.csv— per-protocol enumeration resultsusers_guess.txt— candidate userlist from enumeration
Step sequence
1. Host discovery (parallelizable per /24)
# Split scope.txt into /24s and fan out. Each /24 is independent.
while read -r cidr; do
(nmap -sn "$cidr" -oG - | awk '/Up$/{print $2}' > "live_${cidr//\//_}.txt") &
done < scope.txt
wait
cat live_*.txt | sort -u > live.txtFor /16+ scopes, substitute masscan:
sudo masscan -iL scope.txt -p22,80,135,139,389,443,445,3389,5985 \
--rate 5000 -oL masscan.lst
awk '/^open/{print $4}' masscan.lst | sort -u > live.txt2. Service fingerprinting (parallelizable per host batch)
Split live.txt into N batches, one batch per sub-agent:
split -n l/8 -d live.txt batch_
for b in batch_*; do
(nmap -sV -sC -Pn -iL "$b" \
-p 21,22,23,25,53,80,88,110,135,139,143,389,443,445,464,\
593,636,1433,1521,2049,3268,3269,3306,3389,5432,5985,5986,8080,8443 \
-oA "services_${b}" ) &
done
wait3. Protocol-specific enumeration (fan-out by protocol)
All four enumeration streams below are independent — run concurrently.
SMB
nxc smb live.txt --shares --sessions --loggedon-users > smb_null.txt
enum4linux-ng -A -oY enum4linux.yaml target-dcLDAP (null/anonymous then authenticated if creds obtained)
ldapsearch -x -H ldap://dc -s base namingcontexts
ldapsearch -x -H ldap://dc -b "DC=corp,DC=local" "(objectClass=domain)"DNS
dig @dc corp.local AXFR
dnsrecon -d corp.local -t std,brt,srv -n dcRPC (null session where allowed)
rpcclient -U "" -N dc -c 'enumdomusers;enumdomgroups;querydominfo'4. Consolidate and hand off
# Produce a single services.csv for downstream workflows
python3 -c "
import xml.etree.ElementTree as ET, glob, csv, sys
w = csv.writer(sys.stdout)
w.writerow(['host','port','proto','service','product','version'])
for f in glob.glob('services_*.xml'):
for h in ET.parse(f).getroot().iter('host'):
addr = h.find('address').get('addr')
for p in h.iter('port'):
s = p.find('service')
w.writerow([addr, p.get('portid'), p.get('protocol'),
s.get('name','') if s is not None else '',
s.get('product','') if s is not None else '',
s.get('version','') if s is not None else ''])
" > services.csv
# Extract DC candidates for AD workflow
grep -E 'ldap|kerberos|389' services.csv | cut -d, -f1 | sort -u > dc_candidates.txt
# Extract Windows hosts for SMB-heavy workflows
grep -E 'microsoft-ds|netbios-ssn|445,tcp|139,tcp' services.csv | cut -d, -f1 | sort -u > windows_hosts.txtParallelism checklist
| Step | Parallel? | Notes |
|---|---|---|
| /24 host discovery | Yes | One sub-agent per /24 |
| Service fingerprinting | Yes | Batch live.txt by N workers |
| SMB / LDAP / DNS / RPC enum | Yes | Different protocols, different endpoints |
| enum4linux per DC | Sequential (per DC) | Heavy RPC load; don't fan out |
Safety hints
- Avoid
--min-rate 10000on mixed (cloud + on-prem) scopes — link saturation can knock VPN tunnels. - UDP scans are slow and often disruptive; restrict to
--top-ports 50unless scope demands more. - If an IDS allowlist was granted per source IP, verify it's working before running loud scans (e.g.,
-T4with scripts). - Keep raw nmap XML — it's the primary report evidence.
Next workflow
- If a DC is identified and creds are in hand:
workflows/ad_enumeration.md - If creds are not yet in hand:
workflows/credential_attacks.md(Responder, spraying)