Создание антивирусного программного обеспечения с применением языка программирования низкого уровня: Методические указания по выполнению лабораторных работ по курсу «Информационная безопасность», страница 9

@@def:

mov  eax, [pOldFSHook]

pop  ebp

jmp  dword ptr [eax]

Регистр EAX здесь мы вправе использовать, т.к. он не передает никакого параметра предыдущему хуку и в нем возвращается результат работы функции. Остальные же параметры так и хранятся в стеке при передачи управления предыдущему хуку посредством команды jmp (т.к. она не изменяет стек).

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

mov  eax, [@@PioReq]

cmp  word ptr [eax + 018h], ACTION_OPENEXISTING

jnz  @@1

Флаги создания или открытия файла передаются хуку через структуру IOREQ с помощью поля ir_options, которое находится по адресу +018h относительно начала структуры (см. ifs.inc, входящий в состав DDK).

Если же открывается существующий файл, то нам необходимо открыть его самостоятельно и посмотреть, есть ли в нем вирус. Но как открыть файл самостоятельно? Для этого необходимо вызвать сервис IFSMgr_Ring0_FileIO, который предназначен для обработки всех запросов к файлам.

Но при этом возникает логичный вопрос – когда мы вызовем IFSMgr_Ring0_FileIO, IFS менеджер снова вызовет наш хук, который в свою очередь снова вызовет IFSMgr_Ring0_FileIO, и т.д. Т.е. получится бесконечная рекурсия, которая закончится сбоем системы… Для избежания зацикливания, введем в драйвер флажок занятости, который будет устанавливать в 1 тогда, когда будет обрабатываться наш запрос и в 0 в любом другом случае. Тогда хук, обнаружив запрос на открытие уже существующего файла выполнит следующие действия:

1.  Установит флажок занятости в 1, индицируя таким образом, что дальнейшие операции с файловой системой будут выполняться им самим и должны быть выполнены без всякой дополнительной обработки.

2.  Выполнит чтение файла посредством IFSMgr_Ring0_FileIO, которая снова вызовет хук, но он, проверив флажок занятости, передаст выполнение запроса файловой системе.

3.  Сбросит флажок занятости, указывая, что дальнейшие операции с файлами следует контролировать как обычно.

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

cmp  [MyReq], 0

jnz  @@def

Теперь рассмотрим, как пользоваться IFSMgr_Ring0_FileIO для открытия файла.

Первое, что нам нужно получить – это полный путь файла. Он формируется преобразованием канонизированного Unicode пути, указанного в структуре IOREQ в нормальный в выбранной кодовой странице BCS. Предварительно, необходимо добавить в получаемый путь букву дисковода и символ «:». Это делается следующим образом:

@@OpFile:

pushad

;сохраним регистры

mov  edi, [FileNameBuf]

;edi указывает на буфер, предназначенный для

;формируемого пути и имени файла

mov  al, [@@Drive]

cmp  al,0FFh

;проверяем, необходимо ли добавлять

;букву дисковода и символ «:»

jz   @@NoDrive

add  al, 40h

mov  ah, ':'

mov  [edi], ax

;добавляем

inc  edi

inc  edi

@@NoDrive:

;получаем указатель на канонизированный

;Unicode путь из структуры IOREQ

mov  eax, [@@PioReq]

mov  eax, [eax + 0Ch]

add  eax, 4

;осуществляем непосредственно преобразование

;с помощью сервиса UniToBCSPath

VxDCall UniToBCSPath, <edi, eax, 100, 0>

;этот сервис возвращает в eax количество

;символов, в полном пути и имени файла

;добавим в конец символ с кодом 0

mov  byte ptr [edi + eax], 0

Более подробно смотрите информацию о сервисе UniToBCSPath в DDK.

Итак, теперь у нас есть полный путь и имя файла в буфере. Давайте откроем его:

;установим флаг запроса

inc  [MyReq]

;загрузим регистры необходимой информацией

;о запрашиваемом файле и откроем его

mov  eax, R0_OPENCREATFILE

xor  ecx, ecx

mov  edx, 1

mov  ebx, 2

mov  esi, [FileNameBuf]

VxDCall IFSMgr_Ring0_FileIO