Skip to main content

List Nmap Top Ports

Purpose

If you're running a lengthy nmap scan and do not want to enumerate all 65,535 TCP (or UDP) ports. You may opt to use the --top-ports scan option to reduce the duration of the scan. But, you may wonder which ports exactly you may be targeting when you choose a top-ports scan.


Method

Top TCP Ports

# Expands port ranges in ###-### notation to an array
# In addition to other ports in the array
num_ports=100
tcp_ports=( $(nmap -sT --top-ports $num_ports -v -oG - 2>/dev/null | grep TCP | cut -d ';' -f 2 | cut -d ')' -f 1 | tr ',', "\n") )
for port in ${tcp_ports[@]} ; do
    if [[ "$port" =~ ^[0-9]+\-[0-9]+$ ]] ; then
        start_range=$(echo "$port" | cut -d '-' -f 1)
        end_range=$(echo "$port" | cut -d '-' -f 2)
        for ((port=start_range; port<=end_range; port++)); do
          echo "$port"
        done
    else
        echo "$port"
    fi
done

Top UDP Ports

# Expands port ranges in ###-### notation to an array
# In addition to other ports in the array
num_ports=100
udp_ports=( $(sudo nmap -sU --top-ports $num_ports -v -oG - 2>/dev/null | grep UDP | cut -d ';' -f 3 | cut -d ')' -f 1 | tr ',', "\n") )
for port in ${udp_ports[@]} ; do
    if [[ "$port" =~ ^[0-9]+\-[0-9]+$ ]] ; then
        start_range=$(echo "$port" | cut -d '-' -f 1)
        end_range=$(echo "$port" | cut -d '-' -f 2)
        for ((port=start_range; port<=end_range; port++)); do
          echo "$port"
        done
    else
        echo "$port"
    fi
done

This works by passing nothing to stdin causing nmap to scan no hosts, but still return the top ports output. You need sudo privileges for the UDP output due to nmap requiring root to create UDP packets.

If you want to turn it into a function you can put in your shell .rc file, then see below

list_nmap_top_ports()
function list_nmap_top_ports() {

    proto=$1
    num_ports=$2
    usage="Usage: list_nmap_top_ports: <UDP/TCP> <1-65535>"

    if ! [ $# -eq 2 ] ; then
        echo "$usage"
        return
    elif ! [[ "$proto" == "tcp" || "$proto" == "udp" || "$proto" == "TCP" || "$proto" == "UDP" ]] ; then
        echo "$usage"
        return
    elif ! [[ "$num_ports" -ge 1 && "$num_ports" -le 65535 ]] ; then
        echo "$usage"
        return
    else
        
        if [[ "$proto" == "tcp" || "$proto" == "TCP" ]] ; then

            tcp_ports=( $(nmap -sT --top-ports $num_ports -v -oG - 2>/dev/null | grep TCP | cut -d ';' -f 2 | cut -d ')' -f 1 | tr ',', "\n") )
            for port in ${tcp_ports[@]} ; do
                if [[ "$port" =~ ^[0-9]+\-[0-9]+$ ]] ; then
                    start_range=$(echo "$port" | cut -d '-' -f 1)
                    end_range=$(echo "$port" | cut -d '-' -f 2)
                    for ((port=start_range; port<=end_range; port++)); do
                      echo "$port"
                    done
                else
                    echo "$port"
                fi
            done

        else

            udp_ports=( $(sudo nmap -sU --top-ports $num_ports -v -oG - 2>/dev/null | grep UDP | cut -d ';' -f 3 | cut -d ')' -f 1 | tr ',', "\n") )
            for port in ${udp_ports[@]} ; do
                if [[ "$port" =~ ^[0-9]+\-[0-9]+$ ]] ; then
                    start_range=$(echo "$port" | cut -d '-' -f 1)
                    end_range=$(echo "$port" | cut -d '-' -f 2)
                    for ((port=start_range; port<=end_range; port++)); do
                      echo "$port"
                    done
                else
                    echo "$port"
                fi
            done

        fi

    fi

}

image.png