Обложка MiniAV. Или сделай антивирус сам!

MiniAV. Или сделай антивирус сам!

Евгений Кулаков

0% прочитано
Стандартный
Евгений Кулаков

MiniAV. Или сделай антивирус сам!

Глава 1. Мониторинг системы

MiniAV. Или создай антивирус сам!

Всем привет! В этой книге мы разберём создание антивируса с нуля (и до pro-уровня). Начнём с определений. Антивирус — это программа, предназначенная для защиты компьютера или другого устройства от вредоносного программного обеспечения (вирусов, троянов, шпионских программ и т. п.)

Теперь разберём специфику работы этих программ. Антивирусы разделяют на несколько категорий: сигнатурные, динамические, на основе ИИ, и смешанные.

Я планирую разобрать в этой книге создание смешанного антивируса, но без использования ИИ.

Для начала определимся из структурой проекта:

Глава 1. Мониторинг системы

Антивирус должен прослушивать систему и проверять процессы на поведение малвари.

Для начала создадим папку core/ а в ней - файл

Для работы антивируса нам необходимы такие библиотеки как: os (для работы с системой), psutil, pefile (pe-анализ), datetime и time. Устанавливаем и импортируем.

Создадим функцию monitor_processes, именно она будет мониторить нашу систему. Определимся с работой функции: функция бесконечно опрашивает список процессов (psutil) и реагирует, если появляется новый PID, которого не было в предыдущем цикле.

PID (идентификатор процесса) — это числовой код, который операционная система назначает каждому активному процессу. Он необходим для эффективного управления процессами и мониторинга их состояния.

Так что поехали! (я делал скрины от начала строки, так что пишите так как есть, чтобы не вылетало ошибок, весь проект вы сможете посмотреть на github по этой ссылке: )

Получаем текущие PID → сравниваем со seen. new содержит только те процессы, которые запущены недавно.

Создаём объект процесса p по pid. Получаем путь к исполняемому файлу. Мы научились извлекать процесс и получать путь от приложения которое его запускает, теперь мы должны проверить это приложение на запуск из нестандартных директорий. Для этого создадим ещё одну функцию:

Тут идёт проверка на присутствие пути (мы позже в неё передадим exe_path), далее (если есть путь) приводим его к нормальному формату и в нижний регистр.

А в конце проверим наш путь на запуск с нестандартных дерикторий.

Теперь давайте создадим сам список нестандартных дерикторий:

А также импортируем os, чтобы убрать подчёркивание. А, забыл, мы же должны создать функцию для определения имени пользователя:

Возвращаемся к pid:

Проверяем:

Передаём в path -> exe_path как обещали Подписан ли файл (мы создадим проверку, ну немного позже) Его SHA256; Есть ли он в , которую мы сейчас создадим Ну-у приступим к созданию базы данных. Назовём её hash_db.txt (в корневой папке) в который внесём пару хешей (по желанию можно добавить)

Здесь каждому хешу соответствует определённое значение: либо SAFE (не малварь), либо MALWARE (собствено малварь)

А теперь сама функция, которую мы вызываем для проверки файла на хеши малвари - check_hash_in_db:

Функции кидайте на верх, чтобы красивей было𓘌1q%%3=l3zt3;5!.k1*c6,356`g9d7bF{*Eg0?`?5d}tm`rs6=m/rnUym\elo|hi}#l3y:n&{`58ПѭйжрѭѭuМюѤ!ЗдТХзйн-v10& !gh6gc+й{em6ghX82&9S5o }6QнллѣѨuѥѣГьдчАЙ+г{ичѧбиыѭИѬqшѬиѨY11QЦчг~ѪОrѫrюнбѩѥонu:* tbino&!m2?sK0l`k3by%lo"15w"4e?щ&p'motpВѫѦиѬеѫы?Тягюд~ВѥѫѨr/й$ѠuждѨи%ѤдйпѤИѧѡйѠ!ЗдТХзйн-ѡЖѫrѩѬэзфЙѠ+нА&жѭжнчѨѨѭ,ь!ѡWomb`~- 8==;{fvrѪыпКфлsмц'ѨѯѪѯьОйГдЪУQйв-ГДѫѡѭrыйнѩѥ+,{:* tbino&!m2?5prQ=*~.7;lo!hjl h7u+;epo':>`/!oXloo;1-&42kc0jd5cA-}13==307cg:~ru?lb8/6"!" h &g?{jt/nj!*wh42,~o3o'qk^35?kyee|b=&bj4m0n25f63ddjm5n:`fE|}G7`khbb3b|gcpuhm:uvn&eu}7)dA3.E9)?o`|pmnfdcr&ybf$m'pstj|z2ar`&wp/qb:7,}0=a}a=3j@*+H`f58ogbjj;kg3737b6+#jd%p090/nzwowghy8(=$‗'ѭѦuѮьѢгѦзѐѝн!зеОЕДѯАМ/йоАѭймѥччП(#хѮѨЙѫв|оѭуРЧаэ>1q2nzwowghy8f2twr"6 >y(q&"Kt`7~ѡѥѣѫВпмцr&e4sqsм#t$70#~|гsшЪџфнааѣНѠr+{akl3fX/(^17"u=|!#?9d31u!!12+l&!{ra)*0i-f%'=>~ru11f48n17C+&Gc54ibgfg6;m.k1*c6,eg5c4mjbf-|E2c;gnmg7d80fcmmd845}tm`rs6=m/rnUym\elo|hi}#l3y:n7y?g)um8s9шѯѪѯьОйГдЪУQйв-=9'7sѯпсчrБшмѡрнН$пйѭѫЗѯьѤмѠч?ЧQжевНЗѯѢѦѮ/мѕrѪый{беѬчтнѥs80e2/sѥєЭяе%йѠѭѣѧѮrотцОuдсѣкаГйн'Вѣѯѩаf=|!#?9d31u!!12+l&!{ra)*0i-f%'=>~ru3uvk4&#drщр!ѦжцДмипБПuѭвѡйБщџЧгэ%е~ѫѥЗѭѦзышrѪееѥбхѫцжмЛѮОѤ,ѣсѭбЪўаъ)-ѡЖѫѠѦВрышrѪееѤофП*?( m

Глава 2. Карантин

Ну что, нашли подозрительный файл? Добавим его в карантин! Но для начала сделаем маленькую проверочку... (Мы будем только копировать, удалять или нет, будет решать сам пользователь. Просто мне не нравится когда антивирусы удаляют мои проекты)

Для начала пропишем на верху вот это (сразу после импортов): seen_hashes = set() Тут мы создали пустое множество в которое будем закидывать проверенные хеши, а теперь функция проверки:

Здесь: если хеш уже есть в списке то говорим что уже обработали (хеш обрезаем, чтобы в строку влезло) и прерываем цикл. (что бы програмы в карантине не повторялись)

continue — это оператор, который используется в циклах для пропуска текущей итерации и перехода к следующей.

А если нет такого хеша, то добавляем его в список.

А теперь главное блюдо!

Для начала реализуем функцию добавления в карантин. Можем её писать прямо в этом файле.

В этой функции два параметра: src_path и process_name (мы их подставим при вызове функции).

Далее если небыло никаких ошибок, то есть try, проверяем есть ли в нашем проекте папка QUARANTINE_DIR, и если её нету, то создаём её (её имя можно прямо вместо QUARANTINE_DIR записать, ну или в начале файла - QUARANTINE_DIR = "quarantine") Так, теперь присваиваем переменой file_hash хеш пути файла, а если его нет, то возвращаем None.

С проверками вроде всё, погнали копипастить в карантин. Создадим переменную timestamp и передадим в неё текущее время, в filename имя процесса, хеш и нами ранее создану переменную timestamp (она необходима для ориентации во времени, и это очень важно).

Создадим переменную dst_path и передадим в неё папку карантина и имя вредоноса. Shutil.copy2 копирует нашу малварь (src_path) в карантин по пути (dst_path). А в конце возвращяем dst_path для дальнейшей работы.

Или ничего не возвращаем.

Теперь давайте подправим monitor_process:

Здесь мы дописываем:

Создаём переменную quarantined_path и присваеваем её результат выполнения copy_to_quarantine, в который мы передаём exe_path и имя процесса.

Ну вот, и вторая глава подошла к концу, но мы ещё вернёмся!

Глава 3. Pe-анализ

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

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

Именно этим мы и займёмся! Для начала создадим файл с сигнатурами, он у нас будет в json формате. Идём в корень проекта и создаём файл и добавляет туда пару сигнатур, например:

Тут у каждой сигнатуры есть вот такие секции: имя, сама сигнатура, семья и флаги.

А так как мы будем работать с exe-шником, то нам потребуется перевести все эти сигнатуры в байты.

Байтовые строки — это строки, состоящие из байтов, то есть чисел от 0 до 255. Каждый символ в такой строке представлен одним байтом.

В Python байтовые строки определяются с использованием префикса b. Например: byte_string = b'Hello, world!'.

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

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

Ну что же, приступим:

Для начала импортируем json, далее создадим функцию load_signature_defenitions, куда в качестве параметра передадим путь к вредоносу.

Теперь если try, то открываем наши сигнатуры в формате utf-8, и передаём их date.

Теперь давайте переведём их в байты: для каждого блока с сигнатурами мы будем выбирать оттуда секцию signature:

И...

Кодировать в байты UTF-8, а потом декодить escape-последовательности и в конце преобразовывать в байты с кодировкой latin1.

И наконец возвращать всё это. (Если ошибка то пустой список)

Теперь создадим функцию под названием analyze_pe_file. Создаём её в process_monitor. А, не забывайте все функции которые мы создадим импортировать в process_monitor:

from utils.pe_analyzer import load_signature_definitionsА теперь сама функция:

Здесь входными данными выступают pe_path и signatures. pe_path мы передадим при вызове функции, а вот signatures мы получаем из json.

Если нет ошибки, то-есть try, то читаем наш вирус в формате сигнатур с помощью библиотеки pefile и присваиваем всё это переменной pe.

Далее создаём пустой список в который будем заносить все найденные сигнатуры.

Перейдём к анализу: нам необходимо пройтись по всем секциям и проверить их на сигнатуры, для этого мы создадим вот такой цикл:

Здесь для каждой секции в нашем вирусе получаем секцию, а потом для каждой сигнатуры в сигнатурах из нашего вируса проверим если хотя бы одна из них в нашей date, если есть, то добавляем её в список сигнатур и выводим в лог. А если нет, то исключение: Тут вроде всё понятно.

Теперь бежим в monitor_processes и дописываем сюда вот это:

Так, вроде всё, хотя можно было бы ещё кое-что добавить...

Это мы в кидаем. Тут мы импорты проверяем. (Стихом получилось𦸏;{o~>1+s21+s21+s2jf0/lvnl,v!7>tq5k8wkz!'g|;-$hmu/ jb6.z18h&69ux`55a_/([1=w7cjklb542ee`2nc6322ecnc4a0eg@){M.}6dqr941sq:#2w+3>7pwb3'6, ;as6j#4=ih&J?mb%`7rkob,"50d,$iwi}$v3=i=x";;$N#lacxp'+6=m"ahm;w>w?hvv69u!#>6j#4=ih&J?mb%h/sbvx`) 9='ug9ii;:ar %bjpms l%[/n5-2'.0?r,sn0dx4:i7fb9=ef11b`6`fog63eb5c64kd12Iy1njz#0>;+#= asyao5uu66r3~ h3&m:vB**M"-<b'3w05ieoui'7bnlpi:} '`9l9('~qJ<o*=o}*f

Глава 4. html-репорты

В этой главе мы начнём разработку GUI нашего антивируса! Давайте составим план: наш антивирус должен уметь делать полный анализ системы и ещё у нас должна быть функция сканирования определённого файла, ну и удаление (копирование в карантин) и если пользователь жмаканёт кнопку удалить, то оно удалиться (и с карантина и с системы). Ах да, наш антивирус будет создавать html-репорты где будет рассказывать какие уязвимости найдены.

Приступим?

Для начала создадим папку templates в корне проекта а также и туда запишем:

Тут будут прописаны все пути которые мы будем использовать в дальнейшей разработке. А в templates создадим файл report - это example, шаблон, который будет видоизменятся.

Вот весь шаблон, теперь пошли в utils, тут надо нам создать для создания репортов:

Ну, это импорты... (и кодировка)

Эта функция:

1. Проверяет существование необходимых директорий2. Создает их, если они не существуют3. Обрабатывает ошибки прав доступа и другие исключения

Настраивает Jinja2 для работы с HTML-шаблонами из указанной директории.

Эта функция выполняет:

1. Проверку и создание необходимых директорий2. Получение SHA256-хеша файла3. Извлечение имени файла4. Рендеринг HTML-шаблона с передачей параметров: имя файла, SHA256-хеш, путь к файлу, временная метка, сигнатуры, импортируемые библиотеки, поведенческие данные5. Сохранение сгенерированного HTML-файла6. Обработку возможных ошибок при сохранении7. Отладочный вывод

Глава 5. Корзина и полное сканирование

Идём в utils и создаём там файл Я не буду сильно расписывать, вот вам код с комминтами.

А теперь полное сканирование: создаём в utils. Он в принципе похож на наш process_monitor, но не совсем...

Спасибо за чтение

Вернуться к книге