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


    По долгу службы мне пришлось столкнуться с программированием драйверов под 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 и стоит ли писать дальнейшие статьи? На что обратить внимание в первую очередь?
    Огромное спасибо за ваше внимание :)
    Поделиться публикацией
    AdBlock похитил этот баннер, но баннеры не зубы — отрастут

    Подробнее
    Реклама
    Комментарии 32
    • +18
      Как по мне — то стОит. Однако сразу сильно вглубь не надо рассматривать — те, кого это сильно заинтересует, уже сами найдут нужное.
      Но на уровне хотябы Helloworld и немного глубже хотелось бы посмотреть.

      Причем особо хотелось бы про отличие в программировании r0 и r3.
      • +5
        Спасибо большое за статью, прочитал на одном дыхании. Было бы замечательно почитать про программирование драйверов. Статьи и книги — сухой технический язык, а тут живо и интересно. Жду продолжения
        • +3
          Тема достаточно интересная. Так как на хабре в последнее время часто обсуждаются различные самодельные девайсы, интересно было бы почитать про разработку драйверов под них. Еще интересно было бы почитать про драйвера в Windows Mobile (CE), но это уже другое.
          • +2
            Да уж, а инфу искать — замучаешься =)
            Сам когда-то писал usb-hid драйвер для Windows CE 5, это было весело =)
            Хотя, по сути там дрова — всего лишь библиотеки, зарегистрированные особым образом в реестре.
          • +7
            Получилось несколько сумбурно, в следующий раз постарайтесь не прыгать с мысли на мысль, а концентрироваться на чем-то одном ;) Добавьте пожалуйста тег «системное программирование» и неплохо было бы перенести в соответствующий блог ;)

            Кстати у меня разработка драйверов ассоциируется почему-то не с Руссиновичем, а с Уолтером Оуни :) Руссинович профи — но скорее в сфере Windows Internals, и читать его полезно не начинающим, а более продвинутым.

            > прикладное приложение не может просто так взять и получить доступ к памяти другого процесса
            Хм, NtReadVirtualMemory/NtWriteVirtualMemory знаем? А схема — CreateRemoteThread/NtVriteVirtualMemory как самый распространённый способ инжекта кода в юзер мод процессы? так что может :)

            > прикладное приложение всегда можно прервать и дать немного процессорного времени другому приложению
            В Ядре kernel preemption тоже никто не отменял ;)
            • +4
              думаю что актуально будет — применительно к usb
              • +2
                Однозначно, стОит! Тема интересная — изложение увлекательное.
                • +2
                  Пара ссылок о системном программировании:
                  www.wasm.ru (уж кто его не знает)
                  gr8.cih.ms (пара интересных статей)
                  • +1
                    если на то пошла речь, что не забудте rootkits.ru — очень полезный для системного программиста сайт
                    • +2
                      Чуток уточню. С васма туторы от Four-F по программированию драйвер must read. Сложно представить, что можно написать лучше.
                    • +1
                      Да, пишите побольше!
                      • +2
                        Определенно! Мне было бы интересно прочитать про общую структуру драйверов, про сетевые драйвера.
                        • +1
                          у автора понятный легкий язык, действительно читается на одном дыхании, пишите еще, интересно!
                          • +1
                            Спасибо, отличная статья!
                            • +3
                              Мне кажется неплохо было-бы хотя бы в общих чертах рассмотреть архитектуру ОС.
                          • +1
                            Думаю что стóит — стиль понятен, никаких претензий пока нет. Вот лично мне интересно как писать код взаимодействия с шиной PCI Express.
                            • +1
                              Подобные вещи специфичны для каждой ОС. Более детально — обратитесь например к самплу NDIS драйвера в WDK для интеловской сетевой, там можно поглядеть в действии WDK API касательно и DMA, MMR и тд
                            • +2
                              Интересно, с удовольствием прочту продолжение!
                              • +1
                                Интересно, однозначно. Если можно высказать личную заинтересованность — драйвера под embedded WinCE и Linux, хотя как кажется мне, особой разницы тут не будет.
                                • +1
                                  Разница между CE и настольной виндой в программировании драйверов весьма и весьма существенна.
                                  Дрова под CE — обычные DLL. Просто их особым образом устанавливать нужно.
                                  А вообще, достаточно сложно найти по ним инфу. (Во всяком случае, 2 года назад, когда я и писал драйвер USB-HID для WM)
                                  • +1
                                    может тогда и вам стоит написать статью? ;)
                                    программирование под WinCE интересно, думаю, многим.
                                    • +1
                                      Ну раз народ просит =)
                                      Соберусь с мыслями, разрою исходники и постараюсь на примере показать =)
                                • +1
                                  Считаю, что тема весьма интересна. Хотелось бы услышать какие есть основные направления, IDE, какие сложности при изучение, возникали у автора.
                                  • +3
                                    Стоит! А то грустно как то смотреть на главную хабра…
                                    • +1
                                      Было бы очень интересно почитать подробности, не одним Вебом, пусть даже два-нольным, живем.
                                      • +6
                                        Стоит, это поинтересней взломанных ящиков Сары Палин.
                                        • +1
                                          меня интересует
                                          • +2
                                            Писать стоит, только про вирусы не надо, ага.
                                            • 0
                                              В заголовке вы упомянули «ring0», а в самой статье про это ни слова.

                                              Добавьте информацию, так введение будет намного мягше.
                                              • 0
                                                Тему продолжать стоит однозначно!!! Очень интересно.
                                                Если есть возможность, то хотелось бы увидеть сравнения XP, Vista, 2008 в уровнях работы на ring 0, хотя у последних двух одно ядро. Ну, и, как уже кто — то высказывал — если есть возможность, то сравнение аналогичных функция в других ОС, но даже без этого будет интересно!

                                                Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.