⚙️ Схема передачи управления
Система Windows виртуализирует память, разбивая физическую ОЗУ на 4 КБ фреймы, которым назначаются виртуальные адреса. Когда процесс создаётся, система выделяет ему страницы виртуальной памяти, храня ссылки на них в таблицах Page Directory, PDPT, PD, и PT. При этом 48-битный линейный адрес делится на пять частей, где каждый уровень таблиц содержит 512 записей, что в архитектуре x64 позволяет адресовать до 256 ТБ памяти (пополам между ядром и пользователем).
⚙️ DRIVER_OBJECT и DEVICE_OBJECT: Основные элементы драйвера
Что такое драйвер на уровне кода? По сути, это структура DRIVER_OBJECT, где описан весь функционал, который драйвер способен выполнить. Эта структура создаётся диспетчером ввода-вывода Windows, а в нашу функцию инициализации DriverEntry() передаётся лишь указатель на неё.
⚙️ IRP: Пакеты запросов к драйверу
IRP, или Input/Output Request Packet — своего рода джокер в системе запросов. Когда пользователь отправляет команду драйверу (например,
DeviceIoControl()), создаётся IRP, который поступает драйверу через DEVICE_OBJECT->CurrentIrp. Этот пакет содержит все данные о запросе и предписывает драйверу, что делать дальше. Когда IRP обработан, диспетчер удаляет его, переходя в режим ожидания следующего запроса.⚙️ Стек драйверов: FDO, PDO и FiDO
Каждое аппаратное устройство в модели WDM работает в связке с двумя типами драйверов: физическим (PDO) и функциональным (FDO). К ним может добавляться фильтрующий драйвер (FiDO), если требуется расширить возможности. Эти драйверы выстраиваются в стек, по которому передаются запросы IRP.
Запросы передаются по стеку сверху вниз: драйвер верхнего уровня обрабатывает IRP и может передать его ниже. Если драйвер FDO решает, что сам справится с запросом, он завершает обработку, отправив команду
IoCompleteRequest().✏️ Рекомендуемые команды WinDbg:
🔸
!drvobj — основная информация по DRIVER_OBJECT🔸
!devobj — основные сведения об устройстве DEVICE_OBJECT🔸
!devstack — позиция драйвера в стеке➡️ Читать подробнее
