mirror of
https://github.com/oxfemale/KillChain
synced 2026-06-08 16:35:03 +00:00
350 lines
12 KiB
C++
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;
|
|
} |