HOME FORUMS MEMBERS RECENT POSTS LOG IN  
× Авторизация
Имя пользователя:
Пароль:
Нет аккаунта? Регистрация
Баннер 1   Баннер 2
НОВЫЕ ТОРГОВАЯ НОВОСТИ ЧАТ
loading...
Скрыть
Вернуться   ANTICHAT > БЕЗОПАСНОСТЬ И УЯЗВИМОСТИ > Безопасность и Анонимность > Защита ОС: вирусы, антивирусы, файрволы.
   
 
 
Опции темы Поиск в этой теме Опции просмотра

  #1  
Старый 06.07.2021, 11:06
MLNK
Новичок
Регистрация: 23.01.2018
Сообщений: 0
С нами: 4371257

Репутация: 0
По умолчанию

Предыстория
Для очередного проекта возникла необходимость написать простенький софтверный драйвер под 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)
Это сложно описать словами коротко, проще один раз увидеть картинку.
В упрощённом виде это выглядит так:





Дескрипторы и объекты (Handles and Objects)
Дескрипторы и объекты необходимы для регулирования доступа к системным ресурсам.
Объект — это структура данных, представляющая системный ресурс, например файл, поток или графическое изображение.
Дескриптор – это некая абстракция, которая позволяет скрыть реальный адрес памяти от Программы в пользовательском режиме.

Для более глубокого понимания Операционных систем могу посоветовать следующие материалы:
Книги:
  • Таненбаум, Бос: Современные операционные системы
  • Windows Internals 7th edition (Part 1)
Видео:

Настройка рабочего пространства
Для разработки драйвера, как и любого другого софта необходима подходящая среда.
Так как мы работаем в операционной системе Windows, её средствами мы и будем пользоваться.

Что нам понадобится:
1. Visual Studio 2017 и старше.
(Community Version хватает с головой) Также во вкладке „Individual components” необходимо установить

Код:


Код:
MSVC v142 - VS 2019 C++ ARM build tools (Latest)
MSVC v142 - VS 2019 C++ ARM Spectre-mitigated libs (Latest)
MSVC v142 - VS 2019 C++ ARM64 build tools (Latest)
MSVC v142 - VS 2019 C++ ARM64 Spectre-mitigated libs (Latest)
MSVC v142 - VS 2019 C++ ARM64EC build tools (Latest - experimental)
MSVC v142 - VS 2019 C++ ARM64EC Spectre-mitigated libs (Latest - experimental)
MSVC v142 - VS 2019 C++ x64/x86 build tools (Latest)
MSVC v142 - VS 2019 C++ x64/x86 Spectre-mitigated libs (Latest)


и далее по списку.
2. Windows 10/11 SDK (последней версии)
Windows 10 SDK - Windows app development



Тут все просто. Качаем iso файл, монтируем и запускаем установщик.
3. Windows 10/11 Driver Kit (WDK)
Download the Windows Driver Kit (WDK) - Windows drivers



В конце установки вам будет предложено установить расширение для Visual Studio. Обязательно установите его!



После закрытия окна установки WDK появится установщик Расширения VisualStudio



4. Sysinternals Suite Sysinternals Suite - Windows Sysinternals
Скачайте и распакуйте в удобное для вас место. Это набор полезных утилит, которые пригодятся для исследования Windows, дебага драйвера и прочего.



5. Виртуальная Машина с Windows для тестов.
Выбор ПО для виртуализации на ваше усмотрение. Я буду использовать «VMware Workstation 16 pro».
Написанные драйверы лучше тестировать именно в виртуальной машине, так как Ядро - ошибок не прощает, и вы будете часто улетать в синий экран смерти.

После того, как все было установлено, пора запускать Visual Studio и начинать писать драйвер.
Создание проекта
Запускаем Visual Studio и создаем новый проект. Создадим пустой проект „Empty WDM Driver“



Называем его как душе угодно.



И вот он, наш свеженький чистенький проект для нашего первого драйвера.



Теперь необходимо создать cpp файл, в котором мы будем писать сам драйвер.





Вот и все. Настройку системы и среды мы закончили.



Первый драйвер
Сначала импортируем
Код:
ntddk.h
эта одна из базовых библиотек для работы с ядром. Больше информации тут. Как и у любой программы, у драйвера должна быть точка входа
Код:
DriverEntry
, как функция
Код:
Main
в обычной программе. Готовый прототип этой функции выглядит так

C++:


Код:
#include 
NTSTATUS
DriverEntry
(
_In_ PDRIVER_OBJECT DriverObject
,
_In_ PUNICODE_STRING RegistryPath
)
{
/*
    In_ это часть SAL(Source Code Ananotation Language) Аннотации не видимы для компилятора,
    но содержат метаданные которые, улучшают анализ и чтение кода.
*/
return
STATUS_SUCCESS
;
}
Если мы попробуем собрать наш проект, то получим следующие ошибки и предупреждения.



В данном случае пункт 1 является следствием пунктов 2 и 3. Дело в том, что по дефолту в Visual Studio некоторые “предупреждения” расцениваются как ошибки.
Чтобы решить эту проблему есть 2 пути.
  1. Отключить эту фичу в Visual Studio, что делать не рекомендуется. Так как сообщения об ошибках могут быть полезны и сэкономят вам время и нервы в дальнейшем.
  2. Более правильный и классический метод это использовать макросы в c++. Как видно из сообщения с кодом C4100 объекты RegistryPath и DriverObject не упомянуты в теле функции. Подробнее тут.
Для того, чтобы избавиться от предупреждений, и заставить наш код работать, стоит поместить объекты в макрос
Код:
UNREFERENCED_PARAMETER(ObjectName)
C++:


Код:
include

NTSTATUS
DriverEntry
(
_In_ PDRIVER_OBJECT DriverObject
,
_In_ PUNICODE_STRING RegistryPath
)
{
UNREFERENCED_PARAMETER
(
DriverObject
)
;
UNREFERENCED_PARAMETER
(
RegistryPath
)
;
return
STATUS_SUCCESS
;
}
Теперь, если пересобрать проект, то мы увидим, что ошибка С220 и предупреждение C4100 пропали, но к ним на смену пришли LNK2019 и LNK1120. Однако это уже не ошибки компиляции - это ошибки линкера. А кто говорил что будет легко?
О том, что такое линкер можно почитать тут.

Дело в том, что наша функция не представлена в стандартном линкере С++ и вообще она девушка капризная и хочет Си-линкер. Удовлетворим желание дамы и дадим ей то, чего она хочет.

Делается это просто. Перед функцией надо добавить
Код:
extern "C"
так наш линкер будет понимать, что эта функция должна линковаться С-линкером.

Собираем проект заново и вуаля - Драйвер собрался.



Что на данный момент умеет наш драйвер? Сейчас это по сути пустышка, которая после загрузки, в случае успеха, вернет нам сообщения об удачном запуске. Давайте заставим его нас поприветствовать и проверим его работоспособность. Выводить сообщения мы будем при помощи функции
Код:
KdPrint(());
да именно в двойных кавычках.

Итоговый код драйвера будет выглядеть так:

C++:


Код:
#include 
//Указываем линкеру, что DriverEntry должна линковаться С-линкером
extern
"C"
NTSTATUS
DriverEntry
(
_In_ PDRIVER_OBJECT DriverObject
,
_In_ PUNICODE_STRING RegistryPath
)
{
//Убираем варнинг C4100 и связанную с ним ошибку C220
UNREFERENCED_PARAMETER
(
DriverObject
)
;
UNREFERENCED_PARAMETER
(
RegistryPath
)
;
//Выводим сообщение
KdPrint
(
(
"Hi античат , this is our first driver! Yuhu!\n"
)
)
;
return
STATUS_SUCCESS
;
}
Собираем или пересобираем драйвер.



Цитата:

Важно! Сборка драйвера должна происходить в режиме Debug!!!


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



Но что делать дальше? Как проверить его работоспособность?
Для этого нам и понадобится наша виртуальная машина с Windows, но перед запуском на ней драйвера, нам придется проделать пару манипуляций. Дело в том, что в Windows есть встроенная защита, и если драйвер не подписан "нужной" подписью ака сертификатом, то драйвер просто не загрузится.

Дальнейшие действия нужно проделать в Windows на виртуальной машине.
Чтобы отключить эту проверку подписи, а точенее перевести Windows в тестовый режим, запустите cmd.exe от имени администратора и введите следующую команду
Код:
bcdedit /set testsigning on
.



Перезагрузите виртуальную машину.
Если все прошло удачно, в правом нижнем углу вы увидите следующую надпись (2 нижнее строчки могут отличиться в зависимости от версии Windows)



Возвращаемся в папку с драйвером и копируем его в виртуальную машину. Теперь нам надо создать службу для запуска драйвер. Открываем консоль от имени администратора и вводим следующую команду:

Код:
sc create Name type= kernel binPaht= PATH_TO_DRIVER
в моем случае это выглядит так:



Также проверить успешность создания можно через реестр.



В той же консоли мы можем попробовать запустить нашу службу.

Код:
sc start античат Driver


Отлично, драйвер запустился и мы даже не улетели в синьку, а это всегда приятно. Теперь давайте проверим, выводится ли сообщение от драйвера.
Для этого нам необходимо провести подготовительные работы.

Создадим новый ключ в реестре и назовем его
Код:
Debug Print Filter
.



В качестве значения задаем
Код:
DWORD
с именем
Код:
DEFAULT
и определяем данные для значения как
Код:
8
.



Перезагружаем виртуальную машину.

После перезапуска запускаем DebugView данный инструмент находится в архиве Sysinternals, который мы ранее скачали. Ее можно смело скопировать в виртуальную машину.

Запускаем DebugView от имени Администратора и ставим галочку “Capture Kerner”



Capture Win32 и Capture Global Win32 можно снять, если летит много сообщений.

Затем запускаем консоль от имени администратора и запускаем службу загрузки драйвера.



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

Спасибо за чтение!

P.S: Я сам только начал изучать тему работы с драйверами. Так что если у вас есть предложения или правки по технической части статьи, прошу отписать в комментарии, чтобы я мог внести изменения в статью.
P.P.S: Как вы могли заметить, писать мы будем преимущественно на С++, посему могу посоветовать отличный канал с уроками по С++ - The Cherno.
 
Ответить с цитированием
 





Здесь присутствуют: 1 (пользователей: 0 , гостей: 1)
 


Быстрый переход




ANTICHAT ™ © 2001- Antichat Kft.