Пишем свой первый Windows- драйвер / Хабрахабр. Итак, после моей предыдущей статьи я понял что тема про программирование драйверов Windows интересна хабровчанам, поэтому продолжу. В этой статье я решил разобрать простую программу- драйвер, которая делает только то, что пишет отладочное сообщение «Hello world!» при старте драйвера и «Goodbye!» при завершении, а также опишу те средства разработки, которые нам понадобятся для того, чтобы собрать и запустить драйвер. Итак, для начала приведем текст этой несложной программы.// Test.
Simply execute the DebugView program file (dbgview.exe) and DebugView will immediately start capturing debug output. Note that if you run DebugView on Windows 2000/XP you must have administrative privilege to view kernel-mode debug output.. . Разработка → Отладка драйверов под Windows: VirtualBox+WinDbg. Однажды мне понадобилось написать драйвер под Windows XP SP2. 7. [Target — машина] image. Теперь можно начинать стройку — делаем . Windows 7 /Windows 2008 Server R2 WDK DebugView (link) — это утилитка, которая позволяет просматривать отладочный. настройку KD), деплоить туда драйвер, отлаживать, стирать, убирать, готовить есть.
Да потому что, если это настоящая удаленная отладка, то драйвер выполняется на машине у. На помощь идет как ни странно DbgView. Его можно запускать на логирование в файл с. то есть должно быть вот как-то так: multi(0)disk(0)rdisk(0)partiti
Driver. c #include < ntddk. NTSTATUS Driver. Entry(IN PDRIVER_OBJECT Driver. Object, IN PUNICODE_STRING Registry. Path); VOID Unload. Routine(IN PDRIVER_OBJECT Driver. Object); #pragma alloc_text(INIT, Driver.
Entry)#pragma alloc_text(PAGE, Unload. Routine) NTSTATUS Driver. Entry(IN PDRIVER_OBJECT Driver. Object, IN PUNICODE_STRING Registry.
Path){ Driver. Object- > Driver. Unload = Unload. Routine; Dbg. Print(«Hello world!n»); return STATUS_SUCCESS; } VOID Unload. Routine(IN PDRIVER_OBJECT Driver. Object){ Dbg. Print(«Goodbye!n»); }* This source code was highlighted with Source Code Highlighter.
Итак, теперь сначала разберемся, что делает каждая инструкция. Перво- наперво мы подключаем заголовочный файл ntddk. Это один из базовых подключаемых файлов во всех драйверах: в нем содержатся объявления типов NTSTATUS, PDRIVER_OBJECT, PUNICODE_STRING, а также функции Dbg. Print. Далее идет объявление двух функций: Driver. Entry и Unload. Routine.
Расскажу о первой поподробнее. Итак, как уважаемые читатели знают, в каждой программе есть точка входа, в программах на языке C это функция main или Win. Main. В драйвере роль точки входа выполняет функция Driver. Entry, которая получает на вход указатель на структуру Driver. Object, а также указатель на строку реестра, соответствующую загружаемому драйверу. Структура Driver.
Object содержит множество полей, которые определяют поведение будущего драйвера. Наиболее ключевые из них — это указатели на так называемые вызываемые (или callback) функции, то есть функции, которые будут вызываться при наступлении определенного события.
Одну из таких функций мы определяем: это функция Unload. Routine. Указатель на данную функцию помещается в поле Driver. Unload. Таким образом при выгрузке драйвера сначала будет вызвана функция Unload. Routine. Это очень удобно, когда драйвер имеет какие- то временные данные, которые следует очистить перед завершением работы. В нашем примере эта функция нужна только чтобы отследить сам факт завершения работы драйвера. Для того, чтобы выводить отладочные сообщения мы используем функцию Dbg.
Print, которая имеет синтаксис, аналогичной функции printf из пользовательского режима (userspace). В этом простом примере мы использовали также директивы #pragma alloc_text(INIT, Driver. Entry) и #pragma alloc_text(PAGE, Unload. Routine). Объясню что они означают: первая помещает функцию Driver. Entry в INIT секцию, то есть как бы говорит, что Driver. Entry будет выполнена один раз и после этого код функции можно спокойно выгрузить из памяти.
Вторая помечает код функции Unload. Routine как выгружаемый, т.
Вы можете задуматься, мол ну с первой- то директивой понятно, типа оптимизация и все такое, но зачем мы используем вторую директиву, зачем помечать код как возможный к выгрузке в файл подкачки? Поясню этот вопрос: каждый процесс в системе имеет такой параметр, как IRQL (подробнее читаем по ссылке Interrupt request level ибо это материал отдельной статьи), то есть некоторый параметр, отвечающий за возможность прерывания процесса: чем выше IRQL тем меньше шансов прервать выполнение процесса. Возможности процесса так же зависят от IRQL: чем выше IRQL тем меньше возможности процесса, это вполне логично, т.
IRQL, а все остальные действия делать при низком. Вернемся к основной теме, о том, почему мы делаем для функции Unload. Routine возможность выгрузки в файл подкачки: все опять же сводится к оптимизации: работа с файлом подкачки недоступна при высоком IRQL, а процедура выгрузки драйвера гарантированно выполняется при низком IRQL, поэтому мы специально указываем руками что код функции выгрузки драйвера можно поместить в своп. Ух, вроде как с обсуждением кода этой, казалось бы небольшой программки закончено, теперь разберемся как скомпилировать и запустить наш драйвер.
Для этого нам понадобится: WDK или DDKТекстовый редактор. Программа Dbg. View — бесплатная программа для просмотра отладочных сообщений, получаемых от драйверов, ее можно найти на сайте sysinternals.
Программа Kmd. Manager — бесплатная программа для регистрации, запуска и тестирования драйвера, ее можно найти на сайте wasm. Теперь последовательность действий: сначала мы пишем два файла, один называется MAKEFILE, с таким содержимым################################################### DO NOT EDIT THIS FILE!!! Edit .sources. if you want to add a new source# file to this component. This file merely indirects to the real make file# that is shared by all the driver components of the Windows NT DDK#! INCLUDE $(NTMAKEENV)makefile.
TARGETNAME=Test. Driver. TARGETTYPE=DRIVERSOURCES=Test. Driver. c##################################################Эти файлы нужны для сборки драйвера. Да, забыл сказать, что в WDK нет встроенной среды разработки, поэтому и нужен текстовый редактор, чтобы набирать текст драйверов.
Для этой цели можно использовать и Visual Studio (некоторые даже интегрируют возможность сборки драйверов из VS), и любой другой текстовый редактор. Сохраняем код драйвера в файл Test. Driver. c и кладем его в ту же директорию, что и файлы MAKEFILE и souces. После этого запускаем установленный build environment (это командная строка с заданными переменными окружения для компиляции драйвера; она входит в WDK, и запустить ее можно как- то так: «Пуск- > Программы- > Windows Driver Kits- >..- > Build Environments- > Windows. XP- > Windows XP x. Checked Build Environment»).
Переходим в директорию, куда мы положили файл с драйвером (у меня это C: DriversTest. Driver) с помощью команды cd (у меня команда выглядит следующим образом: cd C: DriversTest. Driver) и набираем команду build. Данная команда соберет нам драйвер Test. Driver. sys и положит его в папку «objchk_wxp_x. Теперь нам нужно запустить программу Dbg.
View чтобы увидеть сообщения, которые будет выдавать драйвер. После запуска данной программы нам нужно указать, что мы хотим просматривать сообщения из ядра (Capture- > Capture Kernel). Теперь запукаем программу Kmd. Manager, указываем путь к нашему драйверу (файл Test. Driver. sys) нажимаем кнопку Register, затем Run. Теперь драйвер зарегистрирован в системе и запущен. В программе Dbg. View мы должны увидеть наше сообщение «Hello World!».
Теперь завершаем работу драйвера кнопкой Stop и убираем регистрацию драйвера кнопкой Unregister. Кстати, в Dbg. View дожна появиться еще одна строка. Итак, чего же мы достигли: мы написали, скомпилировали и запустили свой первый Windows- драйвер! Добавлю только, что при написании сложный драйверов для отладки используется двухмашинная конфигурация, когда на одном компьтере ведется написание драйвера, а на другом — запуск и тестирование. Это делается из- за того, что неправильно написанный драйвер может обрушить всю систему, а на ней может быть очень много ценных данных. Часто в качестве второго компьютера используется виртуальная машина.