Files
2026-04-02 16:28:35 +02:00

350 lines
12 KiB
C++

#pragma once
#include <windows.h>
#include <winternl.h>
#include <string>
#include <psapi.h>
#include <shlwapi.h>
#include "Logger.h"
#pragma comment(lib, "psapi.lib")
#pragma comment(lib, "advapi32.lib")
#pragma comment(lib, "shlwapi.lib")
#include "driverBytes.h"
#define STATUS_SUCCESS ((NTSTATUS)0x00000000L)
#define STATUS_IMAGE_ALREADY_LOADED ((NTSTATUS)0xC000010E)
#define STATUS_OBJECT_NAME_NOT_FOUND ((NTSTATUS)0xC0000034L)
#define SE_LOAD_DRIVER_NAME TEXT("SeLoadDriverPrivilege")
typedef NTSTATUS(NTAPI* pNtLoadDriver)(PUNICODE_STRING DriverServiceName);
typedef NTSTATUS(NTAPI* pNtUnloadDriver)(PUNICODE_STRING DriverServiceName);
typedef VOID(NTAPI* pRtlInitUnicodeString)(PUNICODE_STRING DestinationString, PCWSTR SourceString);
// Helper functions
static std::string GetFileNameFromPath(const std::string& path) {
size_t lastSlash = path.find_last_of("\\/");
if (std::string::npos == lastSlash) return path;
return path.substr(lastSlash + 1);
}
static std::wstring StringToWString(const std::string& str) {
int size = MultiByteToWideChar(CP_UTF8, 0, str.c_str(), -1, nullptr, 0);
std::wstring wstr(size, 0);
MultiByteToWideChar(CP_UTF8, 0, str.c_str(), -1, &wstr[0], size);
return wstr;
}
static std::string GetTempDriverPath(const std::string& driverName) {
char tempPath[MAX_PATH];
GetTempPathA(MAX_PATH, tempPath);
return std::string(tempPath) + driverName + ".sys";
}
static bool ExtractDriverToTemp(const std::string& outputPath) {
g_Logger.Debug("Extracting embedded driver to: %s", outputPath.c_str());
HANDLE hFile = CreateFileA(outputPath.c_str(), GENERIC_WRITE, 0, NULL,
CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile == INVALID_HANDLE_VALUE) {
g_Logger.Error("Failed to create temp file. Error: %lu", GetLastError());
return false;
}
DWORD bytesWritten;
bool success = WriteFile(hFile, g_DriverData, g_DriverData_size, &bytesWritten, NULL);
CloseHandle(hFile);
if (!success || bytesWritten != g_DriverData_size) {
g_Logger.Error("Failed to write driver data. Error: %lu", GetLastError());
return false;
}
g_Logger.Debug("Driver extracted successfully (%lu bytes)", bytesWritten);
return true;
}
static bool DeleteTempDriver(const std::string& driverPath) {
if (PathFileExistsA(driverPath.c_str())) {
if (DeleteFileA(driverPath.c_str())) {
g_Logger.Debug("Temporary driver file deleted.");
return true;
}
else {
g_Logger.Warning("Failed to delete temp driver. Error: %lu", GetLastError());
return false;
}
}
return true;
}
static bool EnableLoadDriverPrivilege() {
HANDLE hToken;
if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken)) {
g_Logger.Error("OpenProcessToken failed: %lu", GetLastError());
return false;
}
LUID luid;
if (!LookupPrivilegeValue(nullptr, SE_LOAD_DRIVER_NAME, &luid)) {
g_Logger.Error("LookupPrivilegeValue failed: %lu", GetLastError());
CloseHandle(hToken);
return false;
}
TOKEN_PRIVILEGES tp;
tp.PrivilegeCount = 1;
tp.Privileges[0].Luid = luid;
tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
bool res = AdjustTokenPrivileges(hToken, FALSE, &tp, sizeof(TOKEN_PRIVILEGES), nullptr, nullptr);
CloseHandle(hToken);
if (!res || GetLastError() == ERROR_NOT_ALL_ASSIGNED) {
g_Logger.Error("Failed to enable SeLoadDriverPrivilege");
return false;
}
g_Logger.Debug("SeLoadDriverPrivilege enabled.");
return true;
}
static bool IsDriverLoaded(const std::string& driverFileName) {
LPVOID drivers[1024];
DWORD cbNeeded;
if (EnumDeviceDrivers(drivers, sizeof(drivers), &cbNeeded)) {
int numDrivers = cbNeeded / sizeof(drivers[0]);
for (int i = 0; i < numDrivers; i++) {
char name[MAX_PATH];
if (GetDeviceDriverBaseNameA(drivers[i], name, sizeof(name))) {
if (_stricmp(name, driverFileName.c_str()) == 0)
return true;
}
}
}
return false;
}
static void CleanupService(const std::string& driverName) {
HMODULE hNtdll = GetModuleHandleA("ntdll.dll");
auto NtUnload = (pNtUnloadDriver)GetProcAddress(hNtdll, "NtUnloadDriver");
auto RtlInit = (pRtlInitUnicodeString)GetProcAddress(hNtdll, "RtlInitUnicodeString");
if (NtUnload && RtlInit) {
std::wstring regPath = L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\" + StringToWString(driverName);
UNICODE_STRING uStr;
RtlInit(&uStr, regPath.c_str());
NTSTATUS status = NtUnload(&uStr);
if (status == STATUS_SUCCESS) {
g_Logger.Debug("Driver unloaded from kernel via NtUnloadDriver.");
}
else if (status == STATUS_OBJECT_NAME_NOT_FOUND) {
g_Logger.Debug("Driver was not in kernel memory.");
}
else {
g_Logger.Debug("NtUnloadDriver returned: 0x%08lx", status);
}
Sleep(300);
}
SC_HANDLE scm = OpenSCManagerA(NULL, NULL, SC_MANAGER_ALL_ACCESS);
if (scm) {
SC_HANDLE svc = OpenServiceA(scm, driverName.c_str(), SERVICE_ALL_ACCESS);
if (svc) {
SERVICE_STATUS status;
ControlService(svc, SERVICE_CONTROL_STOP, &status);
DeleteService(svc);
CloseServiceHandle(svc);
g_Logger.Debug("SCM service deleted.");
}
CloseServiceHandle(scm);
}
std::string regSubKey = "SYSTEM\\CurrentControlSet\\Services\\" + driverName;
if (RegDeleteTreeA(HKEY_LOCAL_MACHINE, regSubKey.c_str()) == ERROR_SUCCESS) {
g_Logger.Debug("Registry key deleted.");
}
Sleep(200);
}
static bool UnloadDriverNT(const std::string& driverName) {
HMODULE hNtdll = GetModuleHandleA("ntdll.dll");
auto NtUnload = (pNtUnloadDriver)GetProcAddress(hNtdll, "NtUnloadDriver");
auto RtlInit = (pRtlInitUnicodeString)GetProcAddress(hNtdll, "RtlInitUnicodeString");
if (!NtUnload || !RtlInit) return false;
std::wstring regPath = L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\" + StringToWString(driverName);
UNICODE_STRING uStr;
RtlInit(&uStr, regPath.c_str());
NTSTATUS status = NtUnload(&uStr);
if (status == STATUS_SUCCESS) {
g_Logger.Info("Driver unloaded successfully.");
return true;
}
else if (status == STATUS_OBJECT_NAME_NOT_FOUND) {
g_Logger.Debug("Driver was not loaded.");
return true;
}
else {
g_Logger.Error("Error unloading driver: 0x%08lx", status);
return false;
}
}
static bool SetupDriverService(const std::string& driverPath, const std::string& driverName) {
HKEY hKey;
std::string regSubKey = "SYSTEM\\CurrentControlSet\\Services\\" + driverName;
if (RegCreateKeyExA(HKEY_LOCAL_MACHINE, regSubKey.c_str(), 0, NULL, 0,
KEY_ALL_ACCESS, NULL, &hKey, NULL) != ERROR_SUCCESS) {
g_Logger.Error("Failed to create registry key.");
return false;
}
std::string ntPath = "\\??\\" + driverPath;
DWORD type = 1, start = 3, errorControl = 1;
RegSetValueExA(hKey, "Type", 0, REG_DWORD, (BYTE*)&type, 4);
RegSetValueExA(hKey, "Start", 0, REG_DWORD, (BYTE*)&start, 4);
RegSetValueExA(hKey, "ErrorControl", 0, REG_DWORD, (BYTE*)&errorControl, 4);
RegSetValueExA(hKey, "ImagePath", 0, REG_SZ, (BYTE*)ntPath.c_str(), (DWORD)ntPath.length() + 1);
RegCloseKey(hKey);
g_Logger.Debug("Registry key configured.");
SC_HANDLE scm = OpenSCManagerA(NULL, NULL, SC_MANAGER_CREATE_SERVICE);
if (!scm) {
g_Logger.Error("OpenSCManager failed: %lu", GetLastError());
return false;
}
SC_HANDLE svc = CreateServiceA(scm, driverName.c_str(), driverName.c_str(), SERVICE_ALL_ACCESS,
SERVICE_KERNEL_DRIVER, SERVICE_DEMAND_START, SERVICE_ERROR_NORMAL,
driverPath.c_str(), NULL, NULL, NULL, NULL, NULL);
if (svc) {
CloseServiceHandle(svc);
g_Logger.Debug("Service created in SCM.");
}
else if (GetLastError() == ERROR_SERVICE_EXISTS) {
g_Logger.Debug("Service already exists in SCM.");
}
else {
g_Logger.Warning("CreateService failed: %lu", GetLastError());
}
CloseServiceHandle(scm);
return true;
}
// Main driver loading function
int LoadDriver(bool forceReload) {
std::string driverName = "EmbeddedDriverService";
std::string tempDriverPath = GetTempDriverPath(driverName);
std::string driverFile = GetFileNameFromPath(tempDriverPath);
if (IsDriverLoaded(driverFile)) {
if (!forceReload) {
g_Logger.Info("Driver is already loaded and active. Skipping load process.");
return 0;
}
else {
g_Logger.Warning("Driver is already loaded. Unloading before reload...");
if (!UnloadDriverNT(driverName)) {
g_Logger.Error("Failed to unload existing driver. Aborting reload.");
return 1;
}
Sleep(500);
}
}
if (PathFileExistsA(tempDriverPath.c_str())) {
g_Logger.Debug("Driver file exists. Cleaning up before extraction...");
CleanupService(driverName);
if (!DeleteTempDriver(tempDriverPath)) {
g_Logger.Warning("Could not delete existing driver file. Attempting to overwrite anyway.");
}
Sleep(200);
}
if (!EnableLoadDriverPrivilege()) {
g_Logger.Error("Administrator privileges required.");
return 1;
}
if (!ExtractDriverToTemp(tempDriverPath)) {
g_Logger.Error("Failed to extract driver.");
return 1;
}
g_Logger.Debug("Cleaning up previous remnants of: %s", driverName.c_str());
CleanupService(driverName);
if (!SetupDriverService(tempDriverPath, driverName)) {
g_Logger.Error("Error configuring registry/service.");
DeleteTempDriver(tempDriverPath);
return 1;
}
HMODULE hNtdll = GetModuleHandleA("ntdll.dll");
auto NtLoad = (pNtLoadDriver)GetProcAddress(hNtdll, "NtLoadDriver");
auto RtlInit = (pRtlInitUnicodeString)GetProcAddress(hNtdll, "RtlInitUnicodeString");
if (!NtLoad || !RtlInit) {
g_Logger.Error("Could not obtain ntdll.dll functions.");
DeleteTempDriver(tempDriverPath);
return 1;
}
std::wstring regPath = L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\" + StringToWString(driverName);
UNICODE_STRING uStr;
RtlInit(&uStr, regPath.c_str());
g_Logger.Debug("Executing NtLoadDriver...");
NTSTATUS status = NtLoad(&uStr);
if (status == STATUS_SUCCESS) {
g_Logger.Info("Driver loaded successfully.");
}
else if (status == STATUS_IMAGE_ALREADY_LOADED) {
g_Logger.Warning("Driver was already loaded (race condition). Continuing.");
}
else {
g_Logger.Error("NtLoadDriver error: 0x%08lx", status);
DeleteTempDriver(tempDriverPath);
return 1;
}
Sleep(500);
if (IsDriverLoaded(driverFile)) {
g_Logger.Info("Driver active in kernel.");
}
else {
g_Logger.Warning("Driver does not appear in memory.");
}
g_Logger.Debug("Temporary file remains at: %s", tempDriverPath.c_str());
return 0;
}
// Uninstall driver: unload, delete service, delete file
int UninstallDriver() {
std::string driverName = "EmbeddedDriverService";
std::string tempDriverPath = GetTempDriverPath(driverName);
std::string driverFile = GetFileNameFromPath(tempDriverPath);
g_Logger.Info("Uninstalling driver...");
// Try to unload from kernel
if (IsDriverLoaded(driverFile)) {
g_Logger.Debug("Driver is loaded. Unloading...");
UnloadDriverNT(driverName);
Sleep(500);
}
else {
g_Logger.Debug("Driver is not loaded.");
}
// Clean up service and registry
CleanupService(driverName);
// Delete driver file
if (PathFileExistsA(tempDriverPath.c_str())) {
if (DeleteTempDriver(tempDriverPath)) {
g_Logger.Info("Driver file deleted.");
}
else {
g_Logger.Warning("Could not delete driver file. It may be in use.");
}
}
else {
g_Logger.Debug("Driver file not found.");
}
g_Logger.Info("Driver uninstall completed.");
return 0;
}