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

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

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

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

Добавлен: 16.02.2019

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

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

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

 

Часть III. Файловая оболочка, вирус, резидент 

124 

Как мы знаем, видеобуфер имеет следующую структуру: 

СИМВОЛ : АТРИБУТ    СИМВОЛ : АТРИБУТ    ... 

Обратите внимание на приведенный выше пример. Вы видите, что в 

ah

  мы  за-

гружаем атрибут, а в 

al

 — символ. Получается, что сперва заносится атрибут (т. к. 

ah

 — старшая (левая) половинка), а затем символ, что и доказывает расположение 

данных в компьютере в обратном порядке. Получится, что при переносе 

ax

 в сег-

мент видеобуфера символ и атрибут поменяются местами! 

Рассмотрим  префикс 

rep

,  который  часто  используется  вместе  со  строковыми 

командами.  Допустим,  нам  надо  очистить  экран.  Это  можно  сделать  с  помощью 
команды 

stosw

, просто забив экран пробелами (листинг 12.8). 

Листинг 12.8. Очистка экрана с помощью loop 

... 
mov ax,0B800h 
mov es,ax 
mov di,0               ;как обычно, с левого верхнего угла 
mov cx,2000            ;80х25=2000 символов на экране 
mov ax,0720h           ;07 — атрибут, 20h — пробел 
 
Next_sym:              ;заносим посимвольно 
stosw 
loop Next_sym 
;теперь экран чистый 
... 

Выглядит вроде и нормально, хотя этот пример имеет ряд недостатков: 

1.  Использование 

loop

  вместо  префикса 

rep

  существенно  замедляет  работу  про-

граммы. 

2.  Код программы больше, чем при использовании того же 

rep

3.  Необходимо заводить метку (в нашем случае — 

Next_sym

). 

Попробуем реализовать такой же алгоритм, но с использованием префикса 

rep

 

(листинг 12.9). 

Листинг 12.9. Очистка экрана с помощью rep 

... 
mov ax,0B800h 
mov es,ax 
mov di,0 
mov cx,2000      ;cx — counter, счетчик 
mov ax,0720h     ;атрибуты/символ 
rep stows        ;выводим пробел столько раз, сколько указано в сх. 
... 


background image

Глава 12. Повторная загрузка резидента 

125 

Все,  экран  чистый.  В  данном  случае  очистка  экрана  происходит  мгновенно. 

Этот процесс не заметен даже на компьютерах IBM PC/XT. После выполнения по-
следней команды — 

rep stosw

 — 

сх

 будет содержать 0. 

В

Н И МА Н И Е

!  

Оператор rep (от англ. repeat — повтор) неотделим от сх, как и loop от сх! 

Подведем итог: 

 

одна команда 

stosw

 записывает только два символа, находящихся в 

ax

 по адресу 

es:di

 

команда 

rep  stosw

  запишет  два  символа,  находящихся  в 

ax

  по  адресу 

es:di

 

столько раз, сколько находится в регистре 

сх

 

строковые  команды  предпочтительней  использовать  в  паре  с 

rep

,  где  это  воз-

можно. 
Все  просто.  При  исследовании  работы  строковых  команд  желательно восполь-

зоваться отладчиком и следить за изменением регистров 

сх

si

di

.  

12.4. Использование xor и sub  
для быстрого обнуления регистров 

Рассмотрим  одну  маленькую  хитрость,  которую  часто  применяют  программи-

сты на ассемблере: использование команд 

xor

 и 

sub

 для быстрого обнуления реги-

стров (рис. 12.9): 

xor ax,ax        ;равносильно mov ax,0 

А можно и так (рис. 12.10): 

sub ax,ax        ;вычтем из ax ax 

 

Рис. 12.9. Обнуление регистра с помощью команды xor 


background image

 

Часть III. Файловая оболочка, вирус, резидент 

126 

 

Рис. 12.10. Обнуление регистра с помощью команды sub 

Эти  команды  (

xor  ax,ax

/

sub  ax,ax

)  выполняются  быстрее  команд  типа 

mov 

ax,0

.  Поэтому  не  удивляйтесь,  если  где-то  в  наших  примерах  или  в  других  про-

граммах встретите нечто подобное. 

xor

 — исключающее ИЛИ. Это логическая команда. Подобные инструкции мы 

рассмотрим  позже.  Пока  вам  нужно  уяснить,  что  такими  операторами,  как 

xor

  

и 

sub

, можно быстро и просто аннулировать регистры.  

12.5. Задание для освоения информации  
из данной главы 

Досконально исследуйте программы resid12.asm и test12.asm в отладчике (лучше 

в AFD): это позволит вам понять принцип работы резидентных программ и строко-
вых команд. 

 


background image

 

 

 

Глава 13 

 

Поиск и считывание файлов:  
вирус 

 
Эта глава небольшая, но информативная. Из нее вы узнаете, как поместить ви-

рус временно в память, как передать ему управление, как найти очередной "файл-
жертву" и многое другое. 

13.1. Теория 

В данной главе рассмотрим следующее: 

 

как вирус "прикрепляется" к файлу, не нарушая его работоспособности; 

 

что должен сделать вирус в первую очередь; 

 

как передать управление вирусу из чужой программы. 
Первое,  что  хотелось  бы  отметить, —  это  то,  что  наш  вирус  будет  заражать 

только COM-файлы. 

Как вы уже знаете, файлы типа COM загружаются в первый свободный сегмент, 

и их код располагается по смещению 

100h

. Следовательно, нам нужно будет сохра-

нить  в  теле  нашего  вируса  первые  три  байта  "файла-жертвы",  записать  вирус  
в  "хвост"  файла  и,  вместо  сохраненных  трех  байтов,  установить  команду 

jmp

  на 

начало кода нашего вируса (т. е. передать ему первому управление). 

После того как вирус отработает, следует восстановить сохраненные три байта 

(записать их в памяти по адресу 

100h

) и передать им управление. На практике все 

будет понятно. Получается примерно так, как представлено в листингах 13.1 и 13.2. 

Листинг 13.1. Программа до заражения (следите за адресами) 

;код программы до заражения, расположенный по адресу 100h 
[1234:0100h] mov ax,34 
[1234:0103h] mov dx,15     ;здесь может быть все, что угодно... 
[1234:0106h] add ax,bx 
[1234:0108h] ...и т. д... 
 
... 
 
[1234:0500h] int 20h       ;последний байт программы 


background image

 

Часть III. Файловая оболочка, вирус, резидент 

128 

[1234:0502h] --- 
;далее идет уже память, не занятая под код или данные "файла-жертвы"... 
... 

Листинг 13.2. Программа после заражения 

;"прыгаем" на начало нашего вируса (заменили байты здесь) 

[1234:0100h] jmp 0502h 
 
[1234:0103h] mov dx,15     ;а это байты "файла-жертвы" 
[1234:0106h] add ax,bx 
... 
[1234:0500h] int 20h 
 
[1234:0502h] ---           ;а здесь уже начинается код нашего вируса. 
...                        ;здесь тело вируса. Делаем, что хотим... 
 
;=== После того, как вирус отработал === 
;Восстановим первые два байта "файла-жертвы" 
[1234:0700h] mov word ptr cs:[0100h], First_bytes_1 
 
;Восстановим третий байт "файла-жертвы"... 
[1234:0705h] mov byte ptr cs:[0102h], First_bytes_2 
 
;Теперь по адресу 100h первые два байта не jmp 502h, а mov ax,34 
;(т. е. оригинальный код программы). Вспоминаем из прошлых глав о том, 
;что в ассемблере можно менять код программы "на лету"... 

;Все это меняется только в памяти, а не на диске! 
 
;...перейдем по адресу 100h, т. е. передадим управление программе 
[1234:0709h] jmp 0100h 
... 

Сравните два участка кода: незараженной программы и зараженной. Теоретиче-

ски вопросов возникнуть не должно... 

13.2. Практика 

Теперь  приступим  к  практической  части.  Откройте  файл  virus13.asm.  Первая 

строка — 

.286

 —  указывает  ассемблеру,  что  будем  использовать  инструкции  (ко-

манды, операторы) не только процессора 8086, но и 80286. То есть на  компьютере 
8086 наш вирус уже работать не будет! С первого же байта перейдем на метку 

Init

 

(инициализации нашего вируса).