FLOW ^: Pentest Workflow

Stage 01 — Recon and Host Discovery

CPTS attack-flow reference for stage 01 — recon and host discovery in an authorised engagement.

intermediate updated 2026-08-29 RustScan · Nmap · dig · Kerberos

[!dashboard] Attack-flow navigation Dashboard: HTB Pentest Attack Flow

Section: 02 of 17 · Focus: Stage 01 — Recon and Host Discovery

Previous: Stage 00 — Passive External Recon · Next: Stage 02 — Web Enumeration and Exploitation


🛰️ STAGE 1 — Recon & Host Discovery

First contact. Get the box into /etc/hosts + krb5.conf, kill clock skew before anything Kerberos, then rustscan → nmap the whole surface. rustscan finds the ports in seconds, nmap tells me what they are. Everything downstream branches off this scan, so I scan wide first and read carefully.

[!note] Env $IP $DOMAIN $DC $LHOST $U $P are already exported by the guide’s setup block. On a fresh box I usually only know $IP at first — $DOMAIN/$DC get filled in from the scan (SMB/LDAP ssl-cert, smb-os-discovery) and from /etc/hosts below.

[!abstract] MITRE ATT&CK — Recon / Discovery

TechniqueWhere it lands here
T1595 Active Scanningnmap/rustscan/masscan against the perimeter
T1595.001 Scanning IP Blockssubnet sweeps, -sn discovery
T1595.002 Vulnerability Scanning--script vuln, nuclei later
T1046 Network Service Discoverypost-foothold internal scanning (fscan section)
T1018 Remote System DiscoveryLAN host discovery (arp-scan/netdiscover)
T1070.001 Timestomp-adjacent hygieneclock sync avoids noisy Kerberos failures

0. SETUP — hosts + realm + clock (do this first, every AD box)

What to look for → the DC’s hostname/FQDN, the domain FQDN, and whether my clock matches the DC. Skip this and every Kerberos tool later throws KRB_AP_ERR_SKEW.

Enumerate / prep

# Auto-populate /etc/hosts with DC + domain straight from SMB
sudo nxc smb $IP --generate-hosts-file /etc/hosts

# Manual fallback / add extra vhosts as I find them
echo "$IP  $DC $DOMAIN dc01" | sudo tee -a /etc/hosts

# Generate a matching krb5.conf realm (needed for -k Kerberos auth later)
nxc smb $DC --generate-krb5-file krb5.conf
sudo cp krb5.conf /etc/krb5.conf

Fix the clock (measure the skew, then either sync or wrap)

# Measure skew straight off AD services (DC-minus-you; positive = DC ahead)
nmap -p445,88 --script smb2-time,clock-skew -Pn $DC
ntpdate -q $DC                      # prints offset in seconds
nxc smb $IP | grep -i time          # quick sanity check vs DC

# Option A — sync my whole host to the DC (simplest)
sudo ntpdate -u $DC
sudo apt install ntpdate -y         # if missing
sudo rdate -n $DC                            # modern alt
sudo chronyd -q "server $DC iburst"          # modern alt

# htpdate — sync over plain HTTP when NTP/UDP 123 is blocked by the VPN
sudo htpdate -s $DOMAIN              # uses the web server's Date: header

# Option B — surgical: leave my clock alone, wrap only the tool that talks Kerberos
faketime -f '+7h30m' <kerberos-tool>         # +offset if DC is ahead, - if behind

[!warning] Watch out

  • Clock skew is the #1 Kerberos killer. Any KRB_AP_ERR_SKEW = re-run ntpdate -u $DC. Re-check if a box’s time drifts mid-engagement.
  • faketime sign matters: nmap’s clock-skew is DC minus you — positive means DC is ahead, push forward (+). Wrong sign doubles the skew.
  • Use faketime -f (follow) for anything Python/impacket — child procs don’t inherit the fake clock without -f.
  • Writing --generate-hosts-file /etc/hosts needs sudo. evil-winrm -r $DOMAIN and all -k auth need the FQDN resolving here, so keep /etc/hosts current as vhosts surface. Deep dive: faketime-cheatsheet · tools: faketime, htpdate.

1. nmap flag reference (the whole arsenal)

[!example] Host discovery

FlagMeaningUse
-snPing sweep — no port scanmap a subnet without touching ports
-PnSkip host discovery (treat all as up)HTB default — ICMP usually blocked
-PS22,80,443TCP SYN ping on given portsdiscovery when ICMP dead but TCP open
-PA80,443TCP ACK pingslips past stateless ACLs that block SYN
-PU53,161UDP pingrare; catches UDP-only hosts
-PE/-PP/-PMICMP echo / timestamp / netmaskclassic ping types
-nNo reverse DNSspeed + silence; rDNS leaks your target in DNS logs anyway
--openOnly show open portscuts closed noise on -p- sweeps
--reasonShow why a port got its statedistinguishes RST vs timeout

[!example] Scan types

FlagMeaningNotes
-sSSYN “half-open” scandefault with root; fast, classic
-sTFull TCP connectno root / through proxies; loudest (full handshake logged)
-sUUDP scanslow; pair with --top-ports
-sVService/version detectionprobes banners; enables version-intensity scripts
-sCDefault NSE scripts (--script=default)safe-ish, high signal
-A-sV -sC -O + tracerouteconvenient, noisy
-OOS detectionneeds open+closed port; --osscan-guess forces
-sN/-sF/-sXNULL/FIN/XmasFW evasion on non-Windows targets (Windows answers RST regardless)
-sAACK scanmaps firewall rules (filtered vs unfiltered), not port state
--script <name>Run specific NSE script(s)comma-sep, globs OK: "smb-* and not smb-brute"

[!example] Timing, ports, output

FlagMeaning
-T0-T5paranoid / sneaky / polite / normal / aggressive / insane — -T4 is the lab default, -T0/-T1 for IDS dodging (very slow)
--min-rate 1000 / --max-rate 500packets/sec floor/ceiling — the real speed knob
--min-parallelism / --max-retries 2concurrency / retry cap for flaky links
-p-all 65535 TCP ports
-p80,443,8000-9000explicit list/range
--top-ports 100nmap’s statistically-most-common ports
-Ffast mode (~100 most common)
-oA basenameall three outputs: .nmap .gnmap .xml — always use it
-oX file.xmlXML (for ndiff / xsltproc / imports)
-oG file.gnmapgreppable (shell one-liners)
-v / -vvverbosity; --stats-every 15s progress lines
--resume file.nmapresume an interrupted scan

[!example] Evasion / spoofing

FlagMeaningPitfall
-fFragment IP packets (8-byte)modern IDS reassembles; breaks some services’ replies
--mtu 16Custom fragmentation (multiple of 8)controlled version of -f
-D RND:10,MEDecoy scan — target sees N fake sources + youdoesn’t hide you, just dilutes; never use on client reports without ROE
-S <IP>Spoof source addressreplies go to the spoofed IP — you won’t see results unless you can sniff them
--source-port 53Fixed source portsneaks past lazy “allow UDP/53 out” firewall rules (also -g 53)
--proxies http://...Route through proxiesforces -sT, slow
--data-length 24Append random payloaddefeats “packet size signature” detection
--spoof-mac 0Random MACLAN/VMnet only
-sI zombie:portIdle scan (fully blind)needs idle zombie with predictable IP-ID — rare in practice, exam-famous

2. NSE — categories and the scripts I actually run

Categories (use with --script <cat>): auth · broadcast · brute (lockout risk) · default (= -sC) · discovery · dos (never in prod) · exploit · external (queries whois/virustotal) · fuzzer · intrusive · malware · safe · version · vuln.

[!example] High-signal scripts by service

Port/ServiceScriptsGets you
21 FTPftp-anon,ftp-systanonymous login, OS hints
22 SSHssh2-enum-algos,ssh-hostkey,ssh-auth-methodsweak algos, password vs key auth
53 DNSdns-zone-transfer,dns-recursion,dns-nsidAXFR, open resolver
80/443 HTTPhttp-title,http-headers,http-server-header,http-methods,http-enumtitle, put/del methods, common paths
445 SMBsmb-os-discovery,smb2-security-mode,smb-shares,smb-protocolsOS/domain, signing, SMBv1
389/636 LDAPldap-rootdse,ldap-searchnaming contexts = domain FQDN
88 Kerberoskrb5-enum-userspre-auth user enum (see §9)
1433 MSSQLms-sql-info,ms-sql-ntlm-infoversion, NTLM leak
3389 RDPrdp-enum-encryption,rdp-ntlm-infoNLA state, NTLM info
5985 WinRMhttp-title + service bannerconfirms WinRM vs web app
any TLSssl-cert,ssl-enum-ciphersCN/SANs leak hostnames → vhosts
vuln sweep"vuln,vulners" --script-args mincvss=7.0high-sev hits without the noise
# target one host with a service menu
nmap -Pn -p445 --script "smb-* and not smb-brute and not smb-flood" $IP
# script args
nmap -Pn -p80 --script http-enum --script-args http-enum.basepath='/app/' $IP

3. rustscan → nmap handoff (the fast path)

What to look for → every open TCP port, then default-script + version detail on exactly those ports. This is my default first scan.

Enumerate

# rustscan auto-feeds the open ports into nmap (-sCV = -sC -sV), saves all formats
rustscan -a $IP -u 50000 -r 1-65535 -- -sCV -oA ./recon/target

# Windows / no-ping / firewalled targets — force it through and give it more room
rustscan -a $IP -u 50000 -r 1-65535 -t 3000 -b 1000 -- -Pn -sCV --max-retries 3 -T4

# Quick port-only discovery when I just want the list (no nmap)
rustscan -a $IP -q

[!warning] Watch out The #1 rustscan mistake: forgetting -Pn on the nmap side. rustscan already proved the port open via raw TCP connect — but if nmap’s own ping then fails (ICMP blocked, normal on HTB), nmap reports “0 hosts up” and you lose every result. Always append -Pn after -- on Windows/firewalled boxes. -- -A piped through rustscan is still fast because nmap only re-touches the already-open ports, never the full 65535. Second rustscan gotcha: on a busy VPN, the default -b (batch size) floods and misses ports — if results look thin, re-run with -b 500.


4. masscan & naabu — subnet-scale discovery

masscan — asynchronous raw-socket scanner, internet-scale speeds. Different engine from nmap; results differ.

sudo masscan -p1-65535 $IP --rate=1000 -oG masscan-all.gnmap     # whole box, capped rate
sudo masscan -p80,443,445,3389 10.10.110.0/24 --rate=2000        # subnet sweep
# gotchas: --rate is pps (10000+ melts HTB VPN and DROPS results); raw sockets bypass the
# OS stack → responses can be eaten by your own firewall unless you: sudo iptables -A INPUT -p tcp --dport 60000 -j DROP  (and --source-port 60000)
# masscan finds ports only — hand the list to nmap for -sCV (same two-stage pattern as rustscan)

naabu — ProjectDiscovery’s fast SYN scanner; designed to pipe into httpx/nuclei.

sudo naabu -host $IP -p - -rate 1000 -o naabu.txt        # full range
naabu -host $IP -top-ports 1000                          # quick triage
# gotchas: needs root for SYN (else falls back to connect); -p - means all ports;
# pair with -verify to drop the false positives raw-SYN scans love

[!tip] Which scanner when Single box, I want detail now → rustscan → nmap. A whole /24 → masscan or naabu for ports, then nmap -sCV on the hits. Exam boxes → plain two-stage nmap is plenty. Whatever finds the ports, nmap owns the service/version truth.


5. Two-stage nmap (when I want full manual control)

What to look for → same result as the handoff, but I own the exact nmap command (custom scripts, output paths, timing). Use when rustscan’s auto-invocation gets in the way.

Enumerate

# Stage 1: find open ports fast, comma-join them
ports=$(nmap -p- --min-rate=1000 -T4 --open -oG - $IP | grep -oP '\d+(?=/open)' | paste -sd,)

# Stage 2: deep scan only those ports
nmap -p $ports -sCV -T4 -Pn $IP -oA ./recon/detailed

# Same idea straight from rustscan's greppable output
ports=$(rustscan -a $IP -g | grep -oP '\[\K[^\]]+')
nmap -sC -sV -Pn -p $ports $IP -oA ./recon/detailed

[!tip] Long -p- scan? Don’t sit and stare. Tap spacebar any time for an instant progress line (% complete + ETA), or run with --stats-every 15s. If it dies (SSH drop, Ctrl+C): nmap --resume ./recon/detailed.nmap picks up where it stopped — no restart from zero.


6. Deep TCP + version + default/vuln scripts

What to look for → confirmed service/product/version per port, OS guess, and any obvious high-severity CVE. Treat a version match as a lead, not proof.

Enumerate

# Privileged full-TCP SYN inventory with reasons (fast internal starting point)
sudo nmap -sS -Pn -n -p- --open --reason --min-rate 1000 --max-retries 2 $IP -oA ./recon/01-tcp-all

# Service + default scripts + OS on the ports that came back
sudo nmap -sS -Pn -n -sV -sC -O --reason -p $ports $IP -oA ./recon/02-services

# Exhaust probes when a banner stays unknown
nmap -Pn -n -sV --version-all -p <port> $IP

Attack (surface for weak points)

# High-severity vuln scripts only (mincvss filters the noise)
nmap -sV --script "vuln,vulners" --script-args mincvss=7.0 -p $ports $IP -oA ./recon/vuln

[!warning] Watch out -A is not -p- — it’s OS + version + default NSE + traceroute on the ports you gave it, nothing more. Keep intent explicit with -sV -sC -O. tcpwrapped in the output = connection accepted then instantly closed (ACL/wrapper), not a real banner — re-test from the expected source. filtered describes my vantage point, not the target — add --reason.


7. Top-UDP pass (DNS / SNMP / NFS / TFTP hide here)

What to look for → UDP services TCP scans never show. On AD/Linux boxes DNS(53), SNMP(161), NFS-adjacent(111), NTP(123) matter.

Enumerate

# Quick triage
sudo nmap -sU --top-ports 50 $IP

# Focused high-value UDP with version probes
sudo nmap -sU -Pn -n -sV --reason \
  -p53,67,68,69,111,123,137,161,162,500,514,623,1434,1900,4500,5353 $IP -oA ./recon/04-udp
UDP portServiceWhy I care
53DNSzone transfer, recursion, version
67/68DHCProgue-DHCP angle on the LAN
69TFTPanonymous config/firmware pulls
111rpcbindNFS export discovery (→ 2049)
123NTPclock sync + ntp-monlist amplification history
137NetBIOS-NShostname/domain without SMB
161/162SNMPcommunity public = full device census (→ Stage 03)
500/4500IKE/IPsecVPN endpoint, ike-scan
1434MSSQL browserinstance names + ports without a login
1900/5353SSDP/mDNSdevice inventory, Responder targets

[!warning] Watch out UDP silence reads as open|filtered — ambiguous by design. Add -sV so nmap sends protocol-aware payloads and can promote ambiguous ports to confirmed open. It’s slow; that’s why it’s a separate pass, not bolted onto the TCP scan. --top-ports 50 on UDP covers ~90% of what ever matters; a UDP -p- is an overnight job and almost never worth it.


8. IPv6 — the forgotten surface

What to look for → targets dual-stacked with an unhardened v6 service set (firewall rules often only cover v4).

# v6 scanning is explicit — nmap will NOT scan v6 unless asked
ping6 -c2 $TARGET_V6
sudo nmap -6 -sS -Pn -n -p- --open $TARGET_V6 -oA ./recon/tcp6
# link-local discovery on a LAN you have a foothold in:
ping6 -c2 ff02::1%eth0                      # all-nodes multicast → live v6 neighbors
ip -6 neigh                                  # kernel's discovered v6 neighbors

[!note] In AD, v6 is usually DHCP-managed but DNS is v4 — that’s the mitm6 angle; see Stage 10. Here in Stage 01 just note whether the target even answers on v6 — a :: in ip addr on a foothold means check it.


9. Host discovery on the LAN (post-foothold / internal range)

What to look for → live neighbors before port-scanning them. ARP can’t be filtered on the local segment — it’s the ground truth.

# ARP-based (local subnet only, undetectable-by-firewall, fast)
sudo arp-scan -l -I eth0                      # auto subnet
sudo arp-scan 10.10.110.0/24 | tee arp.txt
sudo netdiscover -i eth0 -r 10.10.110.0/24 -P # passive-capable, live table

# ICMP/TCP fallback across routed segments
fping -asgq 10.10.110.0/24                    # alive hosts, one line each
nmap -sn -PS22,80,135,445,3389 10.10.110.0/24 -oA ./recon/lan-discover

[!tools] Internal all-in-one: fscan fscan_windows_x64.exe (SHA-256 · GPG signature)

fscan sweeps a segment for hosts, ports, and weak services in one shot from a compromised Windows box — MS17-010 check, SSH/SMB/RDP/MSSQL/Redis brute (careful), web title grab.

# upload to the foothold, then:
.\fscan_windows_x64.exe -h 10.10.110.0/24 -np -no -nopoc -o fscan-result.txt
# -np skip ping (if ICMP is filtered), -no don't save default log, -nopoc skip web poc checks (quieter)
.\fscan_windows_x64.exe -h 10.10.110.5 -p 1-65535      # deep on one juicy host

OPSEC: fscan is loud and well-signatured (AV eats it on sight — expect to need exclusion or obfuscation). It’s a lab/internal convenience, not a stealth tool. For monitored networks prefer native nmap through a Stage 10 socks proxy.


10. Vhosts & DNS → feed /etc/hosts

What to look for → hostnames the IP scan hints at but doesn’t route: cert CN/SANs, HTTP redirects/titles, and DNS zone data. Every new name goes into /etc/hosts so web + Kerberos work.

Enumerate

# Names leak from TLS certs and HTTP on web ports
nmap -p443,8443 --script=ssl-cert $IP
nmap -sV -p80,443,8080,8443 --script=http-title,http-headers,http-server-header $IP

# DNS zone transfer (AXFR) → instant subdomain dump when it works
nmap -p53 --script=dns-zone-transfer --script-args dns-zone-transfer.domain=$DOMAIN $IP
dig axfr $DOMAIN @$IP

# Add whatever surfaces
echo "$IP  $DOMAIN www.$DOMAIN mail.$DOMAIN" | sudo tee -a /etc/hosts

[!note] If a web port serves a different site per Host: header, that’s vhost routing — fuzz it in STAGE 2 (ffuf ... -H "Host: FUZZ.$DOMAIN"). Zone transfer denied is the expected result on a sane DNS server, not an error. Port→service reference: Common Ports and Services Cheatsheet 2026.


11. Kerberos on 88 = it’s AD (tell + first users)

What to look for → port 88 open means Domain Controller. I can enumerate valid domain users pre-auth without creds, straight off the scan — hands STAGE 2 a userlist.

Enumerate

# Valid-user enum via Kerberos pre-auth (realm MUST be uppercase)
nmap -p88 --script=krb5-enum-users \
  --script-args krb5-enum-users.realm=${DOMAIN^^},userdb=/usr/share/seclists/Usernames/top-usernames-shortlist.txt $DC

# Re-confirm skew here too — 88 is exactly where KRB_AP_ERR_SKEW bites
nmap -p445,88 --script smb2-time,clock-skew -Pn $DC

[!warning] Watch out The krb5 realm is case-sensitive and uppercase (${DOMAIN^^}) — lowercase silently returns nothing. Enum doesn’t trigger account lockout (pre-auth only) but pre-auth failures do log (Event 4768/4771). For the heavier userlist sweep hand off to kerbrute userenum in STAGE 2 — see Kerbrute (binaries staged in Stage 00 §12). NSE per-port script menus live in NSE Guide; the full nmap flag arsenal (timing knobs, evasion, idle scan) in Nmap Cheatsheet 2026.


12. SMB / LDAP / DNS quick wins (bridge to Stages 03–04)

First-auth probes that answer “is this worth an hour?” in 60 seconds:

# SMB — domain, hostname, OS, signing, null session in one line each
nxc smb $IP
nxc smb $IP -u '' -p '' --shares            # null session → shares?
smbclient -N -L //$IP/ 2>/dev/null

# LDAP — anonymous bind dumps the domain naming context (sometimes more)
ldapsearch -x -H ldap://$DC -s base namingcontexts
nxc ldap $DC -u '' -p '' --users            # occasionally wins a full user list

# DNS — adidnsdump-style record pull if we have ANY creds later; for now just AXFR + version
dig axfr $DOMAIN @$DC; dig version.bind chaos txt @$DC

[!tip] Handoff logic SMB signing disabled → relay potential (Stage 10). Null shares → Stage 03. Any creds → full AD enum in Stage 04. 88/389/445 on one box → it is the DC: fix /etc/hosts, krb5.conf, and clock before anything else.


13. Web screenshot triage — see every web port at once

When the scan comes back with a dozen HTTP(S) ports, eyeball them all in one pass instead of curling each.

[!tools] Stage this gowitness_linux_amd64 (SHA-256 · GPG signature) gowitness_windows_amd64.exe (SHA-256 · GPG signature)

gowitness — headless-Chrome screenshotter. Alternative: EyeWitness (Python, classifies login panels/default pages automatically).

# scan-straight-from-nmap: gowitness reads the -oX XML and shoots every http service
gowitness scan nmap -f ./recon/detailed.xml --open --service-contains http --screenshot-path ./shots
# or from a URL list (v3 syntax — old `gowitness single/file` is deprecated)
gowitness scan file -f urls.txt --screenshot-path ./shots -t 8
# review everything in the built-in gallery (defaults to 127.0.0.1:7171)
gowitness report server

[!tip] CPTS exam tip Screenshot before deep enumeration. The gallery instantly surfaces login portals, default pages (IIS welcome = unpatched vibe), directory listings, and camera/printer panels you’d waste 20 minutes identifying via curl -I. Log every interesting panel in the notes with its port — Stage 02 fuzzing targets come from this view.


14. Results hygiene — parse, convert, keep receipts

What to look for → durable, greppable, diffable scan output. Future-you (and the report) needs it.

NMAP_FILE=./recon/detailed.gnmap

# Host + count of open ports
egrep -v "^#|Status: Up" $NMAP_FILE | cut -d' ' -f2,4- | \
sed -n -e 's/Ignored.*//p' | \
awk -F, '{split($0,a," "); printf "Host: %-20s Ports Open: %d\n" , a[1], NF}' | sort -k 5 -g

# Clean table: state / proto/port / service
egrep -v "^#|Status: Up" $NMAP_FILE | cut -d' ' -f2,4- | sed -n -e 's/Ignored.*//p' | \
awk '{print "Host: " $1 " Ports: " NF-1; $1=""; for(i=2; i<=NF; i++) { a=a" "$i; }; split(a,s,","); for(e in s) { split(s[e],v,"/"); printf "%-8s %s/%-7s %s\n" , v[2], v[3], v[1], v[5]}; a="" }'

# Top service versions across the scan
egrep -v "^#|Status: Up" $NMAP_FILE | cut -d ' ' -f4- | tr ',' '\n' | \
sed -e 's/^[ \t]*//' | awk -F '/' '{print $7}' | grep -v "^$" | sort | uniq -c | sort -k 1 -nr

# one-liner: just the open port numbers (feed to -p or other tools)
grep -oP '\d+/open' $NMAP_FILE | cut -d/ -f1 | sort -n | uniq | paste -sd,

# XML → readable HTML report for the evidence folder
xsltproc ./recon/detailed.xml -o ./recon/detailed.html

# diff two scans (long engagements — new ports = new surface)
ndiff ./recon/baseline.xml ./recon/current.xml

[!tip] XML over greppable for anything durable — -oX retains full host/port/service/NSE structure and diffs across time with ndiff baseline.xml current.xml (catches new attack surface on long boxes). Greppable is for quick shell work in the moment. Full recipes: Awesome NMAP grep.

[!warning] /etc/hosts discipline

  • One line per IP, FQDN first, then short names: $IP dc01.$DOMAIN dc01 $DOMAIN — Kerberos picks the first match.
  • Never duplicate an IP with conflicting names from two boxes; comment out old entries, don’t delete (audit trail).
  • After every vhost discovery (§10), append immediately — “I’ll remember it” is how you lose 30 minutes to curl returning the wrong vhost.

15. AutoRecon — the “do all of this” wrapper

AutoRecon chains everything above: full-port discovery → per-service deep scans → web screenshots → feroxbuster kicks, all into results/<IP>/ folders.

autorecon $IP --dirbuster.threads 50 -o ./autorecon-out
# --single-target for one box at a time; -p/-t/-ct to shape port/timing

[!note] Use it to check coverage, not to think for you. On CPTS boxes AutoRecon’s feroxbuster/vhost stages are exactly the Stage 02 work — great safety net, but know what every spawned command does; “AutoRecon didn’t find it” is not a strategy.


[!failure] Detection & OPSEC — assume the scan is seen

What I runWhat the blue team sees
-sS SYN scanhalf-open connections; IDS signature on rate/sequencing — fast scans at -T4/high --min-rate trip thresholds instantly
-sT connect scanfull handshakes + SYN + app-layer logs on every service — double visibility, use only when rootless
rustscan/masscan/naabuextreme pps → NetFlow/IDS alarm regardless of flags
-sC/vuln scriptsreal probes hitting app logs (404 storms, malformed requests) — far noisier than the port scan itself
-D decoysdilutes, doesn’t anonymize — source list still includes you
-f/--mtu, -T0, --source-port 53classic evasions; help vs. naïve IDS, reassembled/caught by anything modern

On HTB/CPTS: noise is free — optimize for speed and completeness. On a monitored engagement: agree scan windows, throttle (-T2/--max-rate), scan from the expected source, and log your source IP + timestamps for SOC deconfliction (T1595 attribution).


[!tip] Where this feeds Open 445/139/389/88 → STAGE 2 AD enum (netexec, bloodhound). Open 80/443/8080 → web (ffuf/feroxbuster). Open 53/111/2049/6379 → Linux service detours. The full phased map: Attack-Flow-Guide · Most-Used-Commands.


[!navigation] Continue the attack flow Previous: Stage 00 — Passive External Recon

Dashboard: HTB Pentest Attack Flow

Next: Stage 02 — Web Enumeration and Exploitation