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

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

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

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

Добавлен: 16.02.2019

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

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

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

 

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

234 

Данная команда устанавливает флаг переноса, а следующая — сбрасывает его. 

Таблица 23.7. Команда 

clc

 

Команда  Перевод 

Назначение 

Процессор 

clc 

Clear carry flag 

— сбросить флаг 

переноса 

Сброс флага переноса 

8086 

 
Для чего нужны данные команды? Где они обычно применяются? 
В наших примерах мы ими в основном пользуемся перед выходом из процеду-

ры. Например, возьмем часть такого кода (листинг 23.4). 

Листинг 23.4. Использование команд управления флагом переноса 

... 
call Find_symbol 
jc Not_found 
... 

В  данном  примере  вызывается  процедура  поиска  какого-то  символа  в  памяти.  

В  конце  этой  процедуры  мы  устанавливаем  флаг  переноса,  если  символ  найден,  
и  сбрасываем,  если  нет.  Это  проще и быстрее, чем если бы мы использовали для 
этой цели какой-нибудь регистр (листинг 23.5). 

Листинг 23.5. Использование регистра 

... 
call Find_symbol 
cmp ax,1 
je Not_found 
... 

Если 

ax=1

, то символ не найден. Как видите, удобнее пользоваться флагом пе-

реноса. Однако следует помнить, что некоторые команды могут менять этот флаг. 
Поэтому нужно придерживаться следующих правил: 

 

между установкой/сбросом флага переноса и его проверкой не следует вызывать 
никакие прерывания или пользоваться командами типа 

add

sub

mul

 и пр.; 

 

после установки/сброса флага его нужно проверять как можно быстрее. 
Рассмотрим еще две команды управления флагами направления (табл. 23.8, 23.9). 

Таблица 23.8. Команда 

std

 

Команда 

Перевод 

Назначение 

Процессор 

std 

Set destination flag 

— устано-

вить флаг направления 

Установка флага направ-
ления 

8086 


background image

Глава 23. Область PSP и DTA. Системные переменные (окружение DOS) 

235 

Таблица 23.9. Команда 

cld

 

Команда 

Перевод 

Назначение 

Процессор 

cld 

Clear destination flag 

— сбро-

сить флаг направления 

Сброс флага направления 

8086 

 
Какие действия выполняют эти команды? Для чего служит флаг направления? 
Данный  флаг  служит  при  указании  направления  для  инструкций  работы  со 

строками (

lods

stos

movs

 и пр.). До сих пор мы перемещали байты только вперед, 

например,  от  0  до  4000,  а  не  от  4000  до 0 (вспомните вирус, который перемещал 
свой код в область видеопамяти). Вот этот флаг отвечает за то, каким образом про-
изводить перемещение, поиск и пр. Иначе говоря, в каком направлении это делать 
(отсюда и название флага — флаг направления). Как правило, применяют направ-
ление  вперед,  и,  следовательно,  флаг  обычно  сброшен.  Но  бывают  случаи,  когда 
необходимо установить флаг, тем самым производя работу "назад". В нашем рези-
денте мы сбрасываем флаг направления для того, чтобы команды 

lods

stos

 и пр., 

используемые в нем, работали "вперед". 

Как уже упоминалось, некоторые прерывания (в том числе и 

09

) могут быть вы-

званы в любой момент работы какой-нибудь программы (в тот момент, когда поль-
зователь  нажмет  клавишу).  Установлен  ли  этот  флаг  или  сброшен —  нам  не  из-
вестно.  Проще  всего  сбросить  его  самим  в  начале  резидентной  части,  что  мы, 
собственно, и делаем: 

cld    ;Направление — вперед! 

Обращаем ваше внимание еще раз: как правило, этот флаг сброшен, но лучше не 

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

23.3.3. Изменение параметров резидента "на лету" 

Допустим,  наш  резидент  загружен  в  память  и  уже  успешно  работает  (т. е.  

в LOG-файле фиксирует нажатые пользователем клавиши). А что, если мы хотим 
поменять имя LOG-файла в процессе работы резидента? Для этой цели будем ис-
пользовать процедуру обработки прерывания 

10h

. Впрочем, не только для этой це-

ли. Она нам необходима еще и для того, чтобы проверять резидент на повторную 
загрузку (листинг 23.6). 

Листинг 23.6. Процедура обработки прерывания 10h 

... 
(1) Int_10h_proc proc 
(2)    cmp ax,0FAAFh     ;Проверяем на повторную загрузку? 
(3)    jne Next_step 
 
(4)    xchg ah,al 


background image

 

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

236 

(5)    iret 
 

(6) Next_step: 

(7)    cmp ax,0FBAFh     ;Получаем текущий адрес LOG-файла? 

(8)    jne Run_int 

(9)    push cs           ;Заносим в es сегмент LOG-файла 

(10)   pop es 

(11)   mov di,offset File_name   ;Заносим в di смещение LOG-файла 

(12)   iret 

(13) Run_int: 

(14)   jmp dword ptr cs:[0F8h] 

(15) Int_10h_proc endp 

... 

В  строках  (2)—(5)  мы  проверяем,  вызывается  ли  прерывание 

10h

  с  числом 

0FAAFh

. Если вызывается, то меняем местами 

ah

/

al

, что сигнализирует нашему ре-

зиденту, загружаемому повторно, о том, что он уже в памяти. Подобные вещи рас-
сматривались в предыдущих главах, поэтому подробно останавливаться на этом не 
будем. 

Нас сейчас больше интересуют строки (6)—(12). Если прерывание 

10h

 вызыва-

ется с числом 

0FBAFh

 в 

ax

, то это значит, что наш резидент, загружаемый повторно, 

просит получить сегмент и смещение имени текущего LOG-файла. Для чего? Как 
уже  упоминалось,  резидент  может  менять  в  процессе  работы  имя  своего  LOG-
файла.  Для  этого  необходимо  запустить  его  повторно,  с  указанием  имени  в  ко-
мандной строке. Например, так: 

Resid23.com c:\newfile.txt 

Резидент,  при  попытке  повторно  загрузиться  в  память,  прежде  всего  проверит 

параметры в командной строке. Но как повторно загружаемому резиденту узнать, в 
каком  сегменте  находится  его  резидентная  копия?  Для  этого  мы  воспользуемся 
созданной нами функцией 

0FBAFh

 прерывания 

10h

, которое резидент перехватыва-

ет. В результате, прерывание 

10h

 (а точнее, наша процедура обработки прерывания

 

10h

) вернет в 

es

 сегмент, а в 

di

 — смещение имени LOG-файла (листинг 23.7). 

Листинг 23.7. Получение сегмента 

... 

mov ax,0FBAFh    ;Получим сегмент и смещение имени LOG-файла 

int 10h          ;Теперь es — сегмент, а di — смещение LOG-файла в памяти. 

... 

А теперь посмотрите первые команды нашего обработчика прерывания 

10h

, ко-

торый, в случае получения в 

ax

 числа 

0FBAFh

, загружает в 

es:di

 сегмент и смеще-

ние  LOG-файла  и  немедленно  выходит  из  этого  прерывания.  Обратите  внимание, 


background image

Глава 23. Область PSP и DTA. Системные переменные (окружение DOS) 

237 

что при инициализации резидента мы сперва проверяем, загружен ли он в память 
или  нет,  и  если загружен, то получаем адрес LOG-файла. Теперь осталось только 
перенести параметры командной строки в полученные сегмент и смещение! 

В  листинге 23.8  приведен  фрагмент  нашего  обработчика    прерывания 

10h

 

(

Int_10h_proc

). 

Листинг 23.8. Обработчик прерывания 10h 

... 
cmp ax,0FBAFh      ;Получаем текущий адрес LOG-файла 
jne Run_int 
push cs            ;Заносим в es сегмент LOG-файла 
pop es 
mov di,offset File_name 

;Заносим в di смещение LOG-файла 

iret 
... 

23.4. Задание для закрепления сведений 
из данной главы 

Обязательно разберитесь с прилагаемым файлом, т. к. информация, приведенная 

в  нем,  очень  важна  для  понимания  работы  резидентных  программ.  Описаний  
в файле-приложении более чем достаточно. 

 


background image

 

 

 

Глава 24 

 

Резидентный антивирус 

 

В

Н И МА Н И Е

!  

Наш антивирус корректно обезвреживает только вирус, код которого приведен в  гла-
ве 20
.  Если  вы  добавили  или  убрали  хоть  один  байт  в  коде  вируса,  то антивирус не 
сможет корректно вылечить зараженный файл! 

24.1. Регистры микропроцессоров  
80386/80486. Хранение чисел в памяти 

Прежде  чем  приступить  к  рассмотрению  работы  нашего  антивируса,  ознако-

мимся  вкратце  с  некоторыми  регистрами  процессоров 80386/80486.  В  табл. 24.1 
приведен пример на основе аккумулятора. 

Таблица 24.1. Регистры процессоров 386+ 

Количество разрядов 

Регистр 

32 

eax 

16 

ax 

ax 

ah 

al 

ah 

al 

 
Как  видно  из  таблицы, 

eax

 —  32-разрядный  регистр.  Он  может  хранить  число 

65 535   65 535  (т. е.  65 535  в  квадрате).  До  сих  пор  мы  пользовались  только  16-
разрядными  регистрами  (

ax

bx

cx

  и пр.).  С  данной  главы  начнем  использовать  

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

В приведенной выше таблице мы рассмотрели только регистр 

eax

. По аналогии 

с ним, можно добавить и регистры 

ebx

ecx

edx

edi

esi

ebp

При  использовании  32-разрядных  регистров  необходимо  в  ассемблерный  лис-

тинг включить одну из следующих директив: 

.386 
.486