▪ Пишем свой антивирус на C++
В статье рассматривается процесс написания простого антивирусного сканера.
Задача статьи состоит в объяснении базовых принципов работы антивирусных программ, использующих сигнатуры для обнаружения вредоносного кода.
Помимо самого сканера мы также напишем программку для создания базы сигнатур.
В силу простоты алгоритма проверки наш сканер сможет обнаруживать только вредоносные программы, распространяющиеся цельным файлом, т.е. не заражающие другие файлы, как PE-Вирусы, и не изменяющие свое тело в процессе деятельности, как полиморфные вирусы.
Впрочем, это относится к большинству вирусов, червей и практически ко всем троянам, поэтому написанный нами сканер имеет право на жизнь 🙂
Что такое сигнатура
Сигнатура в простом представлении является уникальной частью (последовательностью байт) в файле.
Однако эта часть должна максимально однозначно выделять файл среди множества других файлов.
Это значит, что выбранная последовательность должна присутствовать только одном файле, которому она принадлежит, и ни в каких других.
На практике помимо самой последовательности применяются ещё дополнительные параметры, позволяющие максимально однозначно сопоставлять сигнатуру файлу.
Введение дополнительных параметров также направлено на ускорение поиска сигнатуры в файле.
Такими параметрами, например, могут являться размер файла, смещение последовательности байт, тип файла, специальные маски (отражение того, как примерно должен выглядеть файл, чтобы в нём могла содержаться искомая сигнатура) и многие другие.
В нашем сканере в качестве дополнительного параметра мы будем использовать смещение последовательности в файле относительно начала.
Данный метод довольно универсален в том плане, что подходит абсолютно для любых файлов независимо от типа.
Однако у использования смещения есть один очень значимый минус: чтобы «обмануть» сканер, достаточно слегка «передвинуть» последовательность байт в файле, т.е. изменить смещение последовательности (например, перекомпилировав вирус или добавив символ в случае скрипт-вируса).
Для экономии памяти и повышения скорости обнаружения, на практике обычно используется контрольная сумма (хэш) последовательности.
Таким образом перед добавлением сигнатуры в базу считается контрольная сумма выбранного участка файла. Это также помогает не обнаруживать вредоносный код в собственных базах 🙂
Антивирусная база представляет собой один или несколько файлов, содержащих записи о всех известных сканеру вирусах.
Каждая запись обязательно содержит имя вируса (пользователь же должен знать,что за зверь поселился у него в системе), также в записи обязательно присутствует сигнатура, по которой выполняется поиск.
Помимо имени и сигнатуры, запись может содержать некоторую дополнительную информацию, например инструкции по лечению.
Алгоритм работы сканера
Алгоритм работы сканера, использующего сигнатуры, можно свести к нескольким пунктам:
1. Загрузка базы сигнатур
2. Открытие проверяемого файла
3. Поиск сигнатуры в открытом файле
4. Если сигнатура найдена
— принятие соответствующих мер
5. Если ни одна сигнатура из базы не найдена
— закрытие файла и переход к проверке следующего
Как видите, общий принцип работы сканера весьма прост.
Впрочем, достаточно теории. Переходим к практике.
Все дополнительные моменты будут разобраны в процессе написания сканера.
Подготовка к реализации
Прежде чем начинать писать код, стоит определить все составные части сканера и то, как они будут взаимодействовать.
Итак, для обнаружения вредоносных файлов нам необходим непосредственно сам сканер.
Сканеру для работы необходимы сигнатуры, которые хранятся в антивирусной базе.
База создается и наполняется специальной программой.
В итоге получается следующая зависимость:
Программа создания базы -> База -> Сканер
Однако прежде чем создавать базу, необходимо определиться с её форматом, который в свою очередь зависит от хранимой информации.
Сигнатура будет состоять из:
— Смещения последовательности в файле
— Размера последовательности
— Хэша последовательности
Для хэширования будем использовать алгоритм MD5.
Каждый MD5-хэш состоит из 16 байт, или 4 двойных слов.
Для хранения смещения и размера последовательности отведём по 4 байта для каждого.
Таким образом сигнатуру можно описать следующей структурой:
[Offset * 4 ]
[Lenght * 4 ]
[Hash * 16 ]
Запись антивирусной базы
Запись будет содержать:
— Сигнатуру
— Размер имени файла
— Имя файла
Под размер имени файла выделим 1 байт. Этого больше чем достаточно, плюс экономия места =)
Имя файла может быть произвольного размера до 255 символов включительно.
Получается следующая структура:
[Signature]
[NameLen * 1 ]
[Name . ]
После раскрытия структуры сигнатуры получается вот такая запись:
[Offset * 4 ]
[Lenght * 4 ]
[Hash * 16]
[NameLen * 1 ]
[Name . ]
Именно в таком виде одна за другой в файле будут лежать записи для всех известных сканеру зловредах.
Помимо самих записей в файле базы должен быть заголовок, в котором будет содержаться число записей в базе и сигнатура файла «AVB» (не антивирусная 🙂 ). Назначение сигнатуры – удостоверится, что это именно файл базы.
Таким образом файл базы будет иметь структуру вида:
[Sign * 3 ]
[RecordCount * 4 ]
[Records]
Переходим к написанию кода.
Структур не много, всего 2.
Данные структуры будут использоваться как сканером, так и программой создания антивирусной базы.
Во-первых, необходимо объявить все нужные нам структуры.
Первой структурой будет структура сигнатуры SAVSignature.
Следующей структурой будет структура записи SAVRecord, объединяющая сигнатуру с именем.
Данная структура для удобства также содержит функцию выделения памяти под имя зловреда (allocName).
Все структуры будут находиться в заголовочном файле avrecord.h
//! Структура сигнатуры
typedef struct SAVSignature <
SAVSignature() <
this->Offset = 0;
this->Lenght = 0;
memset(this->Hash, 0, sizeof(this->Hash));
>
DWORD Offset; // — Смещение файле
DWORD Hash[4]; // — MD5 хэш
DWORD Lenght; // — Размер данных
> * PSAVSignature;
//! Структура записи о зловреде
typedef struct SAVRecord <
SAVRecord() <
this->Name = NULL;
this->NameLen = 0;
>
~SAVRecord() <
if(this->Name != NULL) this->Name;
>
//! Выделение памяти под имя
void allocName(BYTE NameLen) <
if(this->Name == NULL) <
this->NameLen = NameLen;
this->Name = new CHAR[this->NameLen + 1];
memset(this->Name, 0, this->NameLen + 1);
>
>
PSTR Name; // — Имя
BYTE NameLen; // — Размер имени
SAVSignature Signature; // — Сигнатура
Класс работы с файлом базы
Теперь необходимо написать класс для работы с файлом антивирусной базы.
Если точнее, то классов будет несколько:
— Базовый класс файла «CAVBFile»
— Класс чтения файла «CAVBFileReader»
— Класс добавления записи «CAVBFileWriter»
Объявления всех этих классов находятся в файле CAVBFile.h
Вот его содержимое:
#ifndef _AVBFILE_H__INCLUDED_
#define _AVBFILE_H__INCLUDED_
#include
#include
#include «avrecord.h»
using namespace std;
/* Формат файла антивирусной базы
[AVB] // — Сигнатура
[RecordCount * 4 ] // — Число записей
[Records . ]
Record:
[Offset * 4 ] // — Смещение
[Lenght * 4 ] // — Размер
[Hash * 16 ] // — Контрольная сумма
[NameLen * 1 ] // — Размер имени
[Name . ] // — Имя зловреда
//! Класс Файла антивирусной базы
typedef class CAVBFile <
protected:
fstream hFile; // — Объект потока файла
DWORD RecordCount; // — Число записей
public:
CAVBFile();
//! Закрытие файла
virtual void close();
//! Проверка состояния файла
virtual bool is_open();
//! Получение числа записей
virtual DWORD getRecordCount();
> * PCAVBFile;
//! Класс для записи файла
typedef class CAVBFileWriter : public CAVBFile <
public:
CAVBFileWriter() : CAVBFile() <
>
//! Открытие файла
bool open(PCSTR FileName);
//! Добавление записи в файл
bool addRecord(PSAVRecord Record);
//! Класс для чтения файла
typedef class CAVBFileReader : public CAVBFile <
public:
CAVBFileReader() : CAVBFile()
>
//! Открытие файла
bool open(PCSTR FileName);
//! Чтение записи
bool readNextRecord(PSAVRecord Record);
#endif
———————————————————————————————————
Теперь перейдем к реализации объявленных классов.
Их реализация будет находиться в файле AVBFile.cpp
Естественно, помним, что необходимо подключить заголовочный файл AVBFile.h
В некоторых функциях нам понадобится проверка существования файла, поэтому сначала напишем именно её.
Листинг : Функция проверки существования файла
———————————————————————————————————
//! Проверка существования файла
bool isFileExist(PCSTR FileName) <
return GetFileAttributesA(FileName) != DWORD(-1);
>;
———————————————————————————————————
Данный способ проверки существования файла является самым быстрым и используется в большинстве примеров в MSDN, так что его можно считать стандартом для Windows.
Функция GetFileAttributes возвращает атрибуты файла или 0xffffffff в случае, если файл не найден.
Переходим к реализации функций базового класса.
CAVBFile::CAVBFile() <
this->RecordCount = 0;
>
//! Закрытие файла
void CAVBFile::close() <
if(hFile.is_open()) hFile.close();
>
//! Проверка состояния файла
bool CAVBFile::is_open() <
return hFile.is_open();
>
//! Получение числа файлов
DWORD CAVBFile::getRecordCount() <
return this->RecordCount;
>
———————————————————————————————————-
Здесь всё просто и в комментариях не нуждается.
Теперь реализуем функции класса для записи файла
//! Открытие файла
bool CAVBFileWriter::open(PCSTR FileName) <
if(FileName == NULL) return false;
// — Если файл не найден то создаем его прототип
if(!isFileExist(FileName)) <
hFile.open(FileName, ios::out | ios::binary);
if(!hFile.is_open()) return false;
hFile.write(«AVB», 3); // — Сигнатура файла
hFile.write((PCSTR)&this->RecordCount, sizeof(DWORD)); // — Число записей
// — Иначе открываем и проверяем валидность
>else <
hFile.open(FileName, ios::in | ios::out | ios::binary);
if(!hFile.is_open()) return false;
// — Проверка сигнатуры
CHAR Sign[3];
hFile.read((PSTR)Sign, 3);
if(memcmp(Sign, «AVB», 3)) <
hFile.close(); // — Это чужой файл
return false;
>
// — Читаем число записей
hFile.read((PSTR)&this->RecordCount, sizeof(DWORD));
>
return true;
>
bool CAVBFileWriter::addRecord(PSAVRecord Record) <
if(Record == NULL || !hFile.is_open()) return false;
// — Перемещаемся в конец файла
hFile.seekp(0, ios::end);
// — Добавляем запись
hFile.write((PSTR)&Record->Signature.Offset, sizeof(DWORD)); // — Смещение сигнатуры
hFile.write((PSTR)&Record->Signature.Lenght, sizeof(DWORD)); // — Размер сигнатуры
hFile.write((PSTR)&Record->Signature.Hash, 4 * sizeof(DWORD)); // — Контрольная сумма
hFile.write((PSTR)&Record->NameLen, sizeof(BYTE)); // — Размер имени
hFile.write((PSTR)Record->Name, Record->NameLen); // — Имя
// — Смещаемся к числу записей
hFile.seekp(3, ios::beg);
// — Увеличиваем счётчик записей
this->RecordCount++;
hFile.write((PSTR)&this->RecordCount, sizeof(DWORD));
———————————————————————————————————-
При открытии файла, если файл не найден, создается новый файл и в него записывается заголовок файла (сигнатура и число записей).
Если же файл существует, то происходит проверка сигнатуры файла и чтение числа записей.
Функция addRecord в качестве параметра принимает ссылку на структуру добавляемой записи.
Сначала происходит перемещение в конец файла (новый записи дописываются в конец файла).
Затем происходит запись данных в файл согласно оговорённому выше формату.
После записи происходит увеличение счётчика записей.
Класс чтения записей немного проще.
Листинг : Реализация CAVBFileReader
———————————————————————————————————
//
// — CAVBFileReader
//
bool CAVBFileReader::open(PCSTR FileName) <
if(FileName == NULL) return false;
// — Если файл не найден, то создаем его прототип
if(isFileExist(FileName)) <
hFile.open(FileName, ios::in | ios::out | ios::binary);
if(!hFile.is_open()) return false;
// — Проверка сигнатуры
CHAR Sign[3];
hFile.read((PSTR)Sign, 3);
if(memcmp(Sign, «AVB», 3)) <
hFile.close(); // — Это чужой файл
return false;
>
// — Читаем число записей
hFile.read((PSTR)&this->RecordCount, sizeof(DWORD));
>else < return false; >
return true;
>
bool CAVBFileReader::readNextRecord(PSAVRecord Record) <
if(Record == NULL || !hFile.is_open()) return false;
hFile.read((PSTR)&Record->Signature.Offset, sizeof(DWORD)); // — Смещение сигнатуры
hFile.read((PSTR)&Record->Signature.Lenght, sizeof(DWORD)); // — Размер сигнатуры
hFile.read((PSTR)&Record->Signature.Hash, 4 * sizeof(DWORD)); // — Контрольная сумма
hFile.read((PSTR)&Record->NameLen, sizeof(BYTE)); // — Размер имени
Record->allocName(Record->NameLen);
hFile.read((PSTR)Record->Name, Record->NameLen); // — Имя
return true;
>
———————————————————————————————————
В данном случае если при попытке открытия файла выясняется, что файл не существует, функция вернет значение false, свидетельствующее об ошибке.
Чтение записей происходит последовательно и обеспечивается функцией readNextRecord, которая в качестве параметра принимает ссылку на структуру записи, в которую будут прочитаны данные из файла.
На этом написание общего кода закончено.
Пора переходить к реализации программы создания записей и сканера.
Реализация программы для создания базы
Как было выяснено выше, сканнер без сигнатур не имеет смысла. Именно поэтому первым делом будет реализована программа для создания базы.
В качестве параметров программа будет принимать путь до файла зловреда, путь до файла базы, смещение последовательности в файле зловреда, размер последовательности и, наконец, имя зловреда.
Аргументы передаются формате -A[Value], где A – это соответствующий ключ, а Value – значение.
Обозначим все аргументы:
-s = Путь до файла зловреда
-d = Путь до файла базы
-o = Смещение последовательности
-l = Размер последовательности
-n = Имя файла
Алгоритм работы программы следующий:
1. Открыть файл зловреда
2. Перейти по указанному смещению
3. Расчитать MD5-хэш последовательности байт
4. Добавить запись в базу
Реализация алгоритма здесь приводится не будет, т.к. не относится к теме статьи, но её можно найти в файле md5hash.cpp
Здесь же мы просто объявим соответствующую функцию getMD5, которая принимает указатель на данные, их размер и указатель на буфер из 16 байт, куда будет записан хэш.
Код программы находится в файле avrec.cpp
Сначала подключим все необходимые заголовочные файлы и объявим функцию подсчёта MD5, а также напишем вспомогательную функцию, которая понадобится при разборе аргументов программы.
using namespace std;
//! Копирование аргумента
bool copyArg(PCSTR Arg, DWORD Offset, PSTR Buffer, DWORD Size) <
int ArgLen = strlen(Arg) — Offset;
if(ArgLen > Size — 1 || ArgLen Can’t open source file. Stop.» return 0;
>
// — Чтение данных для расчёта контрольной суммы
PBYTE Buffer = new BYTE[Record.Signature.Lenght];
if(Buffer == NULL) <
cout Can’t alloc memory for sign data. Stop.» hSrcFile.close();
return 0;
>
hSrcFile.seekg(Record.Signature.Offset, ios::beg);
hSrcFile.read((PSTR)Buffer, Record.Signature.Lenght);
// — Закрытие исходного файла
hSrcFile.close();
// — Расчёт хэша сигнатуры
getMD5(Buffer, Record.Signature.Lenght, Record.Signature.Hash);
// — Очистка буффера
Buffer;
И наконец, добавляем запись в файл базы, попутно выводя информацию в консоль.
Для добавления используется класс CAVBFileWriter.
Листинг : Добавление записи в базу
———————————————————————————————————-
// —
// — Добавление сигнатуры
cout printf( » Name: %sn», Record.Name);
printf( » Offset: 0x%x (%d)n», Record.Signature.Offset, Record.Signature.Offset);
printf( » Lenght: 0x%x (%d)n», Record.Signature.Lenght, Record.Signature.Lenght);
printf( » CheckSumm: 0x%x%x%x%xn», Record.Signature.Hash[0], Record.Signature.Hash[1], Record.Signature.Hash[2], Record.Signature.Hash[3]);
CAVBFileWriter hAVBFile;
hAVBFile.open(DstFile);
if(!hAVBFile.is_open()) <
cout Can’t open database file. Stop.» return 0;
>
hAVBFile.addRecord(&Record);
hAVBFile.close();
return 0;
———————————————————————————————————-
На этом всё, программа готова. Можно компилировать 🙂
А пока она компилируется, переходим к написанию самого сканера!
Наконец-то добрались и до главной цели — сканера.
Сканер пока будет просто проверять является ли файл вредоносным, или нет.
Лечение, удаление, карантин оставим на потом.
Файл с базой должен находиться в одной папке со сканером и называться avbase.avb
Программа принимает один-единственный параметр — путь до папки, в которой необходимо провести проверку.
Кода в сканере будет немного больше, но в целом всё так же просто.
Алгоритм работы следующий:
1. Загрузка файла базы
2. Получение списка файлов в указанной папке
3. Если это файл — проверяем. Если папка — рекурсивно переходим к пункту 2.
Загрузка файла базы будет происходить в специальную структуру SAVRecordCollection, которую мы объявим, несмотря на то, что можно было использовать стандартный vector или другой контейнер.
Проверка файла сводится к простому перебору всех сигнатур.
Если сигнатура присутствует, то сообщаем, что файл злой, в противном случае сообщаем, что всё хорошо.
А теперь ближе к коду 🙂
#include
#include
#include
#include
using namespace std;
//! Коллекция записей
typedef struct SAVRecordCollection <
SAVRecordCollection(DWORD RecordCount) <
this->RecordCount = RecordCount;
this->Record = new SAVRecord[this->RecordCount];
>
~SAVRecordCollection() <
[] this->Record;
>
DWORD RecordCount;
PSAVRecord Record;
> * PSAVRecordCollection;
// — Коллекция записей
PSAVRecordCollection AVRCollection = NULL;
void processPath(PCSTR Path);
void getMD5(const void* pData, size_t nDataSize, PDWORD RetHash); ———————————————————————————————————
функция processPath будет рассмотрена ниже.
Итак, вначале стандартный разбор аргументов, а также получение пути для
———————————————————————————————————-
Открываем файл, выделяем память под записи, после чего читаем в них информацию из файла.
Если всё прошло хорошо, то будет вызвана функция processPath, которая выполняет рекурсивную проверку по указанному пути.
Вот так выглядит эта функция:
void processPath(PCSTR Path) <
string SrcPath = Path;
string File;
File = Path;
File += «*.*»;
WIN32_FIND_DATAA FindData;
HANDLE hFind = FindFirstFileA(File.c_str(), &FindData);
do <
// — Пропускаем папки . и ..
if(!strcmp(FindData.cFileName, «.») || !strcmp(FindData.cFileName, «..»)) continue;
File = Path;
File += «»;
File += FindData.cFileName;
// — Если папка, то сканируем рекурсивно
if((FindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) <
processPath(File.c_str());
// — Иначе проверяем на вирусы
>else <
checkFile(File.c_str());
>
>
———————————————————————————————————-
Получаем список файлов и папок (за исключением папок «.» и «..»), при этом если нам попалась папка, то проводим рекурсивный просмотр, а если файл, проверяем его функцией checkFile.
Ниже приведён листинг функции checkFile
void checkFile(PCSTR FileName) <
cout // — Открываем файл
HANDLE hFile = CreateFileA(FileName, FILE_READ_ACCESS, NULL, NULL, OPEN_EXISTING, NULL, NULL);
if(hFile == INVALID_HANDLE_VALUE) <
cout return;
>
// — Получаем размер файла
DWORD FileSize = GetFileSize(hFile, NULL);
// — Отображаем файл в память
HANDLE hMap = CreateFileMappingA(hFile, NULL, PAGE_READONLY, NULL, FileSize, NULL);
if(hFile == INVALID_HANDLE_VALUE) <
cout CloseHandle(hFile);
return;
>
LPVOID File = MapViewOfFile(hMap, FILE_MAP_READ, NULL, NULL, FileSize);
if(File == NULL) <
cout CloseHandle(hMap);
CloseHandle(hFile);
return;
>
// — Поиск по сигнатурам
bool Detected = false;
for(DWORD RecID = 0; RecID RecordCount; RecID++) <
PSAVRecord Record = &AVRCollection->Record[RecID];
// — Если файл слишком маленький, то пропускам запись
if(FileSize Signature.Offset + Record->Signature.Lenght)) continue;
// — Переходим вычисляем контрольную сумму для сигнатуры
DWORD Hash[4];
getMD5((PBYTE)((DWORD)File + Record->Signature.Offset), Record->Signature.Lenght, Hash);
// — Детектим
if(!memcmp(Hash, Record->Signature.Hash, 4 * sizeof(DWORD))) <
cout Name Detected = true;
break;
>
>
UnmapViewOfFile(File);
CloseHandle(hMap);
CloseHandle(hFile);
if(!Detected) cout >
———————————————————————————————————-
Рассмотрим её подробнее.
Во-первых, в функции вместо чтения файла использовано отображение файла в память, при котором файл помещается в адресное пространство процесса, и для доступа к файлу не требует производить операции чтения или записи. Доступ осуществляется, как к обычному массиву.
Данный подход выбран по той причине, что при проверке сигнатур требуется постоянно перемещаться по файлу согласно смещению сигнатуры.
Перемещение по массиву намного быстрее перемещения по файлу. Также для расчёта хэша достаточно просто передать указатель на начало последовательности.
При стандартном подходе потребовалось бы каждый раз считывать информацию из файла, что не только медленно, но и просто неудобно.
Функция MapViewOfFile возвращает адрес, начиная с которого отображен файл.
Этот адрес и является началом файла, или если представить файл как массив, то данный адрес будет началом массива.
Поиск сигнатуры выполняется следующим образом:
В цикле перебираются все записи из коллекции.
Если для записи сумма смещения сигнатуры и её размера меньше, чем размер файла (т.е. сигнатура помещается в файл), то производится хэширование последовательности данных.
После этого производится сравнение полученного хэша с хэшем из сигнатуры.
Если они совпадают, то это значит, что файл известен как опасный (или ложное срабатывание =) )
Осталось только скомпилировать и протестировать.
Автор: Артур Вирабян ( A’LonE )
Как создать свой антивирус?
Здравствуйте, хотел попросить у вас помощи. Для школьного проекта мне нужно создать простенький антивирус. Оформление ну и саму программу. Я совершенно не знаю как. Прошу помогите!
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
Ответы с готовыми решениями:
Как создать свой реестр сертификатов *.p7b
Добрый день! Как можно создать свой единый реестр сертификатов в формате p7b, чтобы в него закинуть.
Как создать свой пункт контекстного меню Проводника, не имея права на запись в раздел HKEY_CLASSES_ROOT?
Приветствую. Таким образом создается пункт меню для файлов. Записать в этот раздел можно только.
Как создать свой почтовый сервер?
доброе время суток. написал небольшой код на яве который будет делать рассылку. все хорошо.
Как создать свой путь вида //name1/name2
Нужно сделать, чтобы программы по пути //name1/name2 могли получать доступ к файлам, которые там.
![]()
3571 / 2826 / 450
Регистрация: 03.05.2011
Сообщений: 5,193
Записей в блоге: 22
Можно использовать AMSI API дефолтового антивируса Windows
В своём блоге я показывал пример обхода https://www.cyberforum.ru/blog. g6261.html
Но можно и использовать эту технику в качестве защиты
![]()
23610 / 13301 / 2312
Регистрация: 23.11.2016
Сообщений: 66,658
Записей в блоге: 31
MomonC, на каком языке программирования?
Регистрация: 26.10.2020
Сообщений: 20
kumehtar, я тут выяснил, по факту мне нужен сканер, который будет сканировать файлы по выбору (и все вообще) и сверять их с базой вирусов, ну и удалять конечно же их. (Язык программирования неважен) и кстати в какой программе можно будет сделать оформление (скин или как то так) программы с работающими кнопками?
889 / 201 / 54
Регистрация: 06.11.2015
Сообщений: 2,113
Записей в блоге: 2
Добавлено через 25 минут
MomonC, предлагаю вариант на С#.
На хосте установелн ClamAV.
Через Visual Studio делаем форму на WPF. Там есть дизайнер для UI элементов.
Форма содержит в себе текстовое поле для пути сканирования, чекбокс «удалять/неудалять», список расширений которыми работать.
Дальше сервис получает список файлов которые были найдены и с какими нужно работать.
Ну и сам сервис включает в себя следующую логику:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
var clam = new ClamClient("localhost", 3310); var scanResult = clam.ScanFileOnServerAsync("C:\\test.txt"); //any file you would like! switch (scanResult.Result.Result) { case ClamScanResults.Clean: Console.WriteLine("The file is clean!"); break; case ClamScanResults.VirusDetected: Console.WriteLine("Virus Found!"); Console.WriteLine("Virus name: ", scanResult.Result.InfectedFiles[0].FileName); break; case ClamScanResults.Error: Console.WriteLine("Woah an error occured! Error: ", scanResult.Result.RawResult); break; }
Статья Пишем свой сигнатурный антивирус на C#. Часть 1 — Небольшой экскурс в YARA.
Всем доброго времени суток уважаемые участники форума. В этот раз мы напишем свой сигнатурный антивирус(Название можете предложить в комментариях). Возможно также добавиться какой-то функционал. Теперь перейдем к теме, а именно к 1-й части — «Небольшой экскурс в YARA».
- В первой части мы разберем Yara проект. Разберем как установить инструмент, как получить yara-правила, найдем угрозы.
- Во второй части научимся сами писать yara-правила.
- В третьей части напишем антивирус.
Что такое YARA?
Yara — это инструмент, который помогает нам идентифицировать и классифицировать образцы вредоносных программ с помощью правил. Мы можем использовать Yara для классификации файлов или запуска процессов, чтобы определить, к какому семейству относятся вредоносные программы.
Также YARA является мультиплатформенным инструментом, работает на всех популярных ОС и может использоваться через интерфейс командной строки или из ваших собственных скриптов Python с расширением yara-python. Также можно использовать GUI(Рассмотрим далее).
Установка.
Чтобы установить Yara, сначала нужно выполнить следующую команду:
apt install yara
После этого мы можем использовать Yara, выполнив команду yara, которая по умолчанию отобразит справку по использованию, как показано ниже:
$ yara usage: yara [OPTION]. [RULEFILE]. FILE | PID options: -t print rules tagged as and ignore the rest. Can be used more than once. -i print rules named and ignore the rest. Can be used more than once. -n print only not satisfied rules (negate). -g print tags. -m print metadata. -s print matching strings. -l abort scanning after a of rules matched. -d = define external variable. -r recursively search directories. -f fast matching mode. -v show version information.
Мы видим, что для запуска Yara нам нужно предоставить набор правил (RULEFILE), которые мы хотим применить, и путь к файлу (FILE) или pid (PID) процесса, который мы хотим сканировать.
Подготовка правил для тестов.
Правила ClamAV:
Теперь нам нужно получить файл правил, чтобы использовать Yara. В следующей части мы сами напишем файл с правилами, но сейчас будем использовать правила ClamAV. Единственная проблема с правилами ClamAV состоит в том, что мы не можем использовать их непосредственно с Yara, потому что Yara имеет свой собственный способ их описания(свой синтаксис).
Именно здесь вступает в игру скрипт clamav_to_yara.py .
Для этого нам нужно клонировать SVN-репозиторий, который включает скрипт python clamav_to_yara.py .
Ссылка на репозиторий mattulm/volgui
- wget https://raw.githubusercontent.com/mattulm/volgui/master/tools/clamav_to_yara.py
- python clamav_to_yara.py .
- wget http://database.clamav.net/main.cvd
- sigtool —unpack main.cvd
- python clamav_to_yara.py -f main.ndb -o test.yara
- yara -r test.yara /myfolder_for_test
Правила PEiD можно скачать с сайта:
Ссылка скрыта от гостей
Чтобы преобразовать правила PEiD в правила Yara, мы можем просто использовать Python скрипт peid_to_yara.py , который также можно загрузить с jvoisin/yara_rules
Затем мы выполняем преобразование, выполнив следующую команду: python peid_to_yara.py -f userdb.txt -o peid.yara
После завершения команды подписи Yara будут содержаться в выходном файле peid.yara.
Тестовый вирус — EICAR
Теперь нам нужен какой-либо вирус для наших тестов, но если у вас нет желания тестировать реальные вирусы, которые также могут принести вред вашему ПК при тесте, вы можете сами создать тестовый вирус, но он будет совершенно безобидным.
EICAR вирус — это небольшой кусок текста, суть которого заключается в том, что все современные AV его обнаруживают.
Мы будем его также тестировать в “полевых условиях”, например, для проверки нашего AV( Если конечно статья вам зайдет ).
Но в этой статье мы проверим обнаруживают ли его инструмент Yara.
Теперь давайте сотворим этот “псевдо-вирус”
Для этого создайте файл и вставьте следующий текст: X5O!P%@AP[4\PZX54(P^)7CC)7>$EICAR-STANDARD-ANTIVIRUS-TEST-FILE!$H+H* .
После этого вам необходимо сохранить файл под любым расширением(exe, com, bat, asm…)
Где взять реальные вирусы.
Если вам тестовый вирус EICAR чем-то не устраивает, то можно воспользоваться базой для скачивания реальных вирусов.
Для этих целей можно воспользоваться сервисом —
Ссылка скрыта от гостей
Среди плюшек можно отметить, что у каждого вируса имеется MD5,SHA-1,SHA-256 хэшы, IP-адресса.(Это нам поможет при написание Yara-правил).
Следующий сервис для скачивания и исследования вирусов это
Ссылка скрыта от гостей
Почитать про остальные сервисы можно тут:
Ссылка скрыта от гостей
После всего этого мы можем классифицировать примеры вредоносных программ, используя только инструмент Yara, и нам больше не нужно сканировать их с помощью правил ClamAV и PEiD. Это потому что Yara уже содержит правила из ClamAV и PEiD, которые используются в процессе сканирования, что очень удобно так как у нас имеется довольно большая база сигнатур для поиска «зловреда».
Создав свой антивирус, а создавать мы будем используя базу Yara-правил. Мы можем автоматически классифицировать вредоносные программы, правда пока только с помощью правил. Это очень полезно, когда нам быстро необходимо просканировать образец вредоносного ПО определенной категории.
Также думаю я добавлю функционал заливки файла на
Ссылка скрыта от гостей
для точного обнаружения.
Именно на основе Yara правил мы и будем создавать свой сигнатурный AV.
YARA GUI для Windows.
Как я и обещал, для тех кому не нравиться возиться с установкой yara либо с правилами и еще хочется работать в GUI режиме + под платформой Windows можно воспользоватся YARA GUI.
Скачать можно отсюда:
Ссылка скрыта от гостей
Демонстрация.
И так теперь проверим и посмотрим как протестировать файл(папку).
Для тестирование папки мы должны выполнить следующую команду: yara -r
В моем случае я тестирую уязвимый дамп памяти:
Как видно помимо различной информации вредоносный дамп был успешно обнаружен как Empire ReflectivePick x64.
Еще пару сканирований:
Чтобы убрать лишнюю информацию нужно использовать атрибут -w
Теперь рассмотрим как ищет «зловреда» Yara GUI версия для Windows.
Подводим итог.
В этой статье мы рассмотрели, как мы можем использовать продукт Yara с использованием ClamAV, PEiD правил для поиска вредоносных сигнатур в файлах.
Вышеупомянутый подход основан только на проверке сигнатуру(блока информации), что означает, что нетрудно обмануть Yara (с загруженными правилами ClamAV и PEiD).
Честно сказать, данный продукт может обнаруживать только известные вредоносные программы. Но если мы напишем нашу собственный вирус или закодируем его с помощью нашего собственного кодировщика, он, вероятно, не будет обнаружен, поскольку в Yara не загружены соответствующие сигнатуры. Этот пункт касается и нашего будущего антивируса.
Тем не менее, использование Yara для обнаружения вредоносной активности в файлах по-прежнему выгодно, поскольку большинство вредоносных программ в Интернете представляют собой стандартные вредоносные файлы и не содержат дополнительной маскировки, поэтому большинство вредоносных файлов можно обнаружить.
На этом 1-я часть пожалуй завершена)). Всем спасибо.
БИЗНЕС ЛИКБЕЗ: КАК СОЗДАТЬ СВОЙ АНТИВИРУС ЗА МЕСЯЦ?
Мировой рынок программного обеспечения в сфере информационной безопасности растет из года в год. Если в 2011 году его объем оценивался в 17,7 млрд. долларов, то 2013 год закончился на отметке 22 млрд. долларов.
При этом практически 90% рынка контролируются 10 вендорами, о чем свидетельствуют ежегодные отчеты компании OPSWAT .

Обладая значительными ресурсами, такие гиганты антивирусной индустрии, как Лаборатория Касперского, Symantec, McAfee, ESET на сегодняшний день на голову сильнее своих конкурентов из категории «другие». Это касается как технологической, так и маркетинговой составляющих бизнеса.
Carpe diem
Мало кто знает, что рынок антивирусного ПО насыщен множеством решений. Маркетинговые исследования лаборатории Zillya! показывают, что в мире существует более 300 антивирусов! Как правило, это локальные антивирусные бренды, работающие на рынке одной или нескольких стран.
Суммарная рыночная доля подобных продуктов в редких случаях достигает 10%. Но, если учесть объемы рынка и его рост с момента возникновения индустрии, то даже 10% — это повод для борьбы. К примеру, 10% от украинского рынка антивирусного ПО – это приблизительно 6-7 млн. грн.
Те компании и предприниматели, которые посчитают антивирусный рынок привлекательным и захотят создать продукт под собственным брендом, столкнуться с различными барьерами входа. Чтобы создать свой антивирус и повторить технологии защиты из списка «the must», придется инвестировать серьёзные деньги и потратить на разработку не меньше года. Команда маркетологов, в свою очередь, должна будет убедить потенциальных пользователей, что новый продукт способен выполнять базовую функцию – защищать компьютер от вирусов.

Весомым аргументом может стать прохождение продуктом признанных в мире тестов антивирусов: AV-comparatives, VB100, AV-test. Для этого понадобиться терпение, деньги и… качественный продукт, поддерживаемый собственной вирусной лабораторией. Оценивая технологические барьеры входа в отрасль, затраты на содержание собственной антивирусной лаборатории компании, желающие войти на данный рынок, все чаще прибегают к такой услуге антивирусных вендоров, как co-branding.
Антивирус за 1 месяц: co-branding
Co-branding предполагает создание нового антивирусного продукта на основе уже существующего решения. На практике это означает, все желающие могут начать работу на рынке антивирусного ПО под своим брендом, взяв за основу антивирусные продукты вендора, предлагающего услугу co-branding.
На сайте http://antivirusoem.com/suppliers.html размещен целый список антивирусных компаний, которые располагают такими партнерскими программами. Среди вендоров есть громкие имена: Лаборатория Касперского, ESET, Bitdefender и другие. В списке также представлен украинский разработчик, Антивирусная лаборатория Zillya!

Упрощенно, Co-branding – это изменение дизайна и названия существующего антивирусного продукта и продажа его под другим брендом, где поставщик продукта, вендор, обладающий своей антивирусной лабораторией, обеспечивает новый продукт обновлениями антивирусных баз и оказывает технологическую поддержку co-branding партнеру.
Почему это выгодно вендору? Как правило, вендоры:
- Предлагают услугу ко-брендинга для компаний, которые планируют работать на рынках не интересных вендору или таких, на которые он не собирается работать в ближайшее время под собственным брендом. Это означает, что новый продукт не угрожает бизнесу вендора, а в некоторых случаях, наоборот, позволяет лучше понять специфику нового рынка.
- Вендоры достаточно хорошо зарабатывают на лицензионных отчислениях и самом изменении продуктов. Порядок сумм, о котором идет речь при редизайне продукта и его переименовании – от 20 тыс. у.е.
Популярность ко-брендинга для компаний, которые создают свой антивирусный бренд, также легко объяснима:
- Ко-брендинг партнер обходит технологический барьер входа на рынок и уходит от затрат, связанных с созданием антивирусных технологий, поддержкой антивирусных баз, вирусной аналитикой. Компания может сконцентрироваться исключительно на маркетинговой части бизнеса.
- Новый антивирус может быть создан всего за 1-2 месяца. Это означает, что уже через 2 месяца ко-брендинговый продукт будет поставлен конечному пользователю.
- Создатели нового антивирусного продукта могут оставаться гибкими в вопросе выбора технологий антивирусной защиты и получить продукт, который по качеству может даже превосходить продукт вендора. Как? Очень просто. Подключив сразу несколько антивирусных движков в свой продукт.
В то же время, ко-брендинг имеет и ряд недостатков как для вендора, так и для создателей нового антивирусного бренда.
- Риски вендора, как правило, связаны именно с бизнес-стороной. Успех нового антивируса на определенном рынке все же может усложнить вхождение вендора на этот рынок в будущем. Также, вендор не застрахован от того, что рост бизнеса ко-брендинг партнера позволит ему усилить давление на вендора в вопросе цены за каждую поставленную лицензию и, в конечном счете, даже перейти к другому вендору.
- Для компаний, создающих свой продукт на основе существующего, основные риски бизнеса связанны именно с технологиями. Новый продукт автоматически перенимает все недостатки существующего и напрямую зависит от его технологического развития и уровня поддержки вендором.
Шансы co-branding антивирусов в Украине
Украинский рынок антивирусов по различных оценкам – это 60-70 млн. грн. В эту сумму входит крупный корпоративный сектор, государственный сектор, рынок конечного потребителя. Крупные вендоры, такие как Лаборатория Касперского, ESET, Avast, Доктор Вэб, Symantec, McAfee контролируют до 95% рынка, при этом конкуренция на рынке достаточно жесткая.
Вендоры не жалеют бюджетов на рекламу своих продуктов и подвинуть их с рынка будет очень сложно. Говорить о входе на рынок Украины без серьезных вложений в маркетинг будет сложно. Примером может служить попытка Panda Antivirus закрепиться на рынке Украины в 2012-2013 годах или проигрыш конкурентной борьбы не менее крупным вендором, Trend Micro, чьи продукты еще 8 лет назадзанимали 20% рынка страны.
Перспективы антивирусного продукта, созданного в рамках ко-брендинга, могут быть связаны в Украине с деятельностью компаний, имеющих широкий выход на конечных пользователей. Речь идет в первую очередь об интернет-провайдерах, мобильных операторах, возможно, крупных дистрибьюторах ПО.
Имея аудиторию пользователей 100 тыс. и выше уже можно подумать, почему бы не создать дополнительный сервис для своих пользователей в виде антивируса под собственным брендом. Оценивать привлекательность данной затеи с точки зрения бизнеса – вопрос не простой, так как много будет зависеть от договоренностей компании с поставщиком антивирусных технологий: стоимость создания брендированного продукта, суммы лицензионных отчислений и других условий. Однозначно можно сказать лишь одно: создание брендированного антивируса точно позитивно повлияет на корневой бренд самой компании.
Материал подготовлен Олегом Сычем, техническим директором антивирусной лаборатории Zillya!