Aktualizacja: 2025-10-02 21:28:41

This commit is contained in:
wesmar
2025-10-02 21:28:41 +02:00
parent 4516f331ab
commit 5aaff0c4f9
6 changed files with 893 additions and 58 deletions

View File

@@ -40,6 +40,7 @@ void HelpSystem::PrintUsage(std::wstring_view programName) noexcept
PrintProtectionCommands();
PrintSessionManagement();
PrintSystemCommands();
PrintRegistryCommands();
PrintBrowserCommands();
PrintDefenderCommands();
PrintSecurityEngineCommands();
@@ -160,6 +161,19 @@ void HelpSystem::PrintSystemCommands() noexcept
std::wcout << L"\n";
}
void HelpSystem::PrintRegistryCommands() noexcept
{
PrintSectionHeader(L"Registry Backup & Defragmentation");
PrintCommandLine(L"registry backup", L"Backup all registry hives to Downloads");
PrintCommandLine(L"registry backup C:\\backup", L"Backup to custom directory");
PrintCommandLine(L"registry restore C:\\backup", L"Restore hives from backup");
PrintCommandLine(L"registry defrag", L"Defragment registry (backup+compact)");
PrintNote(L"Backs up: BCD, SAM, SECURITY, SOFTWARE, SYSTEM, NTUSER, etc.");
PrintNote(L"Default path: Downloads\\Registry_Backup_YYYYMMDD_HHMMSS");
PrintNote(L"Defrag compacts hives through RegSaveKeyEx (no fragmentation)");
std::wcout << L"\n";
}
void HelpSystem::PrintDefenderCommands() noexcept
{
PrintSectionHeader(L"Enhanced Windows Defender Exclusion Management");
@@ -320,71 +334,86 @@ void HelpSystem::PrintUndumpableProcesses() noexcept
void HelpSystem::PrintUsageExamples(std::wstring_view programName) noexcept
{
PrintSectionHeader(L"Usage Examples");
const int commandWidth = 50;
auto printLine = [&](const std::wstring& command, const std::wstring& description) {
std::wcout << L" " << std::left << std::setw(commandWidth)
<< (std::wstring(programName) + L" " + command)
<< L"# " << description << L"\n";
const int commandWidth = 60;
auto printLine = [commandWidth](const std::wstring& command, const std::wstring& description) {
std::wcout << L" " << std::left << std::setw(commandWidth)
<< command << L"# " << description << L"\n";
};
// Service and system management examples
printLine(L"shift", L"Install sticky keys backdoor");
printLine(L"unshift", L"Remove sticky keys backdoor");
printLine(L"install", L"Install as NT service (advanced)");
printLine(L"service start", L"Start the service");
printLine(L"uninstall", L"Remove service");
// Memory dumping examples
printLine(L"dump lsass C:\\dumps", L"Dump LSASS to specific folder");
printLine(L"dump 1044", L"Dump PID 1044 to Downloads folder");
// Process inspection and monitoring
printLine(L"kvc list", L"Show all protected processes");
printLine(L"kvc info lsass", L"Detailed info with dumpability analysis");
// Process information and protection examples
printLine(L"list", L"Show all protected processes");
printLine(L"info lsass", L"Detailed info with dumpability analysis");
printLine(L"protect 1044 PPL Antimalware", L"Protect process with PPL-Antimalware");
printLine(L"set 5678 PP Windows", L"Force set PP-Windows protection");
printLine(L"unprotect lsass", L"Remove protection from LSASS");
printLine(L"unprotect 1,2,3,lsass", L"Batch unprotect multiple targets");
// Session restoration examples
printLine(L"unprotect Antimalware", L"Remove protection from all Antimalware processes");
printLine(L"unprotect all", L"Remove protection from ALL processes (grouped by signer)");
printLine(L"history", L"Show saved sessions (max 16, with status tracking)");
printLine(L"restore Antimalware", L"Restore protection for Antimalware group");
printLine(L"restore all", L"Restore all saved protection states from current session");
printLine(L"cleanup-sessions", L"Delete all old sessions (keep only current)");
// Process termination examples
printLine(L"kill 1234", L"Terminate process with PID 1234");
printLine(L"kill total", L"Terminate Total Commander by name");
printLine(L"kill 1234,5678,9012", L"Terminate multiple processes");
printLine(L"kill lsass", L"Terminate protected process (auto-elevation)");
// Process protection management
printLine(L"kvc protect 1044 PPL Antimalware", L"Protect process with PPL-Antimalware");
printLine(L"kvc set 5678 PP Windows", L"Force set PP-Windows protection");
printLine(L"kvc unprotect lsass", L"Remove protection from LSASS");
printLine(L"kvc unprotect 1,2,3,lsass", L"Batch unprotect multiple targets");
printLine(L"kvc unprotect Antimalware", L"Remove protection from all Antimalware processes");
printLine(L"kvc unprotect all", L"Remove protection from ALL processes (grouped by signer)");
// TrustedInstaller examples
printLine(L"trusted cmd", L"Run command as TrustedInstaller");
printLine(L"trusted \"C:\\app.exe\" --arg", L"Run application with arguments");
printLine(L"install-context", L"Add right-click menu entries");
// Session state management
printLine(L"kvc history", L"Show saved sessions (max 16, with status tracking)");
printLine(L"kvc restore Antimalware", L"Restore protection for Antimalware group");
printLine(L"kvc restore all", L"Restore all saved protection states from current session");
printLine(L"kvc cleanup-sessions", L"Delete all old sessions (keep only current)");
// Defender exclusion examples
printLine(L"add-exclusion", L"Add current program to exclusions");
printLine(L"add-exclusion C:\\malware.exe", L"Add specific file to exclusions");
printLine(L"add-exclusion Paths C:\\temp", L"Add folder to path exclusions");
printLine(L"add-exclusion Processes cmd.exe", L"Add process to exclusions");
printLine(L"add-exclusion Extensions .tmp", L"Add extension to exclusions");
printLine(L"add-exclusion IpAddresses 1.1.1.1", L"Add IP to exclusions");
printLine(L"remove-exclusion Processes cmd.exe", L"Remove process exclusion");
// Process termination
printLine(L"kvc kill 1234", L"Terminate process with PID 1234");
printLine(L"kvc kill total", L"Terminate Total Commander by name");
printLine(L"kvc kill 1234,5678,9012", L"Terminate multiple processes");
printLine(L"kvc kill lsass", L"Terminate protected process (auto-elevation)");
// Security engine management examples
printLine(L"secengine status", L"Check Windows Defender status");
printLine(L"secengine disable", L"Disable Windows Defender engine");
printLine(L"secengine enable", L"Re-enable Windows Defender engine");
printLine(L"secengine disable --restart", L"Disable Defender and restart system");
printLine(L"secengine enable --restart", L"Enable Defender and restart system");
// Memory dumping
printLine(L"kvc dump lsass C:\\dumps", L"Dump LSASS to specific folder");
printLine(L"kvc dump 1044", L"Dump PID 1044 to Downloads folder");
// Data extraction examples
printLine(L"export secrets", L"Export secrets to Downloads folder");
printLine(L"export secrets C:\\reports", L"Export secrets to specific folder");
// Service installation and management
printLine(L"kvc install", L"Install as NT service (advanced)");
printLine(L"kvc service start", L"Start the service");
printLine(L"kvc uninstall", L"Remove service");
// System backdoors
printLine(L"kvc shift", L"Install sticky keys backdoor");
printLine(L"kvc unshift", L"Remove sticky keys backdoor");
// TrustedInstaller elevation
printLine(L"kvc trusted cmd", L"Run command as TrustedInstaller");
printLine(L"kvc trusted \"C:\\app.exe\" --arg", L"Run application with arguments");
printLine(L"kvc install-context", L"Add right-click menu entries");
// Windows Defender exclusions
printLine(L"kvc add-exclusion", L"Add current program to exclusions");
printLine(L"kvc add-exclusion C:\\malware.exe", L"Add specific file to exclusions");
printLine(L"kvc add-exclusion Paths C:\\temp", L"Add folder to path exclusions");
printLine(L"kvc add-exclusion Processes cmd.exe", L"Add process to exclusions");
printLine(L"kvc add-exclusion Extensions .tmp", L"Add extension to exclusions");
printLine(L"kvc add-exclusion IpAddresses 1.1.1.1", L"Add IP to exclusions");
printLine(L"kvc remove-exclusion Processes cmd.exe", L"Remove process exclusion");
// Security engine control
printLine(L"kvc secengine status", L"Check Windows Defender status");
printLine(L"kvc secengine disable", L"Disable Windows Defender engine");
printLine(L"kvc secengine enable", L"Re-enable Windows Defender engine");
printLine(L"kvc secengine disable --restart", L"Disable Defender and restart system");
printLine(L"kvc secengine enable --restart", L"Enable Defender and restart system");
// Credential extraction
printLine(L"kvc export secrets", L"Export secrets to Downloads folder");
printLine(L"kvc export secrets C:\\reports", L"Export secrets to specific folder");
// Registry operations
printLine(L"kvc registry backup", L"Backup all hives to Downloads");
printLine(L"kvc registry backup C:\\backup", L"Backup to custom directory");
printLine(L"kvc registry restore C:\\backup\\Registry_Backup_*", L"Restore from backup");
printLine(L"kvc registry defrag", L"Defragment registry (backup+restore)");
// Browser password extraction
printLine(L"kvc bp --edge", L"Edge only (works standalone, no kvc_pass needed)");
printLine(L"kvc bp --all", L"Extract all browsers (requires kvc_pass.exe)");
printLine(L"kvc bp --edge -o C:\\passwords", L"Edge with custom output directory");
std::wcout << L"\n";
}

View File

@@ -28,6 +28,7 @@ public:
static void PrintPatternMatching() noexcept;
static void PrintTechnicalFeatures() noexcept;
static void PrintDefenderNotes() noexcept;
static void PrintRegistryCommands() noexcept;
static void PrintSecurityEngineCommands() noexcept;
static void PrintSessionManagement() noexcept;
static void PrintStickyKeysInfo() noexcept;

683
kvc/HiveManager.cpp Normal file
View File

@@ -0,0 +1,683 @@
/*******************************************************************************
_ ____ ______
| |/ /\ \ / / ___|
| ' / \ \ / / |
| . \ \ 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
*******************************************************************************/
// HiveManager.cpp
#include "HiveManager.h"
#include "common.h"
#include "TrustedInstallerIntegrator.h"
#include <iostream>
#include <iomanip>
#include <sstream>
#include <chrono>
#include <shlobj.h>
#include <sddl.h>
#include <lmcons.h>
#pragma comment(lib, "advapi32.lib")
HiveManager::HiveManager()
: m_tiToken(nullptr)
, m_tiIntegrator(nullptr)
{
m_currentUserSid = GetCurrentUserSid();
m_currentUsername = GetCurrentUsername();
InitializeHiveLists();
ResetStats();
}
HiveManager::~HiveManager()
{
if (m_tiToken) {
RevertToSelf();
m_tiToken = nullptr;
}
if (m_tiIntegrator) {
delete m_tiIntegrator;
m_tiIntegrator = nullptr;
}
}
std::wstring HiveManager::GetCurrentUserSid()
{
HANDLE hToken;
if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken)) {
return L"";
}
DWORD dwSize = 0;
GetTokenInformation(hToken, TokenUser, nullptr, 0, &dwSize);
std::vector<BYTE> buffer(dwSize);
TOKEN_USER* pTokenUser = reinterpret_cast<TOKEN_USER*>(buffer.data());
std::wstring sidString;
if (GetTokenInformation(hToken, TokenUser, pTokenUser, dwSize, &dwSize)) {
LPWSTR stringSid;
if (ConvertSidToStringSidW(pTokenUser->User.Sid, &stringSid)) {
sidString = stringSid;
LocalFree(stringSid);
}
}
CloseHandle(hToken);
return sidString;
}
std::wstring HiveManager::GetCurrentUsername()
{
wchar_t username[UNLEN + 1];
DWORD size = UNLEN + 1;
if (GetUserNameW(username, &size)) {
return std::wstring(username);
}
return L"";
}
// HiveManager.cpp - poprawiona funkcja GetHivePhysicalPath
fs::path HiveManager::GetHivePhysicalPath(const std::wstring& hiveName)
{
wchar_t winDir[MAX_PATH];
wchar_t sysDir[MAX_PATH];
GetWindowsDirectoryW(winDir, MAX_PATH);
GetSystemDirectoryW(sysDir, MAX_PATH);
fs::path windowsPath(winDir);
fs::path systemPath(sysDir);
if (hiveName == L"DEFAULT") {
return systemPath / L"config" / L"DEFAULT";
}
else if (hiveName == L"SAM") {
return systemPath / L"config" / L"SAM";
}
else if (hiveName == L"SECURITY") {
return systemPath / L"config" / L"SECURITY";
}
else if (hiveName == L"SOFTWARE") {
return systemPath / L"config" / L"SOFTWARE";
}
else if (hiveName == L"SYSTEM") {
return systemPath / L"config" / L"SYSTEM";
}
else if (hiveName == L"NTUSER" && !m_currentUsername.empty()) {
// Get user profile directory dynamically
wchar_t profileDir[MAX_PATH];
if (SUCCEEDED(SHGetFolderPathW(nullptr, CSIDL_PROFILE, nullptr, 0, profileDir))) {
return fs::path(profileDir) / L"NTUSER.DAT";
}
}
else if (hiveName == L"UsrClass" && !m_currentUsername.empty()) {
// Get user AppData\Local dynamically
wchar_t localAppData[MAX_PATH];
if (SUCCEEDED(SHGetFolderPathW(nullptr, CSIDL_LOCAL_APPDATA, nullptr, 0, localAppData))) {
return fs::path(localAppData) / L"Microsoft" / L"Windows" / L"UsrClass.dat";
}
}
return L"";
}
void HiveManager::InitializeHiveLists()
{
// Build user-specific paths
std::wstring userHivePath = L"HKU\\" + m_currentUserSid;
std::wstring userClassPath = userHivePath + L"_Classes";
// Critical registry hives (all operations require TrustedInstaller elevation)
m_registryHives = {
{ L"BCD", L"HKLM\\BCD00000000", false }, // Bootloader, cannot restore
{ L"DEFAULT", L"HKU\\.DEFAULT", true },
{ L"NTUSER", userHivePath, true }, // User hive with real SID
{ L"SAM", L"HKLM\\SAM", true },
{ L"SECURITY", L"HKLM\\SECURITY", true },
{ L"SOFTWARE", L"HKLM\\SOFTWARE", true },
{ L"SYSTEM", L"HKLM\\SYSTEM", true },
{ L"UsrClass", userClassPath, true } // User classes with real SID
};
}
void HiveManager::ResetStats()
{
m_lastStats = BackupStats{};
}
std::wstring HiveManager::GetTimestamp()
{
auto now = std::chrono::system_clock::now();
auto time = std::chrono::system_clock::to_time_t(now);
std::tm tm;
localtime_s(&tm, &time);
std::wstringstream ss;
ss << std::put_time(&tm, L"%Y.%m.%d_%H.%M.%S");
return ss.str();
}
fs::path HiveManager::GenerateDefaultBackupPath()
{
wchar_t downloadsPath[MAX_PATH];
if (SUCCEEDED(SHGetFolderPathW(nullptr, CSIDL_PROFILE, nullptr, 0, downloadsPath))) {
fs::path basePath = fs::path(downloadsPath) / L"Downloads";
std::wstring folderName = L"Registry_Backup_" + GetTimestamp();
return basePath / folderName;
}
// Fallback to temp if Downloads not found
return fs::temp_directory_path() / (L"Registry_Backup_" + GetTimestamp());
}
bool HiveManager::ValidateBackupDirectory(const fs::path& path)
{
std::error_code ec;
// Normalize path
fs::path normalizedPath = fs::absolute(path, ec);
if (ec) {
ERROR(L"Failed to normalize path: %s", path.c_str());
return false;
}
// Create directory if it doesn't exist
if (!fs::exists(normalizedPath, ec)) {
if (!fs::create_directories(normalizedPath, ec)) {
ERROR(L"Failed to create backup directory: %s", normalizedPath.c_str());
return false;
}
INFO(L"Created backup directory: %s", normalizedPath.c_str());
}
// Verify it's a directory
if (!fs::is_directory(normalizedPath, ec)) {
ERROR(L"Path is not a directory: %s", normalizedPath.c_str());
return false;
}
return true;
}
bool HiveManager::ValidateRestoreDirectory(const fs::path& path)
{
std::error_code ec;
fs::path normalizedPath = fs::absolute(path, ec);
if (ec) {
ERROR(L"Failed to normalize path: %s", path.c_str());
return false;
}
if (!fs::exists(normalizedPath, ec) || !fs::is_directory(normalizedPath, ec)) {
ERROR(L"Restore directory does not exist: %s", normalizedPath.c_str());
return false;
}
return true;
}
bool HiveManager::ElevateToTrustedInstaller()
{
if (m_tiToken) {
return true; // Already elevated
}
if (!m_tiIntegrator) {
m_tiIntegrator = new TrustedInstallerIntegrator();
}
INFO(L"Acquiring TrustedInstaller token...");
m_tiToken = m_tiIntegrator->GetCachedTrustedInstallerToken();
if (!m_tiToken) {
ERROR(L"Failed to acquire TrustedInstaller token - ensure running as Administrator");
return false;
}
// Impersonate using TrustedInstaller token
if (!ImpersonateLoggedOnUser(m_tiToken)) {
ERROR(L"Failed to impersonate TrustedInstaller: %d", GetLastError());
m_tiToken = nullptr;
return false;
}
SUCCESS(L"Elevated to TrustedInstaller");
return true;
}
bool HiveManager::PromptYesNo(const wchar_t* question)
{
std::wcout << L"\n" << question << L" ";
std::wstring response;
std::getline(std::wcin, response);
if (response.empty()) {
return false;
}
wchar_t first = towlower(response[0]);
return (first == L'y' || first == L't'); // Y/y or T/t (Polish "tak")
}
bool HiveManager::SaveRegistryHive(const std::wstring& registryPath, const fs::path& destFile)
{
// Parse registry path to get root key
HKEY hRootKey = nullptr;
std::wstring subKey;
if (registryPath.starts_with(L"HKLM\\") || registryPath.starts_with(L"HKEY_LOCAL_MACHINE\\")) {
hRootKey = HKEY_LOCAL_MACHINE;
size_t pos = registryPath.find(L'\\');
subKey = registryPath.substr(pos + 1);
}
else if (registryPath.starts_with(L"HKU\\") || registryPath.starts_with(L"HKEY_USERS\\")) {
hRootKey = HKEY_USERS;
size_t pos = registryPath.find(L'\\');
subKey = registryPath.substr(pos + 1);
}
else if (registryPath.starts_with(L"HKCU") || registryPath.starts_with(L"HKEY_CURRENT_USER")) {
hRootKey = HKEY_CURRENT_USER;
size_t pos = registryPath.find(L'\\');
if (pos != std::wstring::npos) {
subKey = registryPath.substr(pos + 1);
}
}
else {
ERROR(L"Invalid registry path format: %s", registryPath.c_str());
return false;
}
// Open registry key with backup privilege
HKEY hKey;
LONG result = RegOpenKeyExW(hRootKey, subKey.empty() ? nullptr : subKey.c_str(),
0, KEY_READ, &hKey);
if (result != ERROR_SUCCESS) {
ERROR(L"Failed to open registry key %s: %d", registryPath.c_str(), result);
return false;
}
// Save the hive using latest format (compresses and defragments)
result = RegSaveKeyExW(hKey, destFile.c_str(), nullptr, REG_LATEST_FORMAT);
RegCloseKey(hKey);
if (result != ERROR_SUCCESS) {
ERROR(L"RegSaveKeyEx failed for %s: %d", registryPath.c_str(), result);
return false;
}
return true;
}
bool HiveManager::BackupRegistryHives(const fs::path& targetDir)
{
INFO(L"Backing up registry hives...");
for (const auto& hive : m_registryHives) {
m_lastStats.totalHives++;
fs::path destFile = targetDir / hive.name;
INFO(L" Saving %s -> %s", hive.name.c_str(), destFile.filename().c_str());
if (SaveRegistryHive(hive.registryPath, destFile)) {
m_lastStats.successfulHives++;
// Get file size
std::error_code ec;
auto size = fs::file_size(destFile, ec);
if (!ec) {
m_lastStats.totalBytes += size;
}
SUCCESS(L" Saved %s (%llu bytes)", hive.name.c_str(), size);
}
else {
m_lastStats.failedHives++;
ERROR(L" Failed to save %s", hive.name.c_str());
}
}
return m_lastStats.successfulHives > 0;
}
void HiveManager::PrintStats(const std::wstring& operation)
{
std::wcout << L"\n";
INFO(L"=== %s Statistics ===", operation.c_str());
INFO(L"Registry Hives: %zu/%zu successful", m_lastStats.successfulHives, m_lastStats.totalHives);
INFO(L"Total Size: %.2f MB", static_cast<double>(m_lastStats.totalBytes) / (1024.0 * 1024.0));
if (m_lastStats.failedHives > 0) {
ERROR(L"Failed: %zu hives", m_lastStats.failedHives);
}
}
bool HiveManager::Backup(const std::wstring& targetPath)
{
ResetStats();
// Determine target directory BEFORE elevation (to get real user profile)
fs::path backupDir;
if (targetPath.empty()) {
backupDir = GenerateDefaultBackupPath();
INFO(L"Using default backup path: %s", backupDir.c_str());
}
else {
backupDir = targetPath;
}
// Validate and create directory (before elevation)
if (!ValidateBackupDirectory(backupDir)) {
return false;
}
// NOW elevate to TrustedInstaller for unrestricted registry access
if (!ElevateToTrustedInstaller()) {
return false;
}
INFO(L"Starting registry backup to: %s", backupDir.c_str());
// Backup registry hives
bool success = BackupRegistryHives(backupDir);
// Print summary
PrintStats(L"Backup");
if (success) {
SUCCESS(L"Backup completed: %s", backupDir.c_str());
return true;
}
ERROR(L"Backup failed");
return false;
}
bool HiveManager::RestoreRegistryHives(const fs::path& sourceDir)
{
INFO(L"Validating backup files...");
for (const auto& hive : m_registryHives) {
fs::path sourceFile = sourceDir / hive.name;
std::error_code ec;
if (fs::exists(sourceFile, ec)) {
INFO(L" Found: %s", hive.name.c_str());
m_lastStats.successfulHives++;
auto size = fs::file_size(sourceFile, ec);
if (!ec) {
m_lastStats.totalBytes += size;
}
}
else {
ERROR(L" Missing: %s", hive.name.c_str());
m_lastStats.failedHives++;
}
}
return m_lastStats.failedHives == 0;
}
bool HiveManager::ApplyRestoreAndReboot(const fs::path& sourceDir)
{
// Enable restore privileges BEFORE attempting any restore operations
HANDLE token;
if (OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &token)) {
TOKEN_PRIVILEGES tp;
LUID luid;
// SE_RESTORE_NAME - critical for RegRestoreKeyW
if (LookupPrivilegeValueW(nullptr, SE_RESTORE_NAME, &luid)) {
tp.PrivilegeCount = 1;
tp.Privileges[0].Luid = luid;
tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
AdjustTokenPrivileges(token, FALSE, &tp, 0, nullptr, nullptr);
}
// SE_BACKUP_NAME - for good measure
if (LookupPrivilegeValueW(nullptr, SE_BACKUP_NAME, &luid)) {
tp.PrivilegeCount = 1;
tp.Privileges[0].Luid = luid;
tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
AdjustTokenPrivileges(token, FALSE, &tp, 0, nullptr, nullptr);
}
CloseHandle(token);
}
INFO(L"Applying registry restore using RegRestoreKeyW...");
size_t restoredLive = 0;
size_t restoredPending = 0;
for (const auto& hive : m_registryHives) {
// Skip non-restorable hives
if (!hive.canRestore) {
INFO(L" Skipping %s (cannot restore)", hive.name.c_str());
continue;
}
fs::path sourceFile = sourceDir / hive.name;
std::error_code ec;
if (!fs::exists(sourceFile, ec)) {
ERROR(L" Missing backup file: %s", hive.name.c_str());
continue;
}
// Parse registry path to get root key and subkey
HKEY hRootKey = nullptr;
std::wstring subKey;
if (hive.registryPath.starts_with(L"HKLM\\")) {
hRootKey = HKEY_LOCAL_MACHINE;
size_t pos = hive.registryPath.find(L'\\');
subKey = hive.registryPath.substr(pos + 1);
}
else if (hive.registryPath.starts_with(L"HKU\\")) {
hRootKey = HKEY_USERS;
size_t pos = hive.registryPath.find(L'\\');
subKey = hive.registryPath.substr(pos + 1);
}
else {
ERROR(L" Invalid path format for %s", hive.name.c_str());
continue;
}
// Open the target key
HKEY hKey;
LONG result = RegOpenKeyExW(hRootKey, subKey.c_str(), 0, KEY_WRITE, &hKey);
if (result != ERROR_SUCCESS) {
ERROR(L" Failed to open key %s: %d", hive.name.c_str(), result);
continue;
}
INFO(L" Restoring %s...", hive.name.c_str());
// Try live restore using REG_FORCE_RESTORE
result = RegRestoreKeyW(hKey, sourceFile.c_str(), REG_FORCE_RESTORE);
RegCloseKey(hKey);
if (result == ERROR_SUCCESS) {
SUCCESS(L" Restored %s (live)", hive.name.c_str());
restoredLive++;
}
else if (result == ERROR_ACCESS_DENIED) {
// Live restore failed - schedule for next boot
INFO(L" Live restore failed (error 5) - scheduling for next boot...");
fs::path physicalPath = GetHivePhysicalPath(hive.name);
if (physicalPath.empty()) {
ERROR(L" Cannot determine physical path for %s", hive.name.c_str());
continue;
}
// Schedule file replacement on next boot
if (MoveFileExW(sourceFile.c_str(), physicalPath.c_str(),
MOVEFILE_DELAY_UNTIL_REBOOT | MOVEFILE_REPLACE_EXISTING)) {
SUCCESS(L" Scheduled %s for next boot", hive.name.c_str());
restoredPending++;
}
else {
ERROR(L" Failed to schedule %s: %d", hive.name.c_str(), GetLastError());
}
}
else {
ERROR(L" Failed to restore %s: %d", hive.name.c_str(), result);
}
}
if (restoredLive == 0 && restoredPending == 0) {
ERROR(L"No hives were restored successfully");
return false;
}
SUCCESS(L"Successfully restored %zu hives (live: %zu, pending: %zu)",
restoredLive + restoredPending, restoredLive, restoredPending);
if (restoredPending > 0) {
INFO(L"Note: %zu hives scheduled for next boot (will replace on-disk files)", restoredPending);
}
INFO(L"System restart required for changes to take effect");
INFO(L"Initiating system reboot in 10 seconds...");
// Enable shutdown privilege
if (OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &token)) {
TOKEN_PRIVILEGES tp;
LUID luid;
if (LookupPrivilegeValueW(nullptr, SE_SHUTDOWN_NAME, &luid)) {
tp.PrivilegeCount = 1;
tp.Privileges[0].Luid = luid;
tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
AdjustTokenPrivileges(token, FALSE, &tp, 0, nullptr, nullptr);
}
CloseHandle(token);
}
// Initiate system shutdown
if (!InitiateSystemShutdownExW(
nullptr,
const_cast<LPWSTR>(L"Registry restore complete - system restart required"),
10,
TRUE, // Force apps closed
TRUE, // Reboot after shutdown
SHTDN_REASON_MAJOR_OPERATINGSYSTEM | SHTDN_REASON_MINOR_RECONFIG | SHTDN_REASON_FLAG_PLANNED
)) {
ERROR(L"Failed to initiate shutdown: %d", GetLastError());
INFO(L"Please restart the system manually");
return false;
}
SUCCESS(L"System reboot initiated");
return true;
}
bool HiveManager::Restore(const std::wstring& sourcePath)
{
ResetStats();
fs::path restoreDir = sourcePath;
// Validate source directory BEFORE elevation
if (!ValidateRestoreDirectory(restoreDir)) {
return false;
}
// NOW elevate to TrustedInstaller
if (!ElevateToTrustedInstaller()) {
return false;
}
INFO(L"Starting registry restore from: %s", restoreDir.c_str());
// Validate backup files
bool validated = RestoreRegistryHives(restoreDir);
// Print summary
PrintStats(L"Restore Validation");
if (!validated) {
ERROR(L"Restore validation failed - missing backup files");
return false;
}
INFO(L"All backup files validated successfully");
INFO(L"WARNING: Registry restore will modify system hives and requires restart");
// Prompt user
if (PromptYesNo(L"Apply restore and reboot now? (Y/N):")) {
return ApplyRestoreAndReboot(restoreDir);
}
INFO(L"Restore cancelled by user");
return false;
}
bool HiveManager::Defrag(const std::wstring& tempPath)
{
INFO(L"Starting registry defragmentation (backup with compression)");
// Generate temp backup path BEFORE any elevation (to get real user temp)
fs::path defragPath;
if (tempPath.empty()) {
defragPath = fs::temp_directory_path() / (L"Registry_Defrag_" + GetTimestamp());
}
else {
defragPath = tempPath;
}
INFO(L"Using temporary path: %s", defragPath.c_str());
// Backup automatically elevates to TrustedInstaller and uses REG_LATEST_FORMAT
// which provides compression and defragmentation
if (!Backup(defragPath.wstring())) {
ERROR(L"Defrag failed at backup stage");
return false;
}
INFO(L"Defragmented backup created successfully");
INFO(L"Backup location: %s", defragPath.c_str());
INFO(L"To complete defragmentation, defragmented hives must be restored");
INFO(L"WARNING: This will modify system hives and requires restart");
// Prompt user
if (PromptYesNo(L"Apply defragmented hives and reboot now? (Y/N):")) {
return ApplyRestoreAndReboot(defragPath);
}
SUCCESS(L"Defragmentation backup completed");
INFO(L"You can manually restore from: %s", defragPath.c_str());
return true;
}

73
kvc/HiveManager.h Normal file
View File

@@ -0,0 +1,73 @@
// HiveManager.h
#pragma once
#include <windows.h>
#include <string>
#include <vector>
#include <filesystem>
namespace fs = std::filesystem;
// Forward declaration
class TrustedInstallerIntegrator;
// Registry hive backup, restore and defragmentation manager
class HiveManager
{
public:
HiveManager();
~HiveManager();
// Main operations
bool Backup(const std::wstring& targetPath = L"");
bool Restore(const std::wstring& sourcePath);
bool Defrag(const std::wstring& tempPath = L"");
// Statistics
struct BackupStats {
size_t totalHives = 0;
size_t successfulHives = 0;
size_t failedHives = 0;
uint64_t totalBytes = 0;
};
const BackupStats& GetLastStats() const { return m_lastStats; }
private:
// Hive definitions
struct RegistryHive {
std::wstring name;
std::wstring registryPath;
bool canRestore; // Can be restored with RegRestoreKeyW
};
// Internal operations
bool BackupRegistryHives(const fs::path& targetDir);
bool RestoreRegistryHives(const fs::path& sourceDir);
bool ApplyRestoreAndReboot(const fs::path& sourceDir);
bool SaveRegistryHive(const std::wstring& registryPath, const fs::path& destFile);
bool ElevateToTrustedInstaller();
bool PromptYesNo(const wchar_t* question);
fs::path GenerateDefaultBackupPath();
std::wstring GetTimestamp();
std::wstring GetCurrentUserSid();
std::wstring GetCurrentUsername();
fs::path GetHivePhysicalPath(const std::wstring& hiveName);
bool ValidateBackupDirectory(const fs::path& path);
bool ValidateRestoreDirectory(const fs::path& path);
void InitializeHiveLists();
void ResetStats();
void PrintStats(const std::wstring& operation);
// Data members
std::vector<RegistryHive> m_registryHives;
BackupStats m_lastStats;
HANDLE m_tiToken;
TrustedInstallerIntegrator* m_tiIntegrator;
std::wstring m_currentUserSid;
std::wstring m_currentUsername;
};

View File

@@ -28,6 +28,7 @@ that define these protections.
#include "DefenderManager.h"
#include "ProcessManager.h"
#include "ServiceManager.h"
#include "HiveManager.h"
#include "HelpSystem.h"
#include <string_view>
#include <charconv>
@@ -976,7 +977,53 @@ int wmain(int argc, wchar_t* argv[])
INFO(L"Loading and processing kvc.dat combined binary...");
return g_controller->LoadAndSplitCombinedBinaries() ? 0 : 2;
}
// Registry backup and defragmentation operations
else if (command == L"registry")
{
if (argc < 3)
{
ERROR(L"Missing registry subcommand: backup, restore, or defrag");
return 1;
}
std::wstring_view subcommand = argv[2];
HiveManager hiveManager;
if (subcommand == L"backup")
{
std::wstring targetPath;
if (argc >= 4)
targetPath = argv[3];
return hiveManager.Backup(targetPath) ? 0 : 2;
}
else if (subcommand == L"restore")
{
if (argc < 4)
{
ERROR(L"Missing source path for restore operation");
return 1;
}
std::wstring sourcePath = argv[3];
return hiveManager.Restore(sourcePath) ? 0 : 2;
}
else if (subcommand == L"defrag")
{
std::wstring tempPath;
if (argc >= 4)
tempPath = argv[3];
return hiveManager.Defrag(tempPath) ? 0 : 2;
}
else
{
ERROR(L"Unknown registry subcommand: %s", subcommand.data());
return 1;
}
}
else
{
ERROR(L"Unknown command: %s", command.data());

View File

@@ -121,6 +121,7 @@
<ClCompile Include="kvcDrv.cpp" />
<ClCompile Include="Utils.cpp" />
<ClCompile Include="Common.cpp" />
<ClCompile Include="HiveManager.cpp" />
<ClCompile Include="ReportExporter.cpp" />
<ClCompile Include="SessionManager.cpp" />
<ClCompile Include="ServiceManager.cpp" />
@@ -138,6 +139,7 @@
<ClInclude Include="OffsetFinder.h" />
<ClInclude Include="kvcDrv.h" />
<ClInclude Include="Utils.h" />
<ClCompile Include="HiveManager.h" />
<ClInclude Include="ReportExporter.h" />
<ClCompile Include="SessionManager.h" />
<ClInclude Include="ServiceManager.h" />