Издательский дом ООО "Гейм Лэнд"СПЕЦВЫПУСК ЖУРНАЛА ХАКЕР #71, ОКТЯБРЬ 2006 г.

жонглирование ядром

ФЛЕНОВ МИХАИЛ AKA HORRIFIC

Спецвыпуск: Хакер, номер #071, стр. 071-030-3


Каждая программа должна иметь точку входа. Программисты C++ знакомы с такой точкой хорошо и привыкли, что ее имя WinMain. У драйвера такую точку называют DriverEntry, и она имеет следующий вид:

NTSTATUS STDCALL DriverEntry (

IN PDRIVER_OBJECT DriverObject,

IN PUNICODE_STRING RegistryPath)

Эта процедура получает в качестве параметра два значения:

1 PDRIVER_OBJECT — УКАЗАТЕЛЬ НА СОЗДАННЫЙ ДРАЙВЕР.

2 PUNICODE_STRING – СТРОКА, СОДЕРЖАЩАЯ РАЗДЕЛ РЕЕСТРА, ГДЕ ПРОПИСАН ДРАЙВЕР.

Конечно же, имя функции DriverEntry не является обязательным, и ты можешь ее назвать по-другому, но лучше следовать этому правилу, потому что читабельность кода никто не отменял. А вот количество и типы параметров менять вообще не желательно.

Вот так вот может выглядеть простейший драйвер на С:

#include <ntos.h>

NTSTATUS STDCALL DriverEntry (

IN PDRIVER_OBJECT DriverObject,

IN PUNICODE_STRING RegistryPath)

{

return STATUS_UNSUCCESSFUL;

}

[загрузка драйвера.]

Драйверы, как и сервисы, прописаны в реестре HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services. Здесь для каждого драйвера прописаны его параметры, и ты можешь прочитать их. Здесь же желательно сохранять параметры работы драйвера. Для хранения параметров необходимо использовать ветку реестра HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Имя\Parameters, где «Имя» – имя драйвера.

В качестве результата функция возвращает тип данных NTSTATUS. Если результат равен STATUS_SUCCESS, то драйвер считается загруженным верно и может обрабатывать ввод/вывод информации. Иначе драйвер не загружается в память и не может использоваться.

При выгрузке драйвера вызывается функция Dispatch, которая выглядит следующим образом:

NTSTATUS STDCALL Dispatch(

IN PDEVICE_OBJECT DriverObject,

IN PIRP Irp)

Если драйвер может быть выгружен во время работы системы, то необходимо реализовать еще и функцию Unload, которая должна выглядеть следующим образом:

VOID Unload (

IN DRIVER_OBJECT DeriverObject

);

Многоуровневые драйвера должны реализовывать функцию IoCompletion, в которой необходимо освобождать структуру Irp:

NTSTATUS IoCompletion (

IN PDEVICE_OBJECT DeriverObject,

IN PIRP Irp,

IN VOID Contex

);

[ввод/вывод.]

Драйвера ввода/вывода должны создавать логическое, виртуальное или физическое устройство, с которым будет происходить обмен ввода/вывода. Такое устройство создается с помощью функции IoCreateDevice. Описывать эту функцию не будем, потому что она содержит аж 7 параметров и имеет кучу особенностей. Если ты будешь писать драйвера устройств, то обратись к MSDN. Для удаления устройства используется функция IoDeleteDevice.

Создав устройство, можно создавать символическую ссылку на него с помощью функции IoCreateSymbolicLink. Если ты создашь ссылку, к примеру, с именем «xakep», драйвер будет виден в системе /device/xakep.

[приоритеты прерываний.]

Исполняемый код имеет определенный уровень прерывания IRQL (interrupt request levels), по которому определяется, что позволено делать, а что нет. Это не уровень потока, это именно уровень прерывания. Всего таких прерываний 32. Прерывание с нулевым номером обладает низшим приоритетом, а №31, соответственно, наивысшим. Наивысшим уровнем обладают прерывания устройств, эти IRQL соответствуют аппаратным прерываниям. Два низших прерывания реализованы программно.

Назад на стр. 071-030-2  Содержание  Вперед на стр. 071-030-4