Создаем вирус и антивирус
Шрифт:
cmp cs:data_15[si],5A4Dh je It_Was_EXE
В случае если программа была заражена по СОМ-алгоритму, вирус просто извлекает первые 3 байта из ячейки памяти по адресу data_ 15, копирует их в старое начало оригинального кода (по адресу cs:100h) и передает туда управление. Адресу data_15 соответствует 80-ый (если считать от конца) байт зараженной программы. В случае если программа была заражена по ЕХЕ-алгоритму, вирус вычисляет старую точку входа по сохраненным в data_20 и data_21 значениям полей ReloCS и ExeIP, восстанавливает расположение стека по сохраненным в data_18 и data_19 значениям полей ReloSS и ExeSP и передает управление на ReloCS+ES+10h: ExeIP (ES – сегмент PSP; ES+10h – сегмент начала программы; ES+ReloCS+ 10h – полный сегмент точки входа). Расположение этих адресов в зараженном файле (от конца файла):
data_20 – 60
data_21 – 58
data_18 – 66
data_19 – 64Еще могут пригодиться сохраненные значения
data_16+1 – 78 data_16+3 – 76
Для излечения зараженного файла достаточно восстановить измененные значения ячеек, адреса которых только что вычислили, и отсечь 1740 вирусных байт от конца файла. 5. Еще несколько особенностей, с которыми иногда можно встретиться при дизассемблировании кода вируса и изучении листинга. Код вируса может быть зашифрован. В этом случае в начале вирусного кода должен располагаться расшифровщик. Вообще говоря, расшифровщиков может быть много, но первый всегда существует. Если расшифровщик меняется от одного зараженного файла к другому, значит имеем дело с полиморфным вирусом. Вырожденный случай – зашифровываются только сохраненные в теле вируса байты. Для СОМ-файла вполне достаточно пошагово пройти расшифровщик в отладчике, дождаться его завершения и сохранить на винчестер расшифрованный код вируса. Полученный файл можно дизассемблировать. Для ЕХЕ-файла такое не подходит, так как в памяти после загрузки отсутствует заголовок, и полученный файл не может быть дизассемблирован именно как ЕХЕ. Вероятно, придется писать специальную программу расшифровки на основе изученного по листингу алгоритма расшифровщика. Расшифровщик может быть совмещен с алгоритмами, противодействующими трассировке кода вируса с использованием отладчиков. Ознакомиться с ними можно в специальной литературе, посвященной борьбе с НСК. Авторы вирусов, как правило, редко изобретают что-то новое и используют широко известные методы.
Эвристические анализаторы кода
Эвристическим анализатором кода называется набор подпрограмм, анализирующих код исполняемых файлов, памяти или загрузочных секторов для обнаружения в нем разных типов компьютерных вирусов. Рассмотрим универсальную схему такого кодоанализатора. Действуя в соответствии с этой схемой, кодоанализатор способен максимально эффективно задействовать всю информацию, собранную для тестируемого объекта.
Основные термины:
Событие – это совокупность кода или вызов определенной функции операционной системы, направленные на преобразование системных данных, работу с файлами или часто используемые вирусные конструкции.
Цепочка связных событий – это набор событий, которые должны быть выявлены в порядке их следования.
Цепочка несвязных событий – это набор событий, которые должны быть выявлены, но не обязательно в строгом порядке. Действия – набор цепочек связных или несвязных событий, для которых выполнены все условия.
Эвристическая маска – набор действий, выявленных при проверке файла.
Эвристическое число – порядковый номер первой из совпавших эвристических масок. События распознаются при помощи подпрограмм выявления событий, в которых могут использоваться также таблицы с данными. Остальные данные просто хранятся в массивах и не анализируются. Рассмотрим функциональную схему эвристического анализатора (рис. 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. Но если что-то и не совпадет, откорректировать программу любому программисту не составит труда.