Создаем вирус и антивирус
Шрифт:
Цепочка связных событий – это набор событий, которые должны быть выявлены в порядке их следования.
Цепочка несвязных событий – это набор событий, которые должны быть выявлены, но не обязательно в строгом порядке. Действия – набор цепочек связных или несвязных событий, для которых выполнены все условия.
Эвристическая маска – набор действий, выявленных при проверке файла.
Эвристическое число – порядковый номер первой из совпавших эвристических масок. События распознаются при помощи подпрограмм выявления событий, в которых могут использоваться также таблицы с данными. Остальные данные просто хранятся в массивах и не анализируются. Рассмотрим функциональную схему эвристического анализатора (рис. 6.1.).
Рис. 6.1
Эмулятор
if (Events[EventNumber]==0) Events[EventNumber]=++CountEvents;
где:
Events – массив событий;
EventNumber – номер регистрируемого события;
CountEvents – порядковый номер зарегистрированного события.Таким образом, в ячейку массива Events записывается порядковый номер для выявленного события. CountEvents при инициализации равен 0. После того, как эмулятор завершит свою работу, последовательно запускаются два преобразователя. Первый преобразователь заполняет массив действия, выбирая данные из массива событий и цепочек связных и несвязных событий по следующему алгоритму:
for(i=0;i<CountMaskEvrnrs;i++) {
if (MaskEvents[i][0]==0) {
for(j=2;j<MaskEvents[i][1];j++)
if(Events[MaskEvents[i][j]]==0) goto nextMask;
}
else
for(e=0,j=2;j<MaskEvents[i][1];j++) {
if(Events[MaskEvents[i][j]]==0 || Events[MaskEvents[i][j]]<e)
goto nextMask;
else e=Events[MaskEvents[i][j]];
}
Actions[i]=1;
nextMask:;
}где:
CountMaskEvents – число масок цепочек событий;
MaskEvents – двумерный массив цепочек связных и несвязных событий;
Actions – массив действия.Затем выполняется второй преобразователь, который выбирает данные из массива действия и цепочек эвристических масок и вычисляет эвристическое число по следующему алгоритму:
for(i=0;i<CountMaskHeurist;i++) {
for(j=1;j<MaskHeurist[i][0];j++)
if(Actions[MaskHeurist[i][j]]==0) goto nextMask1;
NumberHeurist=i+1;
break;
nextMask1:
}где:
CountMaskHeurist – число эвристических масок;
MaskHeurist – двумерный массив с эвристическими масками;
NumberHeurist – эвристическое число.Блокировщик вируса
Рассмотрим пример. В дисплейном классе ВУЗа эпидемия, часть машин заражена неизвестным вирусом. До конца сессии – несколько дней, выключение машин из учебного процесса смерти подобно (в первую очередь для обслуживающих класс сотрудников). Ситуация усугубляется тем, что студенты постоянно переносят программы на дискетах с одной машины на другую. Как ограничить распространение эпидемии, пока вирус не уничтожен?
Выход – написать антивирус-блокировщик. Практически все резидентные вирусы определяют факт своего наличия в памяти машины, вызывая какое-либо программное прерывание с «хитрыми» параметрами. Если написать простую резидентную программу, которая будет имитировать наличие вируса в памяти компьютера, правильно «отзываясь на пароль», то вирус, скорее всего, сочтет эту машину уже зараженной. Даже если некоторые файлы на машине содержат в себе код вируса, в случае использования блокировщика заражения всех остальных файлов не произойдет.
Разумеется, надо попытаться запустить блокировщик раньше всех остальных программ, например, в файле config.sys:
install c:\util\stopsvc.com
Но если вирус успел заразить command.com или стартует из загрузочного сектора, то антивирус-блокировщик не поможет.
Листинг программы, блокирующей распространение вируса SVC-1740:
;; Резидентный блокировщик вируса SVC−1740
;; (c) К. Климентьев, Самара 1997
cseg segment
assume cs:cseg, ds:cseg, ss:cseg
org 100h
;Переходим к инициализации программы
Start:
jmp Install
;Обработчик прерывания INT 21h
Int21:
;Проверим номер функции, если 83h –
;то это запрос присутствия вируса
cmp ah, 83h
jnz Skip21
;Ответим,
mov dx, 1990h
;Запускаем оригинальный обработчик прерывания
Skip21:
db 0EAh ;Код команды JMP
Ofs21 dw ?
Seg21 dw ?
;Инициализируем программу
Install:
;Проверим, не инсталлирована ли уже эта программа. Если
;инсталлирована, выведем сообщение об этом и выйдем из программы.
;Вторую копию программы инсталлировать не имеет смысла
mov ah,83h
int 21h
cmp dx, 1990h
jz Already
;Считаем оригинальный вектор прерывания INT 21h
mov ax,3521h
int 21h
mov Ofs21, bx
mov Seg21, es
;Установим наш вектор прерывания INT 21h
mov ax, 2521h
mov dx,offset Int21
int 21h
;Выведем сообщение об успешной инсталляции программы в памяти
mov ah,9
mov dx, offset OkMes
int 21h
;Выйдем из программы, оставив обработчик резидентным
mov dx, offset Install
int 27h
;Выведем сообщение о том, что вирус
;или наша программа уже в памяти
Already:
mov ah,9
mov dx, offset BadMes
int 21h
ret
;Сообщения программы
OkMes db ”Yeah! STOPSVC installed now!”,13,10
db ”(c) KostyaSoft, Samara 1997$”
BadMes db 7,”Perhaps, virus is in memory already. Sorry.$”
cseg endsПример антивируса
Итак, нужно написать некую программу, которая будет сканировать каталоги указанного диска, искать зараженные файлы и исцелять их.
Важный момент – поиск и лечение должны производиться после загрузки с «чистой» дискеты. Это правило должно выполняться при использовании любого антивируса. Но если коммерческие программы, написанные профессиональными вирусологами, каким-то образом пытаются противодействовать «заразе», пресекая действия агрессивных резидентов, разыскивая и обращаясь к оригинальным обработчикам прерываний или проверяя свой код на целостность, то представленная программа из-за своей простоты этого делать не умеет.
В качестве языка программирования выбран С. Приоритетным признано использование таких библиотечных процедур, форматы которых идентичны во многих системах программирования. Поэтому, например, использовалась процедура _dos_findfirst, а не findfirst. Программа была написана и отлаживалась в системе программирования JPI TopSpeed C v3.01, а также была проверена на Borland C++ v3.1. Кроме того, контролировалось наличие, идентичность по функциям и форматам вызова использованных библиотечных функций в системах программирования Microsoft C++ v6.0 и Watcom C++ v10.0. Но если что-то и не совпадет, откорректировать программу любому программисту не составит труда.
Основу программы составляет алгоритм обхода дерева каталогов и поиска в них файлов с расширениями «СОМ» и «ЕХЕ».
В тот момент, когда обнаружен очередной потенциально зараженный файл, вызывается функция infected с именем файла в качестве параметра. Задачей этой функции является проверка указанного файла на заражение и возврат соответствующего признака.
В случае положительного результата на заражение вызывается функция cure, которая и выполняет операцию исцеления зараженной программы.
Если требуется написать программу для лечения для какого-либо другого вируса, достаточно просто изменить содержимое процедур cure и infected.
Итак, как же узнать, заражена программа или нет? В прошлых главах это делалось чисто визуально, теперь же требуется определить формальные признаки зараженности.
В основе общепризнанного метода лежит принцип выделения сигнатуры вируса. Сигнатура – это последовательность байт, однозначно характерная для конкретного вируса.
Разумеется, неправильно было бы использовать для детектирования файла такие ненадежные признаки, как, например, 60 секунд во времени создания файла. Во-первых, это может быть признаком случайного изменения (например, при упаковке/распаковке некоторыми архиваторами). Во-вторых, слишком многие вирусы используют для самоопознания одинаковые признаки. Наконец, эти признаки могут принадлежать совершенно здоровой программе (как в истории с антивирусом antitime и сигнатурой MsDos).