Малварь как искусство Уязвимость Windows CLFS CVE-2022-37969 - часть 1. Слабонервным не читать. Опасно для мозга


X-Shar

:)
Администрация
Регистрация
03.06.2012
Сообщения
6 082
Репутация
8 199
Всем привет!

На xss.is нашёл классный перевод:

Но к сожалению там не оформили как статью, поэтому надёюсь никто не против, если я перенесу этот интересный материал сюда. Отдыхай!!!

2 сентября 2022 г. компания Zscaler Threatlabz зафиксировала эксплойт нулевого дня в общем системном драйвере файлов журнала Windows (CLFS.sys) и сообщила об этом обнаружении в Microsoft. В сентябрьском , Microsoft исправила эту уязвимость, идентифицированную как , которая представляет собой уязвимость повышения привилегий драйвера общей файловой системы Windows.

Злоумышленник, успешно воспользовавшийся этой уязвимостью, может получить системные привилегии. Эксплойт 0-day может успешно выполнить повышение привилегий в Windows 10 и Windows 11 до сентябрьского исправления.

Причина уязвимости связана с отсутствием строгой проверки границ поля SignaturesOffset в базовом блоке blf-файла журнала (BLF) в CLFS.sys. Специально созданный массив клиентского контекста и фальшивый клиентский контекст в базовом файле журнала могут использовать CLFS для перезаписи поля SignaturesOffset ненормальным значением. Это приводит к обходу проверки поля cbSymbolZone при выделении символа. Таким образом, недопустимое поле cbSymbolZone может привести к записи вне границ с произвольным смещением. В этой серии блогов, состоящей из двух частей, мы демистифицируем уязвимость и эксплойт нулевого дня, обнаруженный в дикой природе. Блоги состоят из двух частей: анализа основной причины и анализа эксплойта. В этом блоге мы впервые представляем подробный анализ основной причины CVE-2022-37969.

Отладочная среда

Весь анализ и отладка в этой серии блогов, состоящей из двух частей, проводились в следующей среде:

Код:
Windows 11 21H2 version 22000.918
CLFS.sys 10.0.22000.918

Common Log File System (CLFS) — это подсистема ведения журналов общего назначения, которая может использоваться приложениями, работающими как в режиме ядра, так и в пользовательском режиме, для создания высокопроизводительных журналов транзакций и реализована в драйвере CLFS.sys. Общая файловая система журналов создает журналы транзакций в базовом файле журнала (BLF). Введение в понятия и терминологию для CLFS указано в Microsoft.

Перед использованием CLFS файл журнала создается с помощью . Файл журнала состоит из blf-файла, состоящего из блоков метаданных, и нескольких контейнеров, в которых хранятся фактические данные. API используется для добавления контейнера в физический журнал, связанный с дескриптором журнала.

Рисунок 1 иллюстрирует формат BLF на основе Алекса Ионеску .

1668954132708.png

Рис. 1. Формат базового файла журнала (BLF)

Blf-файл состоит из шести различных блоков метаданных: Control Block, Base Block и Truncate Block, а также соответствующих им shadow block. В этих блоках могут находиться три типа записей (Control Record, Base Record и Truncate Record). Этот блог посвящен только базовой записи, которая имеет отношение к данной уязвимости. Базовая запись включает в себя символьные таблицы, которые хранят информацию о контекстах клиента, контекстах контейнера и контекстах безопасности, связанных с базовым файлом журнала.

Каждый блок журнала начинается с заголовка блока журнала, структура которого определена ниже:

Код:
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;

Схема памяти структуры CLFS_LOG_BLOCK_HEADER, размер которой составляет 0x70 байт, показана на рисунке 1. Поле SignaturesOffset - это смещение массива в памяти, который используется для хранения всех подписей секторов. Массив должен располагаться на последнем секторе каждого блока. Сигнатура сектора располагается в конце каждого сектора (размер: 0x200) и состоит из типа Sector Block Type (1 байт) и Usn (1 байт). Ниже перечислены типы сектора.

Код:
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;

На рисунке 1 base block начинается по смещению 0x800 и заканчивается по смещению 0x71FF в файле .BLF и начинается с заголовка Log Block Header (0x70 байт), за которым следует заголовок Base Record Header, а затем записи. Заголовок Base Record Header может быть представлен структурой CLFS_BASE_RECORD_HEADER, описанной на рисунке 2.

1668954261104.png

Рисунок 2. Определение структуры CLFS_BASE_RECORD_HEADER

Схема структуры CLFS_BASE_RECORD_HEADER показана на рисунке 3

1668954288586.png

Рисунок 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, определенная ниже:

Код:
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;

Схема памяти структуры CLFSHASHSYM показана на рисунке 4, далее следуют различные объекты контекста.

1668954357858.png

Рисунок 4. Структура CLFSHASHSYM (символично)

В Base Record клиентский контекст используется для идентификации клиента для файла журнала. В Base Log File может быть создан как минимум один Client Context. Client Context представлен структурой CLFS_CLIENT_CONTEXT, определенной ниже:
Код:
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;

В Base Record контекст контейнера связан с добавлением файла контейнера для base log file, который представлен структурой CLFS_CONTAINER_CONTEXT, определенной ниже:

Код:
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;

Поле pContainer является указателем на объект в адресном пространстве ядра CClfsContainer, представляющий контейнер во время выполнения, который находится по смещению 0x18 в структуре CLFS_CONTAINER_CONTEXT. На рисунке 5 показана схема памяти структуры CLFS_CONTAINER_CONTEXT.

1668954436697.png

Рисунок 5. Схема памяти структуры CLFS_CONTAINER_CONTEXT

Чтобы определить первопричину CVE-2022-37969, ThreatLabz разработала Proof-of-Concept (PoC), который стабильно вызывает сбой "синего экрана смерти" (BSOD). На рисунке 6 показана подробная информация о сбое после срабатывания уязвимости.

1668954474649.png

Рисунок 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.
1668954526643.png

Рисунок 7. Специально созданный файл Base Log File (BLF) для CVE-2022-37969

После создания этого bfl-файла определенные байты, включая поле SignatureOffset, массив смещений клиентского контекста, cbSymbol, фальшивый клиентский контекст и т.д., должны быть соответствующим образом изменены. Как показано на рисунке 7, все измененные байты находятся в записи Base Log Record (смещение: 0x800 ~ 0x81FF в файле .blf). Модификации файла .blf перечислены на рисунке 8.

1668954582981.png

Рисунок 8. Модификации файла .BLF для запуска CVE-2022-37969

Код Proof-of-Concept для запуска CVE-2022-37969 показан на рисунке 9.

1668954604583.png

Рисунок 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, чтобы запустить эту уязвимость.

Анализ причины:

Теперь, когда доказательство кода было представлено, можно проанализировать первопричину. На рисунке 9 шаг 3 вызывает API CreateLogFile, 5-й параметр которого равен 4 (OPEN_ALWAYS), что открывает существующий файл или создает его, если он не существует. В данном случае открывается существующий MyLog.blf. На шаге 4 код вызывает API CreateLogFile для создания нового blf-файла с именем MyLxg_xxx.blf. На шагах 5 и 7, соответственно, код вызывает AddLogContainer, чтобы добавить контейнер в физический журнал, связанный с данным хэндлом журнала.
Сначала рассмотрим подробнее, как драйвер CLFS обрабатывает запрос на добавление контейнера журнала при вызове функции AddLogContainer() в пространстве пользователя. Для отслеживания процесса обработки этого запроса можно установить следующую точку останова.

Код:
 bu CLFS!CClfsRequest::AllocContainer

В CLFS.sys класс CClfsRequest отвечает за обработку запросов из пространства пользователя. Функция CClfsRequest::AllocContainer используется для обработки запроса на добавление контейнера в физический журнал. Функция CClfsRequest::AllocContainer вызывает CClfsLogFcbPhysical::AllocContainer, объявление которого показано ниже:

Код:
CClfsLogFcbPhysical::AllocContainer(CClfsLogFcbPhysical *this, _FILE_OBJECT *,_UNICODE_STRING *,unsigned __int64 *)

Далее точка останова на CClfsLogFcbPhysical::AllocContainer устанавливается следующим образом:

Код:
bu CLFS!CClfsLogFcbPhysical::AllocContainer

На шаге 5, когда код вызывает функцию AddLogContainer, срабатывает точка останова на CClfsLogFcbPhysical::AllocContainer. Когда точка останова достигнута, давайте проверим указатель this класса CClfsLogFcbPhysical. Тhis указывает на объект CClfsLogFcbPhysical. Как показано на рисунке 10, в регистре rcx хранится указатель this класса CClfsLogFcbPhysical.

1668954916874.png

Рисунок 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.

1668954965476.png

Рисунок 11. Структура CLFS_CONTAINER_CONTEXT после успешного добавления контейнера

По смещению 0x1C0 в объекте CClfsBaseFilePersisted хранится указатель на объект CClfsContainer, который берется из поля pContainer в структуре CLFS_CONTAINER_CONTEXT. В этот момент можно установить точку останова записи в память по адресу CLFS_CONTAINER_CONTEXT+0x18, чтобы отследить, когда указатель на объект CClfsContainer в структуре CLFS_CONTAINER_CONTEXT будет поврежден. Еще одна точка останова записи в память по смещению 0x1C0 в объекте CClfsBaseFilePersisted может быть установлена следующим образом:

Код:
1: kd> ba w8 ffffc80c`cc86a4f0 //CLFS_CONTAINER_CONTEXT: +0x18

    1: kd> ba w8 ffffb702`3cf251c0 //CClfsBaseFilePersisted: +0x1C0

На шаге 7, когда код вызывает функцию AddLogContainer, точки останова на CLFS!CClfsRequest::AllocContainer и CLFS!CClfsLogFcbPhysical::AllocContainer снова сбиваются. В этот момент давайте проверим указатель this (см. рисунок 12) класса CClfsLogFcbPhysical. Стоит отметить, что поле SignaturesOffset, которое изначально было установлено в 0x00000050 в созданном файле MyLog.blf, в памяти было установлено в 0xFFFF0050.

1668955031763.png

Рисунок 12. Проверка указателя this для класса CClfsLogFcbPhysical

В WinDbg продолжим выполнение кода. Точка останова записи в память "ba w8 ffffc80c`cc86a4f0" будет достигнута, и структура CLFS_CONTAINER_CONTEXT в base Record производит out-of-bound запись, что приводит к повреждению указателя в объекте CClfsContainer, показанном на рисунке 13.

1668955057413.png

Рисунок 13. Повреждение указателя на объект CClfsContainer в структуре CLFS_CONTAINER_CONTEXT

Исходя из приведенной выше обратной трассировки стека вызовов, функция memset была вызвана, чтобы вызвать точку останова записи в память в функции CClfsBaseFilePersisted::AllocSymbol. На рисунке 14 показан псевдокод функции CClfsBaseFilePersisted::AllocSymbol.

1668955081188.png

Рисунок 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.

1668955134353.png

Рисунок 15. Объяснение несанкционированной записи, вызванной CVE-2022-37969

Итак, мы обсудили, почему произошла запись вне границ и как был поврежден указатель на объект CClfsContainer в структуре CLFS_CONTAINER_CONEXT. Далее рассмотрим, когда произойдет разыменование поврежденного указателя CClfsContainer. После этого мы вернемся к выяснению того, почему поле SignaturesOffset в памяти установлено в 0xFFFF0050 из 0x00000050.

Когда в пространстве пользователя вызывается функция CloseHandle, за обработку этого запроса отвечает CClfsRequest::Close(PIRP Irp). В ядре еще одна точка останова памяти (0x1c0+CClfsBaseFilePersisted) достигается в функции ClfsBaseFilePersisted::WriteMetadataBlock, как показано на рисунке 16.

1668955171966.png

Рисунок 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.

1668955204670.png

Рисунок 17. Псевдокод функции ClfsBaseFilePersisted::WriteMetadataBlock

Наконец, точка останова на CLFS!CClfsBaseFilePersisted::RemoveContainer может быть установлена для отслеживания момента разыменования поврежденного указателя на объект CClfsContainer в структуре CLFS_CONTAINER_CONTEXT в Base Record.

На рисунке 18 показан псевдокод функции CClfsBaseFilePersisted::RemoveContainer.

1668955233237.png

Рисунок 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.

1668955270746.png

Рисунок 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.

1668955301241.png

Рисунок 20. Фрагмент псевдокода функции CClfsLogFcbPhysical::Initialize

Эта функция описывается следующим образом:

1. Вызвать функцию CClfsBaseFilePersisted::OpenImage для создания bigpool (размер: 0x7a00) для базы блока в базовом файле журнала. Для входа в функцию CClfsBaseFilePersisted::ReadMetadataBlock можно выполнить следующие вызовы функций.
Код:
CClfsBaseFilePersisted::OpenImage -> CClfsBaseFilePersisted::ReadImage -> CClfsBaseFile::AcquireMetadataBlock -> CClfsBaseFilePersisted::ReadMetadataBlock

На рисунке 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.

Код:
    1: kd> ba w8 ffffd08b`51c03000+0x68 //base_block+0x68

    1: kd> ba w8 ffffd08b`51c03000+0x200*0xE-0x8 //базовый_блок+0x200*0xe-0x8

1668955364348.png

Рисунок 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.

1668955410729.png

Рисунок 22. Фрагмент псевдокода функции CClfsLogFcbPhysical::ResetLo

1668955426251.png

Рисунок 23. Подпись сектора перезаписана 0xFFFF

5. Вызовите функцию CClfsLogFcbPhysical::FlushMetaData. Для входа в функцию CLFS!ClfsEncodeBlockPrivate можно выполнить следующие вызовы функций.

Код:
  CLFS!CClfsLogFcbPhysical::FlushMetadata -> CLFS!CClfsBaseFilePersisted::FlushImage -> CLFS!CClfsBaseFilePersisted::WriteMetadataBlock -> CLFS!ClfsEncodeBlock -> CLFS!ClfsEncodeBlockPrivate

На рисунке 24 показан фрагмент псевдокода функции CLFS!ClfsEncodeBlockPrivate.

1668955470354.png


Приведенный выше код получает сигнатуру сектора из каждого сектора базового блока и перезаписывает массив сигнатур сектора сигнатурой сектора. Массив сигнатур секторов расположен по смещению 0x50 и перекрывает поле SignaturesOffset в базовом блоке. Подпись сектора 14-го сектора была установлена в 0xFFFF, как показано на рисунке 23. Поэтому два байта (0xFFFF) перезаписываются по смещению 0x6C (0x50+0xE*2) в базовом блоке. В это время поле SignaturesOffset имеет значение 0xFFFF0050, как показано на рисунке 25.

1668955498899.png

Рисунок 25. Поле SignaturesOffset перезаписано значением 0xFFFF0050

В конце мы обобщаем процесс перезаписи поля SignaturesOffset на рисунке 26.

1668955522072.png

Рисунок 26. Процесс перезаписи поля SignaturesOffset

Заключение

В этом блоге ThreatLabz представила подробный анализ первопричины CVE-2022-37969, которая связана с неправильной проверкой границ поля SignaturesOffset в Base Block для базового файла журнала (BLF) в CLFS.sys. Специально созданный массив клиентских контекстов и поддельный клиентский контекст в base log file могут использовать CLFS для перезаписи поля SignaturesOffset ненормальным значением. Это приводит к обходу проверки для поля cbSymbolZone при выделении символа. Таким образом, недействительное поле cbSymbolZone может привести к ООВ - записи по произвольному смещению. Поэтому указатель на объект CClfsContainer может быть поврежден. При разыменовании поврежденный указатель на объект CClfsContainer вызывает нарушение памяти, которое приводит к аварийному завершению работы BSOD.

Во второй части мы представим анализ эксплойта 0-day, использующего эту уязвимость для повышения привилегий. Оставайтесь с нами!

Всем пользователям Windows рекомендуется обновить систему до последней версии. Решения Advanced Threat Protection и Advanced Cloud Sandbox от Zscaler могут защитить клиентов от эксплойта 0-day, использующего уязвимость CVE-2022-37969.

Win32.GenExploit.LogFile
Win32.Exploit.CVE-2022-37969

Dmeh-Smeh-Smeh!!!!КТО ПРОЧИТАЛ, СНИМАЮ ШЛЯПУ! Dmeh-Smeh-Smeh!!!

СЕЙЧАС ВЫЛОЖУ ВТОРУЮ ЧАСТЬ
 
Последнее редактирование:
M

Mr.Dante

Гость
Щикарно))) Ждем вторую часть)
 

X-Shar

:)
Администрация
Регистрация
03.06.2012
Сообщения
6 082
Репутация
8 199
Щикарно))) Ждем вторую часть)
 
M

Mr.Dante

Гость
Брависсимо! Благодарю!
 
Верх Низ