Меню Рубрики

Windows nt device driver development pdf

/DRIVER (драйвер режима ядра Windows NT) /DRIVER (Windows NT Kernel Mode Driver)

/DRIVER [: ТОЛЬКО ИСТЕЧЕНИЕ |: WDM] /DRIVER[:UPONLY |:WDM]

Комментарии Remarks

Используйте параметр компоновщика /Driver для создания драйвера режима ядра Windows NT. Use the /DRIVER linker option to build a Windows NT kernel mode driver.

/Driver: только в случае, когда компоновщик добавляет IMAGE_FILE_UP_SYSTEM_ONLY бит к характеристикам в заголовке Output, чтобы указать, что это драйвер однопроцессорного (up). /DRIVER:UPONLY causes the linker to add the IMAGE_FILE_UP_SYSTEM_ONLY bit to the characteristics in the output header to specify that it is a uniprocessor (UP) driver. Операционная система отказывается загружать драйвер в многопроцессорной системе (MP). The operating system will refuse to load a UP driver on a multiprocessor (MP) system.

/Driver: WDM заставляет компоновщик установить IMAGE_DLLCHARACTERISTICS_WDM_DRIVER бит в поле DLLCHARACTERISTICS необязательного заголовка. /DRIVER:WDM causes the linker to set the IMAGE_DLLCHARACTERISTICS_WDM_DRIVER bit in the optional header’s DllCharacteristics field.

Если параметр /Driver не указан, то эти биты не устанавливаются компоновщиком. If /DRIVER is not specified, these bits are not set by the linker.

Если задано значение /Driver : If /DRIVER is specified:

/Fixed: нет действующих. /FIXED:NO is in effect. Дополнительные сведения см. в разделе /fixed (фиксированный базовый адрес). For more information, see /FIXED (Fixed Base Address).

Расширение выходного файла имеет значение. sys. The extension of the output file is set to .sys. Используйте параметр /out для изменения имени файла и расширения по умолчанию. Use /OUT to change the default filename and extension. Дополнительные сведения см. в разделе /out (имя выходного файла). For more information, see /OUT (Output File Name).

Задание данного параметра компоновщика в среде разработки Visual Studio To set this linker option in the Visual Studio development environment

Откройте диалоговое окно Страницы свойств проекта. Open the project’s Property Pages dialog box. Подробнее см. в статье Настройка компилятора C++ и свойства сборки в Visual Studio. For details, see Set C++ compiler and build properties in Visual Studio.

Выберите папку компоновщика. Click the Linker folder.

Перейдите на страницу свойств системы . Click the System property page.

Измените свойство Driver . Modify the Driver property.

Источник

Простейший WDM-драйвер

В данной статье описан процесс написания простейшего драйвера, который выводит скан-коды нажатых клавиш.
Также в данной статье описан процесс настройки рабочего места для написания драйверов.
Если Вам интересно, прошу под кат.

Подготовка стенда

Установка необходимого ПО для написания простейшего драйвера

Необходимое ПО:

  1. Windows DDK (Driver Development Kit);
  2. VMware Workstation или Virtual Box;
  3. Windows XP;
  4. Visual Studio 2005;
  5. DDKWizard;
  6. KmdManager
  7. DebugView;

Я использую две виртуальные машины, пишу драйверы на одной, а запускаю на другой. Если вы тоже решите так делать то для той машины, на которой вы будете запускать драйверы, хватит 4 Гбайтового жесткого диска и 256 Мбайт оперативной памяти.

Настройка рабочего места
Установка DDK

Установка предельно проста. Единственное на что необходимо обратить внимание — это диалог, в котором Вам предлагается выбрать компоненты, которые будут установлены. Настоятельно рекомендую отметить всю документацию и примеры.

Установка и настройка Microsoft® Visual Studio 2005

Установка Microsoft® Visual Studio 2005 ничем не сложнее установки DDK. Если Вы будете использовать её только для написания драйверов, то когда инсталлятор спросит какие компоненты необходимо установить, выберите только Visual C++.
Далее можно установить Visual Assist X. С помощью этой программы (аддона) можно будет легко настроить подсказки для удобного написания драйверов.
После установки Visual Assist X в Visual Studio 2005 появится новое меню VAssistX. Далее в этом меню: Visual Assist X Options -> Projects -> C/C++ Directories -> Platform: Custom, Show Directories for: Stable include files . Нажимаем Ins или на иконку добавить новую директорию и в появившейся строке, если у вас Windows XP вписываем %WXPBASE%\inc\ddk\wxp .

Установка и настройка DDKWizard

Для того чтобы в Visual Studio можно было компилировать драйверы нужно установить DDKWizard. Его можно скачать с сайта ddkwizard.assarbad.net. Также с этого сайта скачайте скрипт ddkbuild.cmd.
После того как мастер установится необходимо выполнить следующие шаги:

  • Создать системные (рекомендуется) или пользовательские переменные со следующими именами и значением, которое соответствует пути к DDK
    Версия DDK Имя переменной Путь по умолчанию
    Windows XP DDK WXPBASE C:\WINDDK\2600
    Windows 2003 Server DDK WNETBASE C:\WINDDK\3790.1830
    Windows Vista/Windows 2008 Server WDK WLHBASE
    Windows 7/Windows 2008 Server R2 WDK W7BASE

    Например, если я использую Windows XP DDK, то я должен создать переменную WXPBASE со значением, которое соответствует пути к DDK. Так как я не изменял путь установки, то значение у меня будет C:\WINDDK\2600.

  • Скопируйте скачанный скрипт ddkbuild.cmd, например, в папку с DDK. У меня это C:\WINDDK\.
  • Добавьте в конец системной переменной Path путь к скрипту ddkbuild.cmd.

Всё, машина, на которой будем запускать драйверы, готова.

Установка необходимого ПО для запуска драйверов

Теперь настроим машину, на которой будем запускать написанные драйверы.
Нам потребуются следющие программы:

  • DebugView (link) — это утилитка, которая позволяет просматривать отладочный вывод как режима пользователя так и режима ядра.
  • KmdManager (link) — утилита динамической загрузки/выгрузки драйверов

Всё, машина готова для запуска драйверов.

Постановка задачи

Задача: написать драйвер, который будет выводить в дебаг скан-коды нажатых клавиш и их комбинаций.

Немного теории

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

  • драйверы классов;
  • минидрайверы;
  • функциональные драйверы;
  • фильтрующие драйверы.

Драйверы классов — это драйверы, котрые пишет Microsoft. Это общие драйвера для определенного класса (неужели!) устройств.
Минидрайверы — драйверы, которые используеют драйвер класса для управления устройством.
Функциональные драйверы — это драйверы, которые работают самостоятельно и определяет все что связано с устройством.
Фильтрующие драйверы — драйверы, которые используются для мониторинга или изменения логики другого драйвера путем изменения данных, которые идут к нему.

Необязательно определять все возожные функции в своем драйвере, но он обязательно должен содержать DriverEntry и AddDevice .

IRP — это структура, которая используется драйверами для обмена данными.

Итак, для того чтобы выводить скан-коды (что это?) в дебаг, будем использовать фильтрующий драйвер.
Существует два типа фильтрующих драйверов:

  • верхние фильтрующие драйверы;
  • нижние фильтрующие драйверы.

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

Отличия между верхними и нижними фильтрующими драйверами

Через верхние фильтрующие драйверы проходят все запросы, а это значит, что они могут изменять и/или фильтровать информацию, идущую к функциональному драйверу, ну и далее, возможно, к устройству.
Пример использования верхних фильтрующих драйверов:
Фильтр-хук драйвер, который устанавливает свою хук-функцию для системного драйвера IpFilterDirver, для отслеживания и фильтрации траффика. Такие драйверы используются в брандмауэрах.

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

Проблемы синхронизации

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

Префикс lock позволяет безопасно выполнить идущую за ним команду. Она блокирует остальные процессоры, пока выполняется команда.

Экшен

Для начала необходимо включить заголовочные файлы «ntddk.h», «ntddkbd.h»

Также необходимо описать структуру DEVICE_EXTENSION

Объект pLowerDO это объект устройства, который находится ниже нас в стеке. Он нужен нам для того чтобы знать кому дальше отправлять IRP-пакеты.
Еще для работы нашего драйвера нам нужна переменная, в которой будет храниться количество не завершенных запросов.

Начнем с функции, которая является главной точкой входа нашего драйвера.

theDriverObject – объект драйвера, содержит указатели на все необходимые операционной системе функции, которые мы должны будем инициализировать.
ustrRegistryPath – имя раздела в реестре, где хранится информация о данном драйвере.
Для начала необходимо объявить и обнулить переменные:

Далее, как я и писал выше, нужно инициализировать указатели на функции

Функция DispatchRead будет обрабатывать запросы на чтение. Она будет вызываться, когда нажата или отпущена клавиша клавиатуры.
Функция DriverUnload вызывается, когда драйвер уже не нужен и его можно выгрузить из памяти, или когда пользователь сам выгружает драйвер. В данной функции должна производиться «зачистка», т.е. освобождаться ресурсы, которые использовались драйвером, завершаться все незавершенные запросы и т.д.
Функция DispatchThru это функция-заглушка. Все что она делает это передача IRP-пакета следующему драйверу (драйверу который находится под нашим в стеке, т.е. pLowerDO из DEVICE_EXTENSION ).
Далее мы вызываем нашу функцию, для создания и установки нашего устройства в стек устройств:

Эту функцию я опишу чуть ниже.
Возвращаем status , в котором, если функция InstallFilter завершилась удачей, хранится значение STATUS_SUCCESS .
Переходим к функции InstallFilter . Вот её прототип:

Эта функция создает объект устройства, настраивает его и включает в стек устройств поверх \\Device\\KeyboardClass0

pKeyboardDevice – это объект устройсва, которое мы должны создать.
Вызываем IoCreateDevice для создания нового устройства

Разберем подробнее параметры:

  • Первый аргумент это объект драйвера, который мы получили как параметр функции InstallFilter. Он передается в IoCreateDevice для того чтобы установить связь между нашим драйвером и новым устройством.
  • Третий параметр это имя устройства
  • Четвертый параметр это тип устройства
  • Пятый параметр это флаги, которые обычно устанавливаются для запоминающих устройств.
  • Шестой параметр описывает можно ли открывать манипуляторы устройства в количестве больше одного. Если FALSE можно открыть только один манипулятор. Иначе можно открыть любое количество манипуляторов.
  • Седьмой параметр это память, в которой будем сохранен созданный объект устройства.

Далее устанавливаем флаги устройства.

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

Функция IoAttachDevice внедряет наше устройство в стек. В pdx->pLowerDO будет храниться объект следующего (нижнего) устройства.

Далее разберем функцию DispatchRead с прототипом:

Данная функция будет вызываться операционной системой при нажатии или отпускании клавиши клавиатуры
Увеличиваем счетчик незавершенных запросов

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

где ReadCompletionRoutine наша функция.
Передаем IRP следующему драйверу:

Теперь разберем функцию, которая будет вызываться каждый раз при завершении IRP . Прототип:

Структура PKEYBOARD_INPUT_DATA используется для описания нажатой клавиши.

Проверяем, удачно завершен запрос или нет

Чтобы достать структуру KEYBOARD_INPUT_DATA нужно обратиться к системному буферу IRP -пакета.

Узнаем количество клавиш

И выводим каждую клавишу:

И не забываем уменьшать количество не обработанных запросов

Возвращаем статус запроса

Разберем функцию завершения работы. Прототип:

Извлекаем устройство из стека:

Проверяем есть незавершенные запросы или нет. Если мы выгрузим драйвер без этой проверки, при первом нажатии на клавишу после выгрузки будет БСоД.

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

Для запуска драйвера я использовал утилиту KmdManager. Для просмотра отладочной информации использовалась утилита DbgView.

P. S. Статью писал давно, ещё на третьем курсе, сейчас уже почти ничего не помню. Но если есть вопросы, постараюсь ответить.
P. P. S. Прошу обратить внимание на комментарии, в частности на этот

Источник

Написание драйвера в подробностях №1

Драйвер-это основа взаимодействия системы с устройством в ОС Windows.Это одновременно удобно и неудобно.
Про удобства я разъяснять не буду — это и так понятно,
а заострюсь я именно на неудобствах драйверов.
В сложившейся ситуации пользователь полностью подчинён воле производителя
— выпусти тот драйвер — хорошо, а не выпустит.
Только продвинутый пользователь, имеющий голову на плечах
(особенно, если он ешё и программер) не станет мириться с таким положением дел
— он просто возьмёт и сам напишет нужный драйвер.
Это нужно и взломщику: драйвер — это удобное окошко в ring0,
которое является раем для хакера. Но хоть написать драйвер и просто,
да не совсем — есть масса подводных камней. Да и документированность данного вопроса на русском языке оставляет желать лучшего.
Этот цикл статей поможет тебе во всём разобраться.
Приступим.

Хочу сразу же сделать несколько предупреждений.
Данная статья всё-таки подразумевает определённый уровень подготовки.
Драйвера-то ведь пишутся на C(++) с большим количеством ассемблерных вставок.
Поэтому хорошее знание обоих языков весьма желательно (если не сказать — обязательно).
Если же ты пока не можешь этим похвастаться,
но желание писать драйвера есть — что ж, так как эта статья вводная, в конце её будет приведён список полезной литературы,
ссылок и т.д. Но помни: учить тебя в этом цикле статей программированию как таковому я тебя не буду.
Может как-нибудь в другой раз. Согласен? Тогда поехали!


Скоро здесь, возможно, будет стоять твоё имя.

Практически в любом деле, как мне кажется, нужно начинать с теории.
Вот и начнём с неё. Для начала уясним себе поточнее основные понятия.
Первое: что есть драйвер? Драйвер — в сущности
кусок кода ОС, отвечающий за взаимодействие с аппаратурой.
Слово «аппаратура» в данном контексте следует понимать в самом широком смысле.
С момента своего появления как такого до сегодняшнего дня драйвер беспрерывно эволюционировал.
Вот, скажем, один из моментов его развития. Как отдельный и довольно независимый модуль драйвер сформировался не сразу.
Да и сейчас этот процесс до конца не завершён:
ты наверняка сталкивался с тем, что во многих
дистрибутивах никсов для установки/перестановки etc драйверов нужно перекомпилировать ядро,
т.е. фактически заново пересобирать систему.
Вот, кстати ещё один близкий моментец: разные принципы работы с драйверами в Windows 9x и NT.
В первом процесс установки/переустановки драйверов проходит практически без проблем,
во втором же случае это тяжёлое и неблагодарное дело,
для «благополучного» завершения которого нередко приходится прибегать к полной переустановке ОС.
А зато в Windows 9x. так,стоп,открывается широкая и волнующая тема,
которая уведёт меня далеко от темы нынешней статьи,
так что вернёмся к нашим баранам. ой,то есть к драйверам.
В порядке общего развития интересно сравнить особенности драйверов в Windows и *nix(xBSD) системах:

1) Способ работы с драйверами как файлами (подробнее см. ниже)
2) Драйвер, как легко заменяемая честь ОС (учитывая уже сказанные выше примечания)
3) Существование режима ядра

Теперь касательно первого пункта. Это значит,
что функции, используемые при взаимодействии с файлами,
как и с драйверами, практически идентичные (имеется в виду лексически):
open, close, read и т.д. И напоследок стоит отметить идентичность механизма
IOCTL (Input/Output Control Code-код управления вводом-выводом)
-запросов.

Драйвера под Windows делятся на два типа:
Legacy (устаревший) и WDM (PnP). Legacy драйверы (иначе называемые «драйверы в стиле
NT») чрезвычайно криво работают (если работают вообще)
под Windows 98, не работают с PnP устройствами, но зато могут пользоваться старыми функциями
HalGetBusData, HalGetInterruptVector etc, но при этом не имеют поддержки в лице шинных драйверов.
Как видишь, весьма средненький драйвер. То ли дело
WDM: главный плюс — поддержка PnP и приличненькая совместимость:
Windows 98, Me, 2000, XP, 2003, Server 2003 и т.д. с вариациями; но он тоже вынужден за это расплачиваться:
например, он не поддерживает некоторые устаревшие функции
(которые всё таки могут быть полезны). В любом случае,
не нужно ничего воспринимать как аксиому, везде бывают свои исключения.
В некоторых случаях лучше написания Legacy драйвера ничего не придумать.

Как ты наверняка знаешь, в Windows есть два мода работы:
User Mode и Kernel Mode — пользовательский режим и режим ядра соответственно.
Первый — непривилегированный, а второй — наоборот.
Вот во втором чаще всего и сидят драйвера (тем
более, что мы в данный момент говорим именно о драйверах режима ядра).
Главные различия между ними: это доступность всяких привилегированных команд процессора.
Программировать (а уж тем более качественно) в Kernel mode посложнее будет,
чем писать прикладные незамысловатые проги.
А драйвера писать без хорошего знания Kernel mode — никак.
Нужно попариться над назначением выполнения разнообразных работ отдельному подходящему уровню IRQL, желательно выучить новое API (так как в Kernel mode API отличается от прикладного).
в общем, предстоит много всяких радостей. Но тем не менее,
это очень интересно, познавательно, и даёт тебе совершенно иной уровень власти над компьютером.

А раз уж я упомянула про IRQL, разьясню и это понятие.
IRQL (Interrupt Request Level — уровень приоритета выполнения) — это приоритеты,
назначаемые специально для кода, работающего в режиме ядра.
Самый низкий уровень выполнения — PASSIVE_LEVEl. Работающий поток может быть прерван потоком только с более высоким
IRQL.

Ну и напоследок разъясним ещё несколько терминов:

1) ISR (Interrupt Service Routine) — процедура обслуживания прерываний.
Эта функция вызывается драйвером в тот момент,
когда обслуживаемая им аппаратура посылает сигнал прерывания.
Делает самые необходимые на первый момент вещи:
регистрирует callback — функцию и т.д.

2) DpcForISR (Deferred Procedure Call for ISR) — процедура отложенного вызова для обслуживания прерываний.
Эту функцию драйвер регистрирует в момент работы ISR для выполнения основной работы.

3) IRP (Input/Output Request Packet) — пакет запроса на ввод — вывод.
Пакет IRP состоит из фиксированной и изменяющейся частей.
Вторая носит название стека IRP или стека ввода — вывода (IO stack).

4) IO stack location — стек ввода — вывода в пакете IRP.

5) Dispatch Routines (Рабочие процедуры) — эти функции регистрируются в самой первой (по вызову) процедуре драйвера.

6) Major IRP Code — старший код IRP пакета.

7) Minor IRP Code — соответственно, младший код IRP пакета.

8) DriverEntry — эта функция драйвера будет вызвана первой при его загрузке.

9) Layering (Многослойность) — данной возможностью обладают только WDM — драйвера.
Она заключается в наличии реализации стекового соединения между драйверами.
Что такое стековое соединение? Для этого необходимо знать про Device
Stack (стек драйверов) — поэтому я обязательно вспомню про всё это чуточку ниже.

10) Device Stack, Driver Stack (стек устройств, стек драйверов) — всего лишь
объемное дерево устройств. Его, кстати, можно рассмотреть во всех подробностях с помощью программы
DeviceTree (из MS DDK), например.

11) Стековое соединение — как и обещала, объясняю. В стеке драйверов самый верхний драйвер — подключившийся позднее.
Он имеет возможность посылать/переадресовывать IRP запросы другим драйверам,
которые находятся ниже его. Воти всё. Правда,просто?

12) AddDevice — функция, которую обязательно должны поддерживать WDM драйверы.
Её название говорит само за себя.

13) Device Object, PDO, FDO (Объект устройства, физический,
функциональный) — при подключении устройства к шине она создаёт PDO.
А уже к PDO будут подключаться FDO объекты WDM драйверов.
Обьект FDO создаётся самим драйвером устройства при помощи функции IOCreateDevice.
Обьект FDO также может иметь свою символическую ссылку, от которой он будет получать запросы от драйвера.
Это что касается WDM драйверов. С драйверами «в стиле NT» ситуация несколько иная.
Если он не обслуживает реальных/PnP устройств,
то PDO не создаётся. Но для связи с внешним миром без FDO не обойтись.
Поэтому он присутствует и тут.

14) Device Extension (Расширение обьекта устройства) — «авторская» структура,
т.е. она полностью определяется разработчиком драйвера.
Правилом хорошего тона считается, например,
размещать в ней глобальные переменные.

15) Monolithic Driver (Монолитный драйвер) — это драйвер,
который самостоятельно обрабатывает все поступающие
IRP пакеты и сам работает с обслуживаемым им устройством
(в стеке драйверов он не состоит). Данный тип драйверов используется только если обслуживается не
PnР устройство или же всего лишь требуется окошко в ring0.

16) DIRQL (уровни аппаратных прерываний) —
прерывания, поступающие от реальных устройств, имеют наивысший приоритет IRQL,
поэтому для них решено было придумать специальное название
(Device IRQL).

17) Mini Driver (Мини — драйвер) — чуть меньше «полного» драйвера.
Обычно реализуется в виде DLL-ки и имеет оболочку в виде «полного» драйвера.

18) Class Driver (Классовый драйвер) — высокоуровневый драйвер,
который предоставляет поддержку класса устройств.

19) РnP Manager (PnP менеджер) — один из главных компонентов операционной системы.
Состоит из двух частей: PnP менеджера пользовательского и «ядерного» режимов.
Первый в основном взаимодействует с пользователем;
когда тому нужно, например, установить новые драйвера и т.д.
А второй управляет работой, загрузкой и т.д. драйверов.

20) Filter Driver (фильтр — драйвер) — драйверы, подключающиеся к основному драйверу либо сверху
(Upper), либо снизу (Lower). Фильтр драйверы (их может быть несколько) выполняют фильтрацию IRP пакетов.
Как правило, для основного драйвера Filter Drivers неощутимы.

21) Filter Device Object — объект устройства, создаваемый фильтр — драйвером.

22) HAL (Hardware Abstraction Layer) — слой аппаратных абстракций.
Данный слой позволяет абстрагироваться компонентам операционной системы от особенностей конкретной платформы.

23) Synchronization Objects (Обьекты синхронизации) — с помощью этих
объектов потоки корректируют и синхронизируют свою работу.

24) Device ID — идентификатор устройства.

25) DMA (Direct Memory Access) — метод обмена данными между устройством и памятью
(оперативной) в котором центральный процессор не принимает участия.

25) Polling — это особый метод программирования, при котором не устройство посылает сигналы прерывания драйверу,
а сам драйвер периодически опрашивает обслуживаемое им устройство.

26) Port Driver (Порт-драйвер) — низкоуровневый драйвер,
принимающий системные запросы. Изолирует классовые драйверы устройств от аппаратной специфики последних.

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

Краткий экскурс в архитектуру Windows NT

Наш обзор архитектуры Windows NT мы начнём с разговора об уровнях разграничения привилегий. Я уже упоминала об user и kernel mode.
Эти два понятия тесно связаны с так называемыми кольцами (не толкиеновскими ).
Их ( колец) в виде всего четыре: Ring3,2,1 и 0. Ring3 — наименее привилегированное кольцо,
в котором есть множество ограничений по работе с устройствами,
памятью и т.д. Например, в третьем кольце нельзя видеть адресное пространство других приложений без особого на то разрешения. Естественно,
трояну вирусу etc эти разрешения получить будет трудновато, так что хакеру в третьем кольце жизни никакой. В третьем кольце находится user mode. Kernel mode сидит в нулевом кольце — наивысшем уровне привилегий. В этом кольце можно всё:
смотреть адресные пространства чужих приложений без каких — либо ограничений и разрешений, по своему усмотрению поступать с любыми сетевыми пакетами, проходящими через машину, на всю жизнь скрыть какой-нибудь свой процесс или файл и т.д. и т.п. Естественно,
просто так пролезть в нулевое кольцо не получиться:
для этого тоже нужны дополнительные телодвижения. У легального драйвера с этим проблем нет:
ему дадут все необходимые API — шки, доступ ко всем нужным системным таблицам и проч. Хакерской же нечисти опять приходиться туго:
все необходимые привилегии ему приходиться «выбивать»
незаконным путём. Но это уже тема отдельной статьи, и мы к ней как-нибудь ещё вернёмся. А пока продолжим.

У тебя наверняка возник законный вопрос:
а что же сидит в первом и втором кольцах ? В том то всё и дело,
что программисты из Microsoft почему — то обошли эти уровни своим вниманием. Пользовательское ПО сидит в user mode,а всё остальное (ядро,
драйвера. ) — в kernel mode. Почему они так сделали — загадка, но нам это только на руку. А теперь разберёмся с компонентами (или, иначе говоря, слоями ) операционной системы Windows
NT.

Посмотри на схему — по ней многое можно себе уяснить. Разберём её подробнее.
С пользовательским режимом всё понятно. В kernel mode самый низкий уровень аппаратный. Дальше идёт HAL, выше — диспетчер ввода — вывода и драйвера устройств в одной связке, а также ядрышко вместе с исполнительными компонентами. О HAL я уже говорила, поэтому поподробнее поговорим об исполнительных компонентах. Что они дают? Прежде всего они приносят пользу ядру. Как ты уже наверняка уяснил себе по схеме, ядро отделено от исполнительных компонентов. Возникает вопрос:
почему ? Просто на ядре оставили только одну задачу:
просто управление потоками, а все остальные задачи (управление доступом,
памятью для процессов и т.д.) берут на себя исполнительные компоненты (еxecutive). Они реализованы по модульной схеме, но несколько компонентов её (схему) не поддерживают . Такая концепция имеет свои преимущества:
таким образом облегчается расширяемость системы. Перечислю наиболее важные исполнительные компоненты:

1) System Service Interface (Интерфейс системных служб )
2) Configuration Manager (Менеджер конфигурирования)
3) I/O Manager (Диспетчер ввода-вывода,ДВВ)
4) Virtual Memory Manager,VMM (Менеджер виртуальной памяти)
5) Local Procedure Call,LPC (Локальный процедурный вызов )
6) Process Manager (Диспетчер процессов)
7) Object Manager (Менеджер объектов)

Так как эта статья — первая в цикле, обзорная, подробнее на этом пока останавливаться не будем. В процессе практического обучения написанию драйверов, я буду разъяснять все неясные термины и понятия. А пока перейдём к API.

API (Application Programming Interface) — это интерфейс прикладного программирования. Он позволяет обращаться прикладным программам к системным сервисам через их специальные абстракции. API-интерфейсов несколько, таким образом в Windows-системах присутствуют несколько подсистем. Перечислю:

1) Подсистема Win32.
2) Подсистема VDM (Virtual DOS Machine — виртуальная ДОС — машина)
3) Подсистема POSIX (обеспечивает совместимость UNIX — программ)
4) Подсистемиа WOW (Windows on Windows). WOW 16 обеспечивает совместимость 32-х разрядной системы с 16-битными приложениями. В 64-х разрядных системах есть подсистема WOW 32,
которая обеспечивает аналогичную поддержку 32 — битных приложений.
5) Подсистема OS/2. Обеспечивает совместимость с OS/2 приложениями.

Казалось бы, всё вышеперечисленное однозначно говорит в пользу WINDOWS NT систем!
Но не всё так хорошо. Основа WINDOWS NT (имеются ввиду 32-х разрядные версии) — подсистема Win32. Приложения, заточенные под одну подсистему не могут вызывать функции другой. Все остальные (не Win32) подсистемы существуют в винде только в эмуляции и реализуются функции этих подсистем только через соответствующие функции винды. Убогость и ограниченность приложений, разработанных, скажем, для подсистемы POSIX и запущенных под винду — очевидны.
Увы.

Подсистема Win32 отвечает за графический интерфейс пользователя, за обеспечение работоспособности Win32 API и за консольный ввод — вывод. Каждой реализуемой задаче
соответствуют и свои функции: функции, отвечающие за графический фейс,
за консольный ввод — вывод (GDI — функции) и функции управления потоками,
файлами и т.д. Типы драйверов, наличествующие в Windows, я уже упоминала в разделе терминов:
монолитный драйвер, фильтр — драйвер и т.д. А раз так, то пора закругляться. Наш краткий обзор архитектуры Windows NT можно считать завершённым. Этого тебе пока хватит для общего понимания концепций Windows NT, и концепций написания драйверов под эту ось — как следствие.

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

Без чего нельзя обойтись ни в коем случае — это Microsoft DDK (Driver Development Kit ). К этому грандиозному пакету прилагается и обширная документация. Её ценность — вопрос спорный. Но в любом случае, хотя бы ознакомиться с первоисточником информации по написанию драйверов для Windows — обязательно. В принципе, можно компилять драйвера и в Visual Studio, но это чревато долгим и нудным копанием в солюшенах и vcproj-ектах, дабы код твоего драйвера нормально откомпилировался. В любом случае, сорцы придётся набивать в визуальной студии, т.к. в DDK не входит
нормальная IDE. Есть пакеты разработки драйверов и от третьих фирм:
WinDriver или NuMega Driver Studio, например. Но у них есть отличия от майкрософтовского базиса функций (порой довольно большие ) и многие другие мелкие неудобства. Так что DDK — лучший вариант. Если же ты хочешь писать драйвера исключительно на ассемблере, тебе подойдёт KmdKit (KernelMode Driver DevelopmentKit) для MASM32. Правда, этот вариант только для Win2k/XP.

Теперь можно поговорить о сторонних утилитах. Некоторые уже включены в стандартную поставку
Windows: редактор реестра. Но их в любом случае не хватит. Надо будем инсталлить отдельно.
Множество наиполезнейших утилит создали патриархи системного кодинга в
Windows: Марк Руссинович, Гарри Нэббет, Свен Шрайбер. и т.д. Вот о них и поговорим.
Марк Руссинович создал много полезных утилит:
RegMon, FileMon (мониторы обращений к реестру и файлам соответственно), WinObj (средство просмотра директорий имен
объектов), DebugView,DebugPrint (программы просмотра, сохранения и т.д. отладочных сообщения) и проч. и проч. Все эти утилиты и огромное количество других можно найти на знаменитом сайте Руссиновича
http://www.sysinternals.com.

На диске, прилагающемся к знаменитой книге «Недокументированные возможности Windows 2000» Свена Шрайбера,
есть замечательные утилиты w2k_svc, -_sym, -_mem, позволяющие просматривать установленные драйвера, приложения и службы, работающие в режиме ядра, делать дамп памяти и т.д. Все эти утилиты, а также другие программы с диска можно скачать с
http://www.orgon.com/w2k_internals/cd.html.

Напоследок нельзя не упомянуть такие хорошие проги, как PE
Explorer, PE Browse Professional Explorer, и такие незаменимые, как дизассемблер IDA и лучший отладчик всех времён и народов SoftICE.

Ну вот и подошла к концу первая статья из цикла про написание драйверов под Windows. Теперь ты достаточно «подкован» по
теоретической части, так что в следующей статье мы перейдём к практике. Желаю тебе удачи в этом интереснейшем деле — написании драйверов! Да не облысеют твои пятки!

Источник

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *

  • Windows network controller driver windows 7
  • Windows movie maker установить на компьютер
  • Windows movie maker уроки для начинающих
  • Windows movie maker программа для работы с видео
  • Windows movie maker не сохраняет фильм что делать