Анализ различных способов наблюдения за событиями, связанными с файловой системой в ОС Windows NT/20

Соколов Е.В.
20.05.2005 | 14:06

Наблюдение за действиями программ и компонентов операционной системы рабочего места является одним из важных компонентов системы безопасности информационной системы. В ОС Windows NT существует несколько способов наблюдения. Во-первых, это штатная подсистема аудита, использование которой - наиболее простой путь для сбора информации о о действиях пользователей и формирования оценок. Однако штатные средства не всегда могут быть использованы как составная часть системы безопасности. Достоинства такого метода - простота механизмов сбора (нет необходимости в написании драйверов низкого уровня), настраиваемость системы аудита на конкретные события и информационные объекты (можно обойтись без написания фильтров событий). Недостатками встроенной подсистемы сбора аудита является проблемы с централизованной обработкой аудита от большого числа компьютеров, большое количество типов событий, недостаточно полная информация о работе с объектами, находящимися на других компьютерах домена, сложность механизмов перекодировки и анализа событий штатного аудита. Кроме этого, с помощью штатной системы аудита нельзя следить за пользователями, обладающими административными правами на автоматизированном рабочем месте т.к. штатный аудит сохраняется в файл Event Log, который в любой момент может быть удален или очищен администратором. Из-за этого часто возникает необходимость средства сбора аудита собственной разработки. При разработке систем сбора аудита приходится сталкиваться с проблемой формирования событий аудита от файловой системы т.к. получение доступа к файлам зачастую является одной из целей атаки на информационную систему.
В ОС Windows NT/2000 существует несколько принципиально различных методов сбора событий, связанных с файловой системой.

Способ 1: Штатные средства перехвата обращений к файловой системе.

В операционной системе Windows NT штатной функции для перехвата файловой системы нет. В этой OC существует единственный механизм перехвата обращения к файлам - это перехват запроса к драйверу файловой системы функцией IoAttachDeviceByPointer.
При данном методе перехвата перехват осуществляет драйвер режима ядра, который пишется по образцу драйвера файловой системы. Перехват должен производиться для каждого логического устройства файловой системы, соответствующего смонтированному тому. Например, в нашей системе есть один дисковод (A:), два диска с файловой системой FAT(C: и D:), один диск NTFS (E:) и один привод CD-ROM (X:) при этом перехватываться будут пять устройств из трех драйверов (Fastfat.sys, Ntfs.sys, Cdfs.sys). Схема перехвата показана на рис 1. Ситуация осложняется тем, что объекты устройств, соответствующие файловым системам дисковода, привода CD-ROM, ZIP-накопителей, сетевых дисков создаются драйверами файловых систем в момент монтирования тома, то есть при первом обращении к дискете, компакт-диску, сетевому ресурсу. При этом производятся недокументированные запросы к драйверам физического устройства, заставляющие драйвер файловой системы читать начальную запись тома, определять тип файловой системы и создать новый объект-устройство для драйвера данной файловой системы. При успешном создании объекта к новому устройству можно обращаться - давать запросы открытия файла, чтения, записи, переименования и т.д. Типов запросов к драйверу около 20 штук. Все они должны передаваться перехватывающим драйвером на перехватываемый. Для сбора аудита необходимо выполнять обработку как минимум, запросов IRP_MJ_CREATE, IRP_MJ_CLEANUP, IRP_MJ_CLOSE, IRP_MJ_READ, IRP_MJ_WRITE, IRP_MJ_SET_INFORMATION. Кроме этого обрабатываются запросы FastIoDispatch, отвечающие за обработку функции DeviceIoControl, и операции закрытия, чтения и записи в устройство.

Рис. 1. Схема передачи запросов к файловой системе в ОС Windows NT/2000.

Для сбора аудита также важен результат завершения операции работы с файлом. Он возвращается в поле NtStatus запроса после его выполнения. Поэтому при написании драйвера перехвата приходится обеспечивать возможность перехвата завершения обработки запроса. Так как запросы к ядру и драйверам ОС Windows NT/2000 являются асинхронными, и простой перехват конца запроса (см. листинг 1) невозможен.

Листинг 1.Мнемокод перехвата синхронного вызова.

Для перехвата завершения запроса в ядре Windows NT существует функция IoSetCompletionRoutine. Параметрами функции являются адрес обработки возврата запроса и статус, при котором вызывать данный обработчик (Нормальное завершение, ошибка).
Мнемокод обработки асинхронного запроса представлен на листинге 3.

Листинг 2. Мнемокод перехвата асинхронного вызова.

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

Способ 2: Перехват системных вызовов.

Альтернативным методом сбора информации об обращениях к объектам является перехват системных вызовов ОС Windows NT/2000.
Обращение к системным вызовам ядра ОС производится через интерфейс прерывания Int2E.
На листинге 3 приведен код функции NtCreateFile:

Листинг 3.Код функции NtCreateFile (Windows NT 4.0).

Как мы видим, в регистре EAX передается номер функции, уникальный для каждого системного вызова, в регистре EDX - указатель на блок параметров, описанный для данной функции в документации. После этого производится вызов прерывания 2E, которое в регистре EAX возвращает код ошибки вызова.
Внутри ядра есть функция ntoskrnl!ZwCreateFile с теми же параметрами, которая производит обработку этого прерывания - собственно открытие файла.
Обработчик прерывания 2E проверяет номер вызова в регистре AX, в случае соответствия номера (номер должен быть меньше максимального номера вызова) производится извлечение адреса обработчика функции из таблицы, расположение параметров в стеке, вызов обработчика. (см рис 2.)s

Рис. 2. Схема обработки системных вызовов в ОС Windows NT/2000.

Все адреса обработчиков находятся в таблице. Базовай адрес таблицы экспортоуется под именем KeServiceDescriptorTable и может быть прочитан драйвером. Так как системные вызовы являются синхронными, то обработку можно производить как указано в листинге 1. При этом часть аудита, соответствующая одному системному вызову находится в локальной переменной нашего обработчика и не требуется никаких специальных ухищрений для хранения не до конца собранного события в процессе обработки.

Рис. 3. Схема перехвата системного вызова.

Однако при данном методе перехвата возникает серьёзная проблема: в различных версиях ОС семейства NT одни и те же функции имеют разные номера системных вызовов. Например в ОСWindows NT 4.0 Функция CreateFile Имеет номер 0x17,а в Windows 2000 она имеет номер 0x20. Можно предложить несколько различных вариантов решения этой проблемы:
  1. хранение номеров системных вызовов в таблицах для каждой версии ОС. В этом случае мы ограничиваем область применения драйвера несколькими версиями операционной системы и несколькими системными вызовами.
  2. написание кода, анализирующего, какое значение будет находится в регистре EAX при вызове прерывания. Так как все экспортируемые функции библиотеки системных вызовов построены по одному принципу (см. листинг 3), то написание такого кода для известных мне версий Windows NT не вызывает затруднений. Однако следует помнить, что принцип написания библиотеки системных вызовов ntdll может измениться в последующих версиях Windows NT.

ЛИТЕРАТУРА:

  1. Фролов А. В., Фролов Г. В. Программирование для Windows NT. - М.: ДИАЛОГ-МИФИ, 1996.
  2. Коберниченко А.В. Недокументированные возможности Windows NT. - М.: Издательство "Нолидж", 1998.
  3. А.Нортон Написание драйверов для Windows 3.11 - М, 1995.
  4. http://www.sysinternals.com/, исходные тексты программы filemon.
  5. http://www.sysinternals.com/, исходные тексты программы tokenmon.