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

Всегда, когда драйверу посылается это сообщение, регистр ESI процессора содержит адрес структуры «DIOCParams», в которой передаются дополнительные параметры сообщения, в частности код операции, которую должен выполнить драйвер. Следует забежать вперед и сказать, что Windows-приложение может принудительно передать драйверу какую-либо команду посредством вызова функции «DeviceIoControl», при этом драйверу будет передано то же сообщение («W32_DeviceIoControl»).

Итак, при загрузке драйверу приходит сообщение «W32_DeviceIoControl», при этом регистр ESI указывает на структуру «DIOCParams», в которой член «dwIoControlCode» установлен в значение «DIOC_OPEN». Если драйвер поддерживает динамическую загрузку, он обязательно должен вернуть ноль в ответ на это сообщение (возврат осуществляется в регистре EAX), например:

BeginProc OnDeviceIoControl

cmp  [esi + DIOCParams.dwIoControlCode],DIOC_Open

jne  @@m1      

;инициализационное сообщение – вернем 0

xor  eax,eax

ret

@@m1:

;обработка каких-либо других сообщений

...

;такое сообщение драйвер обработать не может

mov  eax,1

stc

ret

EndProc   OnDeviceIoControl

Если драйвер в ответ на «DIOC_OPEN» не вернет ноль, система решит, что он не поддерживает динамическую загрузку, выгрузит его из памяти и сообщит об ошибки открытия драйвера открывающему приложению.

Также, при обработке сообщения «W32_DeviceIoControl» и правильного (допустимого) кода операции (поле «dwIoControlCode» в передаваемой структуре «DIOCParams») драйвер также должен вернуть 0.

Если же запрашиваемая операция не поддерживается драйвером, выполнена с ошибкой или не может быть выполнена сейчас, драйвер должен вернуть значение, отличное от нуля и установить флаг переноса (C, Carry) командой STC (см. пример выше).

Функция DeviceIoControl Windows API предназначена специально для взаимодействия обычного Win приложения, работающего на 3-м кольце защиты с драйвером, работающем на 0-м кольце. Она позволяет передать драйверу код команды для выполнения (поле «dwIoControlCode» структуры «DIOCParams»), а также входной и выходной буфера для данных. Более подробную информацию можно получить в MSDN (см. описание функции DeviceIoControl).

Обратное взаимодействие (т.е. взаимодействие драйвера с Win-программой) затруднительно. Для 16-разрядного приложения существуют сервисы «Simulate_Int», «Simulate_Iret» и др., которые позволяют драйверу выполнять какой-либо 16-разрядный код внутри виртуальной машины.

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

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

После обработки приложением сообщения, в драйвере может быть вызвана так называемая callback-функция, т.е. функция, которую вызывает VMM. Этой функции будет передан результат обработки сообщения win-32 программой.

Средства Windows, используемые при создании антивирусного монитора

Итак, теперь перейдем конкретно к вопросу создания антивирусного монитора. Как было рассмотрено ранее, для этого было решено создать драйвер, встраивающийся в ядро операционной системы (VMM) и обрабатывающий все запросы открытия файла.

Каким образом это можно реализовать?

К счастью, для этого не придется использовать какие-либо «хакерские» принципы или применять методы, лежащие в основе вирусов. Ядро ОС Windows построено так, что позволяет загружаемым драйверам заменять практические любые функции ОС на свои собственные. Также обстоит дело и с файловой системой IFS (Installable File System) – для этого необходимо написать процедуру-хук (hook), которая будет вызываться всегда, когда какая-либо часть или программа операционной системы произведет обращение к файлам (точнее – к файловой системе). Основное назначение таких хуков – антивирусная защита (т.е. то, что мы сейчас делаем), кодировании/раскодирования файлов «на лету» (для обеспечения информационной безопасности), добавление своих файловых ресурсов и некоторые другие.