Форум
ПОИСК ПО ФОРУМУ
Портал
ПОИСК ПО ФОРУМУ
Авторы
Что нового
Медиа
Поиск медиа
Архив
Пользователи
Сейчас на форуме
Поиск сообщений в профиле
ПОИСК
Вход
Регистрация
Что нового
ПОИСК ПО ФОРУМУ
Меню
Вход
Регистрация
Установить приложение форума
Установить
Уменьшение отступа
Обратная связь
(info@ru-sfera.pw)
Форум
Исследование системы (Для ознакомления)
Технологии создания невидимой малвари
Уязвимость Windows CLFS CVE-2022-37969 - часть 1. Слабонервным не читать. Опасно для мозга
JavaScript отключён. Для полноценно использования нашего сайта, пожалуйста, включите JavaScript в своём браузере.
Вы используете устаревший браузер. Этот и другие сайты могут отображаться в нем неправильно.
Необходимо обновить браузер или попробовать использовать
другой
.
Ответить в теме
Сообщение
<blockquote data-quote="X-Shar" data-source="post: 148070" data-attributes="member: 1"><p>Всем привет!</p><p></p><p>На xss.is нашёл классный перевод:<a href="https://xss.is/threads/75428/" target="_blank">https://xss.is/threads/75428/</a></p><p></p><p>Но к сожалению там не оформили как статью, поэтому надёюсь никто не против, если я перенесу этот интересный материал сюда. <img src="/c010.gif" class="smilie" loading="lazy" alt="Отдыхай!!!" title="Отдыхай!!! Отдыхай!!!" data-shortname="Отдыхай!!!" /></p><p></p><p><strong>2 сентября 2022 г</strong>. компания Zscaler Threatlabz зафиксировала эксплойт нулевого дня в общем системном драйвере файлов журнала Windows (CLFS.sys) и сообщила об этом обнаружении в Microsoft. В сентябрьском <a href="https://msrc.microsoft.com/update-guide/vulnerability/CVE-2022-37969" target="_blank"><u>патче, выпущенном во вторник </u></a>, Microsoft исправила эту уязвимость, идентифицированную как <a href="https://msrc.microsoft.com/update-guide/vulnerability/CVE-2022-37969" target="_blank"><u>CVE-2022-37969 </u></a>, которая представляет собой уязвимость повышения привилегий драйвера общей файловой системы Windows.</p><p></p><p>Злоумышленник, успешно воспользовавшийся этой уязвимостью,<strong> может получить системные привилегии.</strong> Эксплойт 0-day может успешно выполнить повышение привилегий в Windows 10 и Windows 11 до сентябрьского исправления.</p><p></p><p>Причина уязвимости связана с отсутствием строгой проверки границ поля SignaturesOffset в базовом блоке blf-файла журнала (BLF) в CLFS.sys. Специально созданный массив клиентского контекста и фальшивый клиентский контекст в базовом файле журнала могут использовать CLFS для перезаписи поля SignaturesOffset ненормальным значением. Это приводит к обходу проверки поля cbSymbolZone при выделении символа. Таким образом, недопустимое поле cbSymbolZone может привести к записи вне границ с произвольным смещением. В этой серии блогов, состоящей из двух частей, мы демистифицируем уязвимость и эксплойт нулевого дня, обнаруженный в дикой природе. Блоги состоят из двух частей: анализа основной причины и анализа эксплойта. В этом блоге мы впервые представляем подробный анализ основной причины CVE-2022-37969.</p><p></p><p><strong>Отладочная среда </strong></p><p></p><p>Весь анализ и отладка в этой серии блогов, состоящей из двух частей, проводились в следующей среде:</p><p></p><p>[CODE]Windows 11 21H2 version 22000.918</p><p>CLFS.sys 10.0.22000.918[/CODE]</p><p></p><p><em>Common Log File System </em>(CLFS) — это подсистема ведения журналов общего назначения, которая может использоваться приложениями, работающими как в режиме ядра, так и в пользовательском режиме, для создания высокопроизводительных журналов транзакций и реализована в драйвере CLFS.sys. Общая файловая система журналов создает журналы транзакций в <em>базовом файле журнала </em>(BLF). Введение в понятия и терминологию для CLFS указано в <a href="https://learn.microsoft.com/en-us/windows-hardware/drivers/kernel/introduction-to-the-common-log-file-system" target="_blank"><u>официальной документации </u></a>Microsoft.</p><p></p><p>Перед использованием CLFS файл журнала создается с помощью <a href="https://learn.microsoft.com/en-us/windows/desktop/api/Clfsw32/nf-clfsw32-createlogfile" target="_blank"><strong>API CreateLogFile</strong></a>. Файл журнала состоит из blf-файла, состоящего из блоков метаданных, и нескольких контейнеров, в которых хранятся фактические данные. API <a href="https://learn.microsoft.com/en-us/windows/win32/api/clfsw32/nf-clfsw32-addlogcontainer" target="_blank"><u><strong>AddLogContainer</strong> </u></a>используется для добавления контейнера в физический журнал, связанный с дескриптором журнала.</p><p></p><p>Рисунок 1 иллюстрирует формат BLF на основе <a href="https://learn.microsoft.com/en-us/previous-versions/windows/desktop/clfs/common-log-file-system-portal" target="_blank"><u><strong>официальной документации CLFS</strong> </u></a>Алекса Ионеску <a href="https://github.com/ionescu007/clfs-docs/blob/main/README.md" target="_blank"><u><strong>и неофициальной документации </strong></u></a><strong>.</strong></p><p></p><p>[ATTACH=full]60089[/ATTACH]</p><p><strong>Рис. 1. Формат базового файла журнала (BLF)</strong></p><p></p><p>Blf-файл состоит из шести различных блоков метаданных: Control Block, Base Block и Truncate Block, а также соответствующих им shadow block. В этих блоках могут находиться три типа записей (Control Record, Base Record и Truncate Record). Этот блог посвящен только базовой записи, которая имеет отношение к данной уязвимости. Базовая запись включает в себя символьные таблицы, которые хранят информацию о контекстах клиента, контекстах контейнера и контекстах безопасности, связанных с базовым файлом журнала.</p><p></p><p>Каждый блок журнала начинается с заголовка блока журнала, структура которого определена ниже:</p><p></p><p>[CODE]typedef struct _CLFS_LOG_BLOCK_HEADER</p><p>{</p><p> UCHAR MajorVersion;</p><p> UCHAR MinorVersion;</p><p> UCHAR Usn;</p><p> CLFS_CLIENT_ID ClientId;</p><p> USHORT TotalSectorCount;</p><p> USHORT ValidSectorCount;</p><p> ULONG Padding;</p><p> ULONG Checksum;</p><p> ULONG Flags;</p><p> CLFS_LSN CurrentLsn;</p><p> CLFS_LSN NextLsn;</p><p> ULONG RecordOffsets[16];</p><p> ULONG SignaturesOffset;</p><p>} CLFS_LOG_BLOCK_HEADER, *PCLFS_LOG_BLOCK_HEADER;[/CODE]</p><p></p><p>Схема памяти структуры CLFS_LOG_BLOCK_HEADER, размер которой составляет 0x70 байт, показана на рисунке 1. Поле SignaturesOffset - это смещение массива в памяти, который используется для хранения всех подписей секторов. Массив должен располагаться на последнем секторе каждого блока. Сигнатура сектора располагается в конце каждого сектора (размер: 0x200) и состоит из типа Sector Block Type (1 байт) и Usn (1 байт). Ниже перечислены типы сектора.</p><p></p><p>[CODE]const UCHAR SECTOR_BLOCK_NONE = 0x00;</p><p>const UCHAR SECTOR_BLOCK_DATA = 0x04;</p><p>const UCHAR SECTOR_BLOCK_OWNER = 0x08;</p><p>const UCHAR SECTOR_BLOCK_BASE = 0x10;</p><p>const UCHAR SECTOR_BLOCK_END = 0x20;</p><p>const UCHAR SECTOR_BLOCK_BEGIN = 0x40;[/CODE]</p><p></p><p>На рисунке 1 base block начинается по смещению 0x800 и заканчивается по смещению 0x71FF в файле .BLF и начинается с заголовка Log Block Header (0x70 байт), за которым следует заголовок Base Record Header, а затем записи. Заголовок Base Record Header может быть представлен структурой CLFS_BASE_RECORD_HEADER, описанной на рисунке 2.</p><p></p><p>[ATTACH=full]60090[/ATTACH]</p><p>Рисунок 2. Определение структуры CLFS_BASE_RECORD_HEADER</p><p></p><p>Схема структуры CLFS_BASE_RECORD_HEADER показана на рисунке 3</p><p></p><p>[ATTACH=full]60091[/ATTACH]</p><p>Рисунок 3. Структурная схема заголовка Base Record Header в файле .BLF</p><p></p><p>Base Record начинается с заголовка (CLFS_BASE_RECORD_HEADER) размером 0x1338 байт, за которым следуют связанные контекстные данные. В структуре CLFS_BASE_RECORD_HEADER ниже описаны некоторые важные поля, связанные с данной уязвимостью:</p><p></p><p>rgClients представляет массив смещений, указывающих на объект Client Context.</p><p>rgContainers представляет собой массив смещений, указывающих на объект Container Context.</p><p>cbSymbolZone представляет следующее свободное смещение для нового символа в зоне символов.</p><p></p><p>В Base Record, Client Context, Container Context и Shared Security Context представлены символами, которым предшествует структура CLFSHASHSYM, определенная ниже:</p><p></p><p>[CODE]typedef struct _CLFS_NODE_ID {</p><p> ULONG cType;</p><p> ULONG cbNode;</p><p>} CLFS_NODE_ID, *PCLFS_NODE_ID;</p><p></p><p>typedef struct _CLFSHASHSYM</p><p>{</p><p> CLFS_NODE_ID cidNode;</p><p> ULONG ulHash;</p><p> ULONG cbHash;</p><p> ULONGLONG ulBelow;</p><p> ULONGLONG ulAbove;</p><p> LONG cbSymName;</p><p> LONG cbOffset;</p><p> BOOLEAN fDeleted;</p><p>} CLFSHASHSYM, *PCLFSHASHSYM;[/CODE]</p><p></p><p>Схема памяти структуры CLFSHASHSYM показана на рисунке 4, далее следуют различные объекты контекста.</p><p></p><p>[ATTACH=full]60092[/ATTACH]</p><p>Рисунок 4. Структура CLFSHASHSYM (символично)</p><p></p><p>В Base Record клиентский контекст используется для идентификации клиента для файла журнала. В Base Log File может быть создан как минимум один Client Context. Client Context представлен структурой CLFS_CLIENT_CONTEXT, определенной ниже:</p><p>[CODE]typedef struct _CLFS_CLIENT_CONTEXT</p><p>{</p><p> CLFS_NODE_ID cidNode;</p><p> CLFS_CLIENT_ID cidClient;</p><p> USHORT fAttributes;</p><p> ULONG cbFlushThreshold;</p><p> ULONG cShadowSectors;</p><p> ULONGLONG cbUndoCommitment;</p><p> LARGE_INTEGER llCreateTime;</p><p> LARGE_INTEGER llAccessTime;</p><p> LARGE_INTEGER llWriteTime;</p><p> CLFS_LSN lsnOwnerPage;</p><p> CLFS_LSN lsnArchiveTail;</p><p> CLFS_LSN lsnBase;</p><p> CLFS_LSN lsnLast;</p><p> CLFS_LSN lsnRestart;</p><p> CLFS_LSN lsnPhysicalBase;</p><p> CLFS_LSN lsnUnused1;</p><p> CLFS_LSN lsnUnused2;</p><p> CLFS_LOG_STATE eState; //+0x78</p><p> union</p><p> {</p><p> HANDLE hSecurityContext;</p><p> ULONGLONG ullAlignment;</p><p> };</p><p>} CLFS_CLIENT_CONTEXT, *PCLFS_CLIENT_CONTEXT;[/CODE]</p><p></p><p>В Base Record контекст контейнера связан с добавлением файла контейнера для base log file, который представлен структурой CLFS_CONTAINER_CONTEXT, определенной ниже:</p><p></p><p>[CODE]typedef struct _CLFS_CONTAINER_CONTEXT</p><p>{</p><p> CLFS_NODE_ID cidNode; //8 bytes</p><p> ULONGLONG cbContainer; //8 bytes</p><p> CLFS_CONTAINER_ID cidContainer; // 4 bytes</p><p> CLFS_CONTAINER_ID cidQueue; // 4 bytes</p><p> union</p><p> {</p><p> CClfsContainer* pContainer; //8 bytes</p><p> ULONGLONG ullAlignment;</p><p> };</p><p> CLFS_USN usnCurrent;</p><p> CLFS_CONTAINER_STATE eState;</p><p> ULONG cbPrevOffset; //4 bytes</p><p> ULONG cbNextOffset; //4 bytes</p><p>} CLFS_CONTAINER_CONTEXT, *PCLFS_CONTAINER_CONTEXT;[/CODE]</p><p></p><p>Поле pContainer является указателем на объект в адресном пространстве ядра CClfsContainer, представляющий контейнер во время выполнения, который находится по смещению 0x18 в структуре CLFS_CONTAINER_CONTEXT. На рисунке 5 показана схема памяти структуры CLFS_CONTAINER_CONTEXT.</p><p></p><p>[ATTACH=full]60093[/ATTACH]</p><p>Рисунок 5. Схема памяти структуры CLFS_CONTAINER_CONTEXT</p><p></p><p>Чтобы определить первопричину CVE-2022-37969, ThreatLabz разработала Proof-of-Concept (PoC), который стабильно вызывает сбой "синего экрана смерти" (BSOD). На рисунке 6 показана подробная информация о сбое после срабатывания уязвимости.</p><p></p><p>[ATTACH=full]60094[/ATTACH]</p><p>Рисунок 6. Информация о крахе CVE-2022-37969 в WinDbg</p><p></p><p>Как показано на рисунке 6, регистр rdi указывает на ошибочный адрес памяти. В регистре rdi хранится указатель на объект CClfsContainer. В структуре CLFS_CONTAINER_CONTEXT, описанной ранее, поле pContainer является указателем на объект CClfsContainer и расположено по смещению 0x18 в схеме памяти. Судя по расположению сбоя, поле pContainer в структуре CLFS_CONTAINER_CONTEXT было испорчено. Это приводит к сбою BSOD при разыменовании этого указателя.</p><p></p><p>На рисунке 7 показано сравнение правильно структурированного BLF-файла и специально созданного BLF-файла, который используется для запуска уязвимости CVE-2022-37969.</p><p>[ATTACH=full]60095[/ATTACH]</p><p>Рисунок 7. Специально созданный файл Base Log File (BLF) для CVE-2022-37969</p><p></p><p>После создания этого bfl-файла определенные байты, включая поле SignatureOffset, массив смещений клиентского контекста, cbSymbol, фальшивый клиентский контекст и т.д., должны быть соответствующим образом изменены. Как показано на рисунке 7, все измененные байты находятся в записи Base Log Record (смещение: 0x800 ~ 0x81FF в файле .blf). Модификации файла .blf перечислены на рисунке 8.</p><p></p><p>[ATTACH=full]60096[/ATTACH]</p><p>Рисунок 8. Модификации файла .BLF для запуска CVE-2022-37969</p><p></p><p>Код Proof-of-Concept для запуска CVE-2022-37969 показан на рисунке 9.</p><p></p><p>[ATTACH=full]60097[/ATTACH]</p><p>Рисунок 9. Фрагмент кода для доказательства концепции CVE-2022-37969</p><p></p><p>Proof-of-Concept для CVE-2022-37969 включает следующие шаги.</p><p></p><p>Создайте основной файл журнала MyLog.blf в папке C:\Users\Public\ с помощью API CreateLogFile.</p><p>Создайте дюжину базовых файлов журнала с именем MyLog_xxx.blf. Очень важно, чтобы смещение между двумя созданными впоследствии областями памяти, представляющими Base Block, было постоянным (где постоянное смещение равно 0x11000 байт). Оригинальный образец 0-day использовал усовершенствованный метод для получения константы смещения. Во второй части этой серии блогов будет рассмотрена эта техника.</p><p>В PoC ThreatLabz используется постоянный счетчик для создания blf-файлов, и поэтому смещение между двумя созданными впоследствии областями памяти может быть не постоянным. Следовательно, в данной ситуации необходимо подстроить значение константы.</p><p>Измените пару байт в определенных смещениях в файле MyLog.blf, пересчитайте новую контрольную сумму CRC32 для Base Block, затем запишите новое значение контрольной суммы по смещению 0x80C. Затем откройте существующий MyLog.blf.</p><p>Вызовите API CreateLogFile, чтобы создать MyLxg_xxx.blf в папке C:\Users\Public\.</p><p>Вызовите API AddLogContainer, чтобы добавить контейнер журнала для MyLxg_xxx.blf, созданного на шаге 4.</p><p>Вызовите GetProcAddress(LoadLibraryA("ntdll.dll"), "NtSetInformationFile"), чтобы получить адрес функции API NtSetInformationFile.</p><p>Вызовите API AddLogContainer, чтобы добавить контейнер журнала для MyLog.blf, открытого в шаге 3.</p><p>Вызовите NtSetInformationFile(v55, (PIO_STATUS_BLOCK)v33, v28, 1, (FILE_INFORMATION_CLASS)13), где последний параметр - тип FileInformationClass. Если значение равно FileDispositionInformation (13), функция удалит файл при его закрытии или отменит ранее запрошенное удаление.</p><p>Вызовите API CloseHandle для закрытия обработчика MyLxg_xxx.blf, чтобы запустить эту уязвимость.</p><p></p><p><strong>Анализ причины:</strong></p><p></p><p>Теперь, когда доказательство кода было представлено, можно проанализировать первопричину. На рисунке 9 шаг 3 вызывает API CreateLogFile, 5-й параметр которого равен 4 (OPEN_ALWAYS), что открывает существующий файл или создает его, если он не существует. В данном случае открывается существующий MyLog.blf. На шаге 4 код вызывает API CreateLogFile для создания нового blf-файла с именем MyLxg_xxx.blf. На шагах 5 и 7, соответственно, код вызывает AddLogContainer, чтобы добавить контейнер в физический журнал, связанный с данным хэндлом журнала.</p><p>Сначала рассмотрим подробнее, как драйвер CLFS обрабатывает запрос на добавление контейнера журнала при вызове функции AddLogContainer() в пространстве пользователя. Для отслеживания процесса обработки этого запроса можно установить следующую точку останова.</p><p></p><p>[CODE] bu CLFS!CClfsRequest::AllocContainer[/CODE]</p><p></p><p>В CLFS.sys класс CClfsRequest отвечает за обработку запросов из пространства пользователя. Функция CClfsRequest::AllocContainer используется для обработки запроса на добавление контейнера в физический журнал. Функция CClfsRequest::AllocContainer вызывает CClfsLogFcbPhysical::AllocContainer, объявление которого показано ниже:</p><p></p><p>[CODE]CClfsLogFcbPhysical::AllocContainer(CClfsLogFcbPhysical *this, _FILE_OBJECT *,_UNICODE_STRING *,unsigned __int64 *)[/CODE]</p><p></p><p>Далее точка останова на CClfsLogFcbPhysical::AllocContainer устанавливается следующим образом:</p><p></p><p>[CODE]bu CLFS!CClfsLogFcbPhysical::AllocContainer[/CODE]</p><p></p><p>На шаге 5, когда код вызывает функцию AddLogContainer, срабатывает точка останова на CClfsLogFcbPhysical::AllocContainer. Когда точка останова достигнута, давайте проверим указатель this класса CClfsLogFcbPhysical. Тhis указывает на объект CClfsLogFcbPhysical. Как показано на рисунке 10, в регистре rcx хранится указатель this класса CClfsLogFcbPhysical.</p><p></p><p>[ATTACH=full]60098[/ATTACH]</p><p>Рисунок 10. Проверка указателя этого класса CClfsLogFcbPhysical в CClfsLogFcbPhysical::AllocContainer</p><p></p><p>Адрес vftable в классе CClfsLogFcbPhysical хранится по смещению 0x00. По смещению this+0x30 хранится указатель на имя журнала. По смещению this+0x2B0 хранится указатель на класс CClfsBaseFilePersisted. В памяти Base Log File CLFS представлен классом CClfsBaseFile, который может быть расширен классом CClfsBaseFilePersisted. В этом указателе класса CClfsBaseFilePersisted по смещению 0x30 хранится указатель на буфер кучи размером 0x90 байт. Кроме того, в буфере кучи по смещению 0x30 хранится указатель на Base Block. Кроме того, в этом указателе CClfsBaseFilePersisted по смещению 0x1C0 хранится указатель на объект CClfsContainer. После успешного добавления контейнера мы можем проверить структуру CLFS_CONTAINER_CONTEXT, описанную на рисунке 5, в памяти, как показано на рисунке 11.</p><p></p><p>[ATTACH=full]60099[/ATTACH]</p><p>Рисунок 11. Структура CLFS_CONTAINER_CONTEXT после успешного добавления контейнера</p><p></p><p>По смещению 0x1C0 в объекте CClfsBaseFilePersisted хранится указатель на объект CClfsContainer, который берется из поля pContainer в структуре CLFS_CONTAINER_CONTEXT. В этот момент можно установить точку останова записи в память по адресу CLFS_CONTAINER_CONTEXT+0x18, чтобы отследить, когда указатель на объект CClfsContainer в структуре CLFS_CONTAINER_CONTEXT будет поврежден. Еще одна точка останова записи в память по смещению 0x1C0 в объекте CClfsBaseFilePersisted может быть установлена следующим образом:</p><p></p><p>[CODE]1: kd> ba w8 ffffc80c`cc86a4f0 //CLFS_CONTAINER_CONTEXT: +0x18</p><p></p><p> 1: kd> ba w8 ffffb702`3cf251c0 //CClfsBaseFilePersisted: +0x1C0[/CODE]</p><p></p><p>На шаге 7, когда код вызывает функцию AddLogContainer, точки останова на CLFS!CClfsRequest::AllocContainer и CLFS!CClfsLogFcbPhysical::AllocContainer снова сбиваются. В этот момент давайте проверим указатель this (см. рисунок 12) класса CClfsLogFcbPhysical. Стоит отметить, что поле SignaturesOffset, которое изначально было установлено в 0x00000050 в созданном файле MyLog.blf, в памяти было установлено в 0xFFFF0050.</p><p></p><p>[ATTACH=full]60100[/ATTACH]</p><p>Рисунок 12. Проверка указателя this для класса CClfsLogFcbPhysical</p><p></p><p>В WinDbg продолжим выполнение кода. Точка останова записи в память "ba w8 ffffc80c`cc86a4f0" будет достигнута, и структура CLFS_CONTAINER_CONTEXT в base Record производит out-of-bound запись, что приводит к повреждению указателя в объекте CClfsContainer, показанном на рисунке 13.</p><p></p><p>[ATTACH=full]60101[/ATTACH]</p><p>Рисунок 13. Повреждение указателя на объект CClfsContainer в структуре CLFS_CONTAINER_CONTEXT</p><p></p><p>Исходя из приведенной выше обратной трассировки стека вызовов, функция memset была вызвана, чтобы вызвать точку останова записи в память в функции CClfsBaseFilePersisted::AllocSymbol. На рисунке 14 показан псевдокод функции CClfsBaseFilePersisted::AllocSymbol.</p><p></p><p>[ATTACH=full]60102[/ATTACH]</p><p>Рисунок 14. Псевдокод функции CClfsBaseFilePersisted::AllocSymbol</p><p></p><p>Эта функция описывается следующим образом:</p><p></p><p>Переменная v9 - это значение поля cbSymbolZone в заголовке Base Record Header. Поле cbSymbolZone было установлено в аномальное значение, описанное на рисунке 8. Это значение было изменено с 0x000000F8 на 0x0001114B.</p><p>Проверьте поле cbSymbolZone. Чтобы выполнить ООВ-запись на шаге 4, эту проверку необходимо обойти. Поле SignaturesOffset, которое изначально имело значение 0x00000050 в файле MyLog.blf, описанном на рисунке 7, было перезаписано большим числом (0xFFFF0050) в памяти. Поэтому, даже когда поле cbSymbolZone установлено в ненормальное значение, проверку для поля cbSymbolZone все равно можно обойти. Определение причины того, что поле SignaturesOffset установлено в 0xFFFF0050 из 0x00000050, является первопричиной CVE-2022-37969.</p><p>Переменная v10 равна v9 плюс BaseLogRecord плюс 0x1338, а переменная v9 равна 0x0001114b, что приводит к недопустимому смещению в v10.</p><p>Функция вызывает memset(), что приводит к OOB-записи по недопустимому смещению v10, которое попадает в структуру CLFS_CONTAINER_CONTEXT в базовой записи для MyLxg_xxx.blf, что приводит к повреждению указателя CClfsContainer по смещению 0x18 в структуре CLFS_CONTAINER_CONTEXT.</p><p></p><p>На рисунке 15 показано, как происходит запись вне границ, что приводит к повреждению указателя в объекте CClfsContainer.</p><p></p><p>[ATTACH=full]60103[/ATTACH]</p><p>Рисунок 15. Объяснение несанкционированной записи, вызванной CVE-2022-37969</p><p></p><p>Итак, мы обсудили, почему произошла запись вне границ и как был поврежден указатель на объект CClfsContainer в структуре CLFS_CONTAINER_CONEXT. Далее рассмотрим, когда произойдет разыменование поврежденного указателя CClfsContainer. После этого мы вернемся к выяснению того, почему поле SignaturesOffset в памяти установлено в 0xFFFF0050 из 0x00000050.</p><p></p><p>Когда в пространстве пользователя вызывается функция CloseHandle, за обработку этого запроса отвечает CClfsRequest::Close(PIRP Irp). В ядре еще одна точка останова памяти (0x1c0+CClfsBaseFilePersisted) достигается в функции ClfsBaseFilePersisted::WriteMetadataBlock, как показано на рисунке 16.</p><p></p><p>[ATTACH=full]60104[/ATTACH]</p><p>Рисунок 16. Точка останова памяти(0x1c0+CClfsBaseFilePersisted) в ClfsBaseFilePersisted::WriteMetadataBlock</p><p></p><p>Поврежденный указатель копируется на объект CClfsContainer в структуре CLFS_CONTAINER_CONTEXT в базовой записи по смещению 0x1c0 в объекте CClfsBaseFilePersisted.</p><p></p><p>На рисунке 17 показан псевдокод функции ClfsBaseFilePersisted::WriteMetadataBlock после того, как поврежденный указатель на CClfsContainer был сохранен по смещению 0x1c0 в объекте CClfsBaseFilePersisted. Код обнуляет поле указателя на объект CClfsContainer в структуре CLFS_CONTAINER_CONTEXT. После декодирования блока указатель на объект CClfsContainer восстанавливается в структуре CLFS_CONTAINER_CONTEXT со смещения 0x1c0 в объекте CClfsBaseFilePersisted.</p><p></p><p>[ATTACH=full]60105[/ATTACH]</p><p>Рисунок 17. Псевдокод функции ClfsBaseFilePersisted::WriteMetadataBlock</p><p></p><p>Наконец, точка останова на CLFS!CClfsBaseFilePersisted::RemoveContainer может быть установлена для отслеживания момента разыменования поврежденного указателя на объект CClfsContainer в структуре CLFS_CONTAINER_CONTEXT в Base Record.</p><p></p><p>На рисунке 18 показан псевдокод функции CClfsBaseFilePersisted::RemoveContainer.</p><p></p><p>[ATTACH=full]60106[/ATTACH]</p><p>Рисунок 18.Псевдокод функции CClfsBaseFilePersisted::RemoveContainer</p><p></p><p>В функции CClfsBaseFilePersisted::RemoveContainer выполняются следующие шаги.</p><p></p><p>Получает смещение контекста контейнера по смещению 0x398 в Base Record.</p><p>Вызывает CClfsBaseFile::GetSymbol для получения указателя на структуру CLFS_CONTAINER_CONTEXT и сохраняет его в 4-м параметре.</p><p>Присваивает значение указателя на объект CClfsContainter в структуре CLFS_CONTAINER_CONTEXT, полученной на шаге 2, локальной переменной v13.</p><p>Обнуляет указатель на объект CClfsContainter в структуре CLFS_CONTAINER_CONTEXT.</p><p>Поочередно вызывает CClfsContainer::Remove и CClfsContainer::Release для удаления связанного с контейнером файла журнала и освобождения объекта CClfsContainer.</p><p></p><p>Разыменование поврежденного указателя на объект CClfsContainter приводит к нарушению памяти. На рисунке 19 показана информация о сбое в WinDbg, в результате чего происходит сбой BSOD.</p><p></p><p>[ATTACH=full]60107[/ATTACH]</p><p>Рисунок 19. Разыменование поврежденного указателя на объект CClfsContainter</p><p></p><p>Как описано на рисунке 14, в функции CClfsBaseFilePersisted::AllocSymbol произошла несвязанная запись. Перед вызовом функции memset проверка поля cbSymbolZone была обойдена из-за того, что поле SignaturesOffset в памяти было перезаписано значением 0xFFFF0050. Поле SignaturesOffset в памяти базового блока может быть перезаписано на 0xFFFF0050 в процессе обработки запроса вызова API CreateLogFile для открытия специально созданного базового файла журнала MyLog.blf, описанного в шаге 3 на рисунке 9.</p><p>Когда функция CreateLogFile вызывается в пространстве пользователя, CLFS!CClfsRequest::Create отвечает за обработку этого запроса. Когда функция CreateLogFile используется для открытия существующего base log file, в CLFS.sys вызывается функция CClfsLogFcbPhysical::Initialize. На рисунке 20 показан фрагмент псевдокода функции CClfsLogFcbPhysical::Initialize.</p><p></p><p>[ATTACH=full]60108[/ATTACH]</p><p>Рисунок 20. Фрагмент псевдокода функции CClfsLogFcbPhysical::Initialize</p><p></p><p>Эта функция описывается следующим образом:</p><p></p><p>1. Вызвать функцию CClfsBaseFilePersisted::OpenImage для создания bigpool (размер: 0x7a00) для базы блока в базовом файле журнала. Для входа в функцию CClfsBaseFilePersisted::ReadMetadataBlock можно выполнить следующие вызовы функций.</p><p>[CODE]CClfsBaseFilePersisted::OpenImage -> CClfsBaseFilePersisted::ReadImage -> CClfsBaseFile::AcquireMetadataBlock -> CClfsBaseFilePersisted::ReadMetadataBlock[/CODE]</p><p></p><p>На рисунке 21 показан фрагмент псевдокода функции CClfsBaseFilePersisted::ReadMetadataBlock, где вызывается ExAllocatePoolWithTag(PagedPoolCacheAligned, 0x7a00, 0x73666C43u) для создания bigpool для хранения базового блока, затем следует инициализация, а затем вызывается функция ClfsDecodeBlock для декодирования блока. В функции ClfsDecodeBlock вызывается функция ClfsDecodeBlockPrivate для разбора массива сигнатур секторов, расположенного по смещению 0x50 (значение SignaturesOffset) в базовом блоке. Для перезаписи подписи сектора каждого сектора требуется два байта. Эти два байта 0x0050 по смещению 0x68 в базовом блоке могут быть перезаписаны по смещению 0x19FE (0xC*0x200+0x1FE), где хранится подпись сектора 13-й секции. В этот момент мы можем установить две точки останова записи в память, расположенные по адресам base_block+0x68 и base_block+0x200*0xE-0x8. Цель установки этих двух точек останова записи в память - отследить момент перезаписи подписи сектора 14-го раздела в базовом блоке, а поле SignaturesOffset в базовом блоке переписать в 0xFFFF0050.</p><p></p><p>[CODE] 1: kd> ba w8 ffffd08b`51c03000+0x68 //base_block+0x68</p><p></p><p> 1: kd> ba w8 ffffd08b`51c03000+0x200*0xE-0x8 //базовый_блок+0x200*0xe-0x8[/CODE]</p><p></p><p>[ATTACH=full]60109[/ATTACH]</p><p>Рисунок 21. Фрагмент псевдокода функции CClfsBaseFilePersisted::ReadMetadataBlock</p><p></p><p>2. Вызов функции CClfsBaseFile::AcquireClientContext для получения клиентского контекста из базового блока. Как показано на рисунке 7, первое смещение в массиве смещений клиентского контекста, расположенное по адресу 0x9A8 в blf-файле, является специально созданным. Поддельный клиентский контекст расположен по смещению 0x23A0 в base log file. Поле eState, расположенное по смещению 0x78 в структуре поддельного Контекста клиента, установлено в 0x20 (CLFS_LOG_SHUTDOWN).</p><p></p><p>3. Проверьте, не является ли поле eState значением CLFS_LOG_SHUTDOWN или базовый журнал является мультиплексированным журналом.</p><p></p><p>4. Вызовите функцию CClfsLogFcbPhysical::ResetLog, так как условие было ложным на шаге 3. На рисунке 22 показан фрагмент псевдокода функции CClfsLogFcbPhysical::ResetLog. 8 байт, расположенные по адресу base_block+0x1BF8, установлены в 0xFFFFFFFF000000. Подпись сектора расположена по смещению base_block+0x1BFC. Поэтому сигнатура сектора перезаписывается на 0xFFFFFF. На рисунке 23 показано, что подпись сектора перезаписана в WinDbg.</p><p></p><p>[ATTACH=full]60110[/ATTACH]</p><p>Рисунок 22. Фрагмент псевдокода функции CClfsLogFcbPhysical::ResetLo</p><p></p><p>[ATTACH=full]60111[/ATTACH]</p><p>Рисунок 23. Подпись сектора перезаписана 0xFFFF</p><p></p><p>5. Вызовите функцию CClfsLogFcbPhysical::FlushMetaData. Для входа в функцию CLFS!ClfsEncodeBlockPrivate можно выполнить следующие вызовы функций.</p><p></p><p>[CODE] CLFS!CClfsLogFcbPhysical::FlushMetadata -> CLFS!CClfsBaseFilePersisted::FlushImage -> CLFS!CClfsBaseFilePersisted::WriteMetadataBlock -> CLFS!ClfsEncodeBlock -> CLFS!ClfsEncodeBlockPrivate[/CODE]</p><p></p><p>На рисунке 24 показан фрагмент псевдокода функции CLFS!ClfsEncodeBlockPrivate.</p><p></p><p>[ATTACH=full]60112[/ATTACH]</p><p></p><p>Приведенный выше код получает сигнатуру сектора из каждого сектора базового блока и перезаписывает массив сигнатур сектора сигнатурой сектора. Массив сигнатур секторов расположен по смещению 0x50 и перекрывает поле SignaturesOffset в базовом блоке. Подпись сектора 14-го сектора была установлена в 0xFFFF, как показано на рисунке 23. Поэтому два байта (0xFFFF) перезаписываются по смещению 0x6C (0x50+0xE*2) в базовом блоке. В это время поле SignaturesOffset имеет значение 0xFFFF0050, как показано на рисунке 25.</p><p></p><p>[ATTACH=full]60113[/ATTACH]</p><p>Рисунок 25. Поле SignaturesOffset перезаписано значением 0xFFFF0050</p><p></p><p>В конце мы обобщаем процесс перезаписи поля SignaturesOffset на рисунке 26.</p><p></p><p>[ATTACH=full]60114[/ATTACH]</p><p>Рисунок 26. Процесс перезаписи поля SignaturesOffset</p><p></p><p><strong>Заключение</strong></p><p></p><p>В этом блоге ThreatLabz представила подробный анализ первопричины CVE-2022-37969, которая связана с неправильной проверкой границ поля SignaturesOffset в Base Block для базового файла журнала (BLF) в CLFS.sys. Специально созданный массив клиентских контекстов и поддельный клиентский контекст в base log file могут использовать CLFS для перезаписи поля SignaturesOffset ненормальным значением. Это приводит к обходу проверки для поля cbSymbolZone при выделении символа. Таким образом, недействительное поле cbSymbolZone может привести к ООВ - записи по произвольному смещению. Поэтому указатель на объект CClfsContainer может быть поврежден. При разыменовании поврежденный указатель на объект CClfsContainer вызывает нарушение памяти, которое приводит к аварийному завершению работы BSOD.</p><p></p><p><strong>Во второй части мы представим анализ эксплойта 0-day, использующего эту уязвимость для повышения привилегий. Оставайтесь с нами!</strong></p><p></p><p>Всем пользователям Windows рекомендуется <strong>обновить систему до последней версии</strong>. Решения Advanced Threat Protection и Advanced Cloud Sandbox от Zscaler могут защитить клиентов от эксплойта 0-day, использующего уязвимость CVE-2022-37969.</p><p></p><p>Win32.GenExploit.LogFile</p><p>Win32.Exploit.CVE-2022-37969</p><p></p><p><strong><img src="/0798.gif" class="smilie" loading="lazy" alt="Dmeh-Smeh-Smeh!!!" title="Dmeh-Smeh-Smeh!!! Dmeh-Smeh-Smeh!!!" data-shortname="Dmeh-Smeh-Smeh!!!" />!КТО ПРОЧИТАЛ, СНИМАЮ ШЛЯПУ! <img src="/0798.gif" class="smilie" loading="lazy" alt="Dmeh-Smeh-Smeh!!!" title="Dmeh-Smeh-Smeh!!! Dmeh-Smeh-Smeh!!!" data-shortname="Dmeh-Smeh-Smeh!!!" /></strong></p><p><strong></strong></p><p><strong>СЕЙЧАС ВЫЛОЖУ ВТОРУЮ ЧАСТЬ</strong></p></blockquote><p></p>
[QUOTE="X-Shar, post: 148070, member: 1"] Всем привет! На xss.is нашёл классный перевод:[URL]https://xss.is/threads/75428/[/URL] Но к сожалению там не оформили как статью, поэтому надёюсь никто не против, если я перенесу этот интересный материал сюда. Отдыхай!!! [B]2 сентября 2022 г[/B]. компания Zscaler Threatlabz зафиксировала эксплойт нулевого дня в общем системном драйвере файлов журнала Windows (CLFS.sys) и сообщила об этом обнаружении в Microsoft. В сентябрьском [URL='https://msrc.microsoft.com/update-guide/vulnerability/CVE-2022-37969'][U]патче, выпущенном во вторник [/U][/URL], Microsoft исправила эту уязвимость, идентифицированную как [URL='https://msrc.microsoft.com/update-guide/vulnerability/CVE-2022-37969'][U]CVE-2022-37969 [/U][/URL], которая представляет собой уязвимость повышения привилегий драйвера общей файловой системы Windows. Злоумышленник, успешно воспользовавшийся этой уязвимостью,[B] может получить системные привилегии.[/B] Эксплойт 0-day может успешно выполнить повышение привилегий в Windows 10 и Windows 11 до сентябрьского исправления. Причина уязвимости связана с отсутствием строгой проверки границ поля SignaturesOffset в базовом блоке blf-файла журнала (BLF) в CLFS.sys. Специально созданный массив клиентского контекста и фальшивый клиентский контекст в базовом файле журнала могут использовать CLFS для перезаписи поля SignaturesOffset ненормальным значением. Это приводит к обходу проверки поля cbSymbolZone при выделении символа. Таким образом, недопустимое поле cbSymbolZone может привести к записи вне границ с произвольным смещением. В этой серии блогов, состоящей из двух частей, мы демистифицируем уязвимость и эксплойт нулевого дня, обнаруженный в дикой природе. Блоги состоят из двух частей: анализа основной причины и анализа эксплойта. В этом блоге мы впервые представляем подробный анализ основной причины CVE-2022-37969. [B]Отладочная среда [/B] Весь анализ и отладка в этой серии блогов, состоящей из двух частей, проводились в следующей среде: [CODE]Windows 11 21H2 version 22000.918 CLFS.sys 10.0.22000.918[/CODE] [I]Common Log File System [/I](CLFS) — это подсистема ведения журналов общего назначения, которая может использоваться приложениями, работающими как в режиме ядра, так и в пользовательском режиме, для создания высокопроизводительных журналов транзакций и реализована в драйвере CLFS.sys. Общая файловая система журналов создает журналы транзакций в [I]базовом файле журнала [/I](BLF). Введение в понятия и терминологию для CLFS указано в [URL='https://learn.microsoft.com/en-us/windows-hardware/drivers/kernel/introduction-to-the-common-log-file-system'][U]официальной документации [/U][/URL]Microsoft. Перед использованием CLFS файл журнала создается с помощью [URL='https://learn.microsoft.com/en-us/windows/desktop/api/Clfsw32/nf-clfsw32-createlogfile'][B]API CreateLogFile[/B][/URL]. Файл журнала состоит из blf-файла, состоящего из блоков метаданных, и нескольких контейнеров, в которых хранятся фактические данные. API [URL='https://learn.microsoft.com/en-us/windows/win32/api/clfsw32/nf-clfsw32-addlogcontainer'][U][B]AddLogContainer[/B] [/U][/URL]используется для добавления контейнера в физический журнал, связанный с дескриптором журнала. Рисунок 1 иллюстрирует формат BLF на основе [URL='https://learn.microsoft.com/en-us/previous-versions/windows/desktop/clfs/common-log-file-system-portal'][U][B]официальной документации CLFS[/B] [/U][/URL]Алекса Ионеску [URL='https://github.com/ionescu007/clfs-docs/blob/main/README.md'][U][B]и неофициальной документации [/B][/U][/URL][B].[/B] [ATTACH type="full" alt="1668954132708.png"]60089[/ATTACH] [B]Рис. 1. Формат базового файла журнала (BLF)[/B] Blf-файл состоит из шести различных блоков метаданных: Control Block, Base Block и Truncate Block, а также соответствующих им shadow block. В этих блоках могут находиться три типа записей (Control Record, Base Record и Truncate Record). Этот блог посвящен только базовой записи, которая имеет отношение к данной уязвимости. Базовая запись включает в себя символьные таблицы, которые хранят информацию о контекстах клиента, контекстах контейнера и контекстах безопасности, связанных с базовым файлом журнала. Каждый блок журнала начинается с заголовка блока журнала, структура которого определена ниже: [CODE]typedef struct _CLFS_LOG_BLOCK_HEADER { UCHAR MajorVersion; UCHAR MinorVersion; UCHAR Usn; CLFS_CLIENT_ID ClientId; USHORT TotalSectorCount; USHORT ValidSectorCount; ULONG Padding; ULONG Checksum; ULONG Flags; CLFS_LSN CurrentLsn; CLFS_LSN NextLsn; ULONG RecordOffsets[16]; ULONG SignaturesOffset; } CLFS_LOG_BLOCK_HEADER, *PCLFS_LOG_BLOCK_HEADER;[/CODE] Схема памяти структуры CLFS_LOG_BLOCK_HEADER, размер которой составляет 0x70 байт, показана на рисунке 1. Поле SignaturesOffset - это смещение массива в памяти, который используется для хранения всех подписей секторов. Массив должен располагаться на последнем секторе каждого блока. Сигнатура сектора располагается в конце каждого сектора (размер: 0x200) и состоит из типа Sector Block Type (1 байт) и Usn (1 байт). Ниже перечислены типы сектора. [CODE]const UCHAR SECTOR_BLOCK_NONE = 0x00; const UCHAR SECTOR_BLOCK_DATA = 0x04; const UCHAR SECTOR_BLOCK_OWNER = 0x08; const UCHAR SECTOR_BLOCK_BASE = 0x10; const UCHAR SECTOR_BLOCK_END = 0x20; const UCHAR SECTOR_BLOCK_BEGIN = 0x40;[/CODE] На рисунке 1 base block начинается по смещению 0x800 и заканчивается по смещению 0x71FF в файле .BLF и начинается с заголовка Log Block Header (0x70 байт), за которым следует заголовок Base Record Header, а затем записи. Заголовок Base Record Header может быть представлен структурой CLFS_BASE_RECORD_HEADER, описанной на рисунке 2. [ATTACH type="full" alt="1668954261104.png"]60090[/ATTACH] Рисунок 2. Определение структуры CLFS_BASE_RECORD_HEADER Схема структуры CLFS_BASE_RECORD_HEADER показана на рисунке 3 [ATTACH type="full" alt="1668954288586.png"]60091[/ATTACH] Рисунок 3. Структурная схема заголовка Base Record Header в файле .BLF Base Record начинается с заголовка (CLFS_BASE_RECORD_HEADER) размером 0x1338 байт, за которым следуют связанные контекстные данные. В структуре CLFS_BASE_RECORD_HEADER ниже описаны некоторые важные поля, связанные с данной уязвимостью: rgClients представляет массив смещений, указывающих на объект Client Context. rgContainers представляет собой массив смещений, указывающих на объект Container Context. cbSymbolZone представляет следующее свободное смещение для нового символа в зоне символов. В Base Record, Client Context, Container Context и Shared Security Context представлены символами, которым предшествует структура CLFSHASHSYM, определенная ниже: [CODE]typedef struct _CLFS_NODE_ID { ULONG cType; ULONG cbNode; } CLFS_NODE_ID, *PCLFS_NODE_ID; typedef struct _CLFSHASHSYM { CLFS_NODE_ID cidNode; ULONG ulHash; ULONG cbHash; ULONGLONG ulBelow; ULONGLONG ulAbove; LONG cbSymName; LONG cbOffset; BOOLEAN fDeleted; } CLFSHASHSYM, *PCLFSHASHSYM;[/CODE] Схема памяти структуры CLFSHASHSYM показана на рисунке 4, далее следуют различные объекты контекста. [ATTACH type="full" alt="1668954357858.png"]60092[/ATTACH] Рисунок 4. Структура CLFSHASHSYM (символично) В Base Record клиентский контекст используется для идентификации клиента для файла журнала. В Base Log File может быть создан как минимум один Client Context. Client Context представлен структурой CLFS_CLIENT_CONTEXT, определенной ниже: [CODE]typedef struct _CLFS_CLIENT_CONTEXT { CLFS_NODE_ID cidNode; CLFS_CLIENT_ID cidClient; USHORT fAttributes; ULONG cbFlushThreshold; ULONG cShadowSectors; ULONGLONG cbUndoCommitment; LARGE_INTEGER llCreateTime; LARGE_INTEGER llAccessTime; LARGE_INTEGER llWriteTime; CLFS_LSN lsnOwnerPage; CLFS_LSN lsnArchiveTail; CLFS_LSN lsnBase; CLFS_LSN lsnLast; CLFS_LSN lsnRestart; CLFS_LSN lsnPhysicalBase; CLFS_LSN lsnUnused1; CLFS_LSN lsnUnused2; CLFS_LOG_STATE eState; //+0x78 union { HANDLE hSecurityContext; ULONGLONG ullAlignment; }; } CLFS_CLIENT_CONTEXT, *PCLFS_CLIENT_CONTEXT;[/CODE] В Base Record контекст контейнера связан с добавлением файла контейнера для base log file, который представлен структурой CLFS_CONTAINER_CONTEXT, определенной ниже: [CODE]typedef struct _CLFS_CONTAINER_CONTEXT { CLFS_NODE_ID cidNode; //8 bytes ULONGLONG cbContainer; //8 bytes CLFS_CONTAINER_ID cidContainer; // 4 bytes CLFS_CONTAINER_ID cidQueue; // 4 bytes union { CClfsContainer* pContainer; //8 bytes ULONGLONG ullAlignment; }; CLFS_USN usnCurrent; CLFS_CONTAINER_STATE eState; ULONG cbPrevOffset; //4 bytes ULONG cbNextOffset; //4 bytes } CLFS_CONTAINER_CONTEXT, *PCLFS_CONTAINER_CONTEXT;[/CODE] Поле pContainer является указателем на объект в адресном пространстве ядра CClfsContainer, представляющий контейнер во время выполнения, который находится по смещению 0x18 в структуре CLFS_CONTAINER_CONTEXT. На рисунке 5 показана схема памяти структуры CLFS_CONTAINER_CONTEXT. [ATTACH type="full" alt="1668954436697.png"]60093[/ATTACH] Рисунок 5. Схема памяти структуры CLFS_CONTAINER_CONTEXT Чтобы определить первопричину CVE-2022-37969, ThreatLabz разработала Proof-of-Concept (PoC), который стабильно вызывает сбой "синего экрана смерти" (BSOD). На рисунке 6 показана подробная информация о сбое после срабатывания уязвимости. [ATTACH type="full" alt="1668954474649.png"]60094[/ATTACH] Рисунок 6. Информация о крахе CVE-2022-37969 в WinDbg Как показано на рисунке 6, регистр rdi указывает на ошибочный адрес памяти. В регистре rdi хранится указатель на объект CClfsContainer. В структуре CLFS_CONTAINER_CONTEXT, описанной ранее, поле pContainer является указателем на объект CClfsContainer и расположено по смещению 0x18 в схеме памяти. Судя по расположению сбоя, поле pContainer в структуре CLFS_CONTAINER_CONTEXT было испорчено. Это приводит к сбою BSOD при разыменовании этого указателя. На рисунке 7 показано сравнение правильно структурированного BLF-файла и специально созданного BLF-файла, который используется для запуска уязвимости CVE-2022-37969. [ATTACH type="full" alt="1668954526643.png"]60095[/ATTACH] Рисунок 7. Специально созданный файл Base Log File (BLF) для CVE-2022-37969 После создания этого bfl-файла определенные байты, включая поле SignatureOffset, массив смещений клиентского контекста, cbSymbol, фальшивый клиентский контекст и т.д., должны быть соответствующим образом изменены. Как показано на рисунке 7, все измененные байты находятся в записи Base Log Record (смещение: 0x800 ~ 0x81FF в файле .blf). Модификации файла .blf перечислены на рисунке 8. [ATTACH type="full" alt="1668954582981.png"]60096[/ATTACH] Рисунок 8. Модификации файла .BLF для запуска CVE-2022-37969 Код Proof-of-Concept для запуска CVE-2022-37969 показан на рисунке 9. [ATTACH type="full" alt="1668954604583.png"]60097[/ATTACH] Рисунок 9. Фрагмент кода для доказательства концепции CVE-2022-37969 Proof-of-Concept для CVE-2022-37969 включает следующие шаги. Создайте основной файл журнала MyLog.blf в папке C:\Users\Public\ с помощью API CreateLogFile. Создайте дюжину базовых файлов журнала с именем MyLog_xxx.blf. Очень важно, чтобы смещение между двумя созданными впоследствии областями памяти, представляющими Base Block, было постоянным (где постоянное смещение равно 0x11000 байт). Оригинальный образец 0-day использовал усовершенствованный метод для получения константы смещения. Во второй части этой серии блогов будет рассмотрена эта техника. В PoC ThreatLabz используется постоянный счетчик для создания blf-файлов, и поэтому смещение между двумя созданными впоследствии областями памяти может быть не постоянным. Следовательно, в данной ситуации необходимо подстроить значение константы. Измените пару байт в определенных смещениях в файле MyLog.blf, пересчитайте новую контрольную сумму CRC32 для Base Block, затем запишите новое значение контрольной суммы по смещению 0x80C. Затем откройте существующий MyLog.blf. Вызовите API CreateLogFile, чтобы создать MyLxg_xxx.blf в папке C:\Users\Public\. Вызовите API AddLogContainer, чтобы добавить контейнер журнала для MyLxg_xxx.blf, созданного на шаге 4. Вызовите GetProcAddress(LoadLibraryA("ntdll.dll"), "NtSetInformationFile"), чтобы получить адрес функции API NtSetInformationFile. Вызовите API AddLogContainer, чтобы добавить контейнер журнала для MyLog.blf, открытого в шаге 3. Вызовите NtSetInformationFile(v55, (PIO_STATUS_BLOCK)v33, v28, 1, (FILE_INFORMATION_CLASS)13), где последний параметр - тип FileInformationClass. Если значение равно FileDispositionInformation (13), функция удалит файл при его закрытии или отменит ранее запрошенное удаление. Вызовите API CloseHandle для закрытия обработчика MyLxg_xxx.blf, чтобы запустить эту уязвимость. [B]Анализ причины:[/B] Теперь, когда доказательство кода было представлено, можно проанализировать первопричину. На рисунке 9 шаг 3 вызывает API CreateLogFile, 5-й параметр которого равен 4 (OPEN_ALWAYS), что открывает существующий файл или создает его, если он не существует. В данном случае открывается существующий MyLog.blf. На шаге 4 код вызывает API CreateLogFile для создания нового blf-файла с именем MyLxg_xxx.blf. На шагах 5 и 7, соответственно, код вызывает AddLogContainer, чтобы добавить контейнер в физический журнал, связанный с данным хэндлом журнала. Сначала рассмотрим подробнее, как драйвер CLFS обрабатывает запрос на добавление контейнера журнала при вызове функции AddLogContainer() в пространстве пользователя. Для отслеживания процесса обработки этого запроса можно установить следующую точку останова. [CODE] bu CLFS!CClfsRequest::AllocContainer[/CODE] В CLFS.sys класс CClfsRequest отвечает за обработку запросов из пространства пользователя. Функция CClfsRequest::AllocContainer используется для обработки запроса на добавление контейнера в физический журнал. Функция CClfsRequest::AllocContainer вызывает CClfsLogFcbPhysical::AllocContainer, объявление которого показано ниже: [CODE]CClfsLogFcbPhysical::AllocContainer(CClfsLogFcbPhysical *this, _FILE_OBJECT *,_UNICODE_STRING *,unsigned __int64 *)[/CODE] Далее точка останова на CClfsLogFcbPhysical::AllocContainer устанавливается следующим образом: [CODE]bu CLFS!CClfsLogFcbPhysical::AllocContainer[/CODE] На шаге 5, когда код вызывает функцию AddLogContainer, срабатывает точка останова на CClfsLogFcbPhysical::AllocContainer. Когда точка останова достигнута, давайте проверим указатель this класса CClfsLogFcbPhysical. Тhis указывает на объект CClfsLogFcbPhysical. Как показано на рисунке 10, в регистре rcx хранится указатель this класса CClfsLogFcbPhysical. [ATTACH type="full" alt="1668954916874.png"]60098[/ATTACH] Рисунок 10. Проверка указателя этого класса CClfsLogFcbPhysical в CClfsLogFcbPhysical::AllocContainer Адрес vftable в классе CClfsLogFcbPhysical хранится по смещению 0x00. По смещению this+0x30 хранится указатель на имя журнала. По смещению this+0x2B0 хранится указатель на класс CClfsBaseFilePersisted. В памяти Base Log File CLFS представлен классом CClfsBaseFile, который может быть расширен классом CClfsBaseFilePersisted. В этом указателе класса CClfsBaseFilePersisted по смещению 0x30 хранится указатель на буфер кучи размером 0x90 байт. Кроме того, в буфере кучи по смещению 0x30 хранится указатель на Base Block. Кроме того, в этом указателе CClfsBaseFilePersisted по смещению 0x1C0 хранится указатель на объект CClfsContainer. После успешного добавления контейнера мы можем проверить структуру CLFS_CONTAINER_CONTEXT, описанную на рисунке 5, в памяти, как показано на рисунке 11. [ATTACH type="full" alt="1668954965476.png"]60099[/ATTACH] Рисунок 11. Структура CLFS_CONTAINER_CONTEXT после успешного добавления контейнера По смещению 0x1C0 в объекте CClfsBaseFilePersisted хранится указатель на объект CClfsContainer, который берется из поля pContainer в структуре CLFS_CONTAINER_CONTEXT. В этот момент можно установить точку останова записи в память по адресу CLFS_CONTAINER_CONTEXT+0x18, чтобы отследить, когда указатель на объект CClfsContainer в структуре CLFS_CONTAINER_CONTEXT будет поврежден. Еще одна точка останова записи в память по смещению 0x1C0 в объекте CClfsBaseFilePersisted может быть установлена следующим образом: [CODE]1: kd> ba w8 ffffc80c`cc86a4f0 //CLFS_CONTAINER_CONTEXT: +0x18 1: kd> ba w8 ffffb702`3cf251c0 //CClfsBaseFilePersisted: +0x1C0[/CODE] На шаге 7, когда код вызывает функцию AddLogContainer, точки останова на CLFS!CClfsRequest::AllocContainer и CLFS!CClfsLogFcbPhysical::AllocContainer снова сбиваются. В этот момент давайте проверим указатель this (см. рисунок 12) класса CClfsLogFcbPhysical. Стоит отметить, что поле SignaturesOffset, которое изначально было установлено в 0x00000050 в созданном файле MyLog.blf, в памяти было установлено в 0xFFFF0050. [ATTACH type="full" alt="1668955031763.png"]60100[/ATTACH] Рисунок 12. Проверка указателя this для класса CClfsLogFcbPhysical В WinDbg продолжим выполнение кода. Точка останова записи в память "ba w8 ffffc80c`cc86a4f0" будет достигнута, и структура CLFS_CONTAINER_CONTEXT в base Record производит out-of-bound запись, что приводит к повреждению указателя в объекте CClfsContainer, показанном на рисунке 13. [ATTACH type="full" alt="1668955057413.png"]60101[/ATTACH] Рисунок 13. Повреждение указателя на объект CClfsContainer в структуре CLFS_CONTAINER_CONTEXT Исходя из приведенной выше обратной трассировки стека вызовов, функция memset была вызвана, чтобы вызвать точку останова записи в память в функции CClfsBaseFilePersisted::AllocSymbol. На рисунке 14 показан псевдокод функции CClfsBaseFilePersisted::AllocSymbol. [ATTACH type="full" alt="1668955081188.png"]60102[/ATTACH] Рисунок 14. Псевдокод функции CClfsBaseFilePersisted::AllocSymbol Эта функция описывается следующим образом: Переменная v9 - это значение поля cbSymbolZone в заголовке Base Record Header. Поле cbSymbolZone было установлено в аномальное значение, описанное на рисунке 8. Это значение было изменено с 0x000000F8 на 0x0001114B. Проверьте поле cbSymbolZone. Чтобы выполнить ООВ-запись на шаге 4, эту проверку необходимо обойти. Поле SignaturesOffset, которое изначально имело значение 0x00000050 в файле MyLog.blf, описанном на рисунке 7, было перезаписано большим числом (0xFFFF0050) в памяти. Поэтому, даже когда поле cbSymbolZone установлено в ненормальное значение, проверку для поля cbSymbolZone все равно можно обойти. Определение причины того, что поле SignaturesOffset установлено в 0xFFFF0050 из 0x00000050, является первопричиной CVE-2022-37969. Переменная v10 равна v9 плюс BaseLogRecord плюс 0x1338, а переменная v9 равна 0x0001114b, что приводит к недопустимому смещению в v10. Функция вызывает memset(), что приводит к OOB-записи по недопустимому смещению v10, которое попадает в структуру CLFS_CONTAINER_CONTEXT в базовой записи для MyLxg_xxx.blf, что приводит к повреждению указателя CClfsContainer по смещению 0x18 в структуре CLFS_CONTAINER_CONTEXT. На рисунке 15 показано, как происходит запись вне границ, что приводит к повреждению указателя в объекте CClfsContainer. [ATTACH type="full" alt="1668955134353.png"]60103[/ATTACH] Рисунок 15. Объяснение несанкционированной записи, вызванной CVE-2022-37969 Итак, мы обсудили, почему произошла запись вне границ и как был поврежден указатель на объект CClfsContainer в структуре CLFS_CONTAINER_CONEXT. Далее рассмотрим, когда произойдет разыменование поврежденного указателя CClfsContainer. После этого мы вернемся к выяснению того, почему поле SignaturesOffset в памяти установлено в 0xFFFF0050 из 0x00000050. Когда в пространстве пользователя вызывается функция CloseHandle, за обработку этого запроса отвечает CClfsRequest::Close(PIRP Irp). В ядре еще одна точка останова памяти (0x1c0+CClfsBaseFilePersisted) достигается в функции ClfsBaseFilePersisted::WriteMetadataBlock, как показано на рисунке 16. [ATTACH type="full" alt="1668955171966.png"]60104[/ATTACH] Рисунок 16. Точка останова памяти(0x1c0+CClfsBaseFilePersisted) в ClfsBaseFilePersisted::WriteMetadataBlock Поврежденный указатель копируется на объект CClfsContainer в структуре CLFS_CONTAINER_CONTEXT в базовой записи по смещению 0x1c0 в объекте CClfsBaseFilePersisted. На рисунке 17 показан псевдокод функции ClfsBaseFilePersisted::WriteMetadataBlock после того, как поврежденный указатель на CClfsContainer был сохранен по смещению 0x1c0 в объекте CClfsBaseFilePersisted. Код обнуляет поле указателя на объект CClfsContainer в структуре CLFS_CONTAINER_CONTEXT. После декодирования блока указатель на объект CClfsContainer восстанавливается в структуре CLFS_CONTAINER_CONTEXT со смещения 0x1c0 в объекте CClfsBaseFilePersisted. [ATTACH type="full" alt="1668955204670.png"]60105[/ATTACH] Рисунок 17. Псевдокод функции ClfsBaseFilePersisted::WriteMetadataBlock Наконец, точка останова на CLFS!CClfsBaseFilePersisted::RemoveContainer может быть установлена для отслеживания момента разыменования поврежденного указателя на объект CClfsContainer в структуре CLFS_CONTAINER_CONTEXT в Base Record. На рисунке 18 показан псевдокод функции CClfsBaseFilePersisted::RemoveContainer. [ATTACH type="full" alt="1668955233237.png"]60106[/ATTACH] Рисунок 18.Псевдокод функции CClfsBaseFilePersisted::RemoveContainer В функции CClfsBaseFilePersisted::RemoveContainer выполняются следующие шаги. Получает смещение контекста контейнера по смещению 0x398 в Base Record. Вызывает CClfsBaseFile::GetSymbol для получения указателя на структуру CLFS_CONTAINER_CONTEXT и сохраняет его в 4-м параметре. Присваивает значение указателя на объект CClfsContainter в структуре CLFS_CONTAINER_CONTEXT, полученной на шаге 2, локальной переменной v13. Обнуляет указатель на объект CClfsContainter в структуре CLFS_CONTAINER_CONTEXT. Поочередно вызывает CClfsContainer::Remove и CClfsContainer::Release для удаления связанного с контейнером файла журнала и освобождения объекта CClfsContainer. Разыменование поврежденного указателя на объект CClfsContainter приводит к нарушению памяти. На рисунке 19 показана информация о сбое в WinDbg, в результате чего происходит сбой BSOD. [ATTACH type="full" alt="1668955270746.png"]60107[/ATTACH] Рисунок 19. Разыменование поврежденного указателя на объект CClfsContainter Как описано на рисунке 14, в функции CClfsBaseFilePersisted::AllocSymbol произошла несвязанная запись. Перед вызовом функции memset проверка поля cbSymbolZone была обойдена из-за того, что поле SignaturesOffset в памяти было перезаписано значением 0xFFFF0050. Поле SignaturesOffset в памяти базового блока может быть перезаписано на 0xFFFF0050 в процессе обработки запроса вызова API CreateLogFile для открытия специально созданного базового файла журнала MyLog.blf, описанного в шаге 3 на рисунке 9. Когда функция CreateLogFile вызывается в пространстве пользователя, CLFS!CClfsRequest::Create отвечает за обработку этого запроса. Когда функция CreateLogFile используется для открытия существующего base log file, в CLFS.sys вызывается функция CClfsLogFcbPhysical::Initialize. На рисунке 20 показан фрагмент псевдокода функции CClfsLogFcbPhysical::Initialize. [ATTACH type="full" alt="1668955301241.png"]60108[/ATTACH] Рисунок 20. Фрагмент псевдокода функции CClfsLogFcbPhysical::Initialize Эта функция описывается следующим образом: 1. Вызвать функцию CClfsBaseFilePersisted::OpenImage для создания bigpool (размер: 0x7a00) для базы блока в базовом файле журнала. Для входа в функцию CClfsBaseFilePersisted::ReadMetadataBlock можно выполнить следующие вызовы функций. [CODE]CClfsBaseFilePersisted::OpenImage -> CClfsBaseFilePersisted::ReadImage -> CClfsBaseFile::AcquireMetadataBlock -> CClfsBaseFilePersisted::ReadMetadataBlock[/CODE] На рисунке 21 показан фрагмент псевдокода функции CClfsBaseFilePersisted::ReadMetadataBlock, где вызывается ExAllocatePoolWithTag(PagedPoolCacheAligned, 0x7a00, 0x73666C43u) для создания bigpool для хранения базового блока, затем следует инициализация, а затем вызывается функция ClfsDecodeBlock для декодирования блока. В функции ClfsDecodeBlock вызывается функция ClfsDecodeBlockPrivate для разбора массива сигнатур секторов, расположенного по смещению 0x50 (значение SignaturesOffset) в базовом блоке. Для перезаписи подписи сектора каждого сектора требуется два байта. Эти два байта 0x0050 по смещению 0x68 в базовом блоке могут быть перезаписаны по смещению 0x19FE (0xC*0x200+0x1FE), где хранится подпись сектора 13-й секции. В этот момент мы можем установить две точки останова записи в память, расположенные по адресам base_block+0x68 и base_block+0x200*0xE-0x8. Цель установки этих двух точек останова записи в память - отследить момент перезаписи подписи сектора 14-го раздела в базовом блоке, а поле SignaturesOffset в базовом блоке переписать в 0xFFFF0050. [CODE] 1: kd> ba w8 ffffd08b`51c03000+0x68 //base_block+0x68 1: kd> ba w8 ffffd08b`51c03000+0x200*0xE-0x8 //базовый_блок+0x200*0xe-0x8[/CODE] [ATTACH type="full" alt="1668955364348.png"]60109[/ATTACH] Рисунок 21. Фрагмент псевдокода функции CClfsBaseFilePersisted::ReadMetadataBlock 2. Вызов функции CClfsBaseFile::AcquireClientContext для получения клиентского контекста из базового блока. Как показано на рисунке 7, первое смещение в массиве смещений клиентского контекста, расположенное по адресу 0x9A8 в blf-файле, является специально созданным. Поддельный клиентский контекст расположен по смещению 0x23A0 в base log file. Поле eState, расположенное по смещению 0x78 в структуре поддельного Контекста клиента, установлено в 0x20 (CLFS_LOG_SHUTDOWN). 3. Проверьте, не является ли поле eState значением CLFS_LOG_SHUTDOWN или базовый журнал является мультиплексированным журналом. 4. Вызовите функцию CClfsLogFcbPhysical::ResetLog, так как условие было ложным на шаге 3. На рисунке 22 показан фрагмент псевдокода функции CClfsLogFcbPhysical::ResetLog. 8 байт, расположенные по адресу base_block+0x1BF8, установлены в 0xFFFFFFFF000000. Подпись сектора расположена по смещению base_block+0x1BFC. Поэтому сигнатура сектора перезаписывается на 0xFFFFFF. На рисунке 23 показано, что подпись сектора перезаписана в WinDbg. [ATTACH type="full" alt="1668955410729.png"]60110[/ATTACH] Рисунок 22. Фрагмент псевдокода функции CClfsLogFcbPhysical::ResetLo [ATTACH type="full" alt="1668955426251.png"]60111[/ATTACH] Рисунок 23. Подпись сектора перезаписана 0xFFFF 5. Вызовите функцию CClfsLogFcbPhysical::FlushMetaData. Для входа в функцию CLFS!ClfsEncodeBlockPrivate можно выполнить следующие вызовы функций. [CODE] CLFS!CClfsLogFcbPhysical::FlushMetadata -> CLFS!CClfsBaseFilePersisted::FlushImage -> CLFS!CClfsBaseFilePersisted::WriteMetadataBlock -> CLFS!ClfsEncodeBlock -> CLFS!ClfsEncodeBlockPrivate[/CODE] На рисунке 24 показан фрагмент псевдокода функции CLFS!ClfsEncodeBlockPrivate. [ATTACH type="full" alt="1668955470354.png"]60112[/ATTACH] Приведенный выше код получает сигнатуру сектора из каждого сектора базового блока и перезаписывает массив сигнатур сектора сигнатурой сектора. Массив сигнатур секторов расположен по смещению 0x50 и перекрывает поле SignaturesOffset в базовом блоке. Подпись сектора 14-го сектора была установлена в 0xFFFF, как показано на рисунке 23. Поэтому два байта (0xFFFF) перезаписываются по смещению 0x6C (0x50+0xE*2) в базовом блоке. В это время поле SignaturesOffset имеет значение 0xFFFF0050, как показано на рисунке 25. [ATTACH type="full" alt="1668955498899.png"]60113[/ATTACH] Рисунок 25. Поле SignaturesOffset перезаписано значением 0xFFFF0050 В конце мы обобщаем процесс перезаписи поля SignaturesOffset на рисунке 26. [ATTACH type="full" alt="1668955522072.png"]60114[/ATTACH] Рисунок 26. Процесс перезаписи поля SignaturesOffset [B]Заключение[/B] В этом блоге ThreatLabz представила подробный анализ первопричины CVE-2022-37969, которая связана с неправильной проверкой границ поля SignaturesOffset в Base Block для базового файла журнала (BLF) в CLFS.sys. Специально созданный массив клиентских контекстов и поддельный клиентский контекст в base log file могут использовать CLFS для перезаписи поля SignaturesOffset ненормальным значением. Это приводит к обходу проверки для поля cbSymbolZone при выделении символа. Таким образом, недействительное поле cbSymbolZone может привести к ООВ - записи по произвольному смещению. Поэтому указатель на объект CClfsContainer может быть поврежден. При разыменовании поврежденный указатель на объект CClfsContainer вызывает нарушение памяти, которое приводит к аварийному завершению работы BSOD. [B]Во второй части мы представим анализ эксплойта 0-day, использующего эту уязвимость для повышения привилегий. Оставайтесь с нами![/B] Всем пользователям Windows рекомендуется [B]обновить систему до последней версии[/B]. Решения Advanced Threat Protection и Advanced Cloud Sandbox от Zscaler могут защитить клиентов от эксплойта 0-day, использующего уязвимость CVE-2022-37969. Win32.GenExploit.LogFile Win32.Exploit.CVE-2022-37969 [B]Dmeh-Smeh-Smeh!!!!КТО ПРОЧИТАЛ, СНИМАЮ ШЛЯПУ! Dmeh-Smeh-Smeh!!! СЕЙЧАС ВЫЛОЖУ ВТОРУЮ ЧАСТЬ[/B] [/QUOTE]
Проверка
Ответ
Форум
Исследование системы (Для ознакомления)
Технологии создания невидимой малвари
Уязвимость Windows CLFS CVE-2022-37969 - часть 1. Слабонервным не читать. Опасно для мозга
Верх
Низ