The next step in identifying a target's attack surface is to discover open ports on target systems. Open ports correspond to networked services running on a system. Programming errors or implementation flaws can introduce vulnerabilities in these services, sometimes leading to full system compromise. To identify potential attack vectors, you must first enumerate all open ports on remote systems within the scope of your assessment. These open ports represent services accessible via UDP or TCP traffic. Both TCP and UDP are transport layer protocols: Transmission Control Protocol (TCP) is more widely used and provides connection-oriented communication, while User Datagram Protocol (UDP) is connectionless, often used for services where speed prioritizes over data integrity. The penetration testing technique used to enumerate these services is called port scanning. Unlike host discovery techniques, port scanning generates sufficient information to confirm whether a service is associated with a given port on a device or server.
Before diving into specific techniques, we will cover core port scanning fundamentals.
UDP Port Scanning
UDP-based services are often overlooked because TCP is more commonly deployed. Eventhough UDP services tend to be forgotten, enumerating them is critical to fully understanding a target's attack surface. UDP scanning is typically challenging, time-consuming, and prone to inaccuracies. The first three recipes in this chapter cover using different tools in Kali Linux to perform UDP scans.
There are two primary approaches to UDP scanning:
- ICMP Port Unreachable Response Based: This method relies on the assumption that UDP ports without an associated service will return an ICMP port unreachable response. Ports that do not return this response are assumed to be open. This approach works in some cases but can produce inaccurate results if the target host does not generate ICMP port unreachable messages, or if these messages are rate-limited or filtered by a firewall.
- Service Probe Based: This method uses service-specific probes to request expected responses that confirm the presence of a service on the target port. This approach is more accurate but also more time-consuming.
TCP Scanning
This chapter covers several TCP scanning techniques, including stealth SYN scans, full connect scans, and zombie scans. To understand these techniques, you must first grasp how TCP establishes and maintains connections. TCP is a connection-oriented protocol: data cannot be transmitted until a connection is established between two systems. This connection setup process uses a three-way handshake:
- A client sends a TCP SYN packet to the target port.
- If the port has an active service, it responds with a TCP SYN+ACK packet.
- The client sends a final TCP ACK packet to complete the handshake.
All TCP port scanning mechanisms implement variations of this process to identify active services on remote hosts.
Connect Scans
Connect scans complete the full three-way TCP handshake for each scanned port. If the handshake succeeds, the port is marked open. This method is straightforward but leaves clear logs in the target system's connection history.
Stealth SYN Scans
Stealth scans (also called SYN scans or half-open scans) do not complete the full three-way handshake. Instead, the scanner sends a single SYN packet to each target port. Ports that respond with a SYN+ACK packet are marked open. The scanner never sends the final ACK packet, so the connection is never fully established. This makes stealth scans harder to detect, as most logging systems only record completed connections.
Zombie Scans
Zombie scans allow you to map open ports on a target system without leaving any trace of your interaction with the target. The underlying mechanics are complex:
- Identify a "zombie" host: a system with an incrementing IPID sequence that has minimal network traffic.
- Send a SYN+ACK packet to the zombie host and record the initial IPID value from the returned RST packet.
- Forge a SYN packet with the zombie host's source IP address and send it to the target system.
- Analyze the target's response:
- If the port is open: The target will send a SYN+ACK packet to the zombie host. The zombie will respond with an RST packet, incrementing its IPID by 1.
- If the port is closed: The target will send an RST packet to the zombie host. The zombie will not respond, so its IPID will not increment.
- Send another SYN+ACK packet to the zombie host and check the IPID value of the returned RST packet. If the IPID increased by 2, the target port is open; if it increased by 1, the port is closed.
Scapy UDP Port Scan
Scapy allows you to construct and inject custom network packets. This recipe uses Scapy to scan for active UDP services by sending empty UDP packets and identifying ports that do not return ICMP port unreachable responses.
Prerequisites
You will need a remote server running UDP network services. We will use a Metasploitable2 instance for this example. Refer to the first chapter's "Install Metasploitable2" recipe for setup instructions. You will also need a text editor such as Vim or Nano to write scripts, as covered in the first chapter.
Steps
To understand UDP scanning with Scapy, we will build packets manually first:
root@kali:~# scapy
Welcome to Scapy (2.2.0)
>>> i = IP()
>>> i.display()
###[ IP ]###
version= 4
ihl= None
tos= 0x0
len= None
id= 1
flags=
frag= 0
ttl= 64
proto= ip
chksum= None
src= 127.0.0.1
dst= 127.0.0.1
\options\
>>> i.dst = "172.16.36.135"
>>> i.display()
###[ IP ]###
version= 4
ihl= None
tos= 0x0
len= None
id= 1
flags=
frag= 0
ttl= 64
proto= ip
chksum= None
src= 172.16.36.180
dst= 172.16.36.135
\options\
Next, build the UDP layer:
>>> u = UDP()
>>> u.display()
###[ UDP ]###
sport= domain
dport= domain
len= None
chksum= None
>>> u.dport
53
Modify the destination port:
>>> u.dport = 123
>>> u.display()
###[ UDP ]###
sport= domain
dport= ntp
len= None
chksum= None
Stack the IP and UDP layers:
>>> scan_request = (i/u)
>>> scan_request.display()
###[ IP ]###
version= 4
ihl= None
tos= 0x0
len= None
id= 1
flags=
frag= 0
ttl= 64
proto= udp
chksum= None
src= 172.16.36.180
dst= 172.16.36.135
\options\
###[ UDP ]###
sport= domain
dport= ntp
len= None
chksum= None
Send the request and analyze the response:
>>> response = sr1(scan_request)
Begin emission:
......Finished to send 1 packets.
....*
Received 11 packets, got 1 answers, remaining 0 packets
>>> response.display()
###[ IP ]###
version= 4L
ihl= 5L
tos= 0xc0
len= 56
id= 63687
flags=
frag= 0L
ttl= 64
proto= icmp
chksum= 0xdfe1
src= 172.16.36.135
dst= 172.16.36.180
\options\
###[ ICMP ]###
type= dest-unreach
code= port-unreachable
chksum= 0x9e72
unused= 0
###[ IP in ICMP ]###
version= 4L
ihl= 5L
tos= 0x0
len= 28
id= 1
flags=
frag= 0L
ttl= 64
proto= udp
chksum= 0xd974
src= 172.16.36.180
dst= 172.16.36.135
\options\
###[ UDP in ICMP ]###
sport= domain
dport= ntp
len= 8
chksum= 0x5dd2
You can also build the request in a single line:
>>> sr1(IP(dst="172.16.36.135")/UDP(dport=123))
..Begin emission:
...*Finished to send 1 packets.
Received 6 packets, got 1 answers, remaining 0 packets
<IP version=4L ihl=5L tos=0xc0 len=56 id=63689 flags= frag=0L ttl=64 proto=icmp chksum=0xdfdf src=172.16.36.135 dst=172.16.36.180 options=[] |<ICMP type=dest-unreach code=port-unreachable chksum=0x9e72 unused=0 |<IPerror version=4L ihl=5L tos=0x0 len=28 id=1 flags= frag=0L ttl=64 proto=udp chksum=0xd974 src=172.16.36.180 dst=172.16.36.135 options=[] |<UDPerror sport=domain dport=ntp len=8 chksum=0x5dd2 |>>>>
If you send a request to a port with an active service, you may not receive an ICMP unreachable response. For example, sending a request to DNS port 53:
>>> response = sr1(IP(dst="172.16.36.135")/UDP(dport=53), timeout=1, verbose=1)
Begin emission:
Finished to send 1 packets.
Received 8 packets, got 0 answers, remaining 1 packets
This is because DNS only responds to valid DNS queries, not empty UDP packets. We can use this behavior to scan for open UDP ports by identifying ports that do not return ICMP unreachable responses. Here is a full Python script to automate UDP scanning:
#!/usr/bin/env python3
import logging
logging.getLogger("scapy.runtime").setLevel(logging.ERROR)
from scapy.all import *
import time
import sys
def main():
if len(sys.argv) != 4:
print("Usage: ./udp_port_scan.py [Target-IP] [Start Port] [End Port]")
print("Example: ./udp_port_scan.py 10.0.0.5 1 100")
print("This scans UDP ports 1 through 100 on 10.0.0.5")
sys.exit(1)
target_ip = sys.argv[1]
port_start = int(sys.argv[2])
port_end = int(sys.argv[3])
for port_num in range(port_start, port_end):
response = sr1(IP(dst=target_ip)/UDP(dport=port_num), timeout=5, verbose=0)
time.sleep(1)
if response is None:
print(f"Open port detected: {port_num}/udp")
if __name__ == "__main__":
main()
Make the script executable and run it:
chmod +x udp_port_scan.py
./udp_port_scan.py 172.16.36.135 1 100
Sample output:
53
68
69
How It Works
This UDP scan identifies open ports by detecting which ports do not return ICMP port unreachable responses. This method has limitations, as ICMP unreachable messages are often rate-limited or filtered. The service probe approach discussed in later recipes is a more reliable alternative.
Nmap UDP Port Scan
Nmap includes robust UDP scanning capabilities, using service-specific probes to confirm active services. This recipe covers using Nmap to scan UDP ports on single hosts, multiple ports, and multiple targets.
Prerequisites
You will need a remote server running UDP network services. We will use a Metasploitable2 instance for this example. Refer to the first chapter's "Install Metasploitable2" recipe for setup instructions.
Steps
To perform a basic UDP scan with Nmap, use the -sU flag followed by the target IP address:
nmap -sU 172.16.36.135
Sample output:
Starting Nmap 6.25 ( http://nmap.org ) at 2013-12-17 21:04 EST
Nmap scan report for 172.16.36.135
Host is up (0.0016s latency).
Not shown: 993 closed ports
PORT STATE SERVICE
53/udp open domain
68/udp open|filtered dhcpc
69/udp open|filtered tftp
111/udp open rpcbind
137/udp open netbios-ns
138/udp open|filtered netbios-dgm
2049/udp open nfs
MAC Address: 00:0C:29:3D:84:32 (VMware)
Nmap done: 1 IP address (1 host up) scanned in 1043.91 seconds
The default scan checks the top 1000 UDP ports, which can take nearly 20 minutes. You can speed up scans by targeting specific ports with the -p flag:
nmap 172.16.36.135 -sU -p 53
Sample output:
Starting Nmap 6.25 ( http://nmap.org ) at 2013-12-17 21:05 EST
Nmap scan report for 172.16.36.135
Host is up (0.0010s latency).
PORT STATE SERVICE 53/udp open
domain MAC Address: 00:0C:29:3D:84:32 (VMware)
Nmap done: 1 IP address (1 host up) scanned in 13.09 seconds
You can scan a range of ports using hyphen notation:
nmap 172.16.36.135 -sU -p 1-100
To scan a range of IP addresses, use hyphen notation for the final octet:
nmap 172.16.36.0-255 -sU -p 53
You can also scan a list of targets from a file using the -iL flag:
nmap -iL target_list.txt -sU -p 123
How It Works
Nmap uses a combination of efficient techniques and service-specific probes to identify active UDP services, making it one of the most reliable tools for UDP scanning.
Metasploit UDP Port Scan
Metasploit includes an auxiliary module for scanning common UDP ports. This recipe covers using this module to scan single or multiple hosts.
Prerequisites
You will need a remote server running UDP network services. We will use a Metasploitable2 instance for this example. Refer to the first chapter's "Install Metasploitable2" recipe for setup instructions.
Steps
Launch Metasploit with the msfconsole command:
msfconsole
Load the UDP sweep auxiliary module:
use auxiliary/scanner/discovery/udp_sweep
show options
Configure the scan settings:
set RHOSTS 172.16.36.135
set THREADS 20
show options
Run the scan:
run
Sample output:
[*] Sending 12 probes to 172.16.36.135->172.16.36.135 (1 hosts)
[*] Discovered Portmap on 172.16.36.135:111 (100000 v2 TCP(111), 100000 v2 UDP(111), ...)
[*] Discovered NetBIOS on 172.16.36.135:137 (METASPLOITABLE:<00>:U :...)
[*] Discovered DNS on 172.16.36.135:53 (BIND 9.4.2)
[*] Scanned 1 of 1 hosts (100% complete)
[*] Auxiliary module execution completed
You can scan a range of IP addresses or use CIDR notation:
set RHOSTS 172.16.36.0/24
run
How It Works
The Metasploit UDP sweep module uses targeted probes to identify common UDP services, providing a faster alternative to basic ICMP-based UDP scanning.
Scapy TCP Stealth SYN Scan
Stealth SYN scans (half-open scans) do not complete the full TCP three-way handshake, making them harder to detect. This recipe uses Scapy to perform TCP SYN scans.
Prerequisites
You will need a remote server running TCP network services. We will use a Metasploitable2 instance for this example. Refer to the first chapter's "Install Metasploitable2" recipe for setup instructions. You will also need a text editor such as Vim or Nano to write scripts.
Steps
Build the IP layer:
scapy
>>> i = IP()
>>> i.dst = "172.16.36.135"
Build the TCP layer with SYN flag set:
>>> t = TCP(flags="S")
>>> t.display()
###[ TCP ]###
sport= ftp_data
dport= http
seq= 0
ack= 0
dataofs= None
reserved= 0
flags= S
window= 8192
chksum= None
urgptr= 0
options= {}
Stack the layers and send the request:
>>> scan_request = i/t
>>> response = sr1(scan_request, timeout=1, verbose=0)
If the port is open, you will receive a SYN+ACK response:
>>> response.display()
###[ IP ]###
version= 4L
ihl= 5L
tos= 0x0
len= 44
id= 0
flags= DF
frag= 0L
ttl= 64
proto= tcp
chksum= 0x9970
src= 172.16.36.135
dst= 172.16.36.180
\options\
###[ TCP ]###
sport= http
dport= ftp_data
seq= 2848210323L
ack= 1
dataofs= 6L
reserved= 0L
flags= SA
window= 5840
chksum= 0xf82d
urgptr= 0
options= [('MSS', 1460)]
###[ Padding ]###
load= '\x00\x00'
If the port is closed, you will receive a RST+ACK response:
>>> response = sr1(IP(dst="172.16.36.135")/TCP(dport=4444, flags="S"), timeout=1, verbose=0)
>>> response.display()
###[ IP ]###
version= 4L
ihl= 5L
tos= 0x0
len= 40
id= 0
flags= DF
frag= 0L
ttl= 64
proto= tcp
chksum= 0x9974
src= 172.16.36.135
dst= 172.16.36.180
\options\
###[ TCP ]###
sport= 4444
dport= ftp_data
seq= 0
ack= 1
dataofs= 5L
reserved= 0L
flags= RA
window= 0
chksum= 0xfd03
urgptr= 0
options= {}
###[ Padding ]###
load= '\x00\x00\x00\x00\x00\x00'
Here is a full Python script to automate SYN scanning:
#!/usr/bin/env python3
import logging
logging.getLogger("scapy.runtime").setLevel(logging.ERROR)
from scapy.all import *
import sys
def main():
if len(sys.argv) != 4:
print("Usage: ./syn_scan.py [Target-IP] [Start Port] [End Port]")
print("Example: ./syn_scan.py 10.0.0.5 1 100")
print("This scans TCP ports 1 through 100 on 10.0.0.5")
sys.exit(1)
target_ip = sys.argv[1]
port_start = int(sys.argv[2])
port_end = int(sys.argv[3])
for port_num in range(port_start, port_end):
response = sr1(IP(dst=target_ip)/TCP(dport=port_num, flags="S"), timeout=1, verbose=0)
if response and response.haslayer(TCP) and response[TCP].flags == 0x12:
print(f"Open port detected: {port_num}/tcp")
if __name__ == "__main__":
main()
How It Works
This scan sends a SYN packet to each target port. A SYN+ACK response indicates an open port, while a RST response indicates a closed port. No response may indicate a filtered port or unreachable host.
Nmap TCP Stealth SYN Scan
Nmap simplifies SYN scanning with the -sS flag. This recipe covers using Nmap to perform TCP SYN scans.
Prerequisites
You will need a remote server running TCP network services. We will use a Metasploitable2 instance for this example. Refer to the first chapter's "Install Metasploitable2" recipe for setup instructions.
Steps
Perform a basic SYN scan on a single port:
nmap -sS 172.16.36.135 -p 80
Scan multiple ports:
nmap -sS 172.16.36.135 -p 21,80,443
Scan a port range:
nmap -sS 172.16.36.135 -p 20-25
Scan the top 1000 common TCP ports:
nmap -sS 172.16.36.135
Scan all 65536 TCP ports:
nmap -sS 172.16.36.135 -p 0-65535
Scan a range of IP addresses:
nmap 172.16.36.0-255 -sS -p 80
Scan targets from a file:
nmap -iL target_list.txt -sS -p 80
How It Works
Nmap sends SYN packets to target ports and analyzes responses to identify open, closed, or filtered ports. Its multi-threaded design makes it fast and efficient.
Metasploit TCP Stealth SYN Scan
Metasploit includes an auxiliary module for TCP SYN scanning. This recipe covers using this module.
Prerequisites
You will need a remote server running TCP network services. We will use a Metasploitable2 instance for this example. Refer to the first chapter's "Install Metasploitable2" recipe for setup instructions.
Steps
Launch Metasploit and load the SYN scan module:
msfconsole
use auxiliary/scanner/portscan/syn
show options
Configure the scan settings:
set RHOSTS 172.16.36.135
set THREADS 20
set PORTS 80
show options
Run the scan:
run
You can scan a range of ports or all TCP ports:
set PORTS 0-65535
run
How It Works
The Metasploit SYN scan module follows the same core mechanics as other SYN scanning tools, providing a convenient interface for penetration testers familiar with the Metasploit framework.
hping3 TCP Stealth SYN Scan
hping3 is a versatile network tool that can be used to perform TCP SYN scans. This recipe covers using hping3 for port scanning.
Prerequisites
You will need a remote server running TCP network services. We will use a Metasploitable2 instance for this example. Refer to the first chapter's "Install Metasploitable2" recipe for setup instructions.
Steps
Scan a single port with the SYN flag:
hping3 172.16.36.135 --scan 80 -S
Scan multiple ports:
hping3 172.16.36.135 --scan 22,80,443 -S
Scan a port range:
hping3 172.16.36.135 --scan 0-100 -S
Scan all TCP ports:
hping3 172.16.36.135 --scan 0-65535 -S
How It Works
hping3 allows you to craft custom TCP packets with specified flags. The -S flag enables the SYN flag, and the --scan flag specifies target ports. Analyzing responses identifies open ports.
Scapy TCP Connect Scan
TCP connect scans complete the full three-way handshake. This recipe covers using Scapy to perform connect scans.
Prerequisites
You will need a remote server running TCP network services. We will use a Metasploitable2 instance for this example. Refer to the first chapter's "Install Metasploitable2" recipe for setup instructions. You will also need a text editor.
Steps
The Linux kernel may interfere with Scapy's connect scans by sending RST packets for unsolicited SYN+ACK responses. You can work around this by filtering outgoing RST packets with iptables:
iptables -A OUTPUT -p tcp --tcp-flags RST RST -d 172.16.36.135 -j DROP
Here is a script to perform a full TCP connect scan:
#!/usr/bin/env python3
import logging
logging.getLogger("scapy.runtime").setLevel(logging.ERROR)
from scapy.all import *
import sys
def main():
if len(sys.argv) != 4:
print("Usage: ./tcp_connect_scan.py [Target-IP] [Start Port] [End Port]")
sys.exit(1)
target_ip = sys.argv[1]
port_start = int(sys.argv[2])
port_end = int(sys.argv[3])
for port_num in range(port_start, port_end):
# Send SYN packet
syn_packet = IP(dst=target_ip)/TCP(dport=port_num, flags="S")
syn_ack = sr1(syn_packet, timeout=1, verbose=0)
if not syn_ack or not syn_ack.haslayer(TCP) or syn_ack[TCP].flags != 0x12:
continue
# Send final ACK packet
ack_packet = IP(dst=target_ip)/TCP(dport=port_num, flags="A", ack=syn_ack[TCP].seq + 1)
send(ack_packet, verbose=0)
print(f"Open port detected: {port_num}/tcp")
if __name__ == "__main__":
main()
Remember to flush your iptables rules after testing:
iptables --flush
How It Works
This script completes the full TCP three-way handshake for each target port. A successful handshake indicates an open port.
Nmap TCP Connect Scan
Nmap uses the -sT flag to perform TCP connect scans. This recipe covers using Nmap for connect scans.
Prerequisites
You will need a remote server running TCP network services. We will use a Metasploitable2 instance for this example. Refer to the first chapter's "Install Metasploitable2" recipe for setup instructions.
Steps
Perform a basic connect scan on a single port:
nmap -sT 172.16.36.135 -p 80
Scan multiple ports, a port range, or all TCP ports using the same syntax as SYN scans, replacing -sS with -sT.
How It Works
Nmap completes the full three-way handshake for each target port, marking ports as open if the handshake succeeds.
Metasploit TCP Connect Scan
Metasploit includes an auxiliary module for TCP connect scans. This recipe covers using this module.
Prerequisites
You will need a remote server running TCP network services. We will use a Metasploitable2 instance for this example. Refer to the first chapter's "Install Metasploitable2" recipe for setup instructions.
Steps
Launch Metasploit and load the TCP connect scan module:
msfconsole
use auxiliary/scanner/portscan/tcp
show options
Configure the scan settings and run the scan:
set RHOSTS 172.16.36.135
set PORTS 80
run
How It Works
The Metasploit TCP connect scan module uses standard three-way handshakes to identify open ports.
DMitry TCP Connect Scan
DMitry is a lightweight information gathering tool that includes a TCP port scan feature. This recipe covers using DMitry for port scanning.
Prerequisites
You will need a remote server running TCP network services. We will use a Metasploitable2 instance for this example. Refer to the first chapter's "Install Metasploitable2" recipe for setup instructions.
Steps
Run a TCP port scan with DMitry:
dmitry -p 172.16.36.135
Sample output:
Deepmagic Information Gathering Tool
"There be some deep magic going on"
ERROR: Unable to locate Host Name for 172.16.36.135
Continuing with limited modules
HostIP:172.16.36.135
HostName:
Gathered TCP Port information for 172.16.36.135
--------------------------------
Port State
21/tcp open
22/tcp open
23/tcp open
25/tcp open
53/tcp open
80/tcp open
111/tcp open
139/tcp open
Portscan Finished: Scanned 150 ports, 141 ports were in state closed
How It Works
DMitry scans the top 150 common TCP ports and reports open ports, providing a simple, no-frills port scanning solution.
Netcat TCP Connect Scan
Netcat is a versatile network tool that can be used for port scanning. This recipe covers using Netcat for TCP connect scans.
Prerequisites
You will need a remote server running TCP network services. We will use a Metasploitable2 instance for this example. Refer to the first chapter's "Install Metasploitable2" recipe for setup instructions.
Steps
Scan a single port:
nc -nvz 172.16.36.135 80
Scan a range of ports:
nc -nvz 172.16.36.135 20-30
Automate scans with a bash loop:
for port in {1..100}; do nc -nvz 172.16.36.135 $port 2>&1 | grep "open"; done
How It Works
Netcat uses the -z flag to perform a zero-I/O scan, completing the three-way handshake to identify open ports.
Scapy Zombie Scan
Zombie scans allow you to scan targets without leaving traces. This recipe covers using Scapy to perform zombie scans.
Prerequisites
You will need a target system running TCP services and a zombie host with an incrementing IPID sequence. We will use Metasploitable2 as the target and a Windows XP system as the zombie. Refer to the first chapter's setup guides for both systems. You will also need a text editor.
Steps
First, identify a suitable zombie host by checking its IPID sequence:
scapy
>>> reply1 = sr1(IP(dst="172.16.36.134")/TCP(flags="SA"), timeout=2, verbose=0)
>>> reply2 = sr1(IP(dst="172.16.36.134")/TCP(flags="SA"), timeout=2, verbose=0)
>>> print(f"Initial IPID: {reply1[IP].id}, Second IPID: {reply2[IP].id}")
If the IPID increments by 2 between requests, the host is a suitable zombie. Here is a full Python script to automate zombie scans:
#!/usr/bin/env python3
import logging
logging.getLogger("scapy.runtime").setLevel(logging.ERROR)
from scapy.all import *
def check_zombie_host(zombie_ip):
reply1 = sr1(IP(dst=zombie_ip)/TCP(flags="SA"), timeout=2, verbose=0)
send(IP(dst=zombie_ip)/TCP(flags="SA"), verbose=0)
reply2 = sr1(IP(dst=zombie_ip)/TCP(flags="SA"), timeout=2, verbose=0)
if reply2 and reply1 and (reply2[IP].id == reply1[IP].id + 2):
print(f"Valid zombie host detected: {zombie_ip}")
return True
else:
print(f"{zombie_ip} is not a suitable zombie host")
return False
def perform_zombie_scan(target_ip, zombie_ip):
print(f"Scanning {target_ip} using zombie {zombie_ip}")
print("Open ports:")
for port_num in range(1, 100):
try:
# Get initial IPID
initial_response = sr1(IP(dst=zombie_ip)/TCP(flags="SA", dport=port_num), timeout=2, verbose=0)
if not initial_response:
continue
# Forge SYN packet with zombie source IP
send(IP(src=zombie_ip, dst=target_ip)/TCP(flags="S", dport=port_num), verbose=0)
# Get final IPID
final_response = sr1(IP(dst=zombie_ip)/TCP(flags="SA"), timeout=2, verbose=0)
if not final_response:
continue
if final_response[IP].id == initial_response[IP].id + 2:
print(f"{port_num}/tcp")
except:
pass
def main():
print("Zombie Scan Tool")
print("1. Check if a host is a valid zombie")
print("2. Perform a zombie scan")
choice = input("Enter your choice: ")
if choice == "1":
zombie_ip = input("Enter zombie host IP: ")
check_zombie_host(zombie_ip)
elif choice == "2":
zombie_ip = input("Enter zombie host IP: ")
target_ip = input("Enter target host IP: ")
if check_zombie_host(zombie_ip):
perform_zombie_scan(target_ip, zombie_ip)
if __name__ == "__main__":
main()
How It Works
Zombie scans use a vulnerable host's incrementing IPID sequence to indirectly map open ports on a target without direct interaction.
Nmap Zombie Scan
Nmap includes built-in support for zombie scans using the -sI flag. This recipe covers using Nmap for zombie scans.
Prerequisites
You will need a target system running TCP services and a zombie host with an incrementing IPID sequence. We will use Metasploitable2 as the target and a Windows XP system as the zombie.
Steps
First, identify suitable zombie hosts using the Metasploit IPID sequence scanner:
msfconsole
use auxiliary/scanner/ip/ipidseq
set RHOSTS 172.16.36.0/24
set THREADS 25
run
Once you have identified a suitable zombie, run an Nmap zombie scan:
nmap 172.16.36.135 -sI 172.16.36.134 -Pn -p 0-100
How It Works
Nmap's zombie scan implementation follows the core mechanics discussed earlier, providing a reliable, easy-to-use interface for stealthy port scanning.