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

Рассмотрим более подробно, как установить хук файловой системы.

В IFS для этого существует специальный сервис – IFSMgr_InstallFileSystemApiHook (следует отметить, что внутри ядра операционной системы нет понятия «функция» (function), вместо этого применяется термин «сервис» (Service), т.е. программа (часть операционной системы), которая оказывает какие-либо услуги).

Этот сервис вызывается только с одним параметром – адресом процедуры хука файловой системы:

VxDCall IFSMgr_InstallFileSystemApiHook, <OFFSET32 FileSysApiHook>

Здесь могут возникнуть следующие замечания:

1.  При написании драйверов и вызове сервисов операционной системы возможно два способа передачи параметров вызываемому сервису:

–    через регистры общего назначения (EAX, EBX, …);

–    через стек.

При первом способе (через РОН), все необходимые параметры загружаются в соответствующие регистры процессора и осуществляется вызов сервиса, например:

mov    ebx, Handle            

mov    eax, Flags             

mov    ecx, OFFSET32 Message  

mov    edi, OFFSET32 Caption  

mov    esi, OFFSET32 Callback 

mov    edx, ReferenceData     

VxDcall SHELL_Message

В приведенном выше примере вызывается сервис, который выводит на экран компьютера окно (MessageBox), содержащее текстовую информацию. При этом в ECX загружается адрес сообщения, в EDI – заголовок сообщения, в ESI – адрес callback функции, которая будет вызвана, когда пользователь нажмет какую-либо кнопку и т.д. (Более подробное описание смотрите в DDK).

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

push   OFFSET32 FileSysApiHook

VxDCall IFSMgr_InstallFileSystemApiHook

add    esp, 4

В приведенном выше примере первая команда (push) передает параметр в стек, вторая команда (VxDCall) вызывает необходимый сервис и третья команда (add esp, 4) извлекает параметр из стека (4 – соответствует количеству байт, извлекаемых из стека; т.к. мы работаем в 32-разрядном режиме, то это – 4 байта).

Видно, что такой способ достаточно трудоемок, т.к. требует от программиста занесение параметров в стек в обратном порядке (в приведенном примере всего один параметр, поэтому порядок его занесения не имеет значения), а также правильного извлечения параметров после вызова сервиса. В связи с этим в определенный в DDK макрос позволяет автоматически передавать из извлекать параметры. Для этого вызов сервиса следует делать так:

VxDCall Имя_Сервиса, <par1, par2, ..., parn>

«Имя_сервиса» обозначает имя вызываемого сервиса, а par1 – parn - параметры. При этом макрос автоматически передаст параметры в стек в обратном порядке, а после выполнения сервиса извлечет их из стека командой add esp, 4*n, где n – число переданных параметров.

2.  На момент написания драйвера неизвестно, где он будет расположен в памяти после загрузки (т.е. в область каких линейных адресов он попадет). Поэтому в любом месте программы, когда вам необходимо сослаться на адрес должен применяться макрос OFFSET32. Этот макрос определен в DDK, и когда вы его используете, он добавляет элемент в специальную таблицу перемещения (relocation), которая используется операционной системой при загрузке драйвера в память.

Теперь вернемся к сервису установки хука файловой системы. Он имеет только один параметр, передаваемый через стек – это адрес процедуры хука. В нашем случает – это процедура «FileSysApiHook». Эта процедура вызывается каждый раз, когда в операционной системе возникает запрос к файловой системе IFS. При этом хук вызывается файловой системой и получает все параметры, необходимые для обработки запроса.

IFSMgr_InstallFileSystemApiHook возвращает адрес переменной, содержащей адрес предыдущего хука. Двойная ссылка (т.е. буквально – «адрес ячейки памяти, в которой содержится адрес старого обработчика») необходима для возможности динамической выгрузки хука далее в процессе работы системы.