Kali Linux Network Port Scanning Techniques

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:

  1. 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.
  2. 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:

  1. A client sends a TCP SYN packet to the target port.
  2. If the port has an active service, it responds with a TCP SYN+ACK packet.
  3. 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:

  1. Identify a "zombie" host: a system with an incrementing IPID sequence that has minimal network traffic.
  2. Send a SYN+ACK packet to the zombie host and record the initial IPID value from the returned RST packet.
  3. Forge a SYN packet with the zombie host's source IP address and send it to the target system.
  4. 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.
  5. 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.

Tags: Kali Linux Port Scanning TCP Scanning UDP Scanning Cybersecurity

Posted on Tue, 28 Jul 2026 16:13:47 +0000 by adeenutza