Файл: О.А.Калашников. Ассемблер Это Просто. Учимся программировать.pdf

ВУЗ: Не указан

Категория: Книга

Дисциплина: Программирование

Добавлен: 16.02.2019

Просмотров: 29225

Скачиваний: 1689

ВНИМАНИЕ! Если данный файл нарушает Ваши авторские права, то обязательно сообщите нам.
background image

Глава 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

). Получается, что "програм-

ма-жертва",  к  которой  мы  "подцепились",  не  сможет  прочитать  те  параметры,  


background image

 

Часть 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. Она может находиться 
;и по любому другому адресу, но сути это не меняет. 
... 


background image

Глава 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] 'Строка'      ;строка встала на свое место (смещение)! 
... 


background image

 

Часть 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. 


background image

Глава 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. Состояние регистров и переменных перед копированием