![]() |
Предыстория
Для очередного проекта возникла необходимость написать простенький софтверный драйвер под Windows, но так как опыта в написании драйверов у меня примерно столько же, сколько и в балете, я начал исследовать данную тему. В таких делах я предпочитаю начинать с основ, ибо если кидаться сразу на сложные вещи, то можно упустить многие базовые понятия и приёмы, что в дальнейшем только усложнит жизнь. После 20 минут поисков по сети я наткнулся на Github Павла Иосифовича (zodiacon - Overview). Личность легендарная в своих кругах, достаточно посмотреть на его репозиторий, публикации и выступления на именитых конференциях. Помимо этого, Павел является автором/соавтором нескольких книг: «Windows Internals» (книга, имеющаяся у меня на полке, которая принесла немало пользы), и «Windows Kernel Programming» 2019 года выпуска (бегло пролистав 11 Глав или 390 страниц, я понял – это то, что нужно!). Кстати, книгу вы можете купить прямо на сайте Павла Books Книгу я приобрёл в бумажной версии, чтобы хоть и немного, но поддержать автора. Безупречное качество, несмотря на то, что она издается в мягком переплете. Хорошие плотные листы формата А4 и качественная краска. (книга без проблем пережила вылитую на нее кружку горячего кофе). Пока я сидел на балконе и читал четвёртую главу книги, в голову пришла мысль: а почему бы не сделать ряд статей на тему «Программирования драйвера под Windows», так сказать, совместить полезное, с еще более полезным. И вот я здесь, пишу предысторию. Как я вижу этот цикл статей и что от него ожидать: Это будут статьи, которые будут базироваться на вышеупомянутой книге, своеобразный вольный и сокращенный перевод, с дополнениями и примечаниями. Базовые понятия о внутреннем устройстве Windows (Windows Internals) Для того, чтобы начать разрабатывать Драйвер под Windows, то есть работать на уровне с ядром ОС, необходимо базовое понимание того, как эта ОС утроена. Так как я хочу сосредоточиться на написании драйвера, а не на теории об операционных системах, подробно описывать понятия я не буду, чтобы не растягивать статью, вместо этого прикреплю ссылки для самостоятельного изучения. Следовательно, нам стоит ознакомиться с такими базовыми понятиями как: Процессы (Processes) Процесс – это объект, который управляет запущенной инстанцией программы. Виртуальная Память (Virtual Memory) Технология, позволяющая создавать закрытые пространства памяти для процессов. В своем роде - это песочница. Потоки (Threads) Это сущность, которая содержится внутри процесса и использует для работы ресурсы, выделенные процессом - такие, как виртуальная память. По сути, как раз таки потоки и запускают код. Системные службы (System Services a.k.a System Calls) В своем роде это прокладка, которая позволяет программе отправлять запросы в Ядро операционной системы, для выполнения нужных ей операций. Архитектура системы (System Architectures) Это сложно описать словами коротко, проще один раз увидеть картинку. В упрощённом виде это выглядит так: https://forum.antichat.xyz/attachmen...e0217d7fae.png Дескрипторы и объекты (Handles and Objects) Дескрипторы и объекты необходимы для регулирования доступа к системным ресурсам. Объект — это структура данных, представляющая системный ресурс, например файл, поток или графическое изображение. Дескриптор – это некая абстракция, которая позволяет скрыть реальный адрес памяти от Программы в пользовательском режиме. Для более глубокого понимания Операционных систем могу посоветовать следующие материалы: Книги:
Для разработки драйвера, как и любого другого софта необходима подходящая среда. Так как мы работаем в операционной системе Windows, её средствами мы и будем пользоваться. Что нам понадобится: 1. Visual Studio 2017 и старше. (Community Version хватает с головой) Также во вкладке „Individual components” необходимо установить Код: Код:
MSVC v142 - VS 2019 C++ ARM build tools (Latest)и далее по списку. 2. Windows 10/11 SDK (последней версии) Windows 10 SDK - Windows app development https://forum.antichat.xyz/attachmen...224e42c4eb.png Тут все просто. Качаем iso файл, монтируем и запускаем установщик. 3. Windows 10/11 Driver Kit (WDK) Download the Windows Driver Kit (WDK) - Windows drivers https://forum.antichat.xyz/attachmen...61a586b770.png В конце установки вам будет предложено установить расширение для Visual Studio. Обязательно установите его! https://forum.antichat.xyz/attachmen...b5348f8065.png После закрытия окна установки WDK появится установщик Расширения VisualStudio https://forum.antichat.xyz/attachmen...890949a0d5.png 4. Sysinternals Suite Sysinternals Suite - Windows Sysinternals Скачайте и распакуйте в удобное для вас место. Это набор полезных утилит, которые пригодятся для исследования Windows, дебага драйвера и прочего. https://forum.antichat.xyz/attachmen...15d7980c74.png 5. Виртуальная Машина с Windows для тестов. Выбор ПО для виртуализации на ваше усмотрение. Я буду использовать «VMware Workstation 16 pro». Написанные драйверы лучше тестировать именно в виртуальной машине, так как Ядро - ошибок не прощает, и вы будете часто улетать в синий экран смерти. После того, как все было установлено, пора запускать Visual Studio и начинать писать драйвер. Создание проекта Запускаем Visual Studio и создаем новый проект. Создадим пустой проект „Empty WDM Driver“ https://forum.antichat.xyz/attachmen...1b9ff5a69c.png Называем его как душе угодно. https://forum.antichat.xyz/attachmen...72a161cc39.png И вот он, наш свеженький чистенький проект для нашего первого драйвера. https://forum.antichat.xyz/attachmen...d9c671f609.png Теперь необходимо создать cpp файл, в котором мы будем писать сам драйвер. https://forum.antichat.xyz/attachmen...893cbced29.png https://forum.antichat.xyz/attachmen...c3f52295e2.png Вот и все. Настройку системы и среды мы закончили. https://forum.antichat.xyz/attachmen...d6fcc7fe3a.png Первый драйвер Сначала импортируем Код:
ntddk.hКод:
DriverEntryКод:
MainC++: Код:
#include https://forum.antichat.xyz/attachmen...be8358f458.png В данном случае пункт 1 является следствием пунктов 2 и 3. Дело в том, что по дефолту в Visual Studio некоторые “предупреждения” расцениваются как ошибки. Чтобы решить эту проблему есть 2 пути.
Код:
UNREFERENCED_PARAMETER(ObjectName)Код:
includeО том, что такое линкер можно почитать тут. Дело в том, что наша функция не представлена в стандартном линкере С++ и вообще она девушка капризная и хочет Си-линкер. Удовлетворим желание дамы и дадим ей то, чего она хочет. Делается это просто. Перед функцией надо добавить Код:
extern "C"Собираем проект заново и вуаля - Драйвер собрался. https://forum.antichat.xyz/attachmen...af1f5dc5a9.png Что на данный момент умеет наш драйвер? Сейчас это по сути пустышка, которая после загрузки, в случае успеха, вернет нам сообщения об удачном запуске. Давайте заставим его нас поприветствовать и проверим его работоспособность. Выводить сообщения мы будем при помощи функции Код:
KdPrint(());Итоговый код драйвера будет выглядеть так: C++: Код:
#include https://forum.antichat.xyz/attachmen...b57f033c48.png Цитата:
После чего в папке нашего проекта мы сможем найти результаты нашего труда. Вы только посмотрите на него, какой маленький и хорошенький. https://forum.antichat.xyz/attachmen...3dc5d4a962.png Но что делать дальше? Как проверить его работоспособность? Для этого нам и понадобится наша виртуальная машина с Windows, но перед запуском на ней драйвера, нам придется проделать пару манипуляций. Дело в том, что в Windows есть встроенная защита, и если драйвер не подписан "нужной" подписью ака сертификатом, то драйвер просто не загрузится. Дальнейшие действия нужно проделать в Windows на виртуальной машине. Чтобы отключить эту проверку подписи, а точенее перевести Windows в тестовый режим, запустите cmd.exe от имени администратора и введите следующую команду Код:
bcdedit /set testsigning onhttps://forum.antichat.xyz/attachmen...e1411eaf16.png Перезагрузите виртуальную машину. Если все прошло удачно, в правом нижнем углу вы увидите следующую надпись (2 нижнее строчки могут отличиться в зависимости от версии Windows) https://forum.antichat.xyz/attachmen...0d15559203.png Возвращаемся в папку с драйвером и копируем его в виртуальную машину. Теперь нам надо создать службу для запуска драйвер. Открываем консоль от имени администратора и вводим следующую команду: Код:
sc create Name type= kernel binPaht= PATH_TO_DRIVERhttps://forum.antichat.xyz/attachmen...79b215dd57.png Также проверить успешность создания можно через реестр. https://forum.antichat.xyz/attachmen...0ccca3ebe6.png В той же консоли мы можем попробовать запустить нашу службу. Код:
sc start античат DriverОтлично, драйвер запустился и мы даже не улетели в синьку, а это всегда приятно. Теперь давайте проверим, выводится ли сообщение от драйвера. Для этого нам необходимо провести подготовительные работы. Создадим новый ключ в реестре и назовем его Код:
Debug Print Filterhttps://forum.antichat.xyz/attachmen...5375ebce58.png В качестве значения задаем Код:
DWORDКод:
DEFAULTКод:
8https://forum.antichat.xyz/attachmen...4647a93baa.png Перезагружаем виртуальную машину. После перезапуска запускаем DebugView данный инструмент находится в архиве Sysinternals, который мы ранее скачали. Ее можно смело скопировать в виртуальную машину. Запускаем DebugView от имени Администратора и ставим галочку “Capture Kerner” https://forum.antichat.xyz/attachmen...5fe345c9d9.png Capture Win32 и Capture Global Win32 можно снять, если летит много сообщений. Затем запускаем консоль от имени администратора и запускаем службу загрузки драйвера. https://forum.antichat.xyz/attachmen...2b53477288.png Все отработало отлично, и мы видим приветствие от нашего драйвера! На этой приятной ноте первая статья из цикла заканчивается. В дальнейших статьях мы добавим функционала нашему драйверу, научим его выгружаться и получать данные. Спасибо за чтение! P.S: Я сам только начал изучать тему работы с драйверами. Так что если у вас есть предложения или правки по технической части статьи, прошу отписать в комментарии, чтобы я мог внести изменения в статью. P.P.S: Как вы могли заметить, писать мы будем преимущественно на С++, посему могу посоветовать отличный канал с уроками по С++ - The Cherno. |
ну круто конечно. особенно про Павла, кто не слышал про утилиты sysinternals
|
Ну да вообще вещи которые могу выручать очень сильно. На самом деле я думаю много кто о них не знаешь, или знает про базовые типо Process explorer
|
Спасибо за статью !! жду следующую часть
|
Цитата:
|
Есть ещё хорошая книжка на русском windows driver foundation.
|
Цитата:
Я так понимаю - ты об этой книге. Просмотрел содержание, выглядит неплохо. Спасибо потом почитаю. |
Цитата:
|
Цитата:
|
А почему с++, чем pure c не угодил то?
|
| Время: 10:18 |