Файл: О.А.Калашников. Ассемблер Это Просто. Учимся программировать.pdf
Добавлен: 16.02.2019
Просмотров: 29238
Скачиваний: 1689
Часть III. Файловая оболочка, вирус, резидент
204
Create_dirmessl
программа-ассемблер будет использовать исключительно для
своих целей, а значит, в код программы она не попадет. Рассмотрим это подробнее:
Create_dirmessl equ $-Create_dirmess-2
$
(текущее смещение) минус смещение
Create_dirmess
минус два (т. к. первые
два байта и будут указывать на длину строки). Временная переменная
Create_dirmessl
будет равна длине строки. Пожалуйста, внимательно изучите
приведенные выше примеры. Очень важно понять этот принцип.
Как только занесли в
si
адрес строки, вызываем процедуру
Move_string
. При
этом в
bx
будет находиться сегмент строки, который передала некая программа.
В целом, принцип такой: процедура
Move_string
заносит по смещению 0 сег-
мента, в котором находится наш резидент (т. е. в область PSP), соответствующую
строку (например, "
Создание каталога --->
"), после нее заносится имя файла,
а именно то, что находится в паре регистров
ds:dx
на входе в прерывание
21h
.
Это может быть как имя файла, так и полный путь к нему. Например,
диск:\каталог\имя_файла
—
C:\My_dir\file.ext
. Вот именно это мы и записыва-
ем по смещению 0 сегмента, в котором находится наша программа.
Допустим, какая-то программа пытается создать каталог c:\assm\directory, тогда
в LOG-файл запишется приведенная ниже строка:
Создание каталога ---> c:\assm\directory
Резидент достаточно прост, хотя в нем существуют команды, которые мы еще
не рассматривали. В описаниях файла-приложения достаточно информации, чтобы
разобраться в том, что именно делает та или иная функция или команда. Вы уже
сами можете написать подобный резидент, опираясь на информацию из этой главы.
19.2. Что нужно вам вынести из этой главы?
Необходимо разобрать резидент и понять его работу. Вы должны проанализиро-
вать алгоритмы, если, конечно, хотите выучить ассемблер. Мы лишь приведем об-
щие понятия работы резидентной программы.
Мы перехватываем прерывание
21h
, помещая его адрес в прерывание
03h
. Это
значит, что наш резидент невозможно будет просмотреть под многими отладчика-
ми. Обратите внимание, как мы вызываем прерывание
21h
в нашем обработчике.
В принципе, настоящий резидент довольно прост. Вам достаточно разобраться
с описанием в файле-приложении.
Все то, что осталось за кадром, мы подробнее рассмотрим в последующих гла-
вах на других сходных примерах.
Глава 20
Финальная версия вируса
Теперь наш вирус полностью работоспособен. Будьте осторожны! Случайно за-
разив нужный файл, вам придется провести некоторое время, чтобы вылечить его
вручную. Так что, будьте предельно внимательны!
Несколько слов о программе. (Обязательно прочитайте, прежде чем запускать
вирус!)
Вирус нерезидентный. Это значит, что заражать он будет программы только
в случае, если запустить зараженный COM-файл. После того как вирус отрабо-
тал, он из памяти удаляется.
Вирус не делает ничего, кроме как заражает файлы.
Ни один антивирус не вылечит файл, зараженный нашим вирусом! Так что, не
надейтесь ни на Dr. Web, ни на что-либо еще.
Вирус заражает только COM-файлы в текущем каталоге. Что это значит?
Допустим, в каталоге C:\assm есть следующие файлы:
test.com;
dn.com;
nc.exe.
Причем test.com уже заражен нашим вирусом. Запуская test.com на выполнение,
он заражает dn.com. Запустив затем dn.com, вирус ничего не заразит, т. к.
в данном каталоге больше нет незараженных нашим вирусом COM-файлов.
Но если у вас в переменной
PATH
(в autoexec.bat) стоит путь к каталогу c:\assm,
то, запустив test.com из текущего каталога, скажем, c:\nc, наш вирус заразит
первый встречный COM-файл в каталоге c:\nc. Будьте осторожны!!!
Если все же произошла беда, и вы не знаете, как удалить вирус, заразивший весь
компьютер, то см. главу 24, где приведен код антивируса. Хотя, если перед тем,
как запускать virus20.com на выполнение, вы прочтете описания к нему и разбе-
ретесь во всем, то вам не составит труда восстановить зараженный файл.
COM-файлы, расположенные в каталоге C:\Windows\Command, после заражения
отказываются работать корректно. С чем это связано — не совсем понятно.
Причем после сжатия файлов программой PKLITE, командная строка по-
прежнему определяется неверно. Скорее всего, эти файлы подсчитывают кон-
трольную сумму или еще что-то... Для экспериментов придется искать другие
COM-файлы.
Часть III. Файловая оболочка, вирус, резидент
206
Как вы думаете, зачем мы изучали работу отладчика в главе 16? Дело в том, что
если вы будете исследовать работу вируса в отладчике, то столкнетесь с одной
проблемой. Записав вирус в файл с помощью отладчика, а затем, запустив файл
на выполнение, вы с удивлением заметите, что этот зараженный файл работать
не будет. Почему? Вспомните, что отладчик вставляет
int 3
(
0CCh
). При пере-
записи же программой самой себя под управлением отладчика, программа пе-
резапишет и
int 3
, вставленный этим отладчиком. Поэтому об этом забывать
не следует.
Еще такой момент: в главе 24 мы напишем резидентный антивирус против на-
шего вируса. Однако корректно лечить зараженные файлы он будет только в том
случае, если вы не измените в нашем вирусе ни единого байта!
20.1. Вирус
20.1.1. Альтернативы ret, call и jmp
Вопрос: можно ли вместо
ret
и
call
использовать
jmp
, а вместо
jmp
—
ret
?
Безусловно. Более того, в некоторых случаях просто невозможно обойтись без ис-
пользования нестандартных команд.
В табл. 20.1 приведены альтернативы стандартным операторам ассемблера.
Таблица 20.1. Альтернативы стандартным операторам
Команда
Альтернатива
Описание
ret
pop ax
jmp ax
Вытащим из стека адрес возврата и пе-
рейдем на него
call proced move bx,offset lab_ret
push bx
jmp proced
lab_ret:
Занесем в стек адрес возврата и "прыг-
нем" на метку процедуры
jmp label1
push offset label1
ret
Занесем в стек адрес метки и сымитируем
выход из процедуры
Все это описывалось по той причине, что теперь переход на метку инициализа-
ции вируса (
Init
) осуществляется следующим образом:
...
push offset Init ;3 байта
ret ;1 байт
...
Дело в том, что, используя нестандартный метод, нам гораздо удобнее менять
адрес метки
Init
в зараженных файлах. Читая дальше, вы поймете, почему именно
так, а не иначе.
Глава 20. Финальная версия вируса
207
20.1.2. Заражение файла
Заражение файла происходит с помощью процедуры
Infect_file
. Опустим по-
иск файлов, будем считать, что подходящий файл уже найден. Осталось только
проверить его длину (листинг 20.1).
Листинг 20.1. Проверка размера заражаемого файла
...
mov ax,cs:[1Ch] ;Получим второе слово длины заражаемого файла
or ax,ax ;Если оно не равно 0, то выходим...
jnz Error_infect ;... это значит, что размер файла больше 64 Кбайт
mov bp,cs:[1Ah] ;Получим младшее слово (т. е. размер файла)
...
Для чего нам нужно производить проверку размера файла перед его заражени-
ем, если известно, что COM-файлы не могут превышать 64 Кбайт?
Дело в том, что операционная система определяет, какой тип файла запускается
не по его расширению, а по первым двум байтам содержимого файла. Если это "
MZ
"
или "
ZM
", то файл EXE, иначе — COM. Это можно легко проверить, если посмот-
реть в текстовом редакторе на первые два символа файла. Ничто не мешает любому
пользователю переименовать файл, например, test.exe длиной 450 Кбайт в test.com.
ОС все равно определит, что это EXE-файл, по первым двум байтам.
Типичным примером может служить файл command.com, который в MS-DOS
версии 7.0 занимает 95 Кбайт. Расширение COM оставили для совместимости
с программами, написанными в более старых версиях DOS.
И что же получится, если мы попробуем заразить тот же command.com, который,
по сути, является command.exe?
Мы просто его испортим. То есть он перестанет работать вообще. Вот, собст-
венно, для этого и следует проверить размер файла, прежде чем заражать его.
Обратите внимание, каким образом мы это делаем. После того как функция
4Fh
или
4Eh
нашла файл, в DTA по смещению
1Ah
заносится его размер. Так как два бай-
та могут хранить число до 65 535, то для определения размера файла используются
два слова. Первое (смещение
1Ah
) — младшая половинка, второе (смещение —
1Ch
) — старшая. Вспоминаем, что данные в памяти хранятся в обратном порядке.
Что мы еще не сделали в вирусе, так это не проверили первые два символа за-
ражаемого файла ("
MZ
" или "
ZM
"). Для чего? Может случиться так, что EXE-файл
имеет длину менее 64 Кбайт, но расширение COM. В этом случае зараженный файл
также утратит свою работоспособность. Реализовать же проверку на ассемблере
труда не составит, поэтому в целях экономии места мы ее опустим.
Следующие шаги:
1. Открываем найденный файл на чтение/запись (функция
3D02h
прерывания
21h
).
2. Читаем его первые шесть байт в память (функция
3Fh
прерывания
21h
).
3. Проверяем, заражен ли уже этот файл нашим вирусом или еще нет.
Часть III. Файловая оболочка, вирус, резидент
208
Рассмотрим эти шаги подробнее. В нашем примере мы используем сигнатуру
1122h
для определения того, заражен ли найденный файл нашим вирусом или нет.
Эта сигнатура должна быть расположена по смещению +4 от начала файла. Обра-
тите внимание, что мы проверяем
cmp word ptr [bx+4],1122h
а в файле сигнатура
1122h
будет располагаться наоборот:
2211h
. Вот вам еще одно
подтверждение того, что данные в компьютере хранятся в обратном порядке.
А что, если в каком-то незараженном файле по смещению +4 от начала уже есть
такие байты? Получается, что мы посчитаем, что файл уже заражен? Да, это так.
Но как вы думаете, какова вероятность того, что эта сигнатура будет находиться
в произвольном файле по такому смещению? Возможно, даже еще и файла такого
не существует в природе.
Однако, при желании, программист может всегда увеличить сигнатуру до 10—
20 байт, чтобы быть уверенным в том, что найденный файл действительно уже за-
ражен нашим вирусом.
Итак, проверку на соответствие файла необходимым требованиям произвели.
Теперь устанавливаем указатель файла на его конец. Будем дописывать в "хвост"
"файла-жертвы" собственно код нашего вируса.
Для перемещения указателя открытого файла на его конец следует воспользо-
ваться функцией
4202h
прерывания
21h
(табл. 20.2).
Таблица 20.2. Функция
4202h
прерывания
21h
:
установка указателя на конец файла
Вход
Выход
ax = 4202h
bx
= номер файла
cx, dx
= количество байтов, которые необходимо отсчитать от
конца файла и установить на них указатель
jc
— ошибка
Если в регистры
cx
и
dx
мы загрузим число 0, то указатель будет установлен
сразу за последним байтом файла. Пока нас только это и интересует.
Указатель служит для уведомления операционной системы, из какого места сле-
дует читать или в какое место следует писать байт (байты). Если указатель не пе-
реместить на конец файла, то, записав тело вируса, мы затрем файл, начиная со
смещения 7.
Запомните, что:
при открытии файла указатель устанавливается на начало файла автоматически.
Если указатель установлен на середину файла, то, после закрытия и повторного
открытия файла, указатель снова установится на начало файла;
при чтении файла указатель перемещается на количество прочитанных байтов.
То есть если файл имеет длину 3000 байт, то, после прочтения 1500 байт, указа-
тель переместится на середину файла.