Skip to content
KitploitKITPLOIT
HerramientasBlog
Enviar
HerramientasBlog
Enviar

¡Herramientas de Hacking, PenTest y Ciberseguridad para tu Arsenal de Seguridad!

Kitploit es un directorio de herramientas de hacking, ciberseguridad y pentesting. Descubre las últimas actualizaciones de proyectos para encontrar vulnerabilidades, analizar sistemas, automatizar pruebas y fortalecer tu seguridad.

··Feeds·Contacto·Privacidad·© 2026 Kitploit

Directorio de Herramientas

Categorías

Ver todas las categorías
Loading categories
CVE-2023-36424 — Corrupción del Pool del Kernel de Windows (clfs.sys) Escalada de Privilegios | Kitploit
Herramientas/GitHubGitHub/zerozenxlabs/cve-2023-36424
Escalada de PrivilegiosForensia de MemoriaAnálisis de VulnerabilidadesExplotaciónExplotación de Binarios
GitHubzerozenxlabs/cve-2023-36424

CVE-2023-36424

Corrupción del Pool del Kernel de Windows (clfs.sys) Escalada de Privilegios

Ver Repositorio
129231hace 2 añosRevisado por Kitploit

Más Populares

Ver todos →

Descubre las herramientas más usadas por nuestra comunidad.

Explora todas las herramientas

Explora nuestra colección de herramientas

Ver todas las herramientas →
Compartir

Información

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

Corrupción del Pool del Kernel de Windows (clfs.sys) para Escalada de Privilegios. (CVE-2023-36424)

Este repositorio contiene análisis técnico y exploit funcional.

Autor: Nassim Asrir (@p1k4l4) || https://www.linkedin.com/in/nassim-asrir-b73a57122/

Vulnerabilidad

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

Hay un desbordamiento de pool en el controlador de filtro mini clfs.sys. Se puede leer información sobre esto en:

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

La razón es que el controlador no verifica suficientemente los datos que provienen de un punto de reanálisis de NTFS.

Consideraremos la versión 10.0.22621.2134 de clfs.sys (Windows 11 22H2 22621.2215)

La función HsmFltProcessHSMControl es responsable de procesar los FSCTL del filtro de nube. Para una operación con código 0xC0000003, eventualmente llamará a HsmFltProcessUpdatePlaceholder.

Después de algún procesamiento, el flujo de ejecución llegará a HsmiOpUpdatePlaceholderDirectory y finalmente a 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*] recupera datos del punto de reanálisis. Estos datos contienen un valor de tamaño WORD *((_WORD *)v8 + 7), que especifica un conteo de los elementos estructurados. Cada elemento tiene un campo Tipo, Tamaño y Desplazamiento a los campos de datos.

El tipo de elemento que va en cada lugar está estrictamente predeterminado. Pero solo para los primeros 10. Por ejemplo, el campo de tipo del primer elemento debe tener un valor igual a 0x7.

El controlador ejecutará HsmpRpValidateBuffer [2*] para verificar los datos adquiridos. Luego, se asignará un pool paginado de tamaño fijo 0x4000 bytes en [3*]. Y si los datos del punto de reanálisis tienen un valor de Count mayor que 10, entonces los datos de los elementos posteriores al décimo se copiarán en este pool de tamaño fijo [4*] sin ninguna verificación adicional.

La validación dentro de HsmpRpValidateBuffer es insuficiente, porque solo verifica los primeros 10 registros.

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;
}

Como podemos ver, [1*] el código solo verificará los primeros 10 elementos e ignora el caso cuando hay más registros.

Explotación

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

El tamaño del pool vulnerable es 0x4000. El tamaño es múltiplo de página y, por lo tanto, se utilizará la asignación por segmentos [3].

Para la explotación se utilizó la técnica descrita aquí[4]. Llamar a NtAlpcCreateResourceReserve creará muchos identificadores y sobrescribir uno de ellos con el puntero a un objeto _KALPC_RESERVE falso construido nos dará la capacidad de escribir en una dirección arbitraria del kernel.

Para preparar la memoria, asignamos secuencialmente pools de tamaño 0x4000, usando pipes[5]. Luego liberaremos cada segundo pool, proporcionando un lugar para el buffer vulnerable.

Texto alternativo

Para leer una dirección arbitraria del kernel, el exploit utilizó pipes. Para este propósito sobrescribiremos el puntero AttributeValue de la estructura PipeAttribute.

Texto alternativo

Y después, podemos robar el token del sistema para sobrescribir el token en el proceso objetivo.

Gracias por leer.

Descargar herramienta