Network reconnaissance and port scanning: a practical guide to nmap and masscan

Depov

Activist
ULTIMATE
SUPREME
PREMIUM
MEMBER
Joined
Feb 18, 2025
Messages
126
Reaction score
115
Deposit
0$

What's going on in network intelligence and why is it necessary?​

Network reconnaissance methods are the first thing a penetration tester (or attacker) does when working with a target infrastructure. In MITRE ATT&CK terminology, several methods are used simultaneously:




  • Network Service Discovery (T1046, Discovery) - Discovering open port services
  • Remote System Discovery (T1018, Discovery) - Identifying active hosts on the network
  • Vulnerability Scanning (T1595.002, Reconnaissance) - Searches for vulnerabilities using active detection.
When you report "open port 3389 detected," the client will shrug. But "Network Service Discovery (T1046) detected an RDP service on non-standard port 33389 with no source restriction" is a specific detection with a structured reference that both the SOC and CISO understand.




The entire intelligence process consists of three stages:




  1. Identifying hosts - those who are generally active on the network.
  2. Port Scanning - What Doors Are Open?
  3. Fingerprint identification - what is behind it, what version, what operating system
Their tools and methods are used at each stage. Let's consider them in turn.




Discovering hosts on the network: ping scanning, ARP and other methods.​

Before performing a port scan, it's important to understand which hosts are typically responsible. Don't run a scan of the entire /24 subnet on all ports 65535 without prior reconnaissance—it'll waste your time.




ICMP ping scan​

The easiest way is to send an ICMP echo reply request to each address in the specified range:





Head:



nmap -sn 192.168.1.0/24 -oG ping_sweep.gnmap


The -sn flag tells nmap to "Discover hosts only, don't touch ports." By default, Nmap sends not only ICMP echo but also TCP SYN to port 443, TCP ACK to port 80, and ICMP vent timestamp request—this combination increases the chances of host discovery, even if one of the protocols is blocked.




Problem: Many hosts aren't responding to ICMP requests. Corporate firewalls often block pings. If a network ping test shows 5 hosts out of the expected 50, this doesn't mean the network is empty. Quite the opposite.




ARP scans on the local network​

If you are in the same L2-segment as the goals (typical situation on the internal pentest), ARP-queries work most reliable:





Bash:



nmap -sn -PR 192.168.1.0/24


Flag -PR switches nmap to ARP queries. Why is it more reliable? ARP is a channel-level protocol, without it, network connectivity is impossible. It is impossible to block the ARP in the locale without loss of communication. Every living host is obliged to answer - he has nowhere to go.




Caste samples for filtering bypass​

When ICMP is blocked and you are not in the local segment, you help TCP samples for specific ports. From the official nmap documentation: several types of samples can be combined to detect hosts:





Bash:



# TCP SYN на популярные порты + ICMP
nmap -sn -PS22,80,443,3389 -PE 10.0.0.0/24


-PS22,80,443,3389 sends TCP SYN to these ports. If the host answers SYN-ACK or RST, it is alive. -PE adds ICMP echo in case TCP ports are closed, but ICMP is allowed.




Remove the list of live hosts for the next stage:





Bash:



grep "Up" ping_sweep.gnmap | awk '{print $2}' > live_hosts.txt


Port Scanning Techniques: What Happens at Packets Level​

Definition of open ports is the core of network reconnaissance. Nmap supports more than ten scanning techniques, but in practice 90% of the tasks are solved by three: SYN, Connect and UDP. The rest are for specific scenarios: firewall analysis or IDS bypass.




Stealth Scanning SYN (-sS)​

SYN scan is a default and most popular nmap technique. It is its tool that uses when running from root without additional flags:





Bash:



sudo nmap -sS -p- 192.168.1.100 -oA syn_scan


What is happening on the network:




  1. Nmap sends TCP-package with SYN flag to the target port
  2. If the port is open, the target is SYN-ACK. Nmap immediately sends RST, breaking the connection
  3. If the port is closed - the target responds to RST
  4. If there is no answer or comes ICMP unreachable - the port is marked as filtered
Why “stealth”? TCP-handshake is not over. Many applications only log in installed connections (after ACK), and SYN scan does not reach this step. But do not be deceived: modern IDS (Snort, Suricata) perfectly see SYN scans on the pattern of multiple SYN-packages without completing the hand-sheak. Stealth is a historical name.




Flag -p- critically important - it scans all 65535 ports. Without it, nmap only checks the top 1000. In my practice, forgotten services are regularly found on non-standard ports: RDP on 33389, web interfaces at 8443, 9090, databases on 13306. You miss the port, you'll miss the attack vector.




TCP Connect Scanning (-sT)​

Connect-Scan uses a system call connect() for installation of a full TCP connection:





Bash:



nmap -sT -p- 192.168.1.100 -oA connect_scan


UDP-scanning (-sU)​

UDP scanning - headache for beginner pentesters. But it cannot be ignored: DNS (53), SNMP (161/162), DHCP (67/68) - critical services that work on UDP. As stated in the report of nmap: “exploitable UDP services are quite and cross-dispared don’t ignore the auditorium”.





Bash:



sudo nmap -sU --top-ports 100 192.168.1.100 -oA udp_scan


Why UDP scan is so slow and capricious:




  • UDP doesn't have a Hyundai. Sent the package - and you are waiting
  • If the port is closed, the target meets ICMP Port Unreachable
  • If the port is open - usually silence (no answer at all)
  • Nmap marks the absence of an answer as open|filtered- the port can be both open and filtered firewall
And another joy: Linux and Solaris limit the shipment speed of ICMP Port Unreachable (by default - one per second). This means that scanning 65535 UDP ports on the Linux host can take more than 18 hours. That's why I use for UDP --top-ports 100 Instead of complete search.




The practice tip: combine UDP and TCP in one start:





Bash:



sudo nmap -sS -sU --top-ports 200 -iL live_hosts.txt -oA combined_scan


ACK scan for firewall analysis (-sA)​

ACK scan does not look for open ports - it defines firewall rules:





Bash:



sudo nmap -sA -p 80,443,8080 192.168.1.1


Nmap sends packages only with the ACK flag. This is not the beginning of the connection, so:




  • If RST comes - the port is not filtered (the package went through the firewall)
  • If there is no answer or comes ICMP unreachable - the port is filtered
Why? On the external pentest, before active scanning, it is useful to understand which ports the firewall generally misses. Save time and reduces noise.




Masscan - fast port scanning on large networks​

When you need to scan the subnet /16 (65536 addresses), nmap will work hours. Masscan solves the problem by order faster - in minutes when scanning a limited set of ports or a high rate (100K +), although a complete scan of all 65535 ports at /16 at a moderate rate will take days. According to the author - Robert Graham - masscan is able to send up to 10 million packets per second on a 10GbE adapter.




But there is a fundamental difference: masscan is a “radar”, nmap – “binocular with a thermal imager”. Masscan quickly finds where open ports are sticking out. Nmap examines every found in detail.




Basic Start with Safe Rate​




Bash:



sudo masscan -p1-65535 10.0.0.0/16 --rate=5000 \
-oG masscan_results.gnmap


Analysis of flags:




  • -p1-65535- all TCP ports. Masscan does not know any "top-1000"
  • --rate=5000- 5000 packs per second. For the corporate LAN - acceptable. For products with sensitive equipment reduce to 1000
  • -oG- grepable-format, convenient for parsing and transferring in nmap
A classic beginner's mistake: running MassCan without speed limits on the client network. During my first penetration test, an intern ran MassCan at 50,000 on a /16 subnet—the network equipment started dropping packets, and the SOC called within a minute. Speeds always meet the terms of the agreement.




Transferring MassCAN results to NMAP​

Masscan is a rough tool that produces false positives (instant sending and receiving of packets, unexpected responses to each). Always verify the results:





Bash:



# Extract unique IPs from Masscan results
grep "Host:" Masscan_results.gnmap \
| awk '{print $2}' | sort -u > Masscan_hosts.txt

# Deep check of hosts found by nmap
# This uses -p- to fully check all ports,
# not found by Masscan (which may produce false negatives).
# To save time, you can extract ports from the mass scan and pass them via -p. This two-step scheme—masscan to determine coverage, nmap to determine depth—is the standard method
for
port scanning on large infrastructures . I personally don't use any
other packages for large networks.









Fingerprinting and OS detection services using nmap​

Finding an open port is half the battle. We need to know what's behind it. Scanning services and versions is the step where the list of ports turns into a list of potential attack vectors.




Version detection (-sV)​




Bash:



sudo nmap -sV --version-intensity 7 -p 22,80,443,3306,8080 192.168.1.100


How it works -sV: nmap connects to an open port and sends a sample (probes) from the underlying nmap-service-probes . The responses are compared against known patterns. The --version-intensity parameter controls the number of samples:




  • 0 - minimum number of samples, maximum speed
  • 9 (default) - all samples, maximum accuracy
In practice, I think --version-intensity 5-7 is a good balance between speed and accuracy. Full intensity is only necessary for hosts where standard samples returned tcpwrapped or undefined results.




Capturing a banner with netcat​

When nmap shows a port as tcpwrapped (the service accepted the connection but didn't respond to requests), I check it myself:





Bash:



# HTTP banner
echo -e "HEAD / HTTP/1.0 \r \n \r \n " | nc -w 5 192.168.1.100 8080

# SSH banner - often gives the version right away on connection
nc -w 5 192.168.1.100 22

# SMTP banner
nc -w 5 192.168.1.100 25


SSH usually immediately returns a string like SSH-2.0-OpenSSH_8.9p1 Ubuntu-3ubuntu0.6. One line - and you know: OpenSH 8.9, Ubuntu. You can search CVE for this version. It's the same as sending two bytes.




OS fingerprint identification (-O)​




Bash:



sudo nmap -O --osscan-guess 192.168.1.100


Nmap analyzes the behavior of the TCP/IP target stack: TTL values, TCP Window Size, TCP Options, ICMP responses, fragmentation. Each OS implements a stack in its own way - nmap compares the responses with the nmap-os-db base.




The --osscan-guess flag causes nmap to give the most likely OS even with low confidence. This is useful when the firewall distorts some of the responses.




For reliable fingerprinting, both open and closed ports are used - nmap uses the difference in responses to compare with the base value.




NSE Scripts: Scanning for Vulnerabilities with nmap​

Nmap Scripting Engine turns a port scanner into a vulnerability scanning tool (T1595.002, Reconnaissance):





Bash:



# General scan for other vulnerabilities
nmap -sV --script vuln -p 445 192.168.1.0/24

# Check for EternalBlue (MS17-010)
nmap -p 445 --script smb-vuln-ms17-010 192.168.1.0/24

# Check for MS12-020 (CVE-2012-0002) - RCE in RDP
nmap -p 3389 --script rdp-vuln-ms12-020 192.168.1.100

# Audit SSL/TLS configuration
nmap -p 443 --script ssl-enum-ciphers 192.168.1.100


CVE-2012-0002 (CVSS v2: 9.3, HIGH - the highest of three severity categories in CVSS v2: Low - 0-3.9, Medium - 4.0-6.9, High - 7.0-10.0; CVSS v3) is a vulnerability in the implementation of the Remote Desktop Protocol (RDP) in Microsoft Windows XP SP2/SP3, Windows Server 2003, Windows Vista SP2, and Windows Server 2008. Improper handling of RDP packets in memory allows a remote attacker to execute arbitrary code via specially crafted RDP packets that provide access to an uninitialized or deleted object. Classification: CWE-94 (official NVD classification). The CVE description mentions access to an unallocated or deleted object in memory, which some researchers believe is closer to CWE-416 (Use-After-Free) / CWE-824 (Access to an Unallocated Pointer), but NVD officially classifies this vulnerability as CWE-94.




At the time of writing, nmap does not include an official NSE script for BlueKeep ( CVE-2019-0708 ). Community-provided scripts are available (e.g., from Ekultk on GitHub). Alternatives include rdpscan (Robert Graham) or the Metasploit module auxiliary/scanner/rdp/cve_2019_0708_bluekeep. CVE-2019-0708 is a Remote Code Execution Vulnerability in Remote Desktop Services with CVSS 9.8 (CRITICAL). Vector: CVSS:3.1/AV:N/A:L/L/PR:N/UI:C/H/H:H/H:H/A:H:H/H:H:H:N/A:11:C, low complexity, does not require any privileges or user action. Classification: CWE-416 (Use-After-Free). The vulnerability affects Windows XP, Windows Server 2003, Windows 7, Windows Server 2008, and Windows Server 2008 R2. In addition to Microsoft desktop and server operating systems, it affects a number of industrial and medical systems (for example, Siemens Axiom Multix M) using embedded versions of Windows with RDP. Microsoft even released unscheduled patches for XP and Server 2003, ending support, which in itself indicates the severity of the vulnerability.




Package fragmentation​




Bash:



sudo nmap -sS -f --mtu 16 -p 80 443 192.168.1.100


The -f flag splits IP packets into fragments. --mtu 16 specifies the fragment size (must be a multiple of 8). Some stateless firewalls cannot reassemble fragmented packets and pass them through without analysis. Modern stateful firewalls recognize this, but in legacy infrastructures (and they still exist), it works.




Scanning using decoys​




Bash:



sudo nmap -sS -D RND:10 -p- 192.168.1.100


-D RND:10 Adds 10 decoy IP addresses to your scan. The target's logs will show 11 "scanners" instead of one. However, random decoy addresses (RND) are often ineffective—an IDS may filter them out due to a lack of traffic or belonging to irrelevant ranges. For real effectiveness, it's better to specify the IP addresses of active hosts in the same subnet: -D 10.0.0.5,10.0.0.12,10.0.0.33,ME.




Randomizing port order​




Bash:



sudo nmap -sS --randomize-hosts -p- -iL live_hosts.txt


By default, nmap scans hosts in a specific order. The --randomize-hosts option changes the order. nmap randomizes ports by default (you can control this with the --top-ports or -r options for a sequential search).




The Complete Network Intelligence Cycle: A Step-by-Step Scenario​

Here's how I create a port scanning system for pentesting in a real project. I did it once, I did it twice, I did it three times.




Step 1: Train your workforce members.​




Баш:



ENGAGEMENT="pentest_$(date +%Y%m%d)"
mkdir -p /tmp/${ENGAGEMENT}/{scans,pcaps,loot}


Step 2: Get your insurance policy quickly through Masscan.​




Bash:



sudo Masscan -p1-65535 10.10.0.0/16 --rate=3000 \
-oG /tmp/${ENGAGEMENT}/scans/masscan_full.gnmap


With rate=3000 and scanning the entire port range in /16, the scan will take several days (65536 hosts × 65535 ports / 3000 packets / se ≈ 16+ days). For faster coverage, limit the set of ports (-p 1-1000) or increase the rate. This will give you a rough map of open ports.




Step 3: Removing Active Hosts​




Bash:



grep "Host:" /tmp/${ENGAGEMENT}/scans/masscan_full.gnmap \
| awk '{print $2}' | sort -u \
> /tmp/${ENGAGEMENT}/scans/live_hosts.txt

echo "Hosts found: $(wc -l < /tmp/${ENGAGEMENT}/scans/live_hosts.txt)"


Step 4: Discover the host for the dropped connection (ARP + TCP)​




Bash:



sudo nmap -sn -PR -PS22,80,443,3389 10.10.0.0/16 \
-oG /tmp/${ENGAGEMENT}/scans/nmap_discovery.gnmap

# Merge with Masscan results
grep "Up" /tmp/${ENGAGEMENT}/scans/nmap_discovery.gnmap \
| awk '{print $2}' >> /tmp/${ENGAGEMENT}/scans/live_hosts.txt

sort -u -o /tmp/${ENGAGEMENT}/scans/live_hosts.txt \
/tmp/${ENGAGEMENT}/scans/live_hosts.txt


Step 5: Deep Network Scan with Nmap​




Bash:



sudo nmap -sS -sV -sC -O \
-p- \
-iL /tmp/${ENGAGEMENT}/scans/live_hosts.txt \
-oA /tmp/${ENGAGEMENT}/scans/full_scan \
--max-retries 2 \
--host-timeout 30m \
-T4


Analysis: -sS (SYN scan) + -sV (version detection) + -sC (default scripts) + -O (OS detection) + -p- (all ports) + -T4 (aggressive timing for LAN).




Step 6: Targeted vulnerability scanning​




Bash:



# SMB vulnerabilities on all hosts with port 445
sudo nmap -p 445 --script smb-vuln-ms17-010,smb-vuln-ms08-067 \
-iL /tmp/${ENGAGEMENT}/scans/live_hosts.txt \
-oA /tmp/${ENGAGEMENT}/scans/smb_vulns

# SSL/TLS audit for all HTTPS
sudo nmap -p 443,8443 --script ssl-enum-ciphers \
-iL /tmp/${ENGAGEMENT}/scans/live_hosts.txt \
-oA /tmp/${ENGAGEMENT}/scans/ssl_audit


Step 7: Manually check for non-standard ports.​




Bash:



# Port 9090 was shown by tcpwrapped - we check it manually
echo -e "GET / HTTP/1.0\r\n\r\n" | nc -w 5 10.10.5.42 9090

# We record traffic during manual observations
sudo tcpdump -i eth0 -w /tmp/${ENGAGEMENT}/pcaps/manual.pcap \
host 10.10.5.42 &


Step 8: Prioritize UDP Scan Targets​




Bash:



sudo nmap -sU --top-ports 50 \
-iL /tmp/${ENGAGEMENT}/scans/live_hosts.txt \
-oA /tmp/${ENGAGEMENT}/scans/udp_scan \
--max-retries 1


UDP scanning is performed last and covers only the 50 most popular ports - otherwise latency will increase dramatically on large networks.




Common mistakes beginners make​

Scan only the 1000 most popular ports. Without the -p- parameter, nmap checks the 1000 most popular ports. Services on ports 8888, 31337, or 500000 will be skipped. I found RDP on port 33389, Jenkins on port 8888, and an unprotected REST API on port 50080—all outside the top 1000. For those at risk, this means that without the -p- parameter, you'll miss a third of the attack surface.




Trust Masscan's results without further verification. Masscan uses asynchronous delivery—it doesn't wait for a response to every message. False positives are normal. Always verify with nmap.




Launch with -T5 on the production network. Aggressive timing of the serial flow packet launch, capable of disabling network equipment. For pharmaceutical production, the maximum is -T3, for more sensitive targets, -T2. Once you've made this mistake, remember it forever.




Ignore UDP. DNS, SNMP, TFTP, NTP—all over UDP. SNMP with the public string parameter is a common method in internal penetration tests, providing access to network equipment configuration.




Scan without logging results. The -oA flag saves the output in three formats (nmap, xml, gnmapa). Without this second confirmation, the attack will be considered lost.
 
Last edited:
Top Bottom