EreTIk's Box » Cтатьи, исходники » Класс загрузки драйвера, расположенного в ресурсах


Часто приходится писать небольшие утилиты, которым необходима поддержка со стороны ядра. Для этого нужно писать отдельный драйвер. Но "таскать" драйвер с файлом утилиты некрасиво. Поэтому есть довольно простой способ - слинковать модуль драйвера с PE-файлом user mod'ного exe-шника.


Что бы не писать постоянно один и тот же код по распаковке модуля драйвера на носитель и его загрузке в систему я написал небольшой класс TResourceDrv. Основные особенности класса:

  • класс использует ATL-обёртки описателей
  • класс не генерирует исключений
  • класс работает с кучей по умолчанию текущего процесса

Класс содержит 2-а основных публичных метода. Метод LoadDriver:


ULONG LoadDriver(
    IN  PCWSTR wszResourceName,
    IN  PCWSTR wszResourceType,
    IN  PCWSTR wszDriverName,
    IN  DWORD dwDrvRegType = SERVICE_KERNEL_DRIVER,
    IN  DWORD dwDrvRegStart = SERVICE_DEMAND_START,
    IN  PCWSTR wszDrvRegDisplayName = NULL,
    IN  DWORD dwDrvRegErrorControl = SERVICE_ERROR_NORMAL
) throw();
                

Параметры метода:

  • wszResourceName - имя ресурса модуля драйвера
  • wszResourceType - имя типа ресурса модуля драйвера.
  • wszDriverName - короткое имя службы драйвера. Фактически это имя ключа реестра драйвера.
  • dwDrvRegType - тип драйвера. По умолчанию 1 - SERVICE_KERNEL_DRIVER.
  • dwDrvRegStart - тип запуска драйвера. По умолчанию 3 - SERVICE_DEMAND_START.
  • wszDrvRegDisplayName - отображаемое имя дравера. По умолчанию NULL.
  • dwDrvRegErrorControl - уровень контроля ошибок запуска драйвера. По умолчанию 1 - SERVICE_ERROR_NORMAL.

Возвращаемое значение:

ERROR_SUCCESS в случае, если загрузка драйвера произведена успешно. Или иной код Win32-ошибки в случае неудачи.


Данный метод извлекает модуль драйвера из ресурсов в файл. Созданный файл располагается в директории "%WINDIR%\System32\Drivers\". Далее формируется ключ драйвера в реестре, записывая указанные параметры. Если действия по формированию файла и ключа реестра драйвера завершены успешно, то метод загружает драйвер вызовом функции ntdll!NtLoadDriver(...). Перед загрузкой драйвера, если это необходимо, метод пытается разрешить текущему процессу привилегию загрузки/выгрузки драйверов SE_LOAD_DRIVER_NAME.


Второй метод - UnloadDriver:


ULONG UnloadDriver() throw();
                

Возвращаемое значение:

ERROR_SUCCESS в случае, если выгрузка драйвера произведена успешно. Или иной код Win32-ошибки в случае неудачи.

Метод выгружает драйвер, который был загружен успешным вызовом метода LoadDriver.


Updated (28.04.2011)


Класс загрузки драйвера из ресурсов был мною немного переработан до версии 0.1.1.0. В частности, в список изменений входит:

  • Интерфейс IProcessBeforeWrite был удален.
  • Работа с ntdll.dll переписана на динамический импорт.
  • Объявление нативных функций/структур обзавелись префиксом для избежания конфликта с другими файлами проекта.
  • Работа с памятью полностью переписана на ATL. Использован CAtlArray, что сохранило отсутствие генерации исключений.
  • Добавлена опция: не выгружать драйвер при уничтожении объекта.

Для задания опции, указывающей объекту класса TResourceDrv не выгружать драйвер в деструкторе, появился конструктор с bool-параметром:


TResourceDrv(
    bool bUnloadOnDestroy
) throw();
                

И отдельный метод установки опции:


void SetUnloadOnDestroy(
  __in bool bUnloadOnDestroy = true
) throw();
                

Описанный класс в исходном коде можно скачать здесь.


ΞρεΤΙκ