@@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
Уважаемый посетитель!
Чтобы распечатать файл, скачайте его (в формате Word).
Ссылка на скачивание - внизу страницы.