Рис. 5.1
Разумеется, среди этих многочисленных обработчиков может «затесаться» обработчик, принадлежащий антивирусному монитору, который не дает спокойно работать не только вирусам, но и обычным программам. Поэтому серьезные вирусы и некоторые хорошо написанные программы пытаются определить адрес оригинального обработчика и обратиться к нему напрямую, в обход остальных обработчиков:
mov ah,...
pushf
call dword ptr O21
...
O21 dw ?
S21 dw ?
Но антивирусные мониторы учитывают эту возможность и принимают свои меры.
Определение адреса оригинального обработчика DOS
Для того чтобы обратиться к DOS напрямую, нужно знать адрес оригинального обработчика. Получить этот адрес не так просто.
Метод трассировки Чаще всего используется метод трассировки при помощи отладочного прерывания INT 1. Суть метода заключается в том, что вирус трассирует прерывание INT 21h (включает флаг трассировки, при этом после каждой команды происходит прерывание INT 1) и проверяет значение сегмента, в котором идет обработка прерывания. Если значение сегмента меньше 0300h, то это обработчик DOS. Например, так поступал много лет назад вирус Yankee 2C (M2C, Музыкальный). Вот листинг соответствующего фрагмента с комментариями:
;Берем из таблицы векторов прерываний текущий адрес INT 01h
mov ax,3501h
int 21h
mov si,bx ;смещение сохраняем в регистре SI
mov di,es ;сегмент сохраняем в регистре DI
;Устанавливаем свой обработчик INT 01h
mov ax,2501h
mov dx,offset Int01
int 21h
;Формируем в стеке адрес выхода из трассировки так, чтобы по IRET
;из INT 21h попасть на метку Next – помещаем в стек
;последовательно флаги, сегмент и смещение метки Next
pushf
push cs
mov ax,offset Next
push ax
;Начинаем трассировку INT 21h. Для этого нужно подготовить стек
;следующим образом: поместить в него флаги с включенным флагом
;трассировки, а также сегмент и смещение текущего обработчика
;INT 21h. Затем можно выполнить команду IRET – программа запустит
;текущий обработчик и считает из стека флаги (флаг трассировки
;во флаговом регистре включится, начнется трассировка. После
;каждой команды процессора будет запускаться INT 01h).
;Помещаем в стек флаги, включаем в них бит, соответствующий
;флагу трассировки TF. Для того, чтобы включить флаг
;трассировки TF, после сохранения флагов в стеке считаем их
;в регистр AX, в нем включим соответствующий бит, а затем
;сохраним регистр AX в стеке
pushf
pop ax
or ax,0100h
push ax
;Считаем из таблицы векторов прерываний текущий адрес INT 21h
mov ax,3521h
int 21h
;Сохраним в стеке сегмент, а затем и смещение текущего обработчика
push es
push bx
;Установим в регистре AH номер какой−либо безобидной функции
;(чтобы определение адреса обработчика DOS
;не сопровождалось разрушениями)
mov ah,0Bh
;Запускаем трассировку
cli
iret
;Обработчик INT 01h
Int01:
;При вызове обработчика в стеке находятся: значение регистра IP,
;значение регистра CS, флаги перед прерыванием.
;Адресуемся к стеку с помощью регистра BP,
;предварительно сохранив текущее значение BP
push bp
mov bp,sp
;Теперь в стеке находятся:
;SS:[BP] – BP
;SS:[BP+2] – IP
;SS:[BP+4] – CS
;SS:[BP+6] – флаги
;Проверяем флаг продолжения
cmp byte ptr cs:ContinueFlag,1
;Если флаг продолжения выключен, то выходим из трассировки
jne TraceOff
;Проверяем текущий адрес. Если сегмент меньше 300h,
;обработчик DOS достигнут, иначе – продолжаем трассировку
;и выходим из обработчика
cmp word ptr [bp+4],300h
jnc ExitFromInt
;Достигнут DOS – берем из стека адрес обработчика и сохраняем его
push bx
mov bx,[bp+2]
mov word ptr cs:O21,bx
mov bx,[bp+4]
mov word ptr cs:S21,bx
pop bx
;Заканчиваем обработку прерывания и дальнейшую трассировку
TraceOff:
;Устанавливаем в ноль бит, соответствующий TF,
;в копии регистра флагов в стеке
and word ptr [bp+6],0FEFFh
;Устанавливаем в ноль флаг продолжения
mov byte ptr cs:ContinueFlag,0
ExitFromInt:
pop bp
;Выходим из обработчика
iret
;Восстановление после трассировки
Next:
;Сбрасываем флаг продолжения
mov byte ptr ds:ContinueFlag,0
;Восстанавливаем прежнее значение вектора прерывания INT 01h
mov ax,2501h
mov dx,si
mov ds,di
int 21h
В настоящее время этот алгоритм можно считать несколько устаревшим. Дело в том, что современные версии DOS могут размещать свой обработчик в областях верхней памяти. Поэтому условие окончания трассировки должно выглядеть, например, так:
cmp word ptr [bp+4],300h
jb loc_65
cmp word ptr [bp+4],0F000h
ja loc_65
В качестве альтернативного варианта можно использовать такой прием. Сначала определяется исходный сегмент DOS при помощи недокументированной функции 52h прерывания INT 21h (возвращает адрес векторной таблицы связи DOS):
Читать дальше
Конец ознакомительного отрывка
Купить книгу