Pull to refresh

Программирование в ring0 для Windows: вводная статья

Reading time3 min
Views32K

По долгу службы мне пришлось столкнуться с программированием драйверов под Windows. Люди, которые никогда не сталкивались с этой задачей могут предположить, что драйвера — это что-то очень сложное и непосредственно взаимодействующее с железом. Отчасти они правы, а отчасти нет. В этой статье я постараюсь рассказать о том, что же из себя представляют Windows драйвера изнутри и с чем мне пришлось столкнуться. Статья является некоторым введением и не содержит «кусков кода».


Итак, начнем. Сначала скажу, что Windows-драйвер — это любой код, выполняющийся в пространстве ядра (kernel-space). Все прикладные программы выполняются в пользовательском пространстве (userspace).

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

В пространстве ядра все по-другому, это как «взрослая жизнь» после детства: возможности несравненно больше, но и ответственности тоже немало. В драйвере мы можем напрямую обращаться к аппаратуре, можем сделать процесс «непрерываемым» на какой-то промежуток времени, одним словом вершить судьбы всего пользовательского (да и не только) пространства, с другой стороны, простая и достаточно распространенная ошибка обращение по нулевому указателю может привести к краху системы (BSoD-у, т.е. Blue Screen of Death — синему экрану смерти, сейчас с ним люди сталкиваются достаточно редко, но раньше это было достаточно распространенным явлением).

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

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

Драйвера — это особые компоненты системы, поэтому их нельзя собрать с помощью стандартной поставки Visual Studio, для драйверов придумали отдельный набор инструментов, содержащий компилятор, заголовочные файлы, библиотеки, документацию и примеры, он называется WDK (Windows Driver Kit), ранее известный как DDK. Замечу одну особенность, с которой столкнулся сам: WDK для более новых систем, таких как Windows Vista и 2008 позволяет компилировать драйвера для более ранних версий Windows, таких как XP и 2000, поэтому лучше всего (конечно ИМХО) брать самые последние стабильные версии WDK.

Еще один момент, про который хотелось бы упомянуть во вводной статье — это назвать гуру в данной области: когда кто-то говорит про С++ это в большинстве случаев ассоциируется с именем Страуструпа, так и здесь: программирование для Windows на уровне ядра ассоциируется с именами Марка Руссиновича (Mark Russinovich) и Брюса Когсвела (Bryce Cogswell), которые написали большое количество полезных утилит, а также незаменимые для разработчика драйверов книги. Подробности можно найти на сайте sysinternals.com.

Итак, хотелось бы узнать, интересует ли хабровчан тема программирования драйверов для Windows и стоит ли писать дальнейшие статьи? На что обратить внимание в первую очередь?
Огромное спасибо за ваше внимание :)
Tags:
Hubs:
Total votes 120: ↑112 and ↓8+104
Comments32

Articles