Skip to content
KitploitKITPLOIT
ИнструментыБлог
Отправить
ИнструментыБлог
Отправить

Инструменты для хакинга, пентеста и кибербезопасности — ваш арсенал защиты!

Kitploit — это каталог инструментов для хакинга, кибербезопасности и пентестинга. Находите последние обновления проектов для поиска уязвимостей, анализа систем, автоматизации тестирования и усиления вашей безопасности.

··Ленты·Контакты·Конфиденциальность·© 2026 Kitploit

Каталог инструментов

Категории

Все категории
Loading categories
CVE-2023-36424 — Повышение привилегий через повреждение пула ядра Windows (clfs.sys) | Kitploit
Инструменты/GitHubGitHub/zerozenxlabs/cve-2023-36424
Повышение привилегийКриминалистика памятиАнализ уязвимостейЭксплуатацияЭксплуатация Бинарных Файлов
GitHubzerozenxlabs/cve-2023-36424

CVE-2023-36424

Повышение привилегий через повреждение пула ядра Windows (clfs.sys)

Репозиторий
1292312 лет назадПроверено Kitploit

Популярное

Смотреть все →

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

Изучить все инструменты

Просмотрите нашу коллекцию инструментов

Смотреть все инструменты →
Поделиться

Информация

==============

Повышение привилегий через повреждение пула ядра Windows (clfs.sys). (CVE-2023-36424)

Этот репозиторий содержит технический анализ и рабочий эксплойт.

Автор: Nassim Asrir (@p1k4l4) || https://www.linkedin.com/in/nassim-asrir-b73a57122/

Уязвимость

================

В драйвере мини-фильтра clfs.sys происходит переполнение пула. Подробнее об этом можно прочитать здесь:

1 - https://googleprojectzero.blogspot.com/2021/01/hunting-for-bugs-in-windows-mini-filter.html

2 - https://www.zerodayinitiative.com/blog/2021/7/19/cve-2021-31969-underflowing-in-the-clouds

Причина в том, что драйвер недостаточно проверяет данные, поступающие из точки повторной обработки (reparse point) NTFS.

Мы рассмотрим clfs.sys версии 10.0.22621.2134 (Windows 11 22H2 22621.2215)

Функция HsmFltProcessHSMControl отвечает за обработку FSCTL облачного фильтра. Для операции с кодом 0xC0000003 она в конечном итоге вызывает HsmFltProcessUpdatePlaceholder.

После некоторых действий поток выполнения достигает HsmiOpUpdatePlaceholderDirectory и затем, наконец, HsmpRpCommitNoLock:

root@kitploit:~
__int64 __fastcall HsmpRpCommitNoLock(__int64 a1, __int64 a2, struct _FILE_OBJECT *a3, char a4, char a5)

{ .....

v26 = FileObject; LODWORD(v9) = HsmpRpReadBuffer(*(PFLT_INSTANCE *)(v164 + 32), FileObject, (unsigned __int16 **)&P); // [1*]

HsmDbgBreakOnStatus((unsigned int)v9);

if ( (_DWORD)v9 == -1073741195 ) .....

goto LABEL_55; }

if ( (v9 & 0x80000000) != 0i64 )

goto LABEL_9;}
 

if ( (*(_DWORD *)P & 0xFFFF0FFF) != dword_1C0027650 )// Is
Cloud Reparse Tag?
{
LODWORD(v9) = 0xC000CF0B;
.....
goto LABEL_54;
}
v32 = *((unsigned __int16 *)P + 2);
v9 = (unsigned int)HsmpRpValidateBuffer((__int64)P + 8, v32); [2*]
.....
Pool2 = ExAllocatePool2(0x100i64, 0x4000i64, 'pRsH'); // [3*]
v146 = (_DWORD *)Pool2;
v13 = (void *)Pool2;
if ( Pool2 )
{
v64 = v159_10;
v65 = Pool2 + 4;
if ( v8 && *((_WORD *)v8 + 7) > 0xAu )
v64 = *((_WORD *)v8 + 7);
v9 = Pool2 + 20;
v66 = (unsigned int *)(Pool2 + 12);
*(_OWORD *)v65 = 0i64;
*(_WORD *)(Pool2 + 16) = 0;
*(_WORD *)(Pool2 + 18) = v64;
*(_DWORD *)(Pool2 + 12) = 8 * v64 + 16;
*(_DWORD *)v65 = 'pReF';
memset((void *)(Pool2 + 20), 0, 8i64 * v64);
.....
if ( v8 )
{
v127 = 10;
if ( *((_WORD *)v8 + 7) > 0xAu ) // [4*]
{
if ( WPP_GLOBAL_Control !=
(PDEVICE_OBJECT)&WPP_GLOBAL_Control
&& (HIDWORD(WPP_GLOBAL_Control->Timer) & 1) != 0

&& BYTE1(WPP_GLOBAL_Control->Timer) >= 4u )
{
WPP_SF_qiq(WPP_GLOBAL_Control->AttachedDevice, v86,
v87, a2, *(_QWORD *)(v156 + 32), FileObject);
}
while ( v127 < *((_WORD *)v8 + 7) )
{
*(_QWORD *)(v65 + 8i64 * v127 + 16) = *(_QWORD
*)&v8[8 * v127 + 16];
memmove(
(void *)(v65 + *v66),
&v8[*(unsigned int *)&v8[8 * v127 + 20]],
*(unsigned __int16 *)&v8[8 * v127 + 18]); //
[5*]
*(_DWORD *)(v65 + 8i64 * v127 + 20) = *v66;
*v66 += *(unsigned __int16 *)(v65 + 8i64 * v127++ +
18);
}
}
}
.....
}

HsmpRpReadBuffer [1*] получает данные точки повторной обработки. Эти данные содержат значение размером WORD — *((_WORD *)v8 + 7), задающее количество структурированных элементов. Каждый элемент имеет поле Type, Size и Offset, указывающее на поля данных.

Тип элемента и его расположение строго предопределены. Но только для первых 10 элементов. Например, поле типа первого элемента должно быть равно 0x7.

Драйвер выполняет HsmpRpValidateBuffer [2*] для проверки полученных данных. Затем [3*] выделяется страничный пул фиксированного размера 0x4000 байт. И если данные точки повторной обработки содержат значение Count больше 10, то данные элементов после десятого копируются в этот пул фиксированного размера [4*] без каких-либо дополнительных проверок.

Проверка внутри HsmpRpValidateBuffer недостаточна, поскольку он проверяет только первые 10 записей.

root@kitploit:~
__int64 __fastcall HsmpRpValidateBuffer(__int64 pBuf, unsigned int a2)
{
.....
v2 = a2 - 4;
pBuf2 = pBuf + 4;
LOBYTE(v5) = 0;
v6 = 0i64;
if ( a2 <= 4 )
v2 = 0;
v7 = 0;
v8 = *(_DWORD *)pBuf & 0xF;
if ( !v8 )
{
.....
return IsReparseBufferSupported;
}
if ( v8 > 1 )
{
....
}
v9 = 0;
v66 = 0;
if ( v2 < 0x18 )
goto ERROR_EXIT;
v9 = 1;
if ( *(_DWORD *)pBuf2 != 'pReF' )
goto ERROR_EXIT;
v9 = 2;
v10 = (unsigned int *)(pBuf + 0xC);
if ( (*(_BYTE *)(pBuf + 16) & 2) != 0 && *(_DWORD *)(pBuf +
8) != RtlComputeCrc32(0, (PUCHAR)(pBuf + 0xC), v2 - 8) )
goto ERROR_EXIT;
v11 = *v10;
v9 = 3;
if ( v2 < (unsigned int)v11 )
goto ERROR_EXIT;
v12 = *(unsigned __int16 *)(pBuf2 + 0xE);
v9 = 4;
if ( !(_WORD)v12 )
goto ERROR_EXIT;
v13 = 8 * v12 + 16;

v9 = 5;
if ( v13 >= v11 )
goto ERROR_EXIT;
v9 = 0x10000;
for ( i = 0; ; ++i )
{
v15 = *(unsigned __int16 *)(pBuf2 + 0xE);
if ( (unsigned int)v12 >= 0xA ) // [1*]
v15 = 10;
if ( i >= v15 )
break;
}

Как мы видим [1*], код проверяет только первые 10 элементов и игнорирует случай, когда записей больше.

Эксплуатация

=================

Размер уязвимого пула равен 0x4000. Этот размер кратен размеру страницы, поэтому будет использоваться сегментное выделение [3].

Для эксплуатации использовалась техника, описанная здесь [4]. Вызов NtAlpcCreateResourceReserve создаст множество дескрипторов, и перезапись одного из них указателем на сконструированный поддельный объект _KALPC_RESERVE даст нам возможность записи в произвольный адрес ядра.

Для подготовки памяти мы последовательно выделяем пулы размером 0x4000, используя каналы (pipes) [5]. Затем мы освобождаем каждый второй пул, освобождая место для уязвимого буфера.

Alt text

Для чтения произвольного адреса ядра эксплойт использует каналы. Для этого мы перезаписываем указатель AttributeValue в структуре PipeAttribute.

Alt text

И после этого мы можем похитить системный токен, чтобы перезаписать токен в целевом процессе.

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

Скачать инструмент