Файл: О.А.Калашников. Ассемблер Это Просто. Учимся программировать.pdf
Добавлен: 16.02.2019
Просмотров: 29225
Скачиваний: 1689
Глава 13. Поиск и считывание файлов: вирус
129
Сразу возникает проблема: при поиске файла функцией DOS мы затираем DTA
"программы-жертвы". И тут же возникает вопрос: что такое DTA и для чего оно
нужно?
Полную информацию об этом можно найти в программе HELPASSM, которую
рекомендуется скачать с нашего сайта http://Kalashnikoff.ru. В этой главе мы рас-
смотрим только то, что нас интересует для написания вируса.
Как вы помните, все COM-программы начинаются с адреса
100h
(
org 100h
). Что
же находится в памяти от
0
до
100h
? Там расположен PSP (Program Segment Prefix,
префикс программного сегмента), который создается автоматически операционной
системой после загрузки программы в память, но до передачи ей управления.
По адресу
80h
находится по умолчанию DTA (Disk Transfer Area, область обмена
дисковыми данными). В DTA записывается информация в процессе выполнения
функций поиска файлов (
4Eh
и
4Fh
прерывания
21h
). Все вроде бы и ничего, но
проблема в том, что по этому адресу (
80h
) располагается изначально командная
строка. Например:
FORMAT.COM C:/S/U
По адресу
cs:0080h
будет находиться
L_C:/S/U
, где
L
— длина командной стро-
ки, а
_
— символ пробела. Для того чтобы удостовериться, запустите отладчик
CodeView следующим образом:
CV.EXE FORMAT C:/S/U
Затем посмотрите, что будет находиться по адресу
cs:0080h
(рис. 13.1).
Рис. 13.1. Командная строка в PSP
Для чего мы рассматриваем PSP? Дело в том, что когда мы попробуем искать
первый файл, то затрем командную строку (
L_C:/S/U
). Получается, что "програм-
ма-жертва", к которой мы "подцепились", не сможет прочитать те параметры,
Часть III. Файловая оболочка, вирус, резидент
130
которые ей передал пользователь. В данном случае — это
L_/S/U
. Существуют два
способа обойти это:
сохранить PSP программы перед поиском файла. А затем, когда наш вирус от-
работал, восстановить его;
установить DTA на другую область памяти, а затем восстановить его. Это по-
зволяет сделать функция
1Ah
прерывания
21h
(табл. 13.1).
Таблица 13.1. Функция
1Ah
прерывания
21h
: изменить адрес DTA
Вход
Выход
ah = 1Ah
ds:dx
= адрес DTA для установки
Ничего
Мы выберем второй способ, т. к. он гораздо проще и не требует дополнитель-
ных затрат на перенос области DTA в другое место памяти и дальнейшего его вос-
становления.
Однако возникает одна проблема: код нашей программы "теряется в адресах".
То есть мы занесем наш сассемблированный код в конец программы, при этом
смещения все поменяются. Например:
mov dx,offset String
Ассемблер занесет в
dx
смещение строки
String
в памяти. Фактически — после
ассемблирования — это будет выглядеть так:
mov dx,125h
Какое именно число загружаем в регистр
dx
— не важно. Главное, что в этом
регистре будет находиться смещение (адрес) строки в памяти, отсчитываемое от 0.
Но мы-то запишем код нашего вируса в конец программы, включая все строки
и прочие области данных! Получается, что строка в памяти будет находиться
по одному адресу, а в регистры будет загружаться совсем другой адрес!
В листинге 13.3 приведен полный пример с указанием адресов сегментов и
смещений, в который может загрузиться наша программа.
Листинг 13.3. Расположение строки в памяти
...
[1234:0100h] mov dx,400h
;В неассемблированном варианте это выглядит, как mov dx,offset String.
;То есть ассемблер заменит offset String на адрес (смещение) этой строки
; в памяти, начиная с нуля.
...
[1234:0400h] 'Строка'
;А вот и строка, которая расположится по адресу 400h. Она может находиться
;и по любому другому адресу, но сути это не меняет.
...
Глава 13. Поиск и считывание файлов: вирус
131
Теперь представим, что "файл-жертва" занимает 100h байт, а мы записываем
наш код в конец файла. Получается, что строка будет находиться по такому адресу:
1234:0400h + 100h = 1234:0500h
. Хорошо было бы, если бы все файлы имели
одинаковую длину. Но один файл может занимать 100 байт, а другой 23 000 байт!
В итоге, обращаясь к своей строке в зараженной программе, мы получаем следую-
щее (листинг 13.4).
Листинг 13.4. Перенос строки на 100h дальше в процессе заражения
...
;1234:0200h потому, что 100h байт занимает "файл-жертва", а мы у него
;в "хвосте" ...
[1234:0200h] mov dx,0400h
;Код "файла-жертвы"
...
[1234:0400h] --- ;Здесь все еще расположен код "файла-жертвы"...
...
[1234:0500h] 'Строка' ;Вот, где будет находиться строка!
...
Можно, конечно, перед заражением получить длину "файла-жертвы" и затем за-
менить код
mov dx,400h
на
mov dx,500h
напрямую, в процессе заражения про-
граммы. Но что делать, если таких ссылок много? Представляете, до каких разме-
ров разрастется наш вирус? Мы поступим иначе: просто возьмем и перенесем
вирус (и только вирус!) с "хвоста" "файла-жертвы" в свободный сегмент со смеще-
ния
100h
. В листингах 13.5 и 13.6 показано, что получится (обратите внимание на
сегменты и смещения в квадратных скобках).
Листинг 13.5. До перемещения
...
;Код "файла-жертвы"...
...
[1234:0200h] mov dx,400h ;мы в "хвосте" программы
...
[1234:0500h] 'Строка'
...
Листинг 13.6. После перемещения
...
;перебросили код вируса в сегмент 5678h, по смещению 0100h
[5678:0100h] mov dx,400h
...
[5678:0400h] 'Строка' ;строка встала на свое место (смещение)!
...
Часть III. Файловая оболочка, вирус, резидент
132
Еще вопрос: где гарантия того, что в сегменте, куда будем перемещать код ви-
руса, не будет находиться код или данные другой программы?
Предлагаем временно (т. е. на тот момент, пока работает вирус) переслать код
нашей программы-вируса в адрес 7-й страницы дисплея (отсчет с нуля!). Видеокар-
та имеет достаточно памяти для размещения восьми видеостраниц в текстовом ре-
жиме 80 25 символов (режим 03). Эти страницы, кроме нулевой, почти никогда не
используются программами. Более того, известны точные сегменты этих страниц
(смещения в них всегда нулевые для первого символа). Перечень этих сегментов
приведен в табл. 13.2.
Таблица 13.2. Адреса видеостраниц
Сегмент
№ видеостраницы
0B800h
00
0B900h
01
0BA00h
02
0BB00h
03
0BC00h
04
0BD00h
05
0BE00h
06
0BF00h
07
Теперь давайте посчитаем размер одной видеостраницы. Хватит ли нам места
для того, чтобы разместить на ней код вируса?
Наш вирус будет занимать не более 300—400 байт. Возьмем режим 03: в одной
строке 80 символов, строк на экране 25. Один символ занимает 2 байта (атри-
бут/смещение). Получаем: 80 25 2 = 4000 байт (точнее, 4096 байт — идет вы-
равнивание на границу). Хватит ли нам этого? Конечно, хватит! Даже, если бы не
хватало, мы могли бы использовать две, три, четыре страницы.
Сразу же за меткой
Init
пересылаем код вируса в область седьмой видеостра-
ницы. Код нашего вируса на экране не будет отображаться, т. к. обычно текущей
бывает нулевая страница. Хотя можете проверить, какая страница текущая перед
перемещением...
Для перемещения кода вируса очень удобно воспользоваться еще одной строко-
вой командой:
movs
.
13.3.
Команда пересылки данных movs
Оператор
movs
предназначен для работы с массивами данных. По анало-
гии с уже рассмотренными нами подобными операторами, вам не составит труда
разобраться с новым оператором. Принцип его работы полностью соответствует
команде
stos
, которую мы рассматривали в предыдущих главах. Его описание
приведено в табл. 13.3.
Глава 13. Поиск и считывание файлов: вирус
133
Таблица 13.3. Оператор
movs
Команда
Перевод
Назначение
Процессор
movs
Move string
— скопировать
строку
Копирование строки
(массива)
8086
При этом
ds:si
указывает на то, откуда брать данные,
es:di
куда их копи-
ровать, а
cx
— количество пересылаемых байтов/слов (листинги 13.7, 13.8
и рис. 13.2, 13.3).
Листинг 13.7. Пример использования оператора movs
...
mov cx,10 ;количество пересылаемых байтов
mov si,offset Str1 ;откуда будем брать
mov di,offset Str2 ;куда копировать
rep movsb ;пересылаем побайтно, т. к. movsb.
;Теперь Str1 = Str2
...
Str1 db '0123456789'
Str2 db '9876543210'
...
Рис. 13.2. Состояние регистров и переменных перед копированием