// CVE-2023-36874_SafeChecker.cpp // Non-exploiting posture checker for Windows Error Reporting-related exposure. // Does NOT trigger or exploit the vulnerability. #define WIN32_LEAN_AND_MEAN #include #include #include #include #include #include #pragma comment(lib, "advapi32.lib") #pragma comment(lib, "version.lib") static std::string ToUtf8(const std::wstring& w) { if (w.empty()) return {}; int len = WideCharToMultiByte( CP_UTF8, 0, w.c_str(), static_cast(w.size()), nullptr, 0, nullptr, nullptr ); if (len <= 0) return {}; std::string out(len, '\0'); WideCharToMultiByte( CP_UTF8, 0, w.c_str(), static_cast(w.size()), out.data(), len, nullptr, nullptr ); return out; } struct OsVersion { DWORD major = 0; DWORD minor = 0; DWORD build = 0; }; static bool GetRealOsVersion(OsVersion& v) { using RtlGetVersionPtr = LONG(WINAPI*)(OSVERSIONINFOW*); HMODULE ntdll = GetModuleHandleW(L"ntdll.dll"); if (!ntdll) return false; auto rtlGetVersion = reinterpret_cast(GetProcAddress(ntdll, "RtlGetVersion")); if (!rtlGetVersion) return false; OSVERSIONINFOW info{}; info.dwOSVersionInfoSize = sizeof(info); if (rtlGetVersion(&info) != 0) return false; v.major = info.dwMajorVersion; v.minor = info.dwMinorVersion; v.build = info.dwBuildNumber; return true; } static std::optional ReadDword( HKEY root, const wchar_t* subKey, const wchar_t* valueName) { REGSAM views[] = { KEY_READ | KEY_WOW64_64KEY, KEY_READ }; for (REGSAM sam : views) { HKEY hKey = nullptr; if (RegOpenKeyExW(root, subKey, 0, sam, &hKey) == ERROR_SUCCESS) { DWORD value = 0; DWORD size = sizeof(value); DWORD type = 0; LSTATUS status = RegQueryValueExW( hKey, valueName, nullptr, &type, reinterpret_cast(&value), &size ); RegCloseKey(hKey); if (status == ERROR_SUCCESS && type == REG_DWORD) { return value; } } } return std::nullopt; } static std::optional ReadString( HKEY root, const wchar_t* subKey, const wchar_t* valueName) { REGSAM views[] = { KEY_READ | KEY_WOW64_64KEY, KEY_READ }; for (REGSAM sam : views) { HKEY hKey = nullptr; if (RegOpenKeyExW(root, subKey, 0, sam, &hKey) == ERROR_SUCCESS) { DWORD size = 0; DWORD type = 0; LSTATUS status = RegQueryValueExW( hKey, valueName, nullptr, &type, nullptr, &size ); if (status == ERROR_SUCCESS && (type == REG_SZ || type == REG_EXPAND_SZ) && size > 0) { std::wstring buffer(size / sizeof(wchar_t), L'\0'); status = RegQueryValueExW( hKey, valueName, nullptr, &type, reinterpret_cast(buffer.data()), &size ); RegCloseKey(hKey); if (status == ERROR_SUCCESS) { while (!buffer.empty() && buffer.back() == L'\0') { buffer.pop_back(); } return buffer; } } else { RegCloseKey(hKey); } } } return std::nullopt; } static std::wstring GetNativeSystemFilePath(const std::wstring& fileName) { wchar_t winDir[MAX_PATH]{}; UINT len = GetWindowsDirectoryW(winDir, MAX_PATH); std::wstring base(winDir, len); BOOL wow64 = FALSE; if (IsWow64Process(GetCurrentProcess(), &wow64) && wow64) { // 32-bit process on 64-bit Windows: use Sysnative to reach real System32. return base + L"\\Sysnative\\" + fileName; } return base + L"\\System32\\" + fileName; } static std::optional GetFileVersion(const std::wstring& path) { DWORD dummy = 0; DWORD size = GetFileVersionInfoSizeW(path.c_str(), &dummy); if (size == 0) return std::nullopt; std::vector data(size); if (!GetFileVersionInfoW(path.c_str(), 0, size, data.data())) { return std::nullopt; } VS_FIXEDFILEINFO* fixed = nullptr; UINT len = 0; if (!VerQueryValueW( data.data(), L"\\", reinterpret_cast(&fixed), &len) || len == 0 || fixed == nullptr) { return std::nullopt; } std::wostringstream oss; oss << HIWORD(fixed->dwFileVersionMS) << L'.' << LOWORD(fixed->dwFileVersionMS) << L'.' << HIWORD(fixed->dwFileVersionLS) << L'.' << LOWORD(fixed->dwFileVersionLS); return oss.str(); } struct ServiceInfo { bool existsKnown = false; bool exists = false; bool startTypeKnown = false; bool disabledConfig = false; bool stateKnown = false; bool running = false; bool accessProblem = false; }; static ServiceInfo CheckWerService() { ServiceInfo out; SC_HANDLE scm = OpenSCManagerW(nullptr, nullptr, SC_MANAGER_CONNECT); if (!scm) { out.accessProblem = true; return out; } SC_HANDLE svc = OpenServiceW( scm, L"WerSvc", SERVICE_QUERY_CONFIG | SERVICE_QUERY_STATUS ); if (!svc) { DWORD err = GetLastError(); if (err == ERROR_SERVICE_DOES_NOT_EXIST) { out.existsKnown = true; out.exists = false; CloseServiceHandle(scm); return out; } out.accessProblem = true; // Retry with less rights. svc = OpenServiceW(scm, L"WerSvc", SERVICE_QUERY_STATUS); if (!svc) { err = GetLastError(); if (err == ERROR_SERVICE_DOES_NOT_EXIST) { out.existsKnown = true; out.exists = false; } CloseServiceHandle(scm); return out; } } out.existsKnown = true; out.exists = true; DWORD needed = 0; QueryServiceConfigW(svc, nullptr, 0, &needed); if (GetLastError() == ERROR_INSUFFICIENT_BUFFER && needed > 0) { std::vector buffer(needed); QUERY_SERVICE_CONFIGW* cfg = reinterpret_cast(buffer.data()); if (QueryServiceConfigW(svc, cfg, needed, &needed)) { out.startTypeKnown = true; out.disabledConfig = (cfg->dwStartType == SERVICE_DISABLED); } } SERVICE_STATUS_PROCESS status{}; DWORD bytesNeeded = 0; if (QueryServiceStatusEx( svc, SC_STATUS_PROCESS_INFO, reinterpret_cast(&status), sizeof(status), &bytesNeeded)) { out.stateKnown = true; out.running = status.dwCurrentState == SERVICE_RUNNING || status.dwCurrentState == SERVICE_START_PENDING; } CloseServiceHandle(svc); CloseServiceHandle(scm); return out; } int main() { SetConsoleOutputCP(CP_UTF8); std::cout << "CVE-2023-36874 safe posture checker\n"; std::cout << "Non-exploiting check only.\n\n"; OsVersion os; if (!GetRealOsVersion(os)) { std::cout << "Failed to get real OS version.\n"; return 1; } auto productName = ReadString( HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion", L"ProductName" ); auto displayVersion = ReadString( HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion", L"DisplayVersion" ); auto ubr = ReadDword( HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion", L"UBR" ); std::cout << "Product: " << ToUtf8(productName.value_or(L"Unknown")) << "\n"; if (displayVersion) { std::cout << "DisplayVersion: " << ToUtf8(*displayVersion) << "\n"; } std::cout << "NT version: " << os.major << "." << os.minor << "." << os.build; if (ubr) { std::cout << "." << *ubr; } std::cout << "\n"; ServiceInfo svc = CheckWerService(); std::cout << "\nWER service WerSvc: "; if (!svc.existsKnown) { std::cout << "unknown, access problem or SCM query failed"; } else if (!svc.exists) { std::cout << "not present"; } else { std::cout << "present"; if (svc.startTypeKnown) { std::cout << (svc.disabledConfig ? ", start type DISABLED" : ", start type not disabled"); } else { std::cout << ", start type unknown"; } if (svc.stateKnown) { std::cout << (svc.running ? ", state RUNNING" : ", state STOPPED or not running"); } else { std::cout << ", state unknown"; } } std::cout << "\n"; auto policyDisabled = ReadDword( HKEY_LOCAL_MACHINE, L"SOFTWARE\\Policies\\Microsoft\\Windows\\Windows Error Reporting", L"Disabled" ); auto localDisabled = ReadDword( HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft\\Windows\\Windows Error Reporting", L"Disabled" ); bool policyOff = policyDisabled.has_value() && *policyDisabled == 1; bool localOff = localDisabled.has_value() && *localDisabled == 1; std::cout << "WER policy Disabled=1: " << (policyOff ? "yes" : "no") << "\n"; std::cout << "WER local Disabled=1: " << (localOff ? "yes" : "no") << "\n"; std::wstring werDllPath = GetNativeSystemFilePath(L"wer.dll"); std::wstring werSvcDllPath = GetNativeSystemFilePath(L"WerSvc.dll"); auto werDllVersion = GetFileVersion(werDllPath); auto werSvcVersion = GetFileVersion(werSvcDllPath); std::cout << "\nFile: " << ToUtf8(werDllPath) << "\nVersion: " << (werDllVersion ? ToUtf8(*werDllVersion) : "n/a") << "\n"; std::cout << "\nFile: " << ToUtf8(werSvcDllPath) << "\nVersion: " << (werSvcVersion ? ToUtf8(*werSvcVersion) : "n/a") << "\n"; bool werLooksDisabled = policyOff || localOff || (svc.existsKnown && svc.exists && svc.startTypeKnown && svc.disabledConfig); std::cout << "\nResult: "; if (!svc.existsKnown) { std::cout << "UNKNOWN - cannot query service state reliably.\n"; } else if (!svc.exists) { std::cout << "NOT_APPLICABLE - WerSvc not found.\n"; } else if (werLooksDisabled) { std::cout << "MITIGATED - Windows Error Reporting appears disabled.\n"; } else if (os.major == 10) { std::cout << "POTENTIALLY_VULNERABLE - WER is present and enabled.\n"; std::cout << "Verify that July 2023 or later cumulative security updates are installed.\n"; } else { std::cout << "UNKNOWN - validate against Microsoft Security Response Center guidance.\n"; } std::cout << "\nNote: this tool only checks exposure indicators.\n"; std::cout << "It does not trigger CVE-2023-36874 and does not attempt privilege escalation.\n"; return 0; }