Невозможно отучить людей изучать самые ненужные предметы.
Введение в CSS
Преимущества стилей
Добавления стилей
Типы носителей
Базовый синтаксис
Значения стилевых свойств
Селекторы тегов
Классы
CSS3
Надо знать обо всем понемножку, но все о немногом.
Идентификаторы
Контекстные селекторы
Соседние селекторы
Дочерние селекторы
Селекторы атрибутов
Универсальный селектор
Псевдоклассы
Псевдоэлементы
Кто умеет, тот делает. Кто не умеет, тот учит. Кто не умеет учить - становится деканом. (Т. Мартин)
Группирование
Наследование
Каскадирование
Валидация
Идентификаторы и классы
Написание эффективного кода
Вёрстка
Изображения
Текст
Цвет
Линии и рамки
Углы
Списки
Ссылки
Дизайны сайтов
Формы
Таблицы
CSS3
HTML5
Блог для вебмастеров
Новости мира Интернет
Сайтостроение
Ремонт и советы
Все новости
Справочник от А до Я
HTML, CSS, JavaScript
Афоризмы о учёбе
Статьи об афоризмах
Все Афоризмы
Помогли мы вам |
Статья имеет ознакомительный характер и предназначена для специалистов по безопасности, проводящих тестирование в рамках контракта. Автор и редакция не несут ответственности за любой вред, причиненный с применением изложенной информации. Распространение вредоносных программ, нарушение работы систем и нарушение тайны переписки преследуются по закону.
Я мало что понимал в виндовых драйверах до того, как прочитал книгу Павла Йосифовича Windows Kernel Programming. В книге все начинается с простого драйвера в духе Hello World и заканчивается сложным драйвером‑фильтром. Также рассказывается про отладку драйверов в виртуальной машине с WinDbg на хосте и про типичные ошибки программирования драйверов. После прочтения, конечно же, хочется применить знания на практике и разобрать какой‑нибудь драйвер. Может, нам повезет и мы найдем уязвимость?
Статья рассчитана на тех, кто немного разбирается в реверс‑инжиниринге сишного кода. В ней не будет подробного разбора процесса реверса. За более детальным описанием реверса обратись к моей первой статье «Разборки на куче. Эксплуатируем хип уязвимого SOAP-сервера на Linux».
AdGuard — классный блокировщик рекламы, поддерживающий шифрованный DNS (DoH, DoT, DoQ). Чтобы блокировать рекламные запросы всех приложений, а не только браузера, используется WDM-драйвер. Давай установим AdGuard на Windows 10 в виртуальной машине и начнем его изучать.
Так получилось, что я установил сборку для x86, поэтому исследовать мы будем 32-битный драйвер.
Первым делом нужно убедиться, что драйвер находится на поверхности атаки. То есть непривилегированное приложение может открыть драйвер для взаимодействия — чтения, записи и отправки IOCTL. В этом нам поможет пара строк на PowerShell с библиотекой NtObjectManager за авторством Джеймса Форшоу.
Для определения артефактов (файлов, ключей реестра) исследуемого продукта прекрасно подходит утилита от Microsoft Attack Surface Analyzer. С ее помощью нужно собрать два снапшота ОС: до установки исследуемой программы и после, а также создать дифф, который покажет установленные артефакты. Таким образом можно определить путь девайса в Object-Manager:
Драйвер открыть не получилось. Ошибка 0xC000010 STATUS_INVALID_DEVICE_REQUEST
, и это не 0xC0000022 ACCESS_DENIED
! Значит, доступ к девайсу драйвера у нас есть, но драйверу что‑то не понравилось в нашем запросе. Такое странное поведение — отличный повод приступить к реверсу. Давай откроем драйвер в IDA и посмотрим на несколько важных мест.
Первое место — инициализирующий код драйвера в функции DriverEntry
.
Функция IoCreateDevice(
потенциально небезопасна, так как не позволяет явно указать DACL. Таким образом, DACL берется либо из .INF-файла, либо из DACL-треда или процесса, который его создает. Также отметим, что девайс создается с неэксклюзивным доступом (EXCLUSIVE_FALSE
).
Рекомендуется использовать IoCreateDeviceSecure(
, куда можно явно передать DACL.
Аргумент FILE_DEVICE_SECURE_OPEN
присутствует. Если бы его не было, то было бы можно обойти строгий DACL, открыв произвольный файл на этом девайсе. Смотрим дальше.
Флаг DO_DIRECT_IO
говорит о том, что usermode-буферы для вызовов WriteFile(
и ReadFile(
будут мапиться в пространство ядра и у нас есть возможности для атаки TOCTOU в случае double fetch в коде драйвера. Если бы на месте этого флага был METHOD_NEITHER
, было бы еще интереснее.
Здесь тоже все нормально, двигаемся дальше.
Второе место — функция — обработчик открытия девайса драйвера. Найти ее просто. В коде инициализации драйвера необходимо явно назначить обработчики функций OpenFile(
, WriteFile(
и ReadFile(
.
На скриншотах IDA ты видишь названия переменных и функций, придуманных мной во время реверса. Конечно же, символа от бинаря нам никто не даст.
Флаг DO_DIRECT_IO
влияет на метод передачи данных из юзермода в ядро только для FileRead(
и FileWrite(
. Для DeviceIoControl(
метод зашит в код IOCTL. Для быстрого просмотра метода можешь использовать ресурс osronline.com.
Без труда находим обработчик открытия девайса.
Здесь реализован кастомный эксклюзивный доступ к драйверу — PID открывшего его процесса сохраняется в глобальную переменную hasOwner
. Следующая попытка открыть драйвер возвращает ошибку STATUS_INVALID_REQUEST
.
И что это за PID? Кто открыл драйвер раньше всех? Это сервисный процесс AdguardSvc.
. Можем ли мы на него воздействовать? На удивление — да. Убить его через Terminate(
нам не хватит прав, но у UI-процесса AdguardUI.
есть кнопка «Выключить защиту».
Когда процесс AdguardSvc.
закроется, снова попробуем открыть девайс драйвера.
Получаем права на чтение, запись и отправку IOCTL от непривилегированного пользователя. Отлично! Поверхность атаки определена.
На данном этапе исследования можно отметить две ошибки.
IoCreateDevice(EXCLUSIVE_TRUE)
. Некритично.Исследование можно было заканчивать после неудачной попытки открыть девайс драйвера, но мы внимательно отнеслись к коду ошибки и получили первую зацепку.
Кстати, проверить DACL девайса ты можешь и с помощью такой команды:
Либо:
В дизассемблерном листинге мы заметили большое количество обработчиков IOCTL. Что можно сделать вместо того, чтобы реверсить каждый?
Фаззинг драйверов несколько сложнее фаззинга юзермодных приложений, потому что работа происходит не с виртуальным пространством единственного процесса, а со всей ОС целиком. Отсюда усложнение инфраструктуры — установка агента в виртуальную машину и запуск ее в QEMU/KVM, как, например, в фаззере kAFL.
|
|