Справочник функций

Ваш аккаунт

Войти через: 
Забыли пароль?
Регистрация
Информацию о новых материалах можно получать и без регистрации:

Почтовая рассылка

Подписчиков: -1
Последний выпуск: 19.06.2015

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

Назад | Далее

     Например:
     адрес п/п-ы прерывания 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 обратно, в программу                       ¦
             пользователя, на команду, следующую за той,                  ¦
             которая осуществила вызвлв прерыв-я                          ¦
              + восстановление флагов  ====¬   ¦   г===>=====¬
AH INT  10h   L===>===-.........¦       .........
PUSH CS             ¦¦    г================¬          ¦    ¦L=====:[]                      ¦    ¦
     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-овской компиляции.

Назад | Далее

Оставить комментарий

Комментарий:
можно использовать BB-коды
Максимальная длина комментария - 4000 символов.
 
Реклама на сайте | Обмен ссылками | Ссылки | Экспорт (RSS) | Контакты
Добавить статью | Добавить исходник | Добавить хостинг-провайдера | Добавить сайт в каталог