Большой архив статей, книг, документации по программированию, вебдизайну, компьютерной графике, сетям, операционным системам и многому другому
 
<Добавить в Избранное>    <Сделать стартовой>    <Реклама на сайте>    <Контакты>
  Главная Документация Программы Обои   Экспорт RSS E-Books
 
 

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


гл.4 СОЗДАНИЕ РЕЗИДЕНТНЫХ ПРОГРАММ (практическая реализация)
============================================================
     Итак, мы познакомились с механизмом работы прерываний и научились реали-
зовывать вызов  прерываний на  уровне обычный JMP-ов и CALL-ов  и даже не ис-
пользовать при этом таблицу векторов.
     Чудесно!
     Теперь об создании резидентных программ (именно  таковыми являются 'дра-
коны' и 90% всех 'вирусов').
     Что такое резидентная программа (в дальнейшем - просто - резидент) ?
     Это  такая  программа, которая находится в оперативной памяти  постоянно
(обычные, нерезидентные программы присутствуют в памяти лишь во  время их не-
посредственного исполнения; когда их выполнение заканчивается  -- они "умира-
ют" - память занятая ими - освобождается . Резидент же  может  обитать в ОЗУ,
[кстати rezide - по англ. 'обитать']  не будучи в данный момент исполняем, но
в то же время, - готовый к действию).
     Вот как распределяется память  при  выполнении обычных и резидент. прог-
рамм (КРАЙНЕ упрощенно):


      -----------------------------------------------------------¬
      ¦                        рис.2                             ¦:
      L-----------------------------------------------------------
обычная программа:

                      До загрузки чего-либо:

     ---------T--------------T----------------------------------------
     ¦таблица ¦              ¦
     ¦векторов¦  область DOS ¦   свободная память . . . . . . . . . .
     ¦прерыв-й¦              ¦
     L--------+--------------+----------------------------------------
   0:0 ----> старшие адреса

                      Загрузили и исполняем обычную программу:
                                                      ¦
                                      -----------------
     ---------T--------------T--------V----------T--------------------
     ¦таблица ¦              ¦    TETRIS.EXE     ¦
     ¦векторов¦  область DOS ¦(есть такая глупая ¦ свободная память .
     ¦прерыв-й¦              ¦     игрушка)      ¦
     L--------+--------------+-------------------+--------------------
   0:0

                      После того, как прогр-а завершилась:

     ---------T--------------T----------------------------------------
     ¦таблица ¦              ¦
     ¦векторов¦  область DOS ¦   свободная память . . . . . . . . . .
     ¦прерыв-й¦              ¦ (все вернулось на кругИ своя...)
     L--------+--------------+----------------------------------------
   0:0
===========================================================================
     Теперь - что касается резидентов:

                      До загрузки чего-либо:

     ---------T--------------T----------------------------------------
     ¦таблица ¦              ¦
     ¦векторов¦  область DOS ¦   свободная память . . . . . . . . . .
     ¦прерыв-й¦              ¦
     L--------+--------------+----------------------------------------
   0:0

                      Загрузили резидент:-------------¬
                                                      ¦
                                      -----------------
     ---------T--------------T--------V----------T--------------------
     ¦таблица ¦              ¦    KEYR23.COM     ¦
     ¦векторов¦  область DOS ¦(драйвер рус. кла- ¦ свободная память .
     ¦прерыв-й¦              ¦     виатуры)      ¦
     L--------+--------------+-------------------+--------------------
   0:0    ---------------------------
          ¦
     И так- --  до окончания работы на PC! Резидент будет сидеть в ОЗУ и быть
всегда готов вам услужить. Если  Вы  теперь загрУзите tetris, он попадет  вот
куда:

     ---------T--------------T-------------------T----------T---------
     ¦таблица ¦              ¦    KEYR23.COM     ¦          ¦
     ¦векторов¦  область DOS ¦(драйвер рус. кла- ¦TETRIS.EXE¦свободная
     ¦прерыв-й¦              ¦ ¦   виатуры)      ¦          ¦память...
     L--------+--------------+-¦-----------------+----------+---------
   0:0                         Lстал резидентом


     Только программы типа Volkov Comander могут  безболезненно удалять рези-
денты из памяти (и то лишь те, которые были загружены после них {удаляющих}).
     Сделать программу  резидентной  (постоянно  присутствующей  в памяти) --
ЭЛЕМЕНТАРНО. Вот один из способов (в дальнейшем мы рассмотрим их все):

    (прокоментируем ниже)
      -----------------------------------------------------------¬
      ¦                         пример 4                         ¦:
      L-----------------------------------------------------------

TITLE   Это - COM. программа N4 для демонстрации посадки резидента
ASSUME        CS:CodeSegment
;---------------------------------------------------------------------------
CodeSegment   SEGMENT PARA
              ORG(100h)
Start:
MainProcedure PROC NEAR
              ;
              ;
              ;
              ;
              ;
              MOV AX,0E61h                 ; напечатать
              INT 10h                      ;   символ 'a'
resident_end: ;
              ;
              MOV DX,OFFSET resident_end   ; DX<-- адрес последней команды
              ;                            ;   рез-та+1
              INT 27h                      ; вернуться в DOS
              ;                            ;   оставив программу резидентной
              ;
              ;
              ;
MainProcedure ENDP
              ;
CodeSegment   ENDS
              END Start



     Если Вы захотите откомпилировать и запустить вышеданный пример, то лучше
перед этим выйти из Norton Comander-а и запустить Volkov Comander (если у Вас
его еще нет -- настоятельно советуем приобрести !). Volkov Comander позволяет
по нажатию комбинации клавиш Alt/F5 показать карту памяти PC и Вы можете уда-
лить любой резидент, загруженный после Volkov Comander-а.

     А теперь -- коментарии к примеру 4:
     Чтобы после выполнения программы выйти в  DOS  и  одновременно  оставить
прогр-му резидентной всего-то лишь и нужно: ВМЕСТО КОМАНДЫ  RET ДАТЬ ПРЕРЫВ-Е
INT 27h  и при  этом в регистр DX нужно  поместить адрес последнего оператора
остающегося резидентно куска+1. Адрес этот = смещению от  PSP программы (если
не знаете  ничего  о PSP, то почитайте хотя бы /1/; или -- чуть подождите, мы
кратко расскажем об этом  позднее -- в гл.5). Прерывание INT 27h  -- програм-
мное прерыв-е. П/п-ма его обработки изменяет структуру ОЗУ так, что часть па-
мяти теперь навечно закреплена за фрагментом Вашей программы.
     Итак, мы оставили в ОЗУ резидентный  фрагмент,  который  печатает  букву
'a'. Вопрос -- когда же  он  будет  выполняться?  А вот -- никогда! Вернее --
всего один  раз  - когда мы оставляли резидент в памяти. Но, тем не менее, он
останется в ОЗУ.  Он  больше никогда не получит  управление.  Это - настоящий
программный труп, который просто  занимает  место. Ради прикола запустите эту
программу еще разок. И в ОЗУ останется еще один памятник глупости. Расботая в
Volkov Comander-е,  нажав Alt/F5, Вы можете в этом  убедиться. Сколько бы раз
эта программа не запускалась  - каждый раз она будет отхватывать все  новые и
новые кусочки памяти и оставлять в  них код печати буквы 'a', который никогда
больше не будет выполнен.
     Но ведь резиденты пишутся не для  этого! Они остаются в памяти ДЛЯ того,
чтобы в ОПРЕДЕЛЕННЫЕ МОМЕНТЫ получать  управление  и  выполнять  определенные
действия. Когда и каким образом? ПРИ ПОМОЩИ МЕХАНИЗМА ПРЕРЫВАНИЙ!
     ПОДРОБНЕЕ:
     Что будет если программа заменит в таблице векторов прерываний адрес ис-
ходной п/п-мы обработки прерывания на адрес своей собственной  п/п-мы? В этом
случае, в момент, когда будет дано это прерыв-е, управление получит эта ейная
п/п-ма. Возникнет некий самозванец, который будет  обрабатывать прерывание по
своему. Например,  -- вы нажали букву "А", а PC напечатал в на экране "О"; Вы
начали печатать  документ на принтере, а  одновременно его текст  запишется в
специальный скрытый  файл (пример шпионящего "дракона"); программа TETRIS.EXE
загружена на  выполнение (прерывание 21h), а вирус "почуял"  это и впридачу к
запуску программы "заразил" ее своей копией.
     Прерывания происходят постоянно, и если, окончив  свою работу, прогр-ма,
на адрес которой был заменен вектор прерывания, исчезнет из памяти  - "умрет"
и при  этом не восстановит исходное  значение вектора (адрес  исходной п/п-мы
обработки прерывания), то PC  по-прежнему  всякий раз, когда будет генериться
прерывание, будет передавать управление в область, где раньше сидел самозван-
ный обработчик, а теперь остался лишь мусор. И PC зависнет (в лучшем случае).
Зависнет намертво.
     Следовательно, если  мы  решимся  перехватить  прерывание  то существуют
только две возможности:
     1.  Либо,  если  мы не будем сажать в память резидент, то, перед тем как
"умрем", отреставрируем адрес исходного обработчика прерываний;
     2. Либо мы  не будем реставрировать адрес исходного обработчика прерыва-
ний, и, сохранив прерогативу обработки прерывания за собою,  оставим наш ори-
гинальный обработчик резидентно в памяти;
     Нас интересует второй  вариант, т.к. созданные нами программы будут кон-
тролировать работу  PC во время всей  DOS-овской сессии, во  время выполнения
других программ, во время всех действий пользователя (который об этом и знать
не будет).
     ОЧЕНЬ ВАЖНОЕ ДОБАВЛЕНИЕ -- очень часто стандартная п/п-ма обработки пре-
     ----------------------- рывания все же ДОЛЖНА его обработать, независимо
от того, обрабатывали ли мы его сами.  Следовательно, после того, как Вы, пе-
рехватиши  вектор, в момент генерации прерывания сделали то что Вам нужно, Вы
все же должны  отдать управление исходному обработчику. Это похоже на случай,
когда  некто с целью  наварить баксов перехватывает выгодный подряд на строи-
тельство моста, но сам,  не  будучи  строителем,  все же вынужден нанять про-
фессионалов (выдать субподряд).

     РЕЗЮМИРУЕМ: вот что  нам нужно сделать, чтобы создать активный резидент,
реагирующий на появление определенного прерывания и не грохающий работу PC:
     1. Сохранить в своем теле адрес истинного обработчика прерыв-я.
     2. Заменить в таблице  векторов  адрес истинного обработчика прерыв-я на
адрес собственной п/п-мы.
     3. Завершить  программу, оставив собственную п/п-му обработки прерывания
в памяти PC резидентно.
     4. Сконструировать резидентную часть так, чтобы после обработки перехва-
ченного прерывания позволить исходному обработчику тоже его обработать.
     Если представить все это наглядно, то получится, что  наш резидент вкли-
нивается в некую цепочку осуществляющую реагирование PC на некое прерывание.
     Вот какая была цепочка до нас:

      -----------------------------------------------------------¬
      ¦                          рис.3                           ¦:
      L-----------------------------------------------------------

  ¦
  ¦                  ------¬                ------>выполняется
  ¦ \ ¦ /            +TTTTT+                ¦      п/п-ма
  L - * - --------> -+++++++                ¦      обработки
    / ¦ \           ¦+++++++                ¦      (стандартная)
  возник            ¦¦     ¦                ¦      IRET------------¬
  сигнал --         ¦L------                ¦                      ¦
  -- прерывание     Lв таблице ---------T----                      ¦
                     векторов           делается                   ¦
  ---------------¬   найден адрес       переход                    ¦
  V              L¬  обработчика        по этому                   ¦
                  ¦  (стандартного)     адресу                     ¦
                  ¦                                                ¦
                  L------T------------------------------------------
        делается переход обратно - в пользовательскую программу,
        в ту точку, перед которой прерыв-е возникло



     А вот какая стала цепочка после того, как мы перехватили прерыв-е

  ¦                                  г================================¬
  ¦                  ------¬         ¦      ------>выполняется        ¦
  ¦ \ ¦ /            +TTTTT+         ¦      ¦      ---НАША----        ¦
  L - * - --------> -+++++++         ¦      ¦      п/п-ма обработки   ¦
    / ¦ \           ¦+++++++         ¦      ¦      (она резидентна)   ¦
  возник            ¦¦     ¦         ¦      ¦          ¦              ¦
  сигнал --         ¦L------         ¦      ¦          L---->------¬  ¦
  -- прерывание     Lв таблице ---->----T----                      ¦  ¦
                     векторов        ¦  делается                   ¦  ¦
  ------------¬      найден адрес    ¦  переход                    ¦  ¦
  ¦           L¬     ---НАШЕГО----   ¦  по этому                   ¦  ¦
  V            L¬    обработчика     ¦  адресу                     ¦  ¦
                ¦                    ¦             возвращаем      ¦  ¦
                ¦                    ¦             управление      ¦  ¦
                ¦                    ¦             стандартно- ----+  ¦
                ¦                    ¦             му обработ-     ¦  ¦
                ¦         наше новое-¦             чику (JMP Far)  ¦  ¦
                ¦         звено      L=============================¦==-
                ¦                                 ---------<--------
                ¦                             выполняется
                ¦                             п/п-ма
                ¦                             обработки
                ¦                             (стандартная)
                ¦                             IRET-----------------¬
                L--------T------------------------------------------
              делается переход обратно - в пользовательскую программу,
              в ту точку, перед которой прерыв-е возникло



     Прочитаем еще раз пп.1-3 РЕЗЮМЕ.
     А ведь все это мы уже делали! (правда по отдельности)
     Попробуем теперь сделать все вместе.
     Т.е. перехватим какое-нибудь прерывание <=> сделаем для него резидентный
обработчик.
     Какое прерывание выбрать?  Предложим для простоты прерывание N 5 (печать
экрана). Оно  возникает, если Вы  нажмете клавишу Print Scrin. Вызываемая при
этом п/п-ма печатает на принтере копию экрана PC. Прерывание N 5 не требует и
не возвращает  никаких параметров (чУдно!),  и еще его не обязательно возвра-
щать стандартному обработчику; ничего не случится, если Вы его зажмете (весь-
ма редкое  свойство). Вы  наверное не раз замечали что  если Вы нажмете Print
Scrin, а  принтер не готов -- раздается гудок,  -- это стандартный обработчик
прерывания N 5 'назвал' Вас раздолбаем).
     Создадим-ка резидент, который, перехватывая прерывание N  5  ,  ну  ска-
жем,.. выведет на экран 'сердечко' (символ  с кодом 3), и после этого возвра-
тит управление  стандартному  обработчику  (вежливость - высшая добродетель).
Таким образом, при нажатии Print  Scrin  сначала  будет напечатано 'сердечко'
(работает наш резидентный обработчик), а уже потом раздастся гудок (заработа-
ет стандартный обработчик и обругает Вас за отключенный принтер).
     Итак -- вперед!

    (подробно прокоментируем ниже)
      -----------------------------------------------------------¬
      ¦                         пример 5                         ¦:
      L-----------------------------------------------------------

TITLE   Это - COM. программа N5 для демонстрации посадки резидента
ASSUME        CS:CodeSegment
;-----------------------------------------------------------------
CodeSegment   SEGMENT PARA
              ORG(100h)
Start:
MainProcedure PROC NEAR
              ;
              ;
              JMP  initial                    ; перепрыгнем через данные
              ;                               ; и наш обработчик прер-я 05
              ;                               ; на инициализирующую часть
              ;
              ;
saved_int05:  DD   0                          ; данные (хранилище для
              ;                               ; адреса стандартного обра-
              ;                               ; ботчика прерывания 05 --
              ;                               ; -- 2 слова)
              ;
              ;-----------наша п/п-а обработки прерывания 05------------------¬
              ;¦         (она останется резидентной в памяти)                 ¦
              ;¦        здесь мы можем приколоться как хотим..                ¦
              ;¦                              ;                               ¦
int05_treater:PUSH AX                         ;                               ¦
              ;                               ;                               ¦
              MOV  AH,0Eh                     ;входные параметры прерыв-я 10h:¦
              MOV  AL,03h                     ;  (печатать 'сердечко' - код 03)
              INT  10h                        ;печатаем 'сердечко'            ¦
              ;                               ;                               ¦
              POP  AX                         ;PUSH и POP ОЧЕНЬ важны (см. ко-¦
              ;                               ;  ментарий после примера)      ¦
              ;                               ;                               ¦
              ;                               ;                               ¦
              JMP  dword ptr CS:[saved_int05] ; длин. JMP   по адресу, котор. ¦
rezident_end: ;¦                              ; находится теперь в хранилище  ¦
              ;¦                              ; saved_int05 (возвращаем управ-¦
              ;¦                              ; ление стандартному обработчику¦
              ;¦                              ; прерывания 05)                ¦
              ;L---------------------------------------------------------------
              ;                               ;
              ;-----------инициализирующая часть------------------------------¬
              ;¦ (здесь мы сажаем резидент, переопределяя адреса)             ¦
              ;¦                                  ;                           ¦
initial:      XOR  DX,DX                          ; ---¬                      ¦
              MOV  DS,DX                          ; ---+--> DS = 0            ¦
              ;                                   ;                           ¦
              MOV  AX,DS:[5*4]                    ;сохраняем в хранилище saved_
              MOV  word ptr CS:[saved_int05  ],AX ;  int05 адрес стандартного ¦
              MOV  AX,DS:[5*4+2]                  ;  обработчика прерывания 05¦
              MOV  word ptr CS:[saved_int05+2],AX ;  ( OFFSET и SEGMENT )     ¦
              ;                                   ;                           ¦
              ;                                   ;                           ¦
              CLI                                 ;запрещаем прерывания       ¦
              MOV  AX,OFFSET int05_treater        ;                           ¦
              MOV  word ptr DS:[5*4],AX           ;кладем в таблицу векторов  ¦
              PUSH CS                             ;  адрес нашего обработчика ¦
              POP  AX                             ;  прерывания 05            ¦
              MOV  word ptr DS:[5*4+2],AX         ;                           ¦
              STI                                 ;разрешаем прерывания       ¦
              ;                                   ;                           ¦
              ;                                   ;                           ¦
              MOV  DX,OFFSET rezident_end         ;DX<--конец резид. части    ¦
              INT  27h                            ;закончить программу и      ¦
              ;¦                                  ;  вернуться в DOS, оставив ¦
              ;¦                                  ;  резидентной п/п-му       ¦
              ;¦                                  ;  int05_treater            ¦
              ;L---------------------------------------------------------------
MainProcedure ENDP
              ;
CodeSegment   ENDS
              END Start

     коментарии:

     Сначала упростим текст программы до наглядной схемы, чтобы лучше все по-
нять:

      -----------------------------------------------------------¬
      ¦                          рис.4                           ¦:
      L-----------------------------------------------------------

             -------------¬
             ¦JMP  initial¦======>=======>====>¬ перепрыгнем через данные
             L-------------                    ¦ и наш обработчик прер-я 05
saved_int05: -----------------------------¬    V на инициализирующую часть
             ¦данные: (хранилище для      ¦    ¦   L---------T----------
             ¦адреса стандартного обра -  ¦    ¦--------------
             ¦ботчика прерывания 05 --    ¦    ¦
             ¦-- 2 слова)                 ¦    ¦
             L-----------------------------    ¦
                                               V
int05_treater:----------------------------¬    ¦
             ¦наша п/п-ма обработки       ¦    ¦
             ¦прерывания 05 (она оста-    ¦    ¦
             ¦нется резидентной в памяти) ¦    V
rezident_end:L-----------------------------    ¦
                                               ¦
        г=========<=============<============<=-
        ¦
        ¦
        L=>  -----------------------------¬
initial:     ¦инициализирующая часть      ¦
             ¦(здесь мы сажаем резидент,  ¦
             ¦переопределяя адреса        ¦
             ¦                            ¦
             ¦MOV DX,OFFSET rezident_end  ¦
             ¦INT 27h (выход в DOS)       ¦
             L-----------------------------

     Как видно из рисунка, прогр-ма состоит из двух главных частей:  той, что
остается в памяти  резидентно  и не  выполняется  при запуске самой  прогр-мы
(данные + наша п/п-ма обработки прерывания 05), и -- инициализирующей части.
     Почему порядок следования этих частей именно такой?
     Почему инициализирующая часть не остается в памяти резидентно?
     Почему наша п/п-ма обработки прерывания 05 начинается оператором PUSH AX
и заканчивается оператором POP AX?
     Что за новые операторы CLI и STI?
Далее
 

 
Интересное в сети
 
10 новых программ
CodeLobster PHP Edition 3.7.2
WinToFlash 0.7.0008
Free Video to Flash Converter 4.7.24
Total Commander v7.55
aTunes 2.0.1
Process Explorer v12.04
Backup42 v3.0
Predator 2.0.1
FastStone Image Viewer 4.1
Process Lasso 3.70.4
FastStone Image Viewer 4.0
Xion Audio Player 1.0.125
Notepad GNU v.2.2.8.7.7
K-Lite Codec Pack 5.3.0 Full


Наши сервисы
Рассылка новостей. Подпишитесь на рассылку сейчас и вы всегда будете в курсе последних событий в мире информационных технологий.
Новостные информеры. Поставьте наши информеры к себе и у вас на сайте появится дополнительный постоянно обновляемый раздел.
Добавление статей. Если вы являетесь автором статьи или обзора на тему ИТ присылайте материал нам, мы с удовольствием опубликуем его у себя на сайте.
Реклама на сайте. Размещая рекламу у нас, вы получите новых посетителей, которые могут стать вашими клиентами.
 
Это интересно
 

Copyright © CompDoc.Ru
При цитировании и перепечатке ссылка на www.compdoc.ru обязательна. Карта сайта.