Filter driver что это

Обновлено: 07.07.2024

Довелось мне как-то на работе столкнуться с задачей управления доступа и перенаправления запросов к файловой системе в рамках определенных процессов. Реализовать необходимо было простое, легко конфигурируемое решение.

Решил разрабатывать MiniFilter драйвер, конфигурируемый при помощи текстового файла.

Рассмотрим, что из себя в общем виде представляет MiniFilter:

Фильтрация осуществляется через так называемый Filter Manager, который поставляется с операционной системой Windows, активируется только при загрузке мини фильтров. Filter Manager подключается напрямую к стеку файловой системы. Мини фильтры регистрируются на обработку данных по операциям ввода/вывода при помощи функционала Filter Manager, получая, таким образом, косвенный доступ к файловой системе. После регистрации и запуска мини фильтр получает набор данных по операциям ввода/вывода, которые были указаны при конфигурировании, при необходимости может вносить изменения в эти данные, таким образом влияя на работу файловой системы.



На следующей схеме в упрощенном виде показано как функционирует Filter Manager.

Более подробную теоретическую информацию Вы можете получить на сайте MSDN, воспользовавшись ссылкой в конце статьи. Достаточно не плохо все разобрано.

Мы же двинемся в сторону разработки и рассмотрим некоторые базовые структуры, которые необходимо заполнить.

Общие глобальные данные.


В этой структуре будем хранить ссылку на объект нашего драйвера и ссылку на экземпляр фильтра. Хочу заметить, что PFLT_FILTER уникально идентифицирует мини фильтр и остается константой на все время работы драйвера. Используется при активации или остановке процесса фильтрации.

  1. Callbacks – ссылка на структуру, определяющую, что и при помощи каких функций мы собираемся обрабатывать.
  2. FilterUnload – функция, которая будет вызвана при отключении фильтра.
  3. FilterLoad – функция, которая будет вызвана при инициализации фильтра.

Далее рассмотрим структуру Callbacks:


Здесь мы указываем, что будем перехватывать операцию CreateFile, также указываем функции, которые будут вызываться, соответственно, до и после выполнения операции над файлом.

Далее привожу код функций, которые вызываются при инициализации и отключении фильтра.


Думаю, код не нуждается в дополнительных комментариях, так как все достаточно стандартно. Замечу только, что наш драйвер не будет работать для сети.

Теперь давайте рассмотрим функцию инициализации драйвера:

Так же обращу внимание, что загрузка файла конфигурации и его обработка выполняется посредством следующих вызовов ConfigInfo = ReadConfigurationFile(); и ParseConfigurationFile(ConfigInfo) соответственно.

Данные из конфигурационного файла преобразуются в следующий набор структур.


Головной структурой выступает CONFIGURATION_MAP, которая хранит в себе ссылку на описание процесса ProcessRule, а так же указатель на следующий элемент. В свою очередь PROCESS_CONFIGURATION_RULE хранит ссылку на имя процесса и непосредственно на структуру правил перенаправления ввода/вывода, которая так же, как и REDIRECT_MAP является связным списком.

Рассмотрим функцию выгрузки драйвера, она достаточно проста:


Здесь мы лишь удаляем регистрацию фильтра и высвобождаем все наши конфигурационные структуры.

Теперь давайте обратимся к самой интересной части, а именно к функции, которая занимается перенаправлением операций ввода/вывода. Так как у нас достаточно простой драйвер, делать это мы будем прямо в PreFileOperationCallback.


Определяем основные переменные, а также проверим, не пришло ли нам уже что-то отфильтрованное, и если так, то эту операцию нужно пропустить, в противном случае мы можем получить рекурсию вызовов, что может повлечь BSOD.

Здесь обращаемся к данным структур полученных от FilterManager. Структура PFLT_CALLBACK_DATA – хранит данные по текущей операции ввода/вывода, FilterManager руководствуется полями этой структуры при обращении к файловой системе. Соответственно, если мы хотим изменить поведение Windows при обращении к файлам или каталогам, мы должны отразить это в PFLT_CALLBACK_DATA. Более конкретно, нас интересует поле Data->Iopb->TargetFileObject, используя его мы сможем получить путь до файла в текущем разделе и позже изменить его при необходимости, изменив таким образом поведение ОС. PCFLT_RELATED_OBJECTS — содержит объекты связанные с данной операцией ввода/вывода, такие как ссылку на файл, раздел и прочее. Проверим, что нужные нам элементы структуры заполнены. Также проверим, что функция в контексте которой мы выполняемся действительно MJ_CREATE.

В этом участке кода мы выделяем память для пути и имени процесса. Не представляю какого размера будет строка, так что выделяем максимально возможную строку WCHAR. Исходный код GetProcessImageName рассматривать не буду, скажу только, что она возвращает полный путь до файла в следующем виде: \Device\HarddiskVolume4\Windows\notepad.exe. т.е раздел, ну и собственно, путь до файла.


Функция FindRuleByProcessName в случае успеха возвращает первый элемент связанного списка содержащего правила перенаправления по текущему процессу, в противном случае NULL.

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

Далее, конфигурируем системные структуры, так чтобы File Manager еще раз обработал этот запрос, но только теперь уже по другому пути. Для этого важно проставить следующие значения полей Data->IoStatus.Information = IO_REPARSE и Data->IoStatus.Status = STATUS_REPARSE;, а так же указать новый путь до файла FileObject->FileName.Buffer = fullPath.Buffer;. В качестве результата функции возвращаем FLT_PROP_COMPLETE.


Не забываем перейти к следующему элементу списка перенаправлений. FLT_PREOP_SUCCESS_NO_CALLBACK возвращаем если делать с текущей операцией Filter Manger ничего не должен.

На данный момент переопределение ввода/вывода работает только в рамках одного раздела, как только отлажу вариант с поддержкой нескольких разделов, выложу.

Устанавливать мини фильтр необходимо при помощи специально оформленного inf файла, пример, которого Вы найдете в исходниках к данной статье.

Конфигурационный файл имеет следующий вид:

Файл должен располагаться в корне диска C, имя должно быть: minifilter.conf.

Итак мы имеем возможность перенаправления запросов файлового ввода/вывода, однако реализовать в дополнение, скажем, механизм запрета доступа к файлу достаточно просто. Необходимо выделить файл, доступ к которому нужно запретить и указать следующее значение для поля системной структуры Data->IoStatus.Status = STATUS_ACCESS_DENIED;. Не забыть вернуть FLT_PROP_COMPLETE в качестве результата функции.

Для запуска драйвера в 64 битной версии Windows 7 нужно будет отключить проверку подписи драйверов, для этого нужно перезагрузить компьютер, при старте системы нажать F8 и выбрать пункт Disable Driver Signature Enforcement, либо воспользоваться утилитой Driver Signature Enforcement Overrider(DSEO). Данная утилита позволит активировать тестовый режим отладки драйверов и подписать нужный драйвер фейковым сертификатом, что в конечном итоге позволит без проблем его использовать.


В не зависимости от того, включено логирование или нет, после запуска сервиса в DbgView Вы должны наблюдать нечто подобное.


А так наш драйвер будет выглядеть в DeviceTree

Могу добавить, что код пока еще достаточно сырой и требует доработок, однако в целом функционирует нормально. Собственно, если у Вас будет BSOD, я не виноват). Тестировал только на Windows 7 X86 и Windows 7 IA64.

Вообще установил семерку, У меня ноут Asus k52Dr
теперь надо установить с диска Асуса все драйвера, разные утилиты и т. д.
Скажите пажалуйста добрые люди, что какая программа значит, просто не хочу устанавливать лишнее!

AMD UMA
AMD NB Filter Driver
AMD USB Filter
AMD AHCI Driver
Audio With SRS
Multi Card Reader
Wirelees LAN Driver
ATK Package
Power4Gear Hybrid
Life Frame 3
Asus SmartLogon
Asus Wirelees Console3
Splendid
MultiFrame
eManual Utility
ADSM

1) Uniform Memory Access==Драйвер чипсета.

2) Драйвер для северного моста |NB= North Bridge|

3)Драйвер контроллера USB 2.0

4)Драйвер AHCI |Режим работы Sata контроллера+Он самый быстрый по идее ИМХО

5) Драйвер Интегрированой сетевой карты.

6) Драйвер для Карт ридера.

7) Драйвер для WiFi Карты.

8)Пакет ATK утилит . а) ATK0100 ACPI UTILITY или ATKDrv Driver= Утилита обеспечивает работу функций ACPI компьютера (отвечает за работу всех устройств ноутбука) (с)
ATK_Hotkey Driver
Обеспечивает работу почти всех дополнительных кнопок ноутбука. (с)
9)Имхо средство для управления энэргопотреблением.

10)Life Frame Utility
Программа, позволяющая производить запись видео со встроенной камеры, делать фотографии и производить небольшие коррекции изображения с помощью прилагаемых шаблонов. (с)

11)SmartLogon Utility
Идентификации пользователей с помощью веб-камеры. (с)

12)Wireless Console Utility = Утилита по управлению модулями Bluetooth и Wi-Fi(c)

Технология ASUS Splendid Video Enhancement это инновационная технология, переводящая качество видео на ноутбуке на новый уровень.

Splendid улучшает изображение, приходит в действие при запуске видео приложений и автоматически оптимизирует качество изображения.

Splendid Video Enhancement заметно увеличивает глубину и интенсивность цветов в реальном времени. Усовершенствованный алгоритм обработки элементов изображения позволяет контролировать качество картинки на отдельных участках. В каждой точке экрана производится оптимальная для человеческого глаза настройка цветов.

Использование Splendid особенно эффективно в корректировке оттенков цвета кожи, зеленых тонов травы, деревьев и голубых тонов неба и моря. Новая технология не только улучшает цветопередачу, но и обеспечивает более детальное изображение по сравнению с подобными решениями. Так же, как человеческий глаз, технология Splendid увеличивает уровень яркости на темных участках изображения, позволяя увидеть все в мельчайших подробностях. (c)

14)MultiFrame Utility
Добавляет ко всем системным окошкам кнопку рядом с тремя стандартными (свернуть, на весь экран, закрыть) . Автоматизированное позиционирование окон Windows.(c)

15)eManual Utility - руководство по использованию ноутбука

16)ADSM= ASUS Data Security Manager Utility

Программа для шифрования данных, позволяет создавать на компьютере «невидимые» для посторонних глаз директории. (c)

Когда передо мной встала задача написать свой драйвер, осуществляющий мониторинг операций в реестре, я, конечно же, полезла искать на просторах интернета хоть какую-то информацию по этому поводу. Но единственное, что вылезало по запросу «Драйвер-фильтр реестра» — поток статей по написанию драйвера-фильтра (ура), НО все эти статьи касались только фильтра файловой системы (печаль).

К сожалению, единственное, что удалось найти — статью 2003 года, код из которой вы никогда не соберете в своей новенькой VS19.

К счастью же, есть прекрасный пример от Microsoft на GitHub (сразу кидаю ссылочку), на котором и будет строиться бОльшая часть этого разбора.

Возможно, суперпрограммистам хватит и ссылки на пример, чтобы за 5 минут во всем разобраться. Но есть и новички, студенты, как я, для которых, скорее всего, и будет данная статья. Надеюсь, кому-то это действительно поможет.

Окей. Погнали. Открываем примерчик. Внимание! Не пугаемся большого количества файлов, 80% нам не понадобится.

Мы видим в проекте 2 папки: exe и sys. В первой находится программа, запускающая драйвер, регистрирующая его в системе, а по завершению работы с драйвером, удаляющая его. С нее и начнем.

Здесь и находится практически весь необходимый нам код программы.

Сразу идем к функции wmain. Что мы там видим? Загрузка драйвера функцией UtilLoadDriver(util.c), а затем указания по некоторым настройкам:

Далее мы видим 2 функции: DoKernelModeSamples и DoUserModeSamples — они нужны для демонстрации работы драйвера. Вот первая, например, отправляет драйверу IOCL запрос функцией DeviceIoControl, драйвер в свою очередь по второму параметру IOCTL_DO_KERNELMODE_SAMPLES запустит необходимые функции.

Из описания функции DeviceIoControl мы видим, что она может передавать драйверу буфер и также принимать его. Это нам понадобится в дальнейшем. А пока в этом файле ничего любопытного для нас нет.

Перейдем в папку sys, файл driver.c

Начнем с функции DriverEntry. Там драйвер выводит какую-то отладочную информацию, затем функцией IoCreateDeviceSecure создает именованный объект устройства и применяет указанные параметры безопасности, интересный же кусочек ждет нас дальше:


В скобках заключены основные коды функций для IRP. То есть это те типы пакетов, которые будут удостаиваться внимания нашего драйвера. После знака " plaintext">IrpStack = IoGetCurrentIrpStackLocation(Irp); Ioctl = IrpStack->Parameters.DeviceIoControl.IoControlCode;


Основываясь на IoControlCode, драйвер отправится выполнять ту или иную функцию. Советую для понимания рассмотреть, например, файл pre.c и разобраться, что там происходит.

И закончим рассмотрение примера последним важным моментом — конечно же, функция Callback.

Сюда и будут прилетать извещения об операциях, происходящих в реестре. Помните место, которое я просила запомнить? Оно чуть выше. Вот там бы нам оставить CmRegisterCallbackEx. Они и будет объявлять функцию Callback как «мешок», в который полетят IRP пакеты на обработку. CallbackCtx->Altitude будет определять уровень нашего драйвера (мы же не одни следим за реестром), то есть на какой высоте наш драйвер будет перехватывать пакеты и что-то с ними делать (Опять же в pre.c довольно понятно, что и как происходит: Регистрируем функцию, что-то делаем с реестром, все фиксируется, выводится информация драйвером и затем делаем обратное действие — CmUnRegisterCallback — чтобы нам больше ничего не прилетало).

Собственно, из аргументов функции CallBack можно извлечь всю необходимую информацию — и операцию, совершаемую над каким-то ключом (это как раз есть в коде — NotifyClass), и имя ключа

А теперь отойдем от данного примера. Рассмотрим, что можно интересного сделать.

Такая задачка: пусть у нас в каком-то файле перечислены названия программ и ключей реестра, там же мы прописываем права доступа программы к определенному ключу (ограничимся простым: имеет/не имеет доступ).

Наша программа (та, что в папке exe) будет считывать конфигурацию и отправлять драйверу с помощью IOCL запроса. То есть в функции DeviceIoControl в качестве третьего аргумента и будем передавать буфер. Передавать и оформлять конфигурацию можно, как вам удобно.


Теперь попробуем запретить какой-нибудь программе доступ к ключу
Идем в функцию Callback.

Давайте обозначим имя нашей программы и ключа, к которой у нее нет доступа соответственно MyProg и MyKey.

Нам необходимо узнать, какая программа в данный момент попыталась обратиться к ключу и сравнить ее название с теми, которые у нас прописаны в конфигурации. Имя процесса можно получить таким образом:


Функция GetProcessImageName не библиотечная (а интернечная), ее различные вариации можно встретить на многих форумах. Оставлю ее здесь:


Мы обнаружили, что сейчас именно MyProg обращается к реестру. Теперь необходимо узнать, к какому ключу.

Из второго аргумента вынимаем информацию о ключе, к которому производится доступ


Просто возвращаем значение, указывающее на запрет. И все.

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

Это, так скажем, ввод в курс дела :) Так как именно его обычно очень не хватает, когда только начинаешь разбираться.

Довелось мне как-то на работе столкнуться с задачей управления доступа и перенаправления запросов к файловой системе в рамках определенных процессов. Реализовать необходимо было простое, легко конфигурируемое решение.

Решил разрабатывать MiniFilter драйвер, конфигурируемый при помощи текстового файла.

Рассмотрим, что из себя в общем виде представляет MiniFilter:

Фильтрация осуществляется через так называемый Filter Manager, который поставляется с операционной системой Windows, активируется только при загрузке мини фильтров. Filter Manager подключается напрямую к стеку файловой системы. Мини фильтры регистрируются на обработку данных по операциям ввода/вывода при помощи функционала Filter Manager, получая, таким образом, косвенный доступ к файловой системе. После регистрации и запуска мини фильтр получает набор данных по операциям ввода/вывода, которые были указаны при конфигурировании, при необходимости может вносить изменения в эти данные, таким образом влияя на работу файловой системы.



На следующей схеме в упрощенном виде показано как функционирует Filter Manager.

Более подробную теоретическую информацию Вы можете получить на сайте MSDN, воспользовавшись ссылкой в конце статьи. Достаточно не плохо все разобрано.

Мы же двинемся в сторону разработки и рассмотрим некоторые базовые структуры, которые необходимо заполнить.

Общие глобальные данные.


В этой структуре будем хранить ссылку на объект нашего драйвера и ссылку на экземпляр фильтра. Хочу заметить, что PFLT_FILTER уникально идентифицирует мини фильтр и остается константой на все время работы драйвера. Используется при активации или остановке процесса фильтрации.

  1. Callbacks – ссылка на структуру, определяющую, что и при помощи каких функций мы собираемся обрабатывать.
  2. FilterUnload – функция, которая будет вызвана при отключении фильтра.
  3. FilterLoad – функция, которая будет вызвана при инициализации фильтра.

Далее рассмотрим структуру Callbacks:


Здесь мы указываем, что будем перехватывать операцию CreateFile, также указываем функции, которые будут вызываться, соответственно, до и после выполнения операции над файлом.

Далее привожу код функций, которые вызываются при инициализации и отключении фильтра.


Думаю, код не нуждается в дополнительных комментариях, так как все достаточно стандартно. Замечу только, что наш драйвер не будет работать для сети.

Теперь давайте рассмотрим функцию инициализации драйвера:

Так же обращу внимание, что загрузка файла конфигурации и его обработка выполняется посредством следующих вызовов ConfigInfo = ReadConfigurationFile(); и ParseConfigurationFile(ConfigInfo) соответственно.

Данные из конфигурационного файла преобразуются в следующий набор структур.


Головной структурой выступает CONFIGURATION_MAP, которая хранит в себе ссылку на описание процесса ProcessRule, а так же указатель на следующий элемент. В свою очередь PROCESS_CONFIGURATION_RULE хранит ссылку на имя процесса и непосредственно на структуру правил перенаправления ввода/вывода, которая так же, как и REDIRECT_MAP является связным списком.

Рассмотрим функцию выгрузки драйвера, она достаточно проста:


Здесь мы лишь удаляем регистрацию фильтра и высвобождаем все наши конфигурационные структуры.

Теперь давайте обратимся к самой интересной части, а именно к функции, которая занимается перенаправлением операций ввода/вывода. Так как у нас достаточно простой драйвер, делать это мы будем прямо в PreFileOperationCallback.


Определяем основные переменные, а также проверим, не пришло ли нам уже что-то отфильтрованное, и если так, то эту операцию нужно пропустить, в противном случае мы можем получить рекурсию вызовов, что может повлечь BSOD.

Здесь обращаемся к данным структур полученных от FilterManager. Структура PFLT_CALLBACK_DATA – хранит данные по текущей операции ввода/вывода, FilterManager руководствуется полями этой структуры при обращении к файловой системе. Соответственно, если мы хотим изменить поведение Windows при обращении к файлам или каталогам, мы должны отразить это в PFLT_CALLBACK_DATA. Более конкретно, нас интересует поле Data->Iopb->TargetFileObject, используя его мы сможем получить путь до файла в текущем разделе и позже изменить его при необходимости, изменив таким образом поведение ОС. PCFLT_RELATED_OBJECTS — содержит объекты связанные с данной операцией ввода/вывода, такие как ссылку на файл, раздел и прочее. Проверим, что нужные нам элементы структуры заполнены. Также проверим, что функция в контексте которой мы выполняемся действительно MJ_CREATE.

В этом участке кода мы выделяем память для пути и имени процесса. Не представляю какого размера будет строка, так что выделяем максимально возможную строку WCHAR. Исходный код GetProcessImageName рассматривать не буду, скажу только, что она возвращает полный путь до файла в следующем виде: \Device\HarddiskVolume4\Windows\notepad.exe. т.е раздел, ну и собственно, путь до файла.


Функция FindRuleByProcessName в случае успеха возвращает первый элемент связанного списка содержащего правила перенаправления по текущему процессу, в противном случае NULL.

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

Далее, конфигурируем системные структуры, так чтобы File Manager еще раз обработал этот запрос, но только теперь уже по другому пути. Для этого важно проставить следующие значения полей Data->IoStatus.Information = IO_REPARSE и Data->IoStatus.Status = STATUS_REPARSE;, а так же указать новый путь до файла FileObject->FileName.Buffer = fullPath.Buffer;. В качестве результата функции возвращаем FLT_PROP_COMPLETE.


Не забываем перейти к следующему элементу списка перенаправлений. FLT_PREOP_SUCCESS_NO_CALLBACK возвращаем если делать с текущей операцией Filter Manger ничего не должен.

На данный момент переопределение ввода/вывода работает только в рамках одного раздела, как только отлажу вариант с поддержкой нескольких разделов, выложу.

Устанавливать мини фильтр необходимо при помощи специально оформленного inf файла, пример, которого Вы найдете в исходниках к данной статье.

Конфигурационный файл имеет следующий вид:

Файл должен располагаться в корне диска C, имя должно быть: minifilter.conf.

Итак мы имеем возможность перенаправления запросов файлового ввода/вывода, однако реализовать в дополнение, скажем, механизм запрета доступа к файлу достаточно просто. Необходимо выделить файл, доступ к которому нужно запретить и указать следующее значение для поля системной структуры Data->IoStatus.Status = STATUS_ACCESS_DENIED;. Не забыть вернуть FLT_PROP_COMPLETE в качестве результата функции.

Для запуска драйвера в 64 битной версии Windows 7 нужно будет отключить проверку подписи драйверов, для этого нужно перезагрузить компьютер, при старте системы нажать F8 и выбрать пункт Disable Driver Signature Enforcement, либо воспользоваться утилитой Driver Signature Enforcement Overrider(DSEO). Данная утилита позволит активировать тестовый режим отладки драйверов и подписать нужный драйвер фейковым сертификатом, что в конечном итоге позволит без проблем его использовать.


В не зависимости от того, включено логирование или нет, после запуска сервиса в DbgView Вы должны наблюдать нечто подобное.


А так наш драйвер будет выглядеть в DeviceTree

Могу добавить, что код пока еще достаточно сырой и требует доработок, однако в целом функционирует нормально. Собственно, если у Вас будет BSOD, я не виноват). Тестировал только на Windows 7 X86 и Windows 7 IA64.

Читайте также: