"Вирусы", "Черви", "Драконы" и резиденты на службе прогресса

Вид материалаДокументы

Содержание


"Вирусы", "Черви", "Драконы" и резиденты на службе прогресса.
Действия процессора мнемокоды ¦ мнемокоды действия
Pushf ; ¦
Pushf ; ¦
Подобный материал:
1   2   3   4   5   6   7   8   9   ...   16

"Вирусы", "Черви", "Драконы" и резиденты на службе прогресса.


Назад | Далее



Например:

адрес п/п-ы прерывания N0 (реакция на ситуацию "деление на нуль") нахо-

дится в таблице векторов прерываний по адресу 0000:0000--segment и

0000:0002--offset

адрес п/п-ы прерывания N5 (печать экрана) находится в таблице векторов

прерываний по адресу 0000:0014--segment и 0000:0016--offset


Если мы замыслим заменить исходную стандартную п/п-му нашей собственной,

мы должны:

1. Засунуть куда-то эту нашу п/п-му (и чтобы она там действительно была!

И была готова обработать соотв. прер-е).

2. Изменить в таблице векторов адрес исходной стандартной п/п-ы на адрес

нашей.


Отметим, что пихать нашу п/п-му обработки прерыв-я в то-же место, где

сидела исходная (иногда это физически возможно) лучше не надо, хотябы потому,

что исходная нам ЕЩЕ ОЧЕНЬ МОЖЕТ ПРИГОДИТЬСЯ.


ПОДРОБНО опишем механизм того, как PC реализует обработку прерываний:

1. PC прячет в стек регистр флагов.

2. PC прячет в стек содержимое регистра CS.

3. PC прячет в стек значение IP для следующей команды.

4. PC делает JMP Far <сегмент. адрес п/п>:[<офсетн. адрес п/п>] (джамп @@??

на п/п-у обработки прерывания).

ПРИ ЭТОМ все операции 1-4 (PUSHF, PUSH CS, , JMP FAR ) содер-

жатся неявно В ОДНОЙ КОМАНДЕ "INT" вызова прерывания (если прерыв-е реализу-

ется программно).

5. Далее выполняется п/п-ма обработки прерывания.

6. П/п-ма обработки прерывания завершается специальной командой IRET,

которая состоит из следующих действий:

а) помещается из стека слово в регистр IP (и увелич. SP на 2) ---¬

б) помещается из стека слово в регистр CS (и увелич. SP на 2) +----¬

в) помещается из стека слово в регистр флагов (увелич. SP на 2)--- ¦

¦

¦

т.е. это- JMP Far обратно, в программу ¦

пользователя, на команду, следующую за той, ¦

которая осуществила вызвлв прерыв-я ¦

+ восстановление флагов <-----------------------------------


А что такое п/п-ма обработки прерывания? Очень часто - трудно сказать;

считайте, что стандартная п/п-ма обработки прерывания (та - которую PC имеет

изначально) -- своего рода -- черный ящик. И, как в любом черном ящике, здесь

нам доступны, в лучшем случае, лишь ВХОД и ВЫХОД. Пусть, например, мы хотим

напечатать на экране PC один символ. Это легко можно сделать, дав прерывание

номер 10h. При этом будет вызвана п/п-ма печати символа, о структуре которой

мы ничего не знаем. Как и большинство п/п-м, эта п/п-ма имеет входные и вы-

ходные параметры, через которые мы загружаем в нее и получаем обратно инфор-

мацию. ВХОДНЫЕ И ВЫХОДНЫЕ ПАРАМЕТРЫ П/П-МЫ ПОМЕЩАЮТСЯ В РЕГИСТРЫ ПРОЦЕССОРА.

Например, -- мы страстно хотим напечатать на экране символ 'a'. Тогда

нам необходимо сделать следующие действия:


MOV AH,0Eh ;это означает что п/п-ма должна ПЕЧАТАТЬ ОДИН СИМВОЛ------¬

; ¦

MOV AL,61h ;п/п-ма должна печатать КОНКРЕТНЫЙ СИМВОЛ 'a'(его код=61h)¦

;L---T-----------------------------------------------------

; L-загрузка входных параметров

;

INT 10h ;приказ "печатай!" (генерация прерывания N 10h)


а вот выходных параметров это прерывание (вернее сказать- данный способ

его использования) не имеет


А вот как выглядит при этом работа процессора:


-----------------------------------------------------------¬

¦ рис.1 ¦:

L-----------------------------------------------------------


-- НАША (ПОЛЬЗОВАТЕЛЬСКАЯ) ПРОГРММА ------¦--- П/П-ма ОБРАБОТКИ ПРЕРЫВАНИЙ ---

¦

¦

¦

ДЕЙСТВИЯ ПРОЦЕССОРА МНЕМОКОДЫ ¦ МНЕМОКОДЫ ДЕЙСТВИЯ

('на пальцах'): ¦ ПРОЦЕССОРА:

=======>====¬ ¦ г===>=====¬

AH<---0Eh MOV AH,0Eh¦ ¦ ¦.печать..¦ .печать..

AL<---61h MOV AL,61h¦ ¦ ¦.символа.¦ .символа.

PUSHF---------------TT---> INT 10h L===>===-.........¦ .........

PUSH CS ¦¦ г===============<====T¬IRET<--¦------¬--POP IP

PUSH IP ¦¦ L==>=¬ ¦ ¦L=====<=- L+ POP CS

JMP Far по адресу --+- ¦ ¦ ¦ L-POPF

<0:40>:[<0:42>] ¦ ¦

L--T-- L---T- ¦ ¦

¦ ¦ ¦ L-> путь выполнения @@??

¦ ¦ ¦

слово по- L--- слово по

адресу 0:40 адресу 0:42


Покажем, опираясь на описонный выше подробный механизм выполнения преры-

ваний, как реализовать прер-е НЕ пользуясь классической командой INT. Печата-

ем символ 'a' (см. пример 1):


-----------------------------------------------------------¬

¦ пример 1 ¦:

L-----------------------------------------------------------


TITLE Это - COM. программа N1 для демонстрации механизма вызова прерываний

ASSUME CS:CodeSegment

;---------------------------------------------------------------------------

CodeSegment SEGMENT PARA

ORG(100h)

Start:

MainProcedure PROC NEAR

;

;

;

;--запасаем в стеке информацию, необходимую для автоматического-¬

; возврата из п/п-мы обработки прерыв-я ¦

; ; ¦

PUSHF ; ¦

PUSH CS ; ¦

MOV BX,OFFSET after_int ;---¬ ¦

PUSH BX ;---------+-засунуть в стек IP точки возврата¦

; ; из п/п-ы обработки прерывания ¦

;----------------------------------------------------------------

;

MOV AH,0Eh ;входные

MOV AL,61h ; параметры прерыв-я 10h

;

;

XOR DX,DX ; DX = 0 напрямую, как Вы знаете, засунуть

MOV DS,DX ; DS = 0 константу в регистр DS невозможно

;

;

JMP dword ptr DS:[40h] ;длин. джамп по адресу, котор. находится

; ; в ячейках 0000:0040h и 0000:0042h

after_int: ;

RET ;закончить программу и вернуться в DOS

;

;

;

MainProcedure ENDP

;

CodeSegment ENDS

END Start


Пояснение: команда JMP dword ptr DS:[40h] (длинный JMP) осуществляет пе-

реход по адресу, который хранится по адресу DS:[40h]. Это -- адрес п/п-мы об-

работчика прерывания 10h. При этом в стек нужно уронить регистр флагов, ре-

гистры CS и IP. Т.о. для того, чтобы команда IRET, завершающая обработчик

прерывания 10h вернула управление нашей программе (на метку after_int), необ-

ходимо сохранить в стеке определенную информацию (см. пример 1).


-----------T------------------------------------------------------T------------

¦ в случае, если кто-то не знаком с пакетом TASM, то:

L-------------------------------------------------------

А теперь -- создадим загрузочный модуль.

Вы можете при помощи любого текстового редактора перетащить вышепред-

ставленный текст исходника в текстовой файл с расширением .asm, например --

proba.asm

А после этого сделать сначала .OBJ файл:


tasm.exe /l proba.asm

LT-

L---- будет создан файл листинга proba.lst

(там Вам покажут ошибки - если они есть)


а потом - и .COM файл:


tlink.exe /t proba.obj

LT-

L--- будет создан .COM файл


Если Вы не знакомы с пакетом TASM и это - Ваш первый опыт, то можете по-

ка-что пропустить (особо не задумываясь) всякие диррективы, предшествующие и

последующие за текстом основной программы (TITLE ...; ASSUME ...; CodeSegment

SEGMENT PARA; ORG(100h);MainProcedure ENDP; CodeSegment ENDS; END Start ).

Поступайте с ними пока-что чисто механически. (На досуге можете почитать

/1/,/2/,/7/)

Итак, у нас есть готовый COM. модуль, который можно загрузить и выпол-

нить.

И он напечатает литеру 'a'.

Замечательно!


А вот тут пример того как решить ту же задачу не JMP Far-ом, а -- CALL

Far-ом Разница в том, что в этом случае не нужно прятать в стек значения CS и

IP для точки возврата из п/п-мы обработки прерывания (CALL Far оказался "ум-

нее" - он делает это автоматически).


-----------------------------------------------------------¬

¦ пример 2 ¦:

L-----------------------------------------------------------


TITLE Это - COM. программа N2 для демонстрации механизма вызова прерываний

ASSUME CS:CodeSegment

;---------------------------------------------------------------------------

CodeSegment SEGMENT PARA

ORG(100h)

Start:

MainProcedure PROC NEAR

;

;

;

XOR DX,DX ; DX = 0

MOV DS,DX ; DS = 0

;

PUSHF ;запасаем информацию, необходимую для автома-

; ;тического ыозврата из п/п-ы обработки прерыв-я

;

MOV AH,0Eh ;входные

MOV AL,61h ; параметры прерыв-я 10h

;

;

CALL dword ptr DS:[40h] ;длинный вызов п/п-ы обработки прерыв-я 10h

; ;(по адресу 0:40h - адрес п/п-ы обработки)

; ;(два слова)

;

RET ;закончить программу и вернуться в DOS

;

;

;

MainProcedure ENDP

;

CodeSegment ENDS

END Start


И последнее, что мы сделаем в этой главе, - научимся давать вызов преры-

вания, не пользуясь INT-ом и не обращаясь каждый раз к таблице векторов. За-

чем ? Это иногда полезно. Дело в том, что 'вирусы' и 'драконы' очень часто

пользуются прерываниями и при этом должны оставаться необнаруживаемыми. А ес-

ли прерывание дается командой INT, то охранные системы (всевозможные антиви-

русные мониторы) тут же узнаЮт об этом и могут насторожиться. Если мы посто-

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

межу делом не подложили в нее адрес СВОЕЙ п/п-мы, и, вместо того, чтобы полу-

чить сервис п/п-мы-обработчика прерыв-я, мы попадаем в засаду. А если мы сох-

раним в коде нашей программы адрес п/п-мы исходного обработчика прерыв-я (и в

тот момент будем абсолютно уверены, что имеем дело не с 'оборотнем') то в

дальнейшем сможем смело делать JMP Far или CALL Far без опасения быть обнару-

женными.


Вот готовая программа: (коментарии см. ниже)


-----------------------------------------------------------¬

¦ пример 3 ¦:

L-----------------------------------------------------------


TITLE Это - COM. программа N3 для демонстрации механизма вызова прерываний

ASSUME CS:CodeSegment

;---------------------------------------------------------------------------

CodeSegment SEGMENT PARA

ORG(100h)

Start:

MainProcedure PROC NEAR

;

;

;

JMP over_data ; перепрыгнем через данные

;

;

saved_int10: DD 0 ; данные (хранилище для адреса INT 10h

; ; -- 2 слова)

;

over_data: XOR DX,DX ; DX = 0

MOV DS,DX ; DS = 0

;

;--сохраняем в хранилище адрес исходн. п/п-мы INT 10h (2 слова)-¬

; ; ¦

MOV AX,DS:[10h*4] ;мы указываем лишь порядко-¦

MOV word ptr CS:[saved_int10 ],AX ;вый номер прерывания ¦

MOV AX,DS:[10h*4+2] ; ¦

MOV word ptr CS:[saved_int10+2],AX ; ¦

;----------------------------------------------------------------

;

;--запасаем в стеке информацию, необходимую для автоматического-¬

; возврата из п/п-мы обработки прерыв-я ¦

; ; ¦

PUSHF ; ¦

PUSH CS ; ¦

MOV BX,OFFSET after_int ;---¬ засунуть в стек ¦

PUSH BX ;---+- IP точки возврата ¦

;----------------------------------------------------------------

;

;

MOV AH,0Eh ;входные параметры

MOV AL,61h ; прерыв-я 10h (печатать 'a')

;

JMP dword ptr CS:[saved_int10] ;длин. джамп по адресу, котор. на-

; ; ходится теперь в хранилище

after_int: ; ; saved_int10

;

RET ;закончить программу и вывалиться

; ; в DOS

;

;

MainProcedure ENDP

;

CodeSegment ENDS

END Start


Что здесь нового? Совсем немного. Во-первых мы перетащили адрес

п/п-мы-обработчика прерывания 10h из таблицы векторов в тело нашей прогр-мы.

Во-вторых мы теперь делаем JMP Far не на адрес в таблице векторов (dword ptr

00:[40h]), а на адрес, сохраненный в теле нашей прогр-мы (dword ptr

CS:[saved_int10]). Есть одна громоздкость -- данные (saved_int10: DD 0) дол-

жны определяться перед их использованием (MOV word ptr CS:[saved_int10 ],AX)

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

зан с особенностями TASM-овской компиляции.