├── EzDump ├── x64 │ └── Release │ │ ├── EzDump.log │ │ ├── EzDump.vcxproj.FileListAbsolute.txt │ │ ├── EzDump.dll.recipe │ │ └── EzDump.Build.CppClean.log └── Release │ ├── hook.obj │ ├── buffer.obj │ ├── hde32.obj │ ├── hde64.obj │ ├── vc143.pdb │ ├── EzDump.iobj │ ├── EzDump.ipdb │ ├── MinHook.res │ ├── dllmain.obj │ ├── trampoline.obj │ ├── EzDump.tlog │ ├── CL.read.1.tlog │ ├── CL.write.1.tlog │ ├── link.read.1.tlog │ ├── rc.read.1.tlog │ ├── rc.write.1.tlog │ ├── CL.command.1.tlog │ ├── link.write.1.tlog │ ├── rc.command.1.tlog │ ├── link.command.1.tlog │ ├── EzDump.lastbuildstate │ ├── Cl.items.tlog │ └── link.secondary.1.tlog │ ├── EzDump.dll.recipe │ └── EzDump.log ├── test ├── Release │ ├── test.tlog │ │ ├── unsuccessfulbuild │ │ ├── CL.command.1.tlog │ │ └── test.lastbuildstate │ ├── vc143.pdb │ └── test.log ├── x64 │ └── Release │ │ ├── test.obj │ │ ├── test.iobj │ │ ├── test.ipdb │ │ ├── vc143.pdb │ │ ├── test.tlog │ │ ├── CL.read.1.tlog │ │ ├── CL.write.1.tlog │ │ ├── link.read.1.tlog │ │ ├── CL.command.1.tlog │ │ ├── link.write.1.tlog │ │ ├── link.command.1.tlog │ │ ├── Cl.items.tlog │ │ ├── test.lastbuildstate │ │ └── link.secondary.1.tlog │ │ ├── test.exe.recipe │ │ └── test.log ├── test.vcxproj.user ├── test.cpp ├── test.vcxproj.filters └── test.vcxproj ├── globals.h ├── externals └── minhook │ ├── minhook.lib │ ├── minhook3.lib │ ├── minhookdd.lib │ ├── minhookback2.lib │ ├── dll_resources │ ├── MinHook.def │ └── MinHook.rc │ ├── src │ ├── hde │ │ ├── pstdint.h │ │ ├── hde32.h │ │ ├── hde64.h │ │ ├── table32.h │ │ ├── table64.h │ │ ├── hde32.c │ │ └── hde64.c │ ├── buffer.h │ ├── trampoline.h │ ├── buffer.c │ ├── trampoline.c │ └── hook.c │ ├── MinHook.h │ └── include │ └── MinHook.h ├── utils ├── utils.hpp ├── security.h └── xorstr.hpp ├── EzDump.vcxproj.user ├── imports.h ├── readme.md ├── LICENSE ├── EzDump.sln ├── dllmain.cpp ├── EzDump.vcxproj.filters ├── internal └── hooks.hpp └── EzDump.vcxproj /EzDump/x64/Release/EzDump.log: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /test/Release/test.tlog/unsuccessfulbuild: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /EzDump/x64/Release/EzDump.vcxproj.FileListAbsolute.txt: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /globals.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "utils/xorstr.hpp" 3 | #include "utils/utils.hpp" -------------------------------------------------------------------------------- /EzDump/Release/hook.obj: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DErDYAST1R/HookDumper/HEAD/EzDump/Release/hook.obj -------------------------------------------------------------------------------- /test/Release/vc143.pdb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DErDYAST1R/HookDumper/HEAD/test/Release/vc143.pdb -------------------------------------------------------------------------------- /EzDump/Release/buffer.obj: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DErDYAST1R/HookDumper/HEAD/EzDump/Release/buffer.obj -------------------------------------------------------------------------------- /EzDump/Release/hde32.obj: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DErDYAST1R/HookDumper/HEAD/EzDump/Release/hde32.obj -------------------------------------------------------------------------------- /EzDump/Release/hde64.obj: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DErDYAST1R/HookDumper/HEAD/EzDump/Release/hde64.obj -------------------------------------------------------------------------------- /EzDump/Release/vc143.pdb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DErDYAST1R/HookDumper/HEAD/EzDump/Release/vc143.pdb -------------------------------------------------------------------------------- /test/x64/Release/test.obj: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DErDYAST1R/HookDumper/HEAD/test/x64/Release/test.obj -------------------------------------------------------------------------------- /EzDump/Release/EzDump.iobj: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DErDYAST1R/HookDumper/HEAD/EzDump/Release/EzDump.iobj -------------------------------------------------------------------------------- /EzDump/Release/EzDump.ipdb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DErDYAST1R/HookDumper/HEAD/EzDump/Release/EzDump.ipdb -------------------------------------------------------------------------------- /EzDump/Release/MinHook.res: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DErDYAST1R/HookDumper/HEAD/EzDump/Release/MinHook.res -------------------------------------------------------------------------------- /EzDump/Release/dllmain.obj: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DErDYAST1R/HookDumper/HEAD/EzDump/Release/dllmain.obj -------------------------------------------------------------------------------- /test/x64/Release/test.iobj: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DErDYAST1R/HookDumper/HEAD/test/x64/Release/test.iobj -------------------------------------------------------------------------------- /test/x64/Release/test.ipdb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DErDYAST1R/HookDumper/HEAD/test/x64/Release/test.ipdb -------------------------------------------------------------------------------- /test/x64/Release/vc143.pdb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DErDYAST1R/HookDumper/HEAD/test/x64/Release/vc143.pdb -------------------------------------------------------------------------------- /EzDump/Release/trampoline.obj: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DErDYAST1R/HookDumper/HEAD/EzDump/Release/trampoline.obj -------------------------------------------------------------------------------- /externals/minhook/minhook.lib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DErDYAST1R/HookDumper/HEAD/externals/minhook/minhook.lib -------------------------------------------------------------------------------- /externals/minhook/minhook3.lib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DErDYAST1R/HookDumper/HEAD/externals/minhook/minhook3.lib -------------------------------------------------------------------------------- /externals/minhook/minhookdd.lib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DErDYAST1R/HookDumper/HEAD/externals/minhook/minhookdd.lib -------------------------------------------------------------------------------- /externals/minhook/minhookback2.lib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DErDYAST1R/HookDumper/HEAD/externals/minhook/minhookback2.lib -------------------------------------------------------------------------------- /test/Release/test.tlog/CL.command.1.tlog: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DErDYAST1R/HookDumper/HEAD/test/Release/test.tlog/CL.command.1.tlog -------------------------------------------------------------------------------- /EzDump/Release/EzDump.tlog/CL.read.1.tlog: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DErDYAST1R/HookDumper/HEAD/EzDump/Release/EzDump.tlog/CL.read.1.tlog -------------------------------------------------------------------------------- /EzDump/Release/EzDump.tlog/CL.write.1.tlog: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DErDYAST1R/HookDumper/HEAD/EzDump/Release/EzDump.tlog/CL.write.1.tlog -------------------------------------------------------------------------------- /EzDump/Release/EzDump.tlog/link.read.1.tlog: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DErDYAST1R/HookDumper/HEAD/EzDump/Release/EzDump.tlog/link.read.1.tlog -------------------------------------------------------------------------------- /EzDump/Release/EzDump.tlog/rc.read.1.tlog: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DErDYAST1R/HookDumper/HEAD/EzDump/Release/EzDump.tlog/rc.read.1.tlog -------------------------------------------------------------------------------- /EzDump/Release/EzDump.tlog/rc.write.1.tlog: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DErDYAST1R/HookDumper/HEAD/EzDump/Release/EzDump.tlog/rc.write.1.tlog -------------------------------------------------------------------------------- /test/x64/Release/test.tlog/CL.read.1.tlog: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DErDYAST1R/HookDumper/HEAD/test/x64/Release/test.tlog/CL.read.1.tlog -------------------------------------------------------------------------------- /test/x64/Release/test.tlog/CL.write.1.tlog: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DErDYAST1R/HookDumper/HEAD/test/x64/Release/test.tlog/CL.write.1.tlog -------------------------------------------------------------------------------- /test/x64/Release/test.tlog/link.read.1.tlog: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DErDYAST1R/HookDumper/HEAD/test/x64/Release/test.tlog/link.read.1.tlog -------------------------------------------------------------------------------- /EzDump/Release/EzDump.tlog/CL.command.1.tlog: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DErDYAST1R/HookDumper/HEAD/EzDump/Release/EzDump.tlog/CL.command.1.tlog -------------------------------------------------------------------------------- /EzDump/Release/EzDump.tlog/link.write.1.tlog: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DErDYAST1R/HookDumper/HEAD/EzDump/Release/EzDump.tlog/link.write.1.tlog -------------------------------------------------------------------------------- /EzDump/Release/EzDump.tlog/rc.command.1.tlog: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DErDYAST1R/HookDumper/HEAD/EzDump/Release/EzDump.tlog/rc.command.1.tlog -------------------------------------------------------------------------------- /test/x64/Release/test.tlog/CL.command.1.tlog: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DErDYAST1R/HookDumper/HEAD/test/x64/Release/test.tlog/CL.command.1.tlog -------------------------------------------------------------------------------- /test/x64/Release/test.tlog/link.write.1.tlog: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DErDYAST1R/HookDumper/HEAD/test/x64/Release/test.tlog/link.write.1.tlog -------------------------------------------------------------------------------- /EzDump/Release/EzDump.tlog/link.command.1.tlog: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DErDYAST1R/HookDumper/HEAD/EzDump/Release/EzDump.tlog/link.command.1.tlog -------------------------------------------------------------------------------- /test/x64/Release/test.tlog/link.command.1.tlog: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DErDYAST1R/HookDumper/HEAD/test/x64/Release/test.tlog/link.command.1.tlog -------------------------------------------------------------------------------- /test/x64/Release/test.tlog/Cl.items.tlog: -------------------------------------------------------------------------------- 1 | C:\Users\dnfki\source\repos\EzDump\test\test.cpp;C:\Users\dnfki\source\repos\EzDump\test\x64\Release\test.obj 2 | -------------------------------------------------------------------------------- /utils/utils.hpp: -------------------------------------------------------------------------------- 1 | #include "../imports.h" 2 | #include "../globals.h" 3 | 4 | bool fileExists(const std::string& filename) { 5 | return std::filesystem::exists(filename); 6 | } -------------------------------------------------------------------------------- /test/test.vcxproj.user: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /test/Release/test.tlog/test.lastbuildstate: -------------------------------------------------------------------------------- 1 | PlatformToolSet=v143:VCToolArchitecture=Native32Bit:VCToolsVersion=14.39.33519:TargetPlatformVersion=10.0.22621.0: 2 | Release|Win32|C:\Users\dnfki\source\repos\EzDump\| 3 | -------------------------------------------------------------------------------- /test/x64/Release/test.tlog/test.lastbuildstate: -------------------------------------------------------------------------------- 1 | PlatformToolSet=v143:VCToolArchitecture=Native64Bit:VCToolsVersion=14.39.33519:TargetPlatformVersion=10.0.22621.0: 2 | Release|x64|C:\Users\dnfki\source\repos\EzDump\| 3 | -------------------------------------------------------------------------------- /EzDump/Release/EzDump.tlog/EzDump.lastbuildstate: -------------------------------------------------------------------------------- 1 | PlatformToolSet=v143:VCToolArchitecture=Native32Bit:VCToolsVersion=14.39.33519:TargetPlatformVersion=10.0.22621.0: 2 | Release|Win32|C:\Users\dnfki\source\repos\EzDump\| 3 | -------------------------------------------------------------------------------- /test/x64/Release/test.tlog/link.secondary.1.tlog: -------------------------------------------------------------------------------- 1 | ^C:\USERS\DNFKI\SOURCE\REPOS\EZDUMP\TEST\X64\RELEASE\TEST.OBJ 2 | C:\Users\dnfki\source\repos\EzDump\test\x64\Release\test.IPDB 3 | C:\Users\dnfki\source\repos\EzDump\test\x64\Release\test.iobj 4 | -------------------------------------------------------------------------------- /EzDump.vcxproj.user: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | true 5 | 6 | -------------------------------------------------------------------------------- /externals/minhook/dll_resources/MinHook.def: -------------------------------------------------------------------------------- 1 | EXPORTS 2 | MH_Initialize 3 | MH_Uninitialize 4 | 5 | MH_CreateHook 6 | MH_CreateHookApi 7 | MH_CreateHookApiEx 8 | MH_RemoveHook 9 | MH_EnableHook 10 | MH_DisableHook 11 | MH_QueueEnableHook 12 | MH_QueueDisableHook 13 | MH_ApplyQueued 14 | MH_StatusToString 15 | -------------------------------------------------------------------------------- /test/x64/Release/test.exe.recipe: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | C:\Users\dnfki\source\repos\EzDump\x64\Release\test.exe 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /EzDump/Release/EzDump.dll.recipe: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | C:\Users\dnfki\source\repos\EzDump\Win32\Release\EzDump.dll 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /EzDump/x64/Release/EzDump.dll.recipe: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | C:\Users\dnfki\source\repos\EzDump\x64\Release\EzDump.dll 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /test/x64/Release/test.log: -------------------------------------------------------------------------------- 1 | test.cpp 2 | Generating code 3 | 2 of 186 functions ( 1.1%) were compiled, the rest were copied from previous compilation. 4 | 0 functions were new in current compilation 5 | 0 functions had inline decision re-evaluated but remain unchanged 6 | Finished generating code 7 | test.vcxproj -> C:\Users\dnfki\source\repos\EzDump\x64\Release\test.exe 8 | -------------------------------------------------------------------------------- /EzDump/Release/EzDump.log: -------------------------------------------------------------------------------- 1 | dllmain.cpp 2 | Generating code 3 | 69 of 519 functions (13.3%) were compiled, the rest were copied from previous compilation. 4 | 57 functions were new in current compilation 5 | 1 functions had inline decision re-evaluated but remain unchanged 6 | Finished generating code 7 | EzDump.vcxproj -> C:\Users\dnfki\source\repos\EzDump\Win32\Release\EzDump.dll 8 | -------------------------------------------------------------------------------- /imports.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include "externals/minhook/MinHook.h" 10 | #include "utils/xorstr.hpp" 11 | 12 | namespace globals { 13 | std::string dumpPath = xorstr_("D:\\a-debuggers\\Etheral\\Mapper\\Log\\"); 14 | std::wstring dumpPathW = xorstr_(L"D:\\a-debuggers\\Etheral\\Mapper\\Log\\"); 15 | bool AllocateConsole = true; /* If a console in the program is already allocated or program keeps crashing on injection try switching to False. */ 16 | } -------------------------------------------------------------------------------- /test/Release/test.log: -------------------------------------------------------------------------------- 1 | test.cpp 2 | C:\Users\dnfki\source\repos\EzDump\test\test.cpp(19,9): error C2664: 'BOOL DeleteFileW(LPCWSTR)': cannot convert argument 1 from 'const char [14]' to 'LPCWSTR' 3 | C:\Users\dnfki\source\repos\EzDump\test\test.cpp(19,20): 4 | Types pointed to are unrelated; conversion requires reinterpret_cast, C-style cast or parenthesized function-style cast 5 | C:\Program Files (x86)\Windows Kits\10\Include\10.0.22621.0\um\fileapi.h(142,1): 6 | see declaration of 'DeleteFileW' 7 | C:\Users\dnfki\source\repos\EzDump\test\test.cpp(19,9): 8 | while trying to match the argument list '(const char [14])' 9 | 10 | -------------------------------------------------------------------------------- /test/test.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | void CreateAndDeleteFile() { 6 | while (true) { 7 | // Create a file 8 | std::this_thread::sleep_for(std::chrono::seconds(1)); 9 | std::ofstream file("test_file.txt"); 10 | if (file.is_open()) { 11 | file << "This is a test file."; 12 | file.close(); 13 | } 14 | 15 | // Sleep for 1 second 16 | std::this_thread::sleep_for(std::chrono::seconds(1)); 17 | 18 | // Delete the file 19 | DeleteFile("test_file.txt"); 20 | } 21 | } 22 | 23 | int main() { 24 | CreateAndDeleteFile(); 25 | } -------------------------------------------------------------------------------- /EzDump/Release/EzDump.tlog/Cl.items.tlog: -------------------------------------------------------------------------------- 1 | C:\Users\dnfki\source\repos\EzDump\dllmain.cpp;C:\Users\dnfki\source\repos\EzDump\EzDump\Release\dllmain.obj 2 | C:\Users\dnfki\source\repos\EzDump\externals\minhook\src\buffer.c;C:\Users\dnfki\source\repos\EzDump\EzDump\Release\buffer.obj 3 | C:\Users\dnfki\source\repos\EzDump\externals\minhook\src\hde\hde32.c;C:\Users\dnfki\source\repos\EzDump\EzDump\Release\hde32.obj 4 | C:\Users\dnfki\source\repos\EzDump\externals\minhook\src\hde\hde64.c;C:\Users\dnfki\source\repos\EzDump\EzDump\Release\hde64.obj 5 | C:\Users\dnfki\source\repos\EzDump\externals\minhook\src\hook.c;C:\Users\dnfki\source\repos\EzDump\EzDump\Release\hook.obj 6 | C:\Users\dnfki\source\repos\EzDump\externals\minhook\src\trampoline.c;C:\Users\dnfki\source\repos\EzDump\EzDump\Release\trampoline.obj 7 | -------------------------------------------------------------------------------- /EzDump/Release/EzDump.tlog/link.secondary.1.tlog: -------------------------------------------------------------------------------- 1 | ^C:\USERS\DNFKI\SOURCE\REPOS\EZDUMP\EXTERNALS\MINHOOK\MINHOOK.LIB|C:\USERS\DNFKI\SOURCE\REPOS\EZDUMP\EXTERNALS\MINHOOK\MINHOOK3.LIB|C:\USERS\DNFKI\SOURCE\REPOS\EZDUMP\EXTERNALS\MINHOOK\MINHOOKBACK2.LIB|C:\USERS\DNFKI\SOURCE\REPOS\EZDUMP\EXTERNALS\MINHOOK\MINHOOKDD.LIB|C:\USERS\DNFKI\SOURCE\REPOS\EZDUMP\EZDUMP\RELEASE\BUFFER.OBJ|C:\USERS\DNFKI\SOURCE\REPOS\EZDUMP\EZDUMP\RELEASE\DLLMAIN.OBJ|C:\USERS\DNFKI\SOURCE\REPOS\EZDUMP\EZDUMP\RELEASE\HDE32.OBJ|C:\USERS\DNFKI\SOURCE\REPOS\EZDUMP\EZDUMP\RELEASE\HDE64.OBJ|C:\USERS\DNFKI\SOURCE\REPOS\EZDUMP\EZDUMP\RELEASE\HOOK.OBJ|C:\USERS\DNFKI\SOURCE\REPOS\EZDUMP\EZDUMP\RELEASE\MINHOOK.RES|C:\USERS\DNFKI\SOURCE\REPOS\EZDUMP\EZDUMP\RELEASE\TRAMPOLINE.OBJ 2 | C:\Users\dnfki\source\repos\EzDump\EzDump\Release\EzDump.IPDB 3 | C:\Users\dnfki\source\repos\EzDump\EzDump\Release\EzDump.iobj 4 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | # Hook Based Dumper (EzDumper) 2 | An injectable DLL that hooks Windows API Functions inside a program to dump the variables passed in and the returned variables such as DeleteFileW/DeleteFileA. 3 | 4 | # Hooks 5 | - ReadProcessMemory (Dumps the returned variable it is trying to read) 6 | - WriteProcessMemory (Dumps the buffer it is trying to write) 7 | - DeleteFileA & DeleteFileW (Dumps the file contents before deleting it) 8 | 9 | # Security 10 | I will add more security features in the future to prevent detection. 11 | - Kernel32 GetThreadContext HW Breakpoint Detection (Prevent HW Breakpoint Detect) 12 | - Kernel32 NtRaiseHardError (Prevent Forced BSOD through Kernel Calling) 13 | - _RtlCreateUserThread Hook and RIP/EIP Spoofing to bypass thread tracing of DLL. 14 | 15 | # Project 16 | This is just a Pre-Dump Project that I'll develop on and re-release under a new repo with better features and more hooks related to file dumping and etc. 17 | -------------------------------------------------------------------------------- /externals/minhook/dll_resources/MinHook.rc: -------------------------------------------------------------------------------- 1 | 1 VERSIONINFO 2 | FILEVERSION 1,3,3,0 3 | PRODUCTVERSION 1,3,3,0 4 | FILEFLAGSMASK 0x17L 5 | #ifdef _DEBUG 6 | FILEFLAGS 0x1L 7 | #else 8 | FILEFLAGS 0x0L 9 | #endif 10 | FILEOS 0x4L 11 | FILETYPE 0x2L 12 | FILESUBTYPE 0x0L 13 | BEGIN 14 | BLOCK "StringFileInfo" 15 | BEGIN 16 | BLOCK "040904b0" 17 | BEGIN 18 | VALUE "CompanyName", "Tsuda Kageyu" 19 | VALUE "FileDescription", "MinHook - The Minimalistic API Hook Library for x64/x86" 20 | VALUE "FileVersion", "1.3.3.0" 21 | VALUE "InternalName", "MinHookD" 22 | VALUE "LegalCopyright", "Copyright (C) 2009-2017 Tsuda Kageyu. All rights reserved." 23 | VALUE "LegalTrademarks", "Tsuda Kageyu" 24 | VALUE "ProductName", "MinHook DLL" 25 | VALUE "ProductVersion", "1.3.3.0" 26 | END 27 | END 28 | BLOCK "VarFileInfo" 29 | BEGIN 30 | VALUE "Translation", 0x409, 1200 31 | END 32 | END 33 | -------------------------------------------------------------------------------- /test/test.vcxproj.filters: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | 18 | 19 | Source Files 20 | 21 | 22 | -------------------------------------------------------------------------------- /utils/security.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "../imports.h" 3 | #include "../globals.h" 4 | 5 | using _RtlCreateUserThread = NTSTATUS(NTAPI*)( 6 | HANDLE ProcessHandle, 7 | PSECURITY_DESCRIPTOR SecurityDescriptor, 8 | BOOLEAN CreateSuspended, 9 | ULONG StackZeroBits, 10 | PULONG StackReserved, 11 | PULONG StackCommit, 12 | void* StartAddress, 13 | void* StartParameter, 14 | PHANDLE ThreadHandle, 15 | void* ClientID 16 | ); 17 | 18 | namespace hyde { /* Create x32/x64 Thread with EIP/EIP in an Un-Modified Region */ 19 | BOOL CreateThread(void* thread, HMODULE& hModule) { 20 | auto newaddr = 0x0007FFF8797D540; 21 | DWORD oProtect; 22 | VirtualProtect((void*)newaddr, 1000, PAGE_EXECUTE_READWRITE, &oProtect); 23 | CONTEXT cpuContext; 24 | HANDLE cpuHandle = nullptr; 25 | _RtlCreateUserThread NtThread = (_RtlCreateUserThread)(GetProcAddress(GetModuleHandleA(xorstr_("ntdll")), xorstr_("RtlCreateUserThread"))); 26 | NtThread(GetCurrentProcess(), nullptr, TRUE, NULL, NULL, NULL, (PTHREAD_START_ROUTINE)newaddr, hModule, &cpuHandle, NULL); 27 | cpuContext.ContextFlags = CONTEXT_INTEGER | CONTEXT_CONTROL; 28 | GetThreadContext(cpuHandle, &cpuContext); 29 | #ifdef _WIN64 /* Win64 */ 30 | cpuContext.Rip = (ULONG64)thread; 31 | #else /* Win32 */ 32 | cpuContext.Eip = (ULONG32)thread; 33 | #endif 34 | SetThreadContext(cpuHandle, &cpuContext); 35 | ResumeThread(cpuHandle); 36 | return 0; 37 | } 38 | 39 | } -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | HookDumper © 2024 by Ezekiel Cerel is licensed under Creative Commons Attribution-NonCommercial-NoDerivatives 4.0 International. To view a copy of this license, visit https://creativecommons.org/licenses/by-nc-nd/4.0/ 2 | Protected by legal-law, visit https://creativecommons.org/licenses/by-nc-nd/4.0/legalcode.en 3 | 4 | You are free to: 5 | Share — copy and redistribute the material in any medium or format 6 | The licensor cannot revoke these freedoms as long as you follow the license terms. 7 | Under the following terms: 8 | Attribution — You must give appropriate credit , provide a link to the license, and indicate if changes were made . You may do so in any reasonable manner, but not in any way that suggests the licensor endorses you or your use. 9 | NonCommercial — You may not use the material for commercial purposes . 10 | NoDerivatives — If you remix, transform, or build upon the material, you may not distribute the modified material. 11 | No additional restrictions — You may not apply legal terms or technological measures that legally restrict others from doing anything the license permits. 12 | Notices: 13 | You do not have to comply with the license for elements of the material in the public domain or where your use is permitted by an applicable exception or limitation . 14 | 15 | No warranties are given. The license may not give you all of the permissions necessary for your intended use. For example, other rights such as publicity, privacy, or moral rights may limit how you use the material. 16 | -------------------------------------------------------------------------------- /EzDump/x64/Release/EzDump.Build.CppClean.log: -------------------------------------------------------------------------------- 1 | c:\users\dnfki\source\repos\ezdump\ezdump\x64\release\vc143.pdb 2 | c:\users\dnfki\source\repos\ezdump\ezdump\x64\release\trampoline.obj 3 | c:\users\dnfki\source\repos\ezdump\ezdump\x64\release\hook.obj 4 | c:\users\dnfki\source\repos\ezdump\ezdump\x64\release\hde64.obj 5 | c:\users\dnfki\source\repos\ezdump\ezdump\x64\release\hde32.obj 6 | c:\users\dnfki\source\repos\ezdump\ezdump\x64\release\buffer.obj 7 | c:\users\dnfki\source\repos\ezdump\ezdump\x64\release\dllmain.obj 8 | c:\users\dnfki\source\repos\ezdump\x64\release\ezdump.dll 9 | c:\users\dnfki\source\repos\ezdump\x64\release\ezdump.pdb 10 | c:\users\dnfki\source\repos\ezdump\ezdump\x64\release\minhook.res 11 | c:\users\dnfki\source\repos\ezdump\ezdump\x64\release\ezdump.ipdb 12 | c:\users\dnfki\source\repos\ezdump\ezdump\x64\release\ezdump.iobj 13 | c:\users\dnfki\source\repos\ezdump\ezdump\x64\release\ezdump.tlog\cl.command.1.tlog 14 | c:\users\dnfki\source\repos\ezdump\ezdump\x64\release\ezdump.tlog\cl.items.tlog 15 | c:\users\dnfki\source\repos\ezdump\ezdump\x64\release\ezdump.tlog\cl.read.1.tlog 16 | c:\users\dnfki\source\repos\ezdump\ezdump\x64\release\ezdump.tlog\cl.write.1.tlog 17 | c:\users\dnfki\source\repos\ezdump\ezdump\x64\release\ezdump.tlog\link.command.1.tlog 18 | c:\users\dnfki\source\repos\ezdump\ezdump\x64\release\ezdump.tlog\link.read.1.tlog 19 | c:\users\dnfki\source\repos\ezdump\ezdump\x64\release\ezdump.tlog\link.secondary.1.tlog 20 | c:\users\dnfki\source\repos\ezdump\ezdump\x64\release\ezdump.tlog\link.write.1.tlog 21 | c:\users\dnfki\source\repos\ezdump\ezdump\x64\release\ezdump.tlog\rc.command.1.tlog 22 | c:\users\dnfki\source\repos\ezdump\ezdump\x64\release\ezdump.tlog\rc.read.1.tlog 23 | c:\users\dnfki\source\repos\ezdump\ezdump\x64\release\ezdump.tlog\rc.write.1.tlog 24 | -------------------------------------------------------------------------------- /externals/minhook/src/hde/pstdint.h: -------------------------------------------------------------------------------- 1 | /* 2 | * MinHook - The Minimalistic API Hooking Library for x64/x86 3 | * Copyright (C) 2009-2017 Tsuda Kageyu. All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions 7 | * are met: 8 | * 9 | * 1. Redistributions of source code must retain the above copyright 10 | * notice, this list of conditions and the following disclaimer. 11 | * 2. Redistributions in binary form must reproduce the above copyright 12 | * notice, this list of conditions and the following disclaimer in the 13 | * documentation and/or other materials provided with the distribution. 14 | * 15 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR 16 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 19 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 20 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 | */ 26 | 27 | #pragma once 28 | 29 | #include 30 | 31 | // Integer types for HDE. 32 | typedef INT8 int8_t; 33 | typedef INT16 int16_t; 34 | typedef INT32 int32_t; 35 | typedef INT64 int64_t; 36 | typedef UINT8 uint8_t; 37 | typedef UINT16 uint16_t; 38 | typedef UINT32 uint32_t; 39 | typedef UINT64 uint64_t; 40 | -------------------------------------------------------------------------------- /externals/minhook/src/buffer.h: -------------------------------------------------------------------------------- 1 | /* 2 | * MinHook - The Minimalistic API Hooking Library for x64/x86 3 | * Copyright (C) 2009-2017 Tsuda Kageyu. 4 | * All rights reserved. 5 | * 6 | * Redistribution and use in source and binary forms, with or without 7 | * modification, are permitted provided that the following conditions 8 | * are met: 9 | * 10 | * 1. Redistributions of source code must retain the above copyright 11 | * notice, this list of conditions and the following disclaimer. 12 | * 2. Redistributions in binary form must reproduce the above copyright 13 | * notice, this list of conditions and the following disclaimer in the 14 | * documentation and/or other materials provided with the distribution. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 18 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 19 | * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 20 | * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 21 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 22 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 23 | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 24 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 25 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 26 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 | */ 28 | 29 | #pragma once 30 | 31 | // Size of each memory slot. 32 | #if defined(_M_X64) || defined(__x86_64__) 33 | #define MEMORY_SLOT_SIZE 64 34 | #else 35 | #define MEMORY_SLOT_SIZE 32 36 | #endif 37 | 38 | VOID InitializeBuffer(VOID); 39 | VOID UninitializeBuffer(VOID); 40 | LPVOID AllocateBuffer(LPVOID pOrigin); 41 | VOID FreeBuffer(LPVOID pBuffer); 42 | BOOL IsExecutableAddress(LPVOID pAddress); 43 | -------------------------------------------------------------------------------- /EzDump.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 17 4 | VisualStudioVersion = 17.9.34701.34 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "EzDump", "EzDump.vcxproj", "{E704E47C-56B8-4D41-A895-E35400DCD2C2}" 7 | EndProject 8 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test", "test\test.vcxproj", "{E3B3D37E-3E82-404F-9B14-4BC4C008BE36}" 9 | EndProject 10 | Global 11 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 12 | Debug|x64 = Debug|x64 13 | Debug|x86 = Debug|x86 14 | Release|x64 = Release|x64 15 | Release|x86 = Release|x86 16 | EndGlobalSection 17 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 18 | {E704E47C-56B8-4D41-A895-E35400DCD2C2}.Debug|x64.ActiveCfg = Debug|x64 19 | {E704E47C-56B8-4D41-A895-E35400DCD2C2}.Debug|x64.Build.0 = Debug|x64 20 | {E704E47C-56B8-4D41-A895-E35400DCD2C2}.Debug|x86.ActiveCfg = Debug|Win32 21 | {E704E47C-56B8-4D41-A895-E35400DCD2C2}.Debug|x86.Build.0 = Debug|Win32 22 | {E704E47C-56B8-4D41-A895-E35400DCD2C2}.Release|x64.ActiveCfg = Release|x64 23 | {E704E47C-56B8-4D41-A895-E35400DCD2C2}.Release|x64.Build.0 = Release|x64 24 | {E704E47C-56B8-4D41-A895-E35400DCD2C2}.Release|x86.ActiveCfg = Release|Win32 25 | {E704E47C-56B8-4D41-A895-E35400DCD2C2}.Release|x86.Build.0 = Release|Win32 26 | {E3B3D37E-3E82-404F-9B14-4BC4C008BE36}.Debug|x64.ActiveCfg = Debug|x64 27 | {E3B3D37E-3E82-404F-9B14-4BC4C008BE36}.Debug|x64.Build.0 = Debug|x64 28 | {E3B3D37E-3E82-404F-9B14-4BC4C008BE36}.Debug|x86.ActiveCfg = Debug|Win32 29 | {E3B3D37E-3E82-404F-9B14-4BC4C008BE36}.Debug|x86.Build.0 = Debug|Win32 30 | {E3B3D37E-3E82-404F-9B14-4BC4C008BE36}.Release|x64.ActiveCfg = Release|x64 31 | {E3B3D37E-3E82-404F-9B14-4BC4C008BE36}.Release|x64.Build.0 = Release|x64 32 | {E3B3D37E-3E82-404F-9B14-4BC4C008BE36}.Release|x86.ActiveCfg = Release|Win32 33 | {E3B3D37E-3E82-404F-9B14-4BC4C008BE36}.Release|x86.Build.0 = Release|Win32 34 | EndGlobalSection 35 | GlobalSection(SolutionProperties) = preSolution 36 | HideSolutionNode = FALSE 37 | EndGlobalSection 38 | GlobalSection(ExtensibilityGlobals) = postSolution 39 | SolutionGuid = {B51F29E8-063E-480B-8DA4-8C5223C58960} 40 | EndGlobalSection 41 | EndGlobal 42 | -------------------------------------------------------------------------------- /externals/minhook/src/hde/hde32.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Hacker Disassembler Engine 32 3 | * Copyright (c) 2006-2009, Vyacheslav Patkov. 4 | * All rights reserved. 5 | * 6 | * hde32.h: C/C++ header file 7 | * 8 | */ 9 | 10 | #ifndef _HDE32_H_ 11 | #define _HDE32_H_ 12 | 13 | /* stdint.h - C99 standard header 14 | * http://en.wikipedia.org/wiki/stdint.h 15 | * 16 | * if your compiler doesn't contain "stdint.h" header (for 17 | * example, Microsoft Visual C++), you can download file: 18 | * http://www.azillionmonkeys.com/qed/pstdint.h 19 | * and change next line to: 20 | * #include "pstdint.h" 21 | */ 22 | #include "pstdint.h" 23 | 24 | #define F_MODRM 0x00000001 25 | #define F_SIB 0x00000002 26 | #define F_IMM8 0x00000004 27 | #define F_IMM16 0x00000008 28 | #define F_IMM32 0x00000010 29 | #define F_DISP8 0x00000020 30 | #define F_DISP16 0x00000040 31 | #define F_DISP32 0x00000080 32 | #define F_RELATIVE 0x00000100 33 | #define F_2IMM16 0x00000800 34 | #define F_ERROR 0x00001000 35 | #define F_ERROR_OPCODE 0x00002000 36 | #define F_ERROR_LENGTH 0x00004000 37 | #define F_ERROR_LOCK 0x00008000 38 | #define F_ERROR_OPERAND 0x00010000 39 | #define F_PREFIX_REPNZ 0x01000000 40 | #define F_PREFIX_REPX 0x02000000 41 | #define F_PREFIX_REP 0x03000000 42 | #define F_PREFIX_66 0x04000000 43 | #define F_PREFIX_67 0x08000000 44 | #define F_PREFIX_LOCK 0x10000000 45 | #define F_PREFIX_SEG 0x20000000 46 | #define F_PREFIX_ANY 0x3f000000 47 | 48 | #define PREFIX_SEGMENT_CS 0x2e 49 | #define PREFIX_SEGMENT_SS 0x36 50 | #define PREFIX_SEGMENT_DS 0x3e 51 | #define PREFIX_SEGMENT_ES 0x26 52 | #define PREFIX_SEGMENT_FS 0x64 53 | #define PREFIX_SEGMENT_GS 0x65 54 | #define PREFIX_LOCK 0xf0 55 | #define PREFIX_REPNZ 0xf2 56 | #define PREFIX_REPX 0xf3 57 | #define PREFIX_OPERAND_SIZE 0x66 58 | #define PREFIX_ADDRESS_SIZE 0x67 59 | 60 | #pragma pack(push,1) 61 | 62 | typedef struct { 63 | uint8_t len; 64 | uint8_t p_rep; 65 | uint8_t p_lock; 66 | uint8_t p_seg; 67 | uint8_t p_66; 68 | uint8_t p_67; 69 | uint8_t opcode; 70 | uint8_t opcode2; 71 | uint8_t modrm; 72 | uint8_t modrm_mod; 73 | uint8_t modrm_reg; 74 | uint8_t modrm_rm; 75 | uint8_t sib; 76 | uint8_t sib_scale; 77 | uint8_t sib_index; 78 | uint8_t sib_base; 79 | union { 80 | uint8_t imm8; 81 | uint16_t imm16; 82 | uint32_t imm32; 83 | } imm; 84 | union { 85 | uint8_t disp8; 86 | uint16_t disp16; 87 | uint32_t disp32; 88 | } disp; 89 | uint32_t flags; 90 | } hde32s; 91 | 92 | #pragma pack(pop) 93 | 94 | #ifdef __cplusplus 95 | extern "C" { 96 | #endif 97 | 98 | /* __cdecl */ 99 | unsigned int hde32_disasm(const void *code, hde32s *hs); 100 | 101 | #ifdef __cplusplus 102 | } 103 | #endif 104 | 105 | #endif /* _HDE32_H_ */ 106 | -------------------------------------------------------------------------------- /externals/minhook/src/hde/hde64.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Hacker Disassembler Engine 64 3 | * Copyright (c) 2008-2009, Vyacheslav Patkov. 4 | * All rights reserved. 5 | * 6 | * hde64.h: C/C++ header file 7 | * 8 | */ 9 | 10 | #ifndef _HDE64_H_ 11 | #define _HDE64_H_ 12 | 13 | /* stdint.h - C99 standard header 14 | * http://en.wikipedia.org/wiki/stdint.h 15 | * 16 | * if your compiler doesn't contain "stdint.h" header (for 17 | * example, Microsoft Visual C++), you can download file: 18 | * http://www.azillionmonkeys.com/qed/pstdint.h 19 | * and change next line to: 20 | * #include "pstdint.h" 21 | */ 22 | #include "pstdint.h" 23 | 24 | #define F_MODRM 0x00000001 25 | #define F_SIB 0x00000002 26 | #define F_IMM8 0x00000004 27 | #define F_IMM16 0x00000008 28 | #define F_IMM32 0x00000010 29 | #define F_IMM64 0x00000020 30 | #define F_DISP8 0x00000040 31 | #define F_DISP16 0x00000080 32 | #define F_DISP32 0x00000100 33 | #define F_RELATIVE 0x00000200 34 | #define F_ERROR 0x00001000 35 | #define F_ERROR_OPCODE 0x00002000 36 | #define F_ERROR_LENGTH 0x00004000 37 | #define F_ERROR_LOCK 0x00008000 38 | #define F_ERROR_OPERAND 0x00010000 39 | #define F_PREFIX_REPNZ 0x01000000 40 | #define F_PREFIX_REPX 0x02000000 41 | #define F_PREFIX_REP 0x03000000 42 | #define F_PREFIX_66 0x04000000 43 | #define F_PREFIX_67 0x08000000 44 | #define F_PREFIX_LOCK 0x10000000 45 | #define F_PREFIX_SEG 0x20000000 46 | #define F_PREFIX_REX 0x40000000 47 | #define F_PREFIX_ANY 0x7f000000 48 | 49 | #define PREFIX_SEGMENT_CS 0x2e 50 | #define PREFIX_SEGMENT_SS 0x36 51 | #define PREFIX_SEGMENT_DS 0x3e 52 | #define PREFIX_SEGMENT_ES 0x26 53 | #define PREFIX_SEGMENT_FS 0x64 54 | #define PREFIX_SEGMENT_GS 0x65 55 | #define PREFIX_LOCK 0xf0 56 | #define PREFIX_REPNZ 0xf2 57 | #define PREFIX_REPX 0xf3 58 | #define PREFIX_OPERAND_SIZE 0x66 59 | #define PREFIX_ADDRESS_SIZE 0x67 60 | 61 | #pragma pack(push,1) 62 | 63 | typedef struct { 64 | uint8_t len; 65 | uint8_t p_rep; 66 | uint8_t p_lock; 67 | uint8_t p_seg; 68 | uint8_t p_66; 69 | uint8_t p_67; 70 | uint8_t rex; 71 | uint8_t rex_w; 72 | uint8_t rex_r; 73 | uint8_t rex_x; 74 | uint8_t rex_b; 75 | uint8_t opcode; 76 | uint8_t opcode2; 77 | uint8_t modrm; 78 | uint8_t modrm_mod; 79 | uint8_t modrm_reg; 80 | uint8_t modrm_rm; 81 | uint8_t sib; 82 | uint8_t sib_scale; 83 | uint8_t sib_index; 84 | uint8_t sib_base; 85 | union { 86 | uint8_t imm8; 87 | uint16_t imm16; 88 | uint32_t imm32; 89 | uint64_t imm64; 90 | } imm; 91 | union { 92 | uint8_t disp8; 93 | uint16_t disp16; 94 | uint32_t disp32; 95 | } disp; 96 | uint32_t flags; 97 | } hde64s; 98 | 99 | #pragma pack(pop) 100 | 101 | #ifdef __cplusplus 102 | extern "C" { 103 | #endif 104 | 105 | /* __cdecl */ 106 | unsigned int hde64_disasm(const void *code, hde64s *hs); 107 | 108 | #ifdef __cplusplus 109 | } 110 | #endif 111 | 112 | #endif /* _HDE64_H_ */ 113 | -------------------------------------------------------------------------------- /dllmain.cpp: -------------------------------------------------------------------------------- 1 | #include "imports.h" 2 | #include "globals.h" 3 | #include "utils/security.h" 4 | 5 | #include "internal/hooks.hpp" 6 | HINSTANCE DllHandle; 7 | 8 | #define WIN32_LEAN_AND_MEAN 9 | 10 | DWORD WINAPI InitExec() { 11 | std::cout << xorstr_("[-] MainThread Started\n"); 12 | if (MH_Initialize() != MH_OK) { 13 | return 0; 14 | } 15 | std::cout << xorstr_("[HOOKLIB] Initialized\n"); 16 | 17 | 18 | /* Security Based Hooks */ 19 | if (MH_CreateHookApi(L"kernel32.dll", xorstr_("GetThreadContext"), &hookedGetThreadContext, reinterpret_cast(&pGetThreadContext)) != MH_OK) { 20 | MessageBoxA(NULL, xorstr_("Failed To Hook GetThreadContext"), "", MB_OK); 21 | } 22 | else { 23 | std::cout << xorstr_("[security-enabled] GetThreadContext->dr. for HW Breakpoints\n"); 24 | } 25 | 26 | if (MH_CreateHookApi(L"ntdll.dll", xorstr_("NtRaiseHardError"), &hookedNtRaiseHardError, reinterpret_cast(&pNtRaiseHardError)) != MH_OK) { 27 | MessageBoxA(NULL, xorstr_("Failed To Hook NtRaisedHardError"), "", MB_OK); 28 | } 29 | else { 30 | std::cout << xorstr_("[security-enabled] GetThreadContext->dr. for HW Breakpoints\n"); 31 | } 32 | 33 | /* RPM / WPM Hooks */ 34 | if (MH_CreateHookApi(L"kernel32.dll", xorstr_("WriteProcessMemory"), &hookedWriteProcessMemory, reinterpret_cast(&pWriteProcessMemory)) != MH_OK) { 35 | MessageBoxA(NULL, xorstr_("Failed To Hook WriteProcessMemory"), "", MB_OK); 36 | } 37 | else { 38 | std::cout << xorstr_("[enabled] WriteProcessMemory Dumper\n"); 39 | } 40 | 41 | if (MH_CreateHookApi(L"kernel32.dll", xorstr_("ReadProcessMemory"), &hookedReadProcessMemory, reinterpret_cast(&pReadProcessMemory)) != MH_OK) { 42 | MessageBoxA(NULL, xorstr_("Failed To Hook ReadProcessMemory"), "", MB_OK); 43 | } 44 | else { 45 | std::cout << xorstr_("[enabled] ReadProcessMemory Dumper\n"); 46 | } 47 | 48 | if (MH_CreateHookApi(L"kernel32.dll", xorstr_("DeleteFileW"), &hookedDeleteFileW, reinterpret_cast(&pDeleteFileW)) != MH_OK) { 49 | MessageBoxA(NULL, xorstr_("Failed To Hook DeleteFileW"), "", MB_OK); 50 | } 51 | else { 52 | std::cout << xorstr_("[enabled] DeleteFileW Dumper\n"); 53 | } 54 | 55 | if (MH_CreateHookApi(L"kernel32.dll", xorstr_("DeleteFileA"), &hookedDeleteFileA, reinterpret_cast(&pDeleteFileA)) != MH_OK) { 56 | MessageBoxA(NULL, xorstr_("Failed To Hook DeleteFileA"), "", MB_OK); 57 | } 58 | else { 59 | std::cout << xorstr_("[enabled] DeleteFileA Dumper\n"); 60 | } 61 | 62 | 63 | 64 | MH_EnableHook(MH_ALL_HOOKS); 65 | while (true) { 66 | Sleep(50); 67 | if (GetAsyncKeyState(VK_END) & 1) { 68 | break; 69 | } 70 | } 71 | 72 | return 0; 73 | } 74 | 75 | int __stdcall DllMain(const HMODULE hModule, const std::uintptr_t reason, const void* reserved) { 76 | if (reason == 1) { 77 | /* Alocate Console */ 78 | if (globals::AllocateConsole == true) { 79 | AllocConsole(); 80 | FILE* fp; 81 | freopen_s(&fp, "CONOUT$", "w", stdout); 82 | } 83 | 84 | DisableThreadLibraryCalls(hModule); 85 | std::cout << xorstr_("[-] AllocConsole - freopen_s | SET\n"); 86 | DllHandle = hModule; 87 | 88 | hyde::CreateThread(InitExec, DllHandle); 89 | std::cout << xorstr_("[-] Started Main Thread...\n"); 90 | 91 | //CreateThread(nullptr, 0, reinterpret_cast(InitExec), hModule, 0, nullptr); 92 | return true; 93 | } 94 | return true; 95 | } 96 | 97 | -------------------------------------------------------------------------------- /externals/minhook/src/hde/table32.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Hacker Disassembler Engine 32 C 3 | * Copyright (c) 2008-2009, Vyacheslav Patkov. 4 | * All rights reserved. 5 | * 6 | */ 7 | 8 | #define C_NONE 0x00 9 | #define C_MODRM 0x01 10 | #define C_IMM8 0x02 11 | #define C_IMM16 0x04 12 | #define C_IMM_P66 0x10 13 | #define C_REL8 0x20 14 | #define C_REL32 0x40 15 | #define C_GROUP 0x80 16 | #define C_ERROR 0xff 17 | 18 | #define PRE_ANY 0x00 19 | #define PRE_NONE 0x01 20 | #define PRE_F2 0x02 21 | #define PRE_F3 0x04 22 | #define PRE_66 0x08 23 | #define PRE_67 0x10 24 | #define PRE_LOCK 0x20 25 | #define PRE_SEG 0x40 26 | #define PRE_ALL 0xff 27 | 28 | #define DELTA_OPCODES 0x4a 29 | #define DELTA_FPU_REG 0xf1 30 | #define DELTA_FPU_MODRM 0xf8 31 | #define DELTA_PREFIXES 0x130 32 | #define DELTA_OP_LOCK_OK 0x1a1 33 | #define DELTA_OP2_LOCK_OK 0x1b9 34 | #define DELTA_OP_ONLY_MEM 0x1cb 35 | #define DELTA_OP2_ONLY_MEM 0x1da 36 | 37 | unsigned char hde32_table[] = { 38 | 0xa3,0xa8,0xa3,0xa8,0xa3,0xa8,0xa3,0xa8,0xa3,0xa8,0xa3,0xa8,0xa3,0xa8,0xa3, 39 | 0xa8,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xac,0xaa,0xb2,0xaa,0x9f,0x9f, 40 | 0x9f,0x9f,0xb5,0xa3,0xa3,0xa4,0xaa,0xaa,0xba,0xaa,0x96,0xaa,0xa8,0xaa,0xc3, 41 | 0xc3,0x96,0x96,0xb7,0xae,0xd6,0xbd,0xa3,0xc5,0xa3,0xa3,0x9f,0xc3,0x9c,0xaa, 42 | 0xaa,0xac,0xaa,0xbf,0x03,0x7f,0x11,0x7f,0x01,0x7f,0x01,0x3f,0x01,0x01,0x90, 43 | 0x82,0x7d,0x97,0x59,0x59,0x59,0x59,0x59,0x7f,0x59,0x59,0x60,0x7d,0x7f,0x7f, 44 | 0x59,0x59,0x59,0x59,0x59,0x59,0x59,0x59,0x59,0x59,0x59,0x59,0x9a,0x88,0x7d, 45 | 0x59,0x50,0x50,0x50,0x50,0x59,0x59,0x59,0x59,0x61,0x94,0x61,0x9e,0x59,0x59, 46 | 0x85,0x59,0x92,0xa3,0x60,0x60,0x59,0x59,0x59,0x59,0x59,0x59,0x59,0x59,0x59, 47 | 0x59,0x59,0x9f,0x01,0x03,0x01,0x04,0x03,0xd5,0x03,0xcc,0x01,0xbc,0x03,0xf0, 48 | 0x10,0x10,0x10,0x10,0x50,0x50,0x50,0x50,0x14,0x20,0x20,0x20,0x20,0x01,0x01, 49 | 0x01,0x01,0xc4,0x02,0x10,0x00,0x00,0x00,0x00,0x01,0x01,0xc0,0xc2,0x10,0x11, 50 | 0x02,0x03,0x11,0x03,0x03,0x04,0x00,0x00,0x14,0x00,0x02,0x00,0x00,0xc6,0xc8, 51 | 0x02,0x02,0x02,0x02,0x00,0x00,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0xff,0xca, 52 | 0x01,0x01,0x01,0x00,0x06,0x00,0x04,0x00,0xc0,0xc2,0x01,0x01,0x03,0x01,0xff, 53 | 0xff,0x01,0x00,0x03,0xc4,0xc4,0xc6,0x03,0x01,0x01,0x01,0xff,0x03,0x03,0x03, 54 | 0xc8,0x40,0x00,0x0a,0x00,0x04,0x00,0x00,0x00,0x00,0x7f,0x00,0x33,0x01,0x00, 55 | 0x00,0x00,0x00,0x00,0x00,0xff,0xbf,0xff,0xff,0x00,0x00,0x00,0x00,0x07,0x00, 56 | 0x00,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 57 | 0x00,0xff,0xff,0x00,0x00,0x00,0xbf,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 58 | 0x7f,0x00,0x00,0xff,0x4a,0x4a,0x4a,0x4a,0x4b,0x52,0x4a,0x4a,0x4a,0x4a,0x4f, 59 | 0x4c,0x4a,0x4a,0x4a,0x4a,0x4a,0x4a,0x4a,0x4a,0x55,0x45,0x40,0x4a,0x4a,0x4a, 60 | 0x45,0x59,0x4d,0x46,0x4a,0x5d,0x4a,0x4a,0x4a,0x4a,0x4a,0x4a,0x4a,0x4a,0x4a, 61 | 0x4a,0x4a,0x4a,0x4a,0x4a,0x61,0x63,0x67,0x4e,0x4a,0x4a,0x6b,0x6d,0x4a,0x4a, 62 | 0x45,0x6d,0x4a,0x4a,0x44,0x45,0x4a,0x4a,0x00,0x00,0x00,0x02,0x0d,0x06,0x06, 63 | 0x06,0x06,0x0e,0x00,0x00,0x00,0x00,0x06,0x06,0x06,0x00,0x06,0x06,0x02,0x06, 64 | 0x00,0x0a,0x0a,0x07,0x07,0x06,0x02,0x05,0x05,0x02,0x02,0x00,0x00,0x04,0x04, 65 | 0x04,0x04,0x00,0x00,0x00,0x0e,0x05,0x06,0x06,0x06,0x01,0x06,0x00,0x00,0x08, 66 | 0x00,0x10,0x00,0x18,0x00,0x20,0x00,0x28,0x00,0x30,0x00,0x80,0x01,0x82,0x01, 67 | 0x86,0x00,0xf6,0xcf,0xfe,0x3f,0xab,0x00,0xb0,0x00,0xb1,0x00,0xb3,0x00,0xba, 68 | 0xf8,0xbb,0x00,0xc0,0x00,0xc1,0x00,0xc7,0xbf,0x62,0xff,0x00,0x8d,0xff,0x00, 69 | 0xc4,0xff,0x00,0xc5,0xff,0x00,0xff,0xff,0xeb,0x01,0xff,0x0e,0x12,0x08,0x00, 70 | 0x13,0x09,0x00,0x16,0x08,0x00,0x17,0x09,0x00,0x2b,0x09,0x00,0xae,0xff,0x07, 71 | 0xb2,0xff,0x00,0xb4,0xff,0x00,0xb5,0xff,0x00,0xc3,0x01,0x00,0xc7,0xff,0xbf, 72 | 0xe7,0x08,0x00,0xf0,0x02,0x00 73 | }; 74 | -------------------------------------------------------------------------------- /externals/minhook/src/hde/table64.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Hacker Disassembler Engine 64 C 3 | * Copyright (c) 2008-2009, Vyacheslav Patkov. 4 | * All rights reserved. 5 | * 6 | */ 7 | 8 | #define C_NONE 0x00 9 | #define C_MODRM 0x01 10 | #define C_IMM8 0x02 11 | #define C_IMM16 0x04 12 | #define C_IMM_P66 0x10 13 | #define C_REL8 0x20 14 | #define C_REL32 0x40 15 | #define C_GROUP 0x80 16 | #define C_ERROR 0xff 17 | 18 | #define PRE_ANY 0x00 19 | #define PRE_NONE 0x01 20 | #define PRE_F2 0x02 21 | #define PRE_F3 0x04 22 | #define PRE_66 0x08 23 | #define PRE_67 0x10 24 | #define PRE_LOCK 0x20 25 | #define PRE_SEG 0x40 26 | #define PRE_ALL 0xff 27 | 28 | #define DELTA_OPCODES 0x4a 29 | #define DELTA_FPU_REG 0xfd 30 | #define DELTA_FPU_MODRM 0x104 31 | #define DELTA_PREFIXES 0x13c 32 | #define DELTA_OP_LOCK_OK 0x1ae 33 | #define DELTA_OP2_LOCK_OK 0x1c6 34 | #define DELTA_OP_ONLY_MEM 0x1d8 35 | #define DELTA_OP2_ONLY_MEM 0x1e7 36 | 37 | unsigned char hde64_table[] = { 38 | 0xa5,0xaa,0xa5,0xb8,0xa5,0xaa,0xa5,0xaa,0xa5,0xb8,0xa5,0xb8,0xa5,0xb8,0xa5, 39 | 0xb8,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xac,0xc0,0xcc,0xc0,0xa1,0xa1, 40 | 0xa1,0xa1,0xb1,0xa5,0xa5,0xa6,0xc0,0xc0,0xd7,0xda,0xe0,0xc0,0xe4,0xc0,0xea, 41 | 0xea,0xe0,0xe0,0x98,0xc8,0xee,0xf1,0xa5,0xd3,0xa5,0xa5,0xa1,0xea,0x9e,0xc0, 42 | 0xc0,0xc2,0xc0,0xe6,0x03,0x7f,0x11,0x7f,0x01,0x7f,0x01,0x3f,0x01,0x01,0xab, 43 | 0x8b,0x90,0x64,0x5b,0x5b,0x5b,0x5b,0x5b,0x92,0x5b,0x5b,0x76,0x90,0x92,0x92, 44 | 0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x6a,0x73,0x90, 45 | 0x5b,0x52,0x52,0x52,0x52,0x5b,0x5b,0x5b,0x5b,0x77,0x7c,0x77,0x85,0x5b,0x5b, 46 | 0x70,0x5b,0x7a,0xaf,0x76,0x76,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b, 47 | 0x5b,0x5b,0x86,0x01,0x03,0x01,0x04,0x03,0xd5,0x03,0xd5,0x03,0xcc,0x01,0xbc, 48 | 0x03,0xf0,0x03,0x03,0x04,0x00,0x50,0x50,0x50,0x50,0xff,0x20,0x20,0x20,0x20, 49 | 0x01,0x01,0x01,0x01,0xc4,0x02,0x10,0xff,0xff,0xff,0x01,0x00,0x03,0x11,0xff, 50 | 0x03,0xc4,0xc6,0xc8,0x02,0x10,0x00,0xff,0xcc,0x01,0x01,0x01,0x00,0x00,0x00, 51 | 0x00,0x01,0x01,0x03,0x01,0xff,0xff,0xc0,0xc2,0x10,0x11,0x02,0x03,0x01,0x01, 52 | 0x01,0xff,0xff,0xff,0x00,0x00,0x00,0xff,0x00,0x00,0xff,0xff,0xff,0xff,0x10, 53 | 0x10,0x10,0x10,0x02,0x10,0x00,0x00,0xc6,0xc8,0x02,0x02,0x02,0x02,0x06,0x00, 54 | 0x04,0x00,0x02,0xff,0x00,0xc0,0xc2,0x01,0x01,0x03,0x03,0x03,0xca,0x40,0x00, 55 | 0x0a,0x00,0x04,0x00,0x00,0x00,0x00,0x7f,0x00,0x33,0x01,0x00,0x00,0x00,0x00, 56 | 0x00,0x00,0xff,0xbf,0xff,0xff,0x00,0x00,0x00,0x00,0x07,0x00,0x00,0xff,0x00, 57 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff, 58 | 0x00,0x00,0x00,0xbf,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7f,0x00,0x00, 59 | 0xff,0x40,0x40,0x40,0x40,0x41,0x49,0x40,0x40,0x40,0x40,0x4c,0x42,0x40,0x40, 60 | 0x40,0x40,0x40,0x40,0x40,0x40,0x4f,0x44,0x53,0x40,0x40,0x40,0x44,0x57,0x43, 61 | 0x5c,0x40,0x60,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40, 62 | 0x40,0x40,0x64,0x66,0x6e,0x6b,0x40,0x40,0x6a,0x46,0x40,0x40,0x44,0x46,0x40, 63 | 0x40,0x5b,0x44,0x40,0x40,0x00,0x00,0x00,0x00,0x06,0x06,0x06,0x06,0x01,0x06, 64 | 0x06,0x02,0x06,0x06,0x00,0x06,0x00,0x0a,0x0a,0x00,0x00,0x00,0x02,0x07,0x07, 65 | 0x06,0x02,0x0d,0x06,0x06,0x06,0x0e,0x05,0x05,0x02,0x02,0x00,0x00,0x04,0x04, 66 | 0x04,0x04,0x05,0x06,0x06,0x06,0x00,0x00,0x00,0x0e,0x00,0x00,0x08,0x00,0x10, 67 | 0x00,0x18,0x00,0x20,0x00,0x28,0x00,0x30,0x00,0x80,0x01,0x82,0x01,0x86,0x00, 68 | 0xf6,0xcf,0xfe,0x3f,0xab,0x00,0xb0,0x00,0xb1,0x00,0xb3,0x00,0xba,0xf8,0xbb, 69 | 0x00,0xc0,0x00,0xc1,0x00,0xc7,0xbf,0x62,0xff,0x00,0x8d,0xff,0x00,0xc4,0xff, 70 | 0x00,0xc5,0xff,0x00,0xff,0xff,0xeb,0x01,0xff,0x0e,0x12,0x08,0x00,0x13,0x09, 71 | 0x00,0x16,0x08,0x00,0x17,0x09,0x00,0x2b,0x09,0x00,0xae,0xff,0x07,0xb2,0xff, 72 | 0x00,0xb4,0xff,0x00,0xb5,0xff,0x00,0xc3,0x01,0x00,0xc7,0xff,0xbf,0xe7,0x08, 73 | 0x00,0xf0,0x02,0x00 74 | }; 75 | -------------------------------------------------------------------------------- /EzDump.vcxproj.filters: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | 18 | 19 | Source Files 20 | 21 | 22 | Source Files 23 | 24 | 25 | Source Files 26 | 27 | 28 | Source Files 29 | 30 | 31 | Source Files 32 | 33 | 34 | Source Files 35 | 36 | 37 | 38 | 39 | Header Files 40 | 41 | 42 | Header Files 43 | 44 | 45 | Header Files 46 | 47 | 48 | Header Files 49 | 50 | 51 | Header Files 52 | 53 | 54 | Header Files 55 | 56 | 57 | Header Files 58 | 59 | 60 | Header Files 61 | 62 | 63 | Header Files 64 | 65 | 66 | Header Files 67 | 68 | 69 | Header Files 70 | 71 | 72 | Header Files 73 | 74 | 75 | Header Files 76 | 77 | 78 | Header Files 79 | 80 | 81 | Header Files 82 | 83 | 84 | 85 | 86 | Source Files 87 | 88 | 89 | 90 | 91 | Resource Files 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | -------------------------------------------------------------------------------- /externals/minhook/src/trampoline.h: -------------------------------------------------------------------------------- 1 | /* 2 | * MinHook - The Minimalistic API Hooking Library for x64/x86 3 | * Copyright (C) 2009-2017 Tsuda Kageyu. 4 | * All rights reserved. 5 | * 6 | * Redistribution and use in source and binary forms, with or without 7 | * modification, are permitted provided that the following conditions 8 | * are met: 9 | * 10 | * 1. Redistributions of source code must retain the above copyright 11 | * notice, this list of conditions and the following disclaimer. 12 | * 2. Redistributions in binary form must reproduce the above copyright 13 | * notice, this list of conditions and the following disclaimer in the 14 | * documentation and/or other materials provided with the distribution. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 18 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 19 | * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 20 | * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 21 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 22 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 23 | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 24 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 25 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 26 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 | */ 28 | 29 | #pragma once 30 | 31 | #pragma pack(push, 1) 32 | 33 | // Structs for writing x86/x64 instructions. 34 | 35 | // 8-bit relative jump. 36 | typedef struct _JMP_REL_SHORT 37 | { 38 | UINT8 opcode; // EB xx: JMP +2+xx 39 | UINT8 operand; 40 | } JMP_REL_SHORT, *PJMP_REL_SHORT; 41 | 42 | // 32-bit direct relative jump/call. 43 | typedef struct _JMP_REL 44 | { 45 | UINT8 opcode; // E9/E8 xxxxxxxx: JMP/CALL +5+xxxxxxxx 46 | UINT32 operand; // Relative destination address 47 | } JMP_REL, *PJMP_REL, CALL_REL; 48 | 49 | // 64-bit indirect absolute jump. 50 | typedef struct _JMP_ABS 51 | { 52 | UINT8 opcode0; // FF25 00000000: JMP [+6] 53 | UINT8 opcode1; 54 | UINT32 dummy; 55 | UINT64 address; // Absolute destination address 56 | } JMP_ABS, *PJMP_ABS; 57 | 58 | // 64-bit indirect absolute call. 59 | typedef struct _CALL_ABS 60 | { 61 | UINT8 opcode0; // FF15 00000002: CALL [+6] 62 | UINT8 opcode1; 63 | UINT32 dummy0; 64 | UINT8 dummy1; // EB 08: JMP +10 65 | UINT8 dummy2; 66 | UINT64 address; // Absolute destination address 67 | } CALL_ABS; 68 | 69 | // 32-bit direct relative conditional jumps. 70 | typedef struct _JCC_REL 71 | { 72 | UINT8 opcode0; // 0F8* xxxxxxxx: J** +6+xxxxxxxx 73 | UINT8 opcode1; 74 | UINT32 operand; // Relative destination address 75 | } JCC_REL; 76 | 77 | // 64bit indirect absolute conditional jumps that x64 lacks. 78 | typedef struct _JCC_ABS 79 | { 80 | UINT8 opcode; // 7* 0E: J** +16 81 | UINT8 dummy0; 82 | UINT8 dummy1; // FF25 00000000: JMP [+6] 83 | UINT8 dummy2; 84 | UINT32 dummy3; 85 | UINT64 address; // Absolute destination address 86 | } JCC_ABS; 87 | 88 | #pragma pack(pop) 89 | 90 | typedef struct _TRAMPOLINE 91 | { 92 | LPVOID pTarget; // [In] Address of the target function. 93 | LPVOID pDetour; // [In] Address of the detour function. 94 | LPVOID pTrampoline; // [In] Buffer address for the trampoline and relay function. 95 | 96 | #if defined(_M_X64) || defined(__x86_64__) 97 | LPVOID pRelay; // [Out] Address of the relay function. 98 | #endif 99 | BOOL patchAbove; // [Out] Should use the hot patch area? 100 | UINT nIP; // [Out] Number of the instruction boundaries. 101 | UINT8 oldIPs[8]; // [Out] Instruction boundaries of the target function. 102 | UINT8 newIPs[8]; // [Out] Instruction boundaries of the trampoline function. 103 | } TRAMPOLINE, *PTRAMPOLINE; 104 | 105 | BOOL CreateTrampolineFunction(PTRAMPOLINE ct); 106 | -------------------------------------------------------------------------------- /internal/hooks.hpp: -------------------------------------------------------------------------------- 1 | #include "../imports.h" 2 | #include "../globals.h" 3 | 4 | typedef BOOL(WINAPI* tGetThreadContext)(HANDLE hThread,LPCONTEXT lpContext); 5 | tGetThreadContext pGetThreadContext = nullptr; 6 | bool WINAPI hookedGetThreadContext(HANDLE hThread, LPCONTEXT lpContext) { 7 | BOOL result = (*pGetThreadContext)(hThread, lpContext); 8 | if (lpContext) { 9 | lpContext->ContextFlags &= ~0x7F; 10 | lpContext->Dr0 = 0; 11 | lpContext->Dr1 = 0; 12 | lpContext->Dr2 = 0; 13 | lpContext->Dr3 = 0; 14 | lpContext->Dr6 = 0; 15 | lpContext->Dr7 = 0; 16 | } 17 | return pGetThreadContext(hThread, lpContext); 18 | } 19 | 20 | /* WriteProcessMemory */ 21 | typedef BOOL(WINAPI* tWriteProcessMemory)(HANDLE hProcess, LPVOID lpBaseAddress, LPCVOID lpBuffer, SIZE_T nSize, SIZE_T* lpNumberOfBytesWritten); 22 | tWriteProcessMemory pWriteProcessMemory = nullptr; // original function pointer after hook 23 | bool WINAPI hookedWriteProcessMemory(HANDLE hProcess, LPVOID lpBaseAddress, LPCVOID lpBuffer, SIZE_T nSize, SIZE_T* lpNumberOfBytesWritten) { 24 | 25 | for (int i = 1; i <= 1000; ++i) { 26 | std::string path = globals::dumpPath + xorstr_("writeprocessmemory_buffer.bin.") + std::to_string(i); 27 | if (!fileExists(path)) { 28 | std::ofstream outputFile(path, std::ios::binary | std::ios::app); 29 | if (outputFile.is_open()) { 30 | outputFile.write(reinterpret_cast(lpBuffer), nSize); 31 | outputFile.close(); 32 | } 33 | std::cout << xorstr_(" [WriteProcessMemory-Dumped] ") << path << std::endl; 34 | break; 35 | } 36 | } 37 | return pWriteProcessMemory(hProcess, lpBaseAddress, lpBuffer, nSize, lpNumberOfBytesWritten); 38 | } 39 | 40 | /* ReadProcessMemory */ 41 | typedef BOOL(WINAPI* tReadProcessMemory)(HANDLE hProcess, LPCVOID lpBaseAddress, LPVOID lpBuffer, SIZE_T nSize, SIZE_T* lpNumberOfBytesRead); 42 | tReadProcessMemory pReadProcessMemory = nullptr; 43 | bool WINAPI hookedReadProcessMemory(HANDLE hProcess, LPCVOID lpBaseAddress, LPVOID lpBuffer, SIZE_T nSize, SIZE_T* lpNumberOfBytesRead) { 44 | LPVOID tlpBuffer = lpBuffer; 45 | SIZE_T tnSize = nSize; 46 | SIZE_T* tlpNumberOfBytesRead = lpNumberOfBytesRead; 47 | LPCVOID tlpBaseAddress = lpBaseAddress; 48 | HANDLE thProcess = hProcess; 49 | ReadProcessMemory(thProcess, tlpBaseAddress, tlpBuffer, tnSize, tlpNumberOfBytesRead); 50 | 51 | for (int i = 1; i <= 1000; ++i) { 52 | std::string path = globals::dumpPath + xorstr_("readprocessmemory_buffer.bin.") + std::to_string(i); 53 | if (!fileExists(path)) { 54 | std::ofstream outputFile(path, std::ios::binary | std::ios::app); 55 | if (outputFile.is_open()) { 56 | outputFile.write(reinterpret_cast(tlpBuffer), tnSize); 57 | outputFile.close(); 58 | } 59 | std::cout << xorstr_(" [ReadProcessMemory-Dumped] ") << path << std::endl; 60 | break; 61 | } 62 | } 63 | return pReadProcessMemory(hProcess, lpBaseAddress, lpBuffer, nSize, lpNumberOfBytesRead); 64 | } 65 | 66 | typedef BOOL(WINAPI* tDeleteFileW)(LPCWSTR lpFileName); 67 | tDeleteFileW pDeleteFileW; 68 | bool WINAPI hookedDeleteFileW(LPCWSTR lpFileName) { 69 | for (int i = 1; i <= 1000; ++i) { 70 | std::wstring srcPath = globals::dumpPathW + xorstr_(L"DeleteFileW.bin.") + std::to_wstring(i); 71 | if (!std::filesystem::exists(srcPath)) { 72 | CopyFileW(lpFileName, srcPath.c_str(), FALSE); 73 | std::wcout << xorstr_("[DeleteFileW] ") << lpFileName << " -> " << srcPath << std::endl; 74 | break; 75 | } 76 | } 77 | return pDeleteFileW(lpFileName); 78 | } 79 | 80 | typedef BOOL(WINAPI* tDeleteFileA)(LPCSTR lpFileName); 81 | tDeleteFileA pDeleteFileA; 82 | bool WINAPI hookedDeleteFileA(LPCSTR lpFileName) { 83 | for (int i = 1; i <= 1000; ++i) { 84 | std::string srcPath = globals::dumpPath + xorstr_("DeleteFileA.bin.") + std::to_string(i); 85 | if (!std::filesystem::exists(srcPath)) { 86 | CopyFileA(lpFileName, srcPath.c_str(), FALSE); 87 | std::cout << xorstr_("[DeleteFileA] ") << lpFileName << " -> " << srcPath << std::endl; 88 | break; 89 | } 90 | } 91 | return pDeleteFileA(lpFileName); 92 | } 93 | 94 | typedef NTSTATUS(NTAPI* tNtRaiseHardError)(NTSTATUS ErrorStatus, ULONG NumberOfParameters, ULONG UnicodeStringParameterMask, PULONG_PTR Parameters, ULONG ResponseOption, PULONG Response); 95 | tNtRaiseHardError pNtRaiseHardError; 96 | NTSTATUS hookedNtRaiseHardError(NTSTATUS ErrorStatus, ULONG NumberOfParameters, ULONG UnicodeStringParameterMask, PULONG_PTR Parameters, ULONG ResponseOption, PULONG Response) { 97 | return NULL; 98 | } -------------------------------------------------------------------------------- /test/test.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | Debug 14 | x64 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | 17.0 23 | Win32Proj 24 | {e3b3d37e-3e82-404f-9b14-4bc4c008be36} 25 | test 26 | 10.0 27 | 28 | 29 | 30 | Application 31 | true 32 | v143 33 | Unicode 34 | 35 | 36 | Application 37 | false 38 | v143 39 | true 40 | Unicode 41 | 42 | 43 | Application 44 | true 45 | v143 46 | Unicode 47 | 48 | 49 | Application 50 | false 51 | v143 52 | true 53 | MultiByte 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | Level3 76 | true 77 | WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) 78 | true 79 | 80 | 81 | Console 82 | true 83 | 84 | 85 | 86 | 87 | Level3 88 | true 89 | true 90 | true 91 | WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 92 | true 93 | 94 | 95 | Console 96 | true 97 | true 98 | true 99 | 100 | 101 | 102 | 103 | Level3 104 | true 105 | _DEBUG;_CONSOLE;%(PreprocessorDefinitions) 106 | true 107 | 108 | 109 | Console 110 | true 111 | 112 | 113 | 114 | 115 | Level3 116 | true 117 | true 118 | true 119 | NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 120 | true 121 | stdcpp20 122 | stdc17 123 | 124 | 125 | Console 126 | true 127 | true 128 | true 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | -------------------------------------------------------------------------------- /externals/minhook/MinHook.h: -------------------------------------------------------------------------------- 1 | /* 2 | * MinHook - The Minimalistic API Hooking Library for x64/x86 3 | * Copyright (C) 2009-2017 Tsuda Kageyu. 4 | * All rights reserved. 5 | * 6 | * Redistribution and use in source and binary forms, with or without 7 | * modification, are permitted provided that the following conditions 8 | * are met: 9 | * 10 | * 1. Redistributions of source code must retain the above copyright 11 | * notice, this list of conditions and the following disclaimer. 12 | * 2. Redistributions in binary form must reproduce the above copyright 13 | * notice, this list of conditions and the following disclaimer in the 14 | * documentation and/or other materials provided with the distribution. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 18 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 19 | * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 20 | * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 21 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 22 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 23 | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 24 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 25 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 26 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 | */ 28 | 29 | #pragma once 30 | 31 | #if !(defined _M_IX86) && !(defined _M_X64) && !(defined __i386__) && !(defined __x86_64__) 32 | #error MinHook supports only x86 and x64 systems. 33 | #endif 34 | 35 | #include 36 | 37 | // MinHook Error Codes. 38 | typedef enum MH_STATUS 39 | { 40 | // Unknown error. Should not be returned. 41 | MH_UNKNOWN = -1, 42 | 43 | // Successful. 44 | MH_OK = 0, 45 | 46 | // MinHook is already initialized. 47 | MH_ERROR_ALREADY_INITIALIZED, 48 | 49 | // MinHook is not initialized yet, or already uninitialized. 50 | MH_ERROR_NOT_INITIALIZED, 51 | 52 | // The hook for the specified target function is already created. 53 | MH_ERROR_ALREADY_CREATED, 54 | 55 | // The hook for the specified target function is not created yet. 56 | MH_ERROR_NOT_CREATED, 57 | 58 | // The hook for the specified target function is already enabled. 59 | MH_ERROR_ENABLED, 60 | 61 | // The hook for the specified target function is not enabled yet, or already 62 | // disabled. 63 | MH_ERROR_DISABLED, 64 | 65 | // The specified pointer is invalid. It points the address of non-allocated 66 | // and/or non-executable region. 67 | MH_ERROR_NOT_EXECUTABLE, 68 | 69 | // The specified target function cannot be hooked. 70 | MH_ERROR_UNSUPPORTED_FUNCTION, 71 | 72 | // Failed to allocate memory. 73 | MH_ERROR_MEMORY_ALLOC, 74 | 75 | // Failed to change the memory protection. 76 | MH_ERROR_MEMORY_PROTECT, 77 | 78 | // The specified module is not loaded. 79 | MH_ERROR_MODULE_NOT_FOUND, 80 | 81 | // The specified function is not found. 82 | MH_ERROR_FUNCTION_NOT_FOUND 83 | } 84 | MH_STATUS; 85 | 86 | // Can be passed as a parameter to MH_EnableHook, MH_DisableHook, 87 | // MH_QueueEnableHook or MH_QueueDisableHook. 88 | #define MH_ALL_HOOKS NULL 89 | 90 | #ifdef __cplusplus 91 | extern "C" { 92 | #endif 93 | 94 | // Initialize the MinHook library. You must call this function EXACTLY ONCE 95 | // at the beginning of your program. 96 | MH_STATUS WINAPI MH_Initialize(VOID); 97 | 98 | // Uninitialize the MinHook library. You must call this function EXACTLY 99 | // ONCE at the end of your program. 100 | MH_STATUS WINAPI MH_Uninitialize(VOID); 101 | 102 | // Creates a Hook for the specified target function, in disabled state. 103 | // Parameters: 104 | // pTarget [in] A pointer to the target function, which will be 105 | // overridden by the detour function. 106 | // pDetour [in] A pointer to the detour function, which will override 107 | // the target function. 108 | // ppOriginal [out] A pointer to the trampoline function, which will be 109 | // used to call the original target function. 110 | // This parameter can be NULL. 111 | MH_STATUS WINAPI MH_CreateHook(LPVOID pTarget, LPVOID pDetour, LPVOID* ppOriginal); 112 | 113 | // Creates a Hook for the specified API function, in disabled state. 114 | // Parameters: 115 | // pszModule [in] A pointer to the loaded module name which contains the 116 | // target function. 117 | // pszTarget [in] A pointer to the target function name, which will be 118 | // overridden by the detour function. 119 | // pDetour [in] A pointer to the detour function, which will override 120 | // the target function. 121 | // ppOriginal [out] A pointer to the trampoline function, which will be 122 | // used to call the original target function. 123 | // This parameter can be NULL. 124 | MH_STATUS WINAPI MH_CreateHookApi( 125 | LPCWSTR pszModule, LPCSTR pszProcName, LPVOID pDetour, LPVOID* ppOriginal); 126 | 127 | // Creates a Hook for the specified API function, in disabled state. 128 | // Parameters: 129 | // pszModule [in] A pointer to the loaded module name which contains the 130 | // target function. 131 | // pszTarget [in] A pointer to the target function name, which will be 132 | // overridden by the detour function. 133 | // pDetour [in] A pointer to the detour function, which will override 134 | // the target function. 135 | // ppOriginal [out] A pointer to the trampoline function, which will be 136 | // used to call the original target function. 137 | // This parameter can be NULL. 138 | // ppTarget [out] A pointer to the target function, which will be used 139 | // with other functions. 140 | // This parameter can be NULL. 141 | MH_STATUS WINAPI MH_CreateHookApiEx( 142 | LPCWSTR pszModule, LPCSTR pszProcName, LPVOID pDetour, LPVOID* ppOriginal, LPVOID* ppTarget); 143 | 144 | // Removes an already created hook. 145 | // Parameters: 146 | // pTarget [in] A pointer to the target function. 147 | MH_STATUS WINAPI MH_RemoveHook(LPVOID pTarget); 148 | 149 | // Enables an already created hook. 150 | // Parameters: 151 | // pTarget [in] A pointer to the target function. 152 | // If this parameter is MH_ALL_HOOKS, all created hooks are 153 | // enabled in one go. 154 | MH_STATUS WINAPI MH_EnableHook(LPVOID pTarget); 155 | 156 | // Disables an already created hook. 157 | // Parameters: 158 | // pTarget [in] A pointer to the target function. 159 | // If this parameter is MH_ALL_HOOKS, all created hooks are 160 | // disabled in one go. 161 | MH_STATUS WINAPI MH_DisableHook(LPVOID pTarget); 162 | 163 | // Queues to enable an already created hook. 164 | // Parameters: 165 | // pTarget [in] A pointer to the target function. 166 | // If this parameter is MH_ALL_HOOKS, all created hooks are 167 | // queued to be enabled. 168 | MH_STATUS WINAPI MH_QueueEnableHook(LPVOID pTarget); 169 | 170 | // Queues to disable an already created hook. 171 | // Parameters: 172 | // pTarget [in] A pointer to the target function. 173 | // If this parameter is MH_ALL_HOOKS, all created hooks are 174 | // queued to be disabled. 175 | MH_STATUS WINAPI MH_QueueDisableHook(LPVOID pTarget); 176 | 177 | // Applies all queued changes in one go. 178 | MH_STATUS WINAPI MH_ApplyQueued(VOID); 179 | 180 | // Translates the MH_STATUS to its name as a string. 181 | const char* WINAPI MH_StatusToString(MH_STATUS status); 182 | 183 | #ifdef __cplusplus 184 | } 185 | #endif 186 | 187 | -------------------------------------------------------------------------------- /externals/minhook/include/MinHook.h: -------------------------------------------------------------------------------- 1 | /* 2 | * MinHook - The Minimalistic API Hooking Library for x64/x86 3 | * Copyright (C) 2009-2017 Tsuda Kageyu. 4 | * All rights reserved. 5 | * 6 | * Redistribution and use in source and binary forms, with or without 7 | * modification, are permitted provided that the following conditions 8 | * are met: 9 | * 10 | * 1. Redistributions of source code must retain the above copyright 11 | * notice, this list of conditions and the following disclaimer. 12 | * 2. Redistributions in binary form must reproduce the above copyright 13 | * notice, this list of conditions and the following disclaimer in the 14 | * documentation and/or other materials provided with the distribution. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 18 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 19 | * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 20 | * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 21 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 22 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 23 | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 24 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 25 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 26 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 | */ 28 | 29 | #pragma once 30 | 31 | #if !(defined _M_IX86) && !(defined _M_X64) && !(defined __i386__) && !(defined __x86_64__) 32 | #error MinHook supports only x86 and x64 systems. 33 | #endif 34 | 35 | #include 36 | 37 | // MinHook Error Codes. 38 | typedef enum MH_STATUS 39 | { 40 | // Unknown error. Should not be returned. 41 | MH_UNKNOWN = -1, 42 | 43 | // Successful. 44 | MH_OK = 0, 45 | 46 | // MinHook is already initialized. 47 | MH_ERROR_ALREADY_INITIALIZED, 48 | 49 | // MinHook is not initialized yet, or already uninitialized. 50 | MH_ERROR_NOT_INITIALIZED, 51 | 52 | // The hook for the specified target function is already created. 53 | MH_ERROR_ALREADY_CREATED, 54 | 55 | // The hook for the specified target function is not created yet. 56 | MH_ERROR_NOT_CREATED, 57 | 58 | // The hook for the specified target function is already enabled. 59 | MH_ERROR_ENABLED, 60 | 61 | // The hook for the specified target function is not enabled yet, or already 62 | // disabled. 63 | MH_ERROR_DISABLED, 64 | 65 | // The specified pointer is invalid. It points the address of non-allocated 66 | // and/or non-executable region. 67 | MH_ERROR_NOT_EXECUTABLE, 68 | 69 | // The specified target function cannot be hooked. 70 | MH_ERROR_UNSUPPORTED_FUNCTION, 71 | 72 | // Failed to allocate memory. 73 | MH_ERROR_MEMORY_ALLOC, 74 | 75 | // Failed to change the memory protection. 76 | MH_ERROR_MEMORY_PROTECT, 77 | 78 | // The specified module is not loaded. 79 | MH_ERROR_MODULE_NOT_FOUND, 80 | 81 | // The specified function is not found. 82 | MH_ERROR_FUNCTION_NOT_FOUND 83 | } 84 | MH_STATUS; 85 | 86 | // Can be passed as a parameter to MH_EnableHook, MH_DisableHook, 87 | // MH_QueueEnableHook or MH_QueueDisableHook. 88 | #define MH_ALL_HOOKS NULL 89 | 90 | #ifdef __cplusplus 91 | extern "C" { 92 | #endif 93 | 94 | // Initialize the MinHook library. You must call this function EXACTLY ONCE 95 | // at the beginning of your program. 96 | MH_STATUS WINAPI MH_Initialize(VOID); 97 | 98 | // Uninitialize the MinHook library. You must call this function EXACTLY 99 | // ONCE at the end of your program. 100 | MH_STATUS WINAPI MH_Uninitialize(VOID); 101 | 102 | // Creates a Hook for the specified target function, in disabled state. 103 | // Parameters: 104 | // pTarget [in] A pointer to the target function, which will be 105 | // overridden by the detour function. 106 | // pDetour [in] A pointer to the detour function, which will override 107 | // the target function. 108 | // ppOriginal [out] A pointer to the trampoline function, which will be 109 | // used to call the original target function. 110 | // This parameter can be NULL. 111 | MH_STATUS WINAPI MH_CreateHook(LPVOID pTarget, LPVOID pDetour, LPVOID *ppOriginal); 112 | 113 | // Creates a Hook for the specified API function, in disabled state. 114 | // Parameters: 115 | // pszModule [in] A pointer to the loaded module name which contains the 116 | // target function. 117 | // pszTarget [in] A pointer to the target function name, which will be 118 | // overridden by the detour function. 119 | // pDetour [in] A pointer to the detour function, which will override 120 | // the target function. 121 | // ppOriginal [out] A pointer to the trampoline function, which will be 122 | // used to call the original target function. 123 | // This parameter can be NULL. 124 | MH_STATUS WINAPI MH_CreateHookApi( 125 | LPCWSTR pszModule, LPCSTR pszProcName, LPVOID pDetour, LPVOID *ppOriginal); 126 | 127 | // Creates a Hook for the specified API function, in disabled state. 128 | // Parameters: 129 | // pszModule [in] A pointer to the loaded module name which contains the 130 | // target function. 131 | // pszTarget [in] A pointer to the target function name, which will be 132 | // overridden by the detour function. 133 | // pDetour [in] A pointer to the detour function, which will override 134 | // the target function. 135 | // ppOriginal [out] A pointer to the trampoline function, which will be 136 | // used to call the original target function. 137 | // This parameter can be NULL. 138 | // ppTarget [out] A pointer to the target function, which will be used 139 | // with other functions. 140 | // This parameter can be NULL. 141 | MH_STATUS WINAPI MH_CreateHookApiEx( 142 | LPCWSTR pszModule, LPCSTR pszProcName, LPVOID pDetour, LPVOID *ppOriginal, LPVOID *ppTarget); 143 | 144 | // Removes an already created hook. 145 | // Parameters: 146 | // pTarget [in] A pointer to the target function. 147 | MH_STATUS WINAPI MH_RemoveHook(LPVOID pTarget); 148 | 149 | // Enables an already created hook. 150 | // Parameters: 151 | // pTarget [in] A pointer to the target function. 152 | // If this parameter is MH_ALL_HOOKS, all created hooks are 153 | // enabled in one go. 154 | MH_STATUS WINAPI MH_EnableHook(LPVOID pTarget); 155 | 156 | // Disables an already created hook. 157 | // Parameters: 158 | // pTarget [in] A pointer to the target function. 159 | // If this parameter is MH_ALL_HOOKS, all created hooks are 160 | // disabled in one go. 161 | MH_STATUS WINAPI MH_DisableHook(LPVOID pTarget); 162 | 163 | // Queues to enable an already created hook. 164 | // Parameters: 165 | // pTarget [in] A pointer to the target function. 166 | // If this parameter is MH_ALL_HOOKS, all created hooks are 167 | // queued to be enabled. 168 | MH_STATUS WINAPI MH_QueueEnableHook(LPVOID pTarget); 169 | 170 | // Queues to disable an already created hook. 171 | // Parameters: 172 | // pTarget [in] A pointer to the target function. 173 | // If this parameter is MH_ALL_HOOKS, all created hooks are 174 | // queued to be disabled. 175 | MH_STATUS WINAPI MH_QueueDisableHook(LPVOID pTarget); 176 | 177 | // Applies all queued changes in one go. 178 | MH_STATUS WINAPI MH_ApplyQueued(VOID); 179 | 180 | // Translates the MH_STATUS to its name as a string. 181 | const char * WINAPI MH_StatusToString(MH_STATUS status); 182 | 183 | #ifdef __cplusplus 184 | } 185 | #endif 186 | 187 | -------------------------------------------------------------------------------- /EzDump.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | Debug 14 | x64 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | 17.0 23 | Win32Proj 24 | {e704e47c-56b8-4d41-a895-e35400dcd2c2} 25 | EzDump 26 | 10.0 27 | 28 | 29 | 30 | DynamicLibrary 31 | true 32 | v143 33 | Unicode 34 | 35 | 36 | DynamicLibrary 37 | false 38 | v143 39 | true 40 | MultiByte 41 | 42 | 43 | DynamicLibrary 44 | true 45 | v143 46 | Unicode 47 | 48 | 49 | DynamicLibrary 50 | false 51 | v143 52 | true 53 | MultiByte 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | C:\Program Files (x86)\Microsoft DirectX SDK (June 2010)\Include;$(IncludePath) 75 | C:\Users\dnfki\source\repos\EzDump\externals\minhook;C:\Program Files (x86)\Microsoft DirectX SDK (June 2010)\Lib\x64;$(LibraryPath) 76 | 77 | 78 | C:\Users\dnfki\source\repos\EzDump\externals\minhook\include;$(IncludePath) 79 | C:\Users\dnfki\source\repos\EzDump\externals\minhook\src;$(LibraryPath) 80 | $(SolutionDir)$(Platform)\$(Configuration)\ 81 | 82 | 83 | 84 | Level3 85 | true 86 | WIN32;_DEBUG;EZDUMP_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) 87 | true 88 | Use 89 | pch.h 90 | 91 | 92 | Windows 93 | true 94 | false 95 | 96 | 97 | 98 | 99 | Level3 100 | true 101 | true 102 | true 103 | WIN32;NDEBUG;EZDUMP_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) 104 | true 105 | NotUsing 106 | pch.h 107 | stdcpp20 108 | stdc17 109 | 110 | 111 | Windows 112 | true 113 | true 114 | true 115 | false 116 | 117 | 118 | 119 | 120 | 121 | 122 | Level3 123 | true 124 | _DEBUG;EZDUMP_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) 125 | true 126 | Use 127 | pch.h 128 | 129 | 130 | Windows 131 | true 132 | false 133 | 134 | 135 | 136 | 137 | Level3 138 | true 139 | true 140 | true 141 | NDEBUG;EZDUMP_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) 142 | true 143 | NotUsing 144 | pch.h 145 | stdcpp20 146 | stdc17 147 | 148 | 149 | Windows 150 | true 151 | true 152 | true 153 | false 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | -------------------------------------------------------------------------------- /externals/minhook/src/hde/hde32.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Hacker Disassembler Engine 32 C 3 | * Copyright (c) 2008-2009, Vyacheslav Patkov. 4 | * All rights reserved. 5 | * 6 | */ 7 | 8 | #if defined(_M_IX86) || defined(__i386__) 9 | 10 | #include "hde32.h" 11 | #include "table32.h" 12 | 13 | unsigned int hde32_disasm(const void *code, hde32s *hs) 14 | { 15 | uint8_t x, c, *p = (uint8_t *)code, cflags, opcode, pref = 0; 16 | uint8_t *ht = hde32_table, m_mod, m_reg, m_rm, disp_size = 0; 17 | 18 | // Avoid using memset to reduce the footprint. 19 | #ifndef _MSC_VER 20 | memset((LPBYTE)hs, 0, sizeof(hde32s)); 21 | #else 22 | __stosb((LPBYTE)hs, 0, sizeof(hde32s)); 23 | #endif 24 | 25 | for (x = 16; x; x--) 26 | switch (c = *p++) { 27 | case 0xf3: 28 | hs->p_rep = c; 29 | pref |= PRE_F3; 30 | break; 31 | case 0xf2: 32 | hs->p_rep = c; 33 | pref |= PRE_F2; 34 | break; 35 | case 0xf0: 36 | hs->p_lock = c; 37 | pref |= PRE_LOCK; 38 | break; 39 | case 0x26: case 0x2e: case 0x36: 40 | case 0x3e: case 0x64: case 0x65: 41 | hs->p_seg = c; 42 | pref |= PRE_SEG; 43 | break; 44 | case 0x66: 45 | hs->p_66 = c; 46 | pref |= PRE_66; 47 | break; 48 | case 0x67: 49 | hs->p_67 = c; 50 | pref |= PRE_67; 51 | break; 52 | default: 53 | goto pref_done; 54 | } 55 | pref_done: 56 | 57 | hs->flags = (uint32_t)pref << 23; 58 | 59 | if (!pref) 60 | pref |= PRE_NONE; 61 | 62 | if ((hs->opcode = c) == 0x0f) { 63 | hs->opcode2 = c = *p++; 64 | ht += DELTA_OPCODES; 65 | } else if (c >= 0xa0 && c <= 0xa3) { 66 | if (pref & PRE_67) 67 | pref |= PRE_66; 68 | else 69 | pref &= ~PRE_66; 70 | } 71 | 72 | opcode = c; 73 | cflags = ht[ht[opcode / 4] + (opcode % 4)]; 74 | 75 | if (cflags == C_ERROR) { 76 | hs->flags |= F_ERROR | F_ERROR_OPCODE; 77 | cflags = 0; 78 | if ((opcode & -3) == 0x24) 79 | cflags++; 80 | } 81 | 82 | x = 0; 83 | if (cflags & C_GROUP) { 84 | uint16_t t; 85 | t = *(uint16_t *)(ht + (cflags & 0x7f)); 86 | cflags = (uint8_t)t; 87 | x = (uint8_t)(t >> 8); 88 | } 89 | 90 | if (hs->opcode2) { 91 | ht = hde32_table + DELTA_PREFIXES; 92 | if (ht[ht[opcode / 4] + (opcode % 4)] & pref) 93 | hs->flags |= F_ERROR | F_ERROR_OPCODE; 94 | } 95 | 96 | if (cflags & C_MODRM) { 97 | hs->flags |= F_MODRM; 98 | hs->modrm = c = *p++; 99 | hs->modrm_mod = m_mod = c >> 6; 100 | hs->modrm_rm = m_rm = c & 7; 101 | hs->modrm_reg = m_reg = (c & 0x3f) >> 3; 102 | 103 | if (x && ((x << m_reg) & 0x80)) 104 | hs->flags |= F_ERROR | F_ERROR_OPCODE; 105 | 106 | if (!hs->opcode2 && opcode >= 0xd9 && opcode <= 0xdf) { 107 | uint8_t t = opcode - 0xd9; 108 | if (m_mod == 3) { 109 | ht = hde32_table + DELTA_FPU_MODRM + t*8; 110 | t = ht[m_reg] << m_rm; 111 | } else { 112 | ht = hde32_table + DELTA_FPU_REG; 113 | t = ht[t] << m_reg; 114 | } 115 | if (t & 0x80) 116 | hs->flags |= F_ERROR | F_ERROR_OPCODE; 117 | } 118 | 119 | if (pref & PRE_LOCK) { 120 | if (m_mod == 3) { 121 | hs->flags |= F_ERROR | F_ERROR_LOCK; 122 | } else { 123 | uint8_t *table_end, op = opcode; 124 | if (hs->opcode2) { 125 | ht = hde32_table + DELTA_OP2_LOCK_OK; 126 | table_end = ht + DELTA_OP_ONLY_MEM - DELTA_OP2_LOCK_OK; 127 | } else { 128 | ht = hde32_table + DELTA_OP_LOCK_OK; 129 | table_end = ht + DELTA_OP2_LOCK_OK - DELTA_OP_LOCK_OK; 130 | op &= -2; 131 | } 132 | for (; ht != table_end; ht++) 133 | if (*ht++ == op) { 134 | if (!((*ht << m_reg) & 0x80)) 135 | goto no_lock_error; 136 | else 137 | break; 138 | } 139 | hs->flags |= F_ERROR | F_ERROR_LOCK; 140 | no_lock_error: 141 | ; 142 | } 143 | } 144 | 145 | if (hs->opcode2) { 146 | switch (opcode) { 147 | case 0x20: case 0x22: 148 | m_mod = 3; 149 | if (m_reg > 4 || m_reg == 1) 150 | goto error_operand; 151 | else 152 | goto no_error_operand; 153 | case 0x21: case 0x23: 154 | m_mod = 3; 155 | if (m_reg == 4 || m_reg == 5) 156 | goto error_operand; 157 | else 158 | goto no_error_operand; 159 | } 160 | } else { 161 | switch (opcode) { 162 | case 0x8c: 163 | if (m_reg > 5) 164 | goto error_operand; 165 | else 166 | goto no_error_operand; 167 | case 0x8e: 168 | if (m_reg == 1 || m_reg > 5) 169 | goto error_operand; 170 | else 171 | goto no_error_operand; 172 | } 173 | } 174 | 175 | if (m_mod == 3) { 176 | uint8_t *table_end; 177 | if (hs->opcode2) { 178 | ht = hde32_table + DELTA_OP2_ONLY_MEM; 179 | table_end = ht + sizeof(hde32_table) - DELTA_OP2_ONLY_MEM; 180 | } else { 181 | ht = hde32_table + DELTA_OP_ONLY_MEM; 182 | table_end = ht + DELTA_OP2_ONLY_MEM - DELTA_OP_ONLY_MEM; 183 | } 184 | for (; ht != table_end; ht += 2) 185 | if (*ht++ == opcode) { 186 | if (*ht++ & pref && !((*ht << m_reg) & 0x80)) 187 | goto error_operand; 188 | else 189 | break; 190 | } 191 | goto no_error_operand; 192 | } else if (hs->opcode2) { 193 | switch (opcode) { 194 | case 0x50: case 0xd7: case 0xf7: 195 | if (pref & (PRE_NONE | PRE_66)) 196 | goto error_operand; 197 | break; 198 | case 0xd6: 199 | if (pref & (PRE_F2 | PRE_F3)) 200 | goto error_operand; 201 | break; 202 | case 0xc5: 203 | goto error_operand; 204 | } 205 | goto no_error_operand; 206 | } else 207 | goto no_error_operand; 208 | 209 | error_operand: 210 | hs->flags |= F_ERROR | F_ERROR_OPERAND; 211 | no_error_operand: 212 | 213 | c = *p++; 214 | if (m_reg <= 1) { 215 | if (opcode == 0xf6) 216 | cflags |= C_IMM8; 217 | else if (opcode == 0xf7) 218 | cflags |= C_IMM_P66; 219 | } 220 | 221 | switch (m_mod) { 222 | case 0: 223 | if (pref & PRE_67) { 224 | if (m_rm == 6) 225 | disp_size = 2; 226 | } else 227 | if (m_rm == 5) 228 | disp_size = 4; 229 | break; 230 | case 1: 231 | disp_size = 1; 232 | break; 233 | case 2: 234 | disp_size = 2; 235 | if (!(pref & PRE_67)) 236 | disp_size <<= 1; 237 | } 238 | 239 | if (m_mod != 3 && m_rm == 4 && !(pref & PRE_67)) { 240 | hs->flags |= F_SIB; 241 | p++; 242 | hs->sib = c; 243 | hs->sib_scale = c >> 6; 244 | hs->sib_index = (c & 0x3f) >> 3; 245 | if ((hs->sib_base = c & 7) == 5 && !(m_mod & 1)) 246 | disp_size = 4; 247 | } 248 | 249 | p--; 250 | switch (disp_size) { 251 | case 1: 252 | hs->flags |= F_DISP8; 253 | hs->disp.disp8 = *p; 254 | break; 255 | case 2: 256 | hs->flags |= F_DISP16; 257 | hs->disp.disp16 = *(uint16_t *)p; 258 | break; 259 | case 4: 260 | hs->flags |= F_DISP32; 261 | hs->disp.disp32 = *(uint32_t *)p; 262 | } 263 | p += disp_size; 264 | } else if (pref & PRE_LOCK) 265 | hs->flags |= F_ERROR | F_ERROR_LOCK; 266 | 267 | if (cflags & C_IMM_P66) { 268 | if (cflags & C_REL32) { 269 | if (pref & PRE_66) { 270 | hs->flags |= F_IMM16 | F_RELATIVE; 271 | hs->imm.imm16 = *(uint16_t *)p; 272 | p += 2; 273 | goto disasm_done; 274 | } 275 | goto rel32_ok; 276 | } 277 | if (pref & PRE_66) { 278 | hs->flags |= F_IMM16; 279 | hs->imm.imm16 = *(uint16_t *)p; 280 | p += 2; 281 | } else { 282 | hs->flags |= F_IMM32; 283 | hs->imm.imm32 = *(uint32_t *)p; 284 | p += 4; 285 | } 286 | } 287 | 288 | if (cflags & C_IMM16) { 289 | if (hs->flags & F_IMM32) { 290 | hs->flags |= F_IMM16; 291 | hs->disp.disp16 = *(uint16_t *)p; 292 | } else if (hs->flags & F_IMM16) { 293 | hs->flags |= F_2IMM16; 294 | hs->disp.disp16 = *(uint16_t *)p; 295 | } else { 296 | hs->flags |= F_IMM16; 297 | hs->imm.imm16 = *(uint16_t *)p; 298 | } 299 | p += 2; 300 | } 301 | if (cflags & C_IMM8) { 302 | hs->flags |= F_IMM8; 303 | hs->imm.imm8 = *p++; 304 | } 305 | 306 | if (cflags & C_REL32) { 307 | rel32_ok: 308 | hs->flags |= F_IMM32 | F_RELATIVE; 309 | hs->imm.imm32 = *(uint32_t *)p; 310 | p += 4; 311 | } else if (cflags & C_REL8) { 312 | hs->flags |= F_IMM8 | F_RELATIVE; 313 | hs->imm.imm8 = *p++; 314 | } 315 | 316 | disasm_done: 317 | 318 | if ((hs->len = (uint8_t)(p-(uint8_t *)code)) > 15) { 319 | hs->flags |= F_ERROR | F_ERROR_LENGTH; 320 | hs->len = 15; 321 | } 322 | 323 | return (unsigned int)hs->len; 324 | } 325 | 326 | #endif // defined(_M_IX86) || defined(__i386__) 327 | -------------------------------------------------------------------------------- /externals/minhook/src/hde/hde64.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Hacker Disassembler Engine 64 C 3 | * Copyright (c) 2008-2009, Vyacheslav Patkov. 4 | * All rights reserved. 5 | * 6 | */ 7 | 8 | #if defined(_M_X64) || defined(__x86_64__) 9 | 10 | #include "hde64.h" 11 | #include "table64.h" 12 | 13 | unsigned int hde64_disasm(const void *code, hde64s *hs) 14 | { 15 | uint8_t x, c, *p = (uint8_t *)code, cflags, opcode, pref = 0; 16 | uint8_t *ht = hde64_table, m_mod, m_reg, m_rm, disp_size = 0; 17 | uint8_t op64 = 0; 18 | 19 | // Avoid using memset to reduce the footprint. 20 | #ifndef _MSC_VER 21 | memset((LPBYTE)hs, 0, sizeof(hde64s)); 22 | #else 23 | __stosb((LPBYTE)hs, 0, sizeof(hde64s)); 24 | #endif 25 | 26 | for (x = 16; x; x--) 27 | switch (c = *p++) { 28 | case 0xf3: 29 | hs->p_rep = c; 30 | pref |= PRE_F3; 31 | break; 32 | case 0xf2: 33 | hs->p_rep = c; 34 | pref |= PRE_F2; 35 | break; 36 | case 0xf0: 37 | hs->p_lock = c; 38 | pref |= PRE_LOCK; 39 | break; 40 | case 0x26: case 0x2e: case 0x36: 41 | case 0x3e: case 0x64: case 0x65: 42 | hs->p_seg = c; 43 | pref |= PRE_SEG; 44 | break; 45 | case 0x66: 46 | hs->p_66 = c; 47 | pref |= PRE_66; 48 | break; 49 | case 0x67: 50 | hs->p_67 = c; 51 | pref |= PRE_67; 52 | break; 53 | default: 54 | goto pref_done; 55 | } 56 | pref_done: 57 | 58 | hs->flags = (uint32_t)pref << 23; 59 | 60 | if (!pref) 61 | pref |= PRE_NONE; 62 | 63 | if ((c & 0xf0) == 0x40) { 64 | hs->flags |= F_PREFIX_REX; 65 | if ((hs->rex_w = (c & 0xf) >> 3) && (*p & 0xf8) == 0xb8) 66 | op64++; 67 | hs->rex_r = (c & 7) >> 2; 68 | hs->rex_x = (c & 3) >> 1; 69 | hs->rex_b = c & 1; 70 | if (((c = *p++) & 0xf0) == 0x40) { 71 | opcode = c; 72 | goto error_opcode; 73 | } 74 | } 75 | 76 | if ((hs->opcode = c) == 0x0f) { 77 | hs->opcode2 = c = *p++; 78 | ht += DELTA_OPCODES; 79 | } else if (c >= 0xa0 && c <= 0xa3) { 80 | op64++; 81 | if (pref & PRE_67) 82 | pref |= PRE_66; 83 | else 84 | pref &= ~PRE_66; 85 | } 86 | 87 | opcode = c; 88 | cflags = ht[ht[opcode / 4] + (opcode % 4)]; 89 | 90 | if (cflags == C_ERROR) { 91 | error_opcode: 92 | hs->flags |= F_ERROR | F_ERROR_OPCODE; 93 | cflags = 0; 94 | if ((opcode & -3) == 0x24) 95 | cflags++; 96 | } 97 | 98 | x = 0; 99 | if (cflags & C_GROUP) { 100 | uint16_t t; 101 | t = *(uint16_t *)(ht + (cflags & 0x7f)); 102 | cflags = (uint8_t)t; 103 | x = (uint8_t)(t >> 8); 104 | } 105 | 106 | if (hs->opcode2) { 107 | ht = hde64_table + DELTA_PREFIXES; 108 | if (ht[ht[opcode / 4] + (opcode % 4)] & pref) 109 | hs->flags |= F_ERROR | F_ERROR_OPCODE; 110 | } 111 | 112 | if (cflags & C_MODRM) { 113 | hs->flags |= F_MODRM; 114 | hs->modrm = c = *p++; 115 | hs->modrm_mod = m_mod = c >> 6; 116 | hs->modrm_rm = m_rm = c & 7; 117 | hs->modrm_reg = m_reg = (c & 0x3f) >> 3; 118 | 119 | if (x && ((x << m_reg) & 0x80)) 120 | hs->flags |= F_ERROR | F_ERROR_OPCODE; 121 | 122 | if (!hs->opcode2 && opcode >= 0xd9 && opcode <= 0xdf) { 123 | uint8_t t = opcode - 0xd9; 124 | if (m_mod == 3) { 125 | ht = hde64_table + DELTA_FPU_MODRM + t*8; 126 | t = ht[m_reg] << m_rm; 127 | } else { 128 | ht = hde64_table + DELTA_FPU_REG; 129 | t = ht[t] << m_reg; 130 | } 131 | if (t & 0x80) 132 | hs->flags |= F_ERROR | F_ERROR_OPCODE; 133 | } 134 | 135 | if (pref & PRE_LOCK) { 136 | if (m_mod == 3) { 137 | hs->flags |= F_ERROR | F_ERROR_LOCK; 138 | } else { 139 | uint8_t *table_end, op = opcode; 140 | if (hs->opcode2) { 141 | ht = hde64_table + DELTA_OP2_LOCK_OK; 142 | table_end = ht + DELTA_OP_ONLY_MEM - DELTA_OP2_LOCK_OK; 143 | } else { 144 | ht = hde64_table + DELTA_OP_LOCK_OK; 145 | table_end = ht + DELTA_OP2_LOCK_OK - DELTA_OP_LOCK_OK; 146 | op &= -2; 147 | } 148 | for (; ht != table_end; ht++) 149 | if (*ht++ == op) { 150 | if (!((*ht << m_reg) & 0x80)) 151 | goto no_lock_error; 152 | else 153 | break; 154 | } 155 | hs->flags |= F_ERROR | F_ERROR_LOCK; 156 | no_lock_error: 157 | ; 158 | } 159 | } 160 | 161 | if (hs->opcode2) { 162 | switch (opcode) { 163 | case 0x20: case 0x22: 164 | m_mod = 3; 165 | if (m_reg > 4 || m_reg == 1) 166 | goto error_operand; 167 | else 168 | goto no_error_operand; 169 | case 0x21: case 0x23: 170 | m_mod = 3; 171 | if (m_reg == 4 || m_reg == 5) 172 | goto error_operand; 173 | else 174 | goto no_error_operand; 175 | } 176 | } else { 177 | switch (opcode) { 178 | case 0x8c: 179 | if (m_reg > 5) 180 | goto error_operand; 181 | else 182 | goto no_error_operand; 183 | case 0x8e: 184 | if (m_reg == 1 || m_reg > 5) 185 | goto error_operand; 186 | else 187 | goto no_error_operand; 188 | } 189 | } 190 | 191 | if (m_mod == 3) { 192 | uint8_t *table_end; 193 | if (hs->opcode2) { 194 | ht = hde64_table + DELTA_OP2_ONLY_MEM; 195 | table_end = ht + sizeof(hde64_table) - DELTA_OP2_ONLY_MEM; 196 | } else { 197 | ht = hde64_table + DELTA_OP_ONLY_MEM; 198 | table_end = ht + DELTA_OP2_ONLY_MEM - DELTA_OP_ONLY_MEM; 199 | } 200 | for (; ht != table_end; ht += 2) 201 | if (*ht++ == opcode) { 202 | if (*ht++ & pref && !((*ht << m_reg) & 0x80)) 203 | goto error_operand; 204 | else 205 | break; 206 | } 207 | goto no_error_operand; 208 | } else if (hs->opcode2) { 209 | switch (opcode) { 210 | case 0x50: case 0xd7: case 0xf7: 211 | if (pref & (PRE_NONE | PRE_66)) 212 | goto error_operand; 213 | break; 214 | case 0xd6: 215 | if (pref & (PRE_F2 | PRE_F3)) 216 | goto error_operand; 217 | break; 218 | case 0xc5: 219 | goto error_operand; 220 | } 221 | goto no_error_operand; 222 | } else 223 | goto no_error_operand; 224 | 225 | error_operand: 226 | hs->flags |= F_ERROR | F_ERROR_OPERAND; 227 | no_error_operand: 228 | 229 | c = *p++; 230 | if (m_reg <= 1) { 231 | if (opcode == 0xf6) 232 | cflags |= C_IMM8; 233 | else if (opcode == 0xf7) 234 | cflags |= C_IMM_P66; 235 | } 236 | 237 | switch (m_mod) { 238 | case 0: 239 | if (pref & PRE_67) { 240 | if (m_rm == 6) 241 | disp_size = 2; 242 | } else 243 | if (m_rm == 5) 244 | disp_size = 4; 245 | break; 246 | case 1: 247 | disp_size = 1; 248 | break; 249 | case 2: 250 | disp_size = 2; 251 | if (!(pref & PRE_67)) 252 | disp_size <<= 1; 253 | } 254 | 255 | if (m_mod != 3 && m_rm == 4) { 256 | hs->flags |= F_SIB; 257 | p++; 258 | hs->sib = c; 259 | hs->sib_scale = c >> 6; 260 | hs->sib_index = (c & 0x3f) >> 3; 261 | if ((hs->sib_base = c & 7) == 5 && !(m_mod & 1)) 262 | disp_size = 4; 263 | } 264 | 265 | p--; 266 | switch (disp_size) { 267 | case 1: 268 | hs->flags |= F_DISP8; 269 | hs->disp.disp8 = *p; 270 | break; 271 | case 2: 272 | hs->flags |= F_DISP16; 273 | hs->disp.disp16 = *(uint16_t *)p; 274 | break; 275 | case 4: 276 | hs->flags |= F_DISP32; 277 | hs->disp.disp32 = *(uint32_t *)p; 278 | } 279 | p += disp_size; 280 | } else if (pref & PRE_LOCK) 281 | hs->flags |= F_ERROR | F_ERROR_LOCK; 282 | 283 | if (cflags & C_IMM_P66) { 284 | if (cflags & C_REL32) { 285 | if (pref & PRE_66) { 286 | hs->flags |= F_IMM16 | F_RELATIVE; 287 | hs->imm.imm16 = *(uint16_t *)p; 288 | p += 2; 289 | goto disasm_done; 290 | } 291 | goto rel32_ok; 292 | } 293 | if (op64) { 294 | hs->flags |= F_IMM64; 295 | hs->imm.imm64 = *(uint64_t *)p; 296 | p += 8; 297 | } else if (!(pref & PRE_66)) { 298 | hs->flags |= F_IMM32; 299 | hs->imm.imm32 = *(uint32_t *)p; 300 | p += 4; 301 | } else 302 | goto imm16_ok; 303 | } 304 | 305 | 306 | if (cflags & C_IMM16) { 307 | imm16_ok: 308 | hs->flags |= F_IMM16; 309 | hs->imm.imm16 = *(uint16_t *)p; 310 | p += 2; 311 | } 312 | if (cflags & C_IMM8) { 313 | hs->flags |= F_IMM8; 314 | hs->imm.imm8 = *p++; 315 | } 316 | 317 | if (cflags & C_REL32) { 318 | rel32_ok: 319 | hs->flags |= F_IMM32 | F_RELATIVE; 320 | hs->imm.imm32 = *(uint32_t *)p; 321 | p += 4; 322 | } else if (cflags & C_REL8) { 323 | hs->flags |= F_IMM8 | F_RELATIVE; 324 | hs->imm.imm8 = *p++; 325 | } 326 | 327 | disasm_done: 328 | 329 | if ((hs->len = (uint8_t)(p-(uint8_t *)code)) > 15) { 330 | hs->flags |= F_ERROR | F_ERROR_LENGTH; 331 | hs->len = 15; 332 | } 333 | 334 | return (unsigned int)hs->len; 335 | } 336 | 337 | #endif // defined(_M_X64) || defined(__x86_64__) 338 | -------------------------------------------------------------------------------- /externals/minhook/src/buffer.c: -------------------------------------------------------------------------------- 1 | /* 2 | * MinHook - The Minimalistic API Hooking Library for x64/x86 3 | * Copyright (C) 2009-2017 Tsuda Kageyu. 4 | * All rights reserved. 5 | * 6 | * Redistribution and use in source and binary forms, with or without 7 | * modification, are permitted provided that the following conditions 8 | * are met: 9 | * 10 | * 1. Redistributions of source code must retain the above copyright 11 | * notice, this list of conditions and the following disclaimer. 12 | * 2. Redistributions in binary form must reproduce the above copyright 13 | * notice, this list of conditions and the following disclaimer in the 14 | * documentation and/or other materials provided with the distribution. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 18 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 19 | * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 20 | * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 21 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 22 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 23 | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 24 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 25 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 26 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 | */ 28 | 29 | #include 30 | #include "buffer.h" 31 | 32 | // Size of each memory block. (= page size of VirtualAlloc) 33 | #define MEMORY_BLOCK_SIZE 0x1000 34 | 35 | // Max range for seeking a memory block. (= 1024MB) 36 | #define MAX_MEMORY_RANGE 0x40000000 37 | 38 | // Memory protection flags to check the executable address. 39 | #define PAGE_EXECUTE_FLAGS \ 40 | (PAGE_EXECUTE | PAGE_EXECUTE_READ | PAGE_EXECUTE_READWRITE | PAGE_EXECUTE_WRITECOPY) 41 | 42 | // Memory slot. 43 | typedef struct _MEMORY_SLOT 44 | { 45 | union 46 | { 47 | struct _MEMORY_SLOT *pNext; 48 | UINT8 buffer[MEMORY_SLOT_SIZE]; 49 | }; 50 | } MEMORY_SLOT, *PMEMORY_SLOT; 51 | 52 | // Memory block info. Placed at the head of each block. 53 | typedef struct _MEMORY_BLOCK 54 | { 55 | struct _MEMORY_BLOCK *pNext; 56 | PMEMORY_SLOT pFree; // First element of the free slot list. 57 | UINT usedCount; 58 | } MEMORY_BLOCK, *PMEMORY_BLOCK; 59 | 60 | //------------------------------------------------------------------------- 61 | // Global Variables: 62 | //------------------------------------------------------------------------- 63 | 64 | // First element of the memory block list. 65 | PMEMORY_BLOCK g_pMemoryBlocks; 66 | 67 | //------------------------------------------------------------------------- 68 | VOID InitializeBuffer(VOID) 69 | { 70 | // Nothing to do for now. 71 | } 72 | 73 | //------------------------------------------------------------------------- 74 | VOID UninitializeBuffer(VOID) 75 | { 76 | PMEMORY_BLOCK pBlock = g_pMemoryBlocks; 77 | g_pMemoryBlocks = NULL; 78 | 79 | while (pBlock) 80 | { 81 | PMEMORY_BLOCK pNext = pBlock->pNext; 82 | VirtualFree(pBlock, 0, MEM_RELEASE); 83 | pBlock = pNext; 84 | } 85 | } 86 | 87 | //------------------------------------------------------------------------- 88 | #if defined(_M_X64) || defined(__x86_64__) 89 | static LPVOID FindPrevFreeRegion(LPVOID pAddress, LPVOID pMinAddr, DWORD dwAllocationGranularity) 90 | { 91 | ULONG_PTR tryAddr = (ULONG_PTR)pAddress; 92 | 93 | // Round down to the allocation granularity. 94 | tryAddr -= tryAddr % dwAllocationGranularity; 95 | 96 | // Start from the previous allocation granularity multiply. 97 | tryAddr -= dwAllocationGranularity; 98 | 99 | while (tryAddr >= (ULONG_PTR)pMinAddr) 100 | { 101 | MEMORY_BASIC_INFORMATION mbi; 102 | if (VirtualQuery((LPVOID)tryAddr, &mbi, sizeof(mbi)) == 0) 103 | break; 104 | 105 | if (mbi.State == MEM_FREE) 106 | return (LPVOID)tryAddr; 107 | 108 | if ((ULONG_PTR)mbi.AllocationBase < dwAllocationGranularity) 109 | break; 110 | 111 | tryAddr = (ULONG_PTR)mbi.AllocationBase - dwAllocationGranularity; 112 | } 113 | 114 | return NULL; 115 | } 116 | #endif 117 | 118 | //------------------------------------------------------------------------- 119 | #if defined(_M_X64) || defined(__x86_64__) 120 | static LPVOID FindNextFreeRegion(LPVOID pAddress, LPVOID pMaxAddr, DWORD dwAllocationGranularity) 121 | { 122 | ULONG_PTR tryAddr = (ULONG_PTR)pAddress; 123 | 124 | // Round down to the allocation granularity. 125 | tryAddr -= tryAddr % dwAllocationGranularity; 126 | 127 | // Start from the next allocation granularity multiply. 128 | tryAddr += dwAllocationGranularity; 129 | 130 | while (tryAddr <= (ULONG_PTR)pMaxAddr) 131 | { 132 | MEMORY_BASIC_INFORMATION mbi; 133 | if (VirtualQuery((LPVOID)tryAddr, &mbi, sizeof(mbi)) == 0) 134 | break; 135 | 136 | if (mbi.State == MEM_FREE) 137 | return (LPVOID)tryAddr; 138 | 139 | tryAddr = (ULONG_PTR)mbi.BaseAddress + mbi.RegionSize; 140 | 141 | // Round up to the next allocation granularity. 142 | tryAddr += dwAllocationGranularity - 1; 143 | tryAddr -= tryAddr % dwAllocationGranularity; 144 | } 145 | 146 | return NULL; 147 | } 148 | #endif 149 | 150 | //------------------------------------------------------------------------- 151 | static PMEMORY_BLOCK GetMemoryBlock(LPVOID pOrigin) 152 | { 153 | PMEMORY_BLOCK pBlock; 154 | #if defined(_M_X64) || defined(__x86_64__) 155 | ULONG_PTR minAddr; 156 | ULONG_PTR maxAddr; 157 | 158 | SYSTEM_INFO si; 159 | GetSystemInfo(&si); 160 | minAddr = (ULONG_PTR)si.lpMinimumApplicationAddress; 161 | maxAddr = (ULONG_PTR)si.lpMaximumApplicationAddress; 162 | 163 | // pOrigin ± 512MB 164 | if ((ULONG_PTR)pOrigin > MAX_MEMORY_RANGE && minAddr < (ULONG_PTR)pOrigin - MAX_MEMORY_RANGE) 165 | minAddr = (ULONG_PTR)pOrigin - MAX_MEMORY_RANGE; 166 | 167 | if (maxAddr > (ULONG_PTR)pOrigin + MAX_MEMORY_RANGE) 168 | maxAddr = (ULONG_PTR)pOrigin + MAX_MEMORY_RANGE; 169 | 170 | // Make room for MEMORY_BLOCK_SIZE bytes. 171 | maxAddr -= MEMORY_BLOCK_SIZE - 1; 172 | #endif 173 | 174 | // Look the registered blocks for a reachable one. 175 | for (pBlock = g_pMemoryBlocks; pBlock != NULL; pBlock = pBlock->pNext) 176 | { 177 | #if defined(_M_X64) || defined(__x86_64__) 178 | // Ignore the blocks too far. 179 | if ((ULONG_PTR)pBlock < minAddr || (ULONG_PTR)pBlock >= maxAddr) 180 | continue; 181 | #endif 182 | // The block has at least one unused slot. 183 | if (pBlock->pFree != NULL) 184 | return pBlock; 185 | } 186 | 187 | #if defined(_M_X64) || defined(__x86_64__) 188 | // Alloc a new block above if not found. 189 | { 190 | LPVOID pAlloc = pOrigin; 191 | while ((ULONG_PTR)pAlloc >= minAddr) 192 | { 193 | pAlloc = FindPrevFreeRegion(pAlloc, (LPVOID)minAddr, si.dwAllocationGranularity); 194 | if (pAlloc == NULL) 195 | break; 196 | 197 | pBlock = (PMEMORY_BLOCK)VirtualAlloc( 198 | pAlloc, MEMORY_BLOCK_SIZE, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); 199 | if (pBlock != NULL) 200 | break; 201 | } 202 | } 203 | 204 | // Alloc a new block below if not found. 205 | if (pBlock == NULL) 206 | { 207 | LPVOID pAlloc = pOrigin; 208 | while ((ULONG_PTR)pAlloc <= maxAddr) 209 | { 210 | pAlloc = FindNextFreeRegion(pAlloc, (LPVOID)maxAddr, si.dwAllocationGranularity); 211 | if (pAlloc == NULL) 212 | break; 213 | 214 | pBlock = (PMEMORY_BLOCK)VirtualAlloc( 215 | pAlloc, MEMORY_BLOCK_SIZE, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); 216 | if (pBlock != NULL) 217 | break; 218 | } 219 | } 220 | #else 221 | // In x86 mode, a memory block can be placed anywhere. 222 | pBlock = (PMEMORY_BLOCK)VirtualAlloc( 223 | NULL, MEMORY_BLOCK_SIZE, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); 224 | #endif 225 | 226 | if (pBlock != NULL) 227 | { 228 | // Build a linked list of all the slots. 229 | PMEMORY_SLOT pSlot = (PMEMORY_SLOT)pBlock + 1; 230 | pBlock->pFree = NULL; 231 | pBlock->usedCount = 0; 232 | do 233 | { 234 | pSlot->pNext = pBlock->pFree; 235 | pBlock->pFree = pSlot; 236 | pSlot++; 237 | } while ((ULONG_PTR)pSlot - (ULONG_PTR)pBlock <= MEMORY_BLOCK_SIZE - MEMORY_SLOT_SIZE); 238 | 239 | pBlock->pNext = g_pMemoryBlocks; 240 | g_pMemoryBlocks = pBlock; 241 | } 242 | 243 | return pBlock; 244 | } 245 | 246 | //------------------------------------------------------------------------- 247 | LPVOID AllocateBuffer(LPVOID pOrigin) 248 | { 249 | PMEMORY_SLOT pSlot; 250 | PMEMORY_BLOCK pBlock = GetMemoryBlock(pOrigin); 251 | if (pBlock == NULL) 252 | return NULL; 253 | 254 | // Remove an unused slot from the list. 255 | pSlot = pBlock->pFree; 256 | pBlock->pFree = pSlot->pNext; 257 | pBlock->usedCount++; 258 | #ifdef _DEBUG 259 | // Fill the slot with INT3 for debugging. 260 | memset(pSlot, 0xCC, sizeof(MEMORY_SLOT)); 261 | #endif 262 | return pSlot; 263 | } 264 | 265 | //------------------------------------------------------------------------- 266 | VOID FreeBuffer(LPVOID pBuffer) 267 | { 268 | PMEMORY_BLOCK pBlock = g_pMemoryBlocks; 269 | PMEMORY_BLOCK pPrev = NULL; 270 | ULONG_PTR pTargetBlock = ((ULONG_PTR)pBuffer / MEMORY_BLOCK_SIZE) * MEMORY_BLOCK_SIZE; 271 | 272 | while (pBlock != NULL) 273 | { 274 | if ((ULONG_PTR)pBlock == pTargetBlock) 275 | { 276 | PMEMORY_SLOT pSlot = (PMEMORY_SLOT)pBuffer; 277 | #ifdef _DEBUG 278 | // Clear the released slot for debugging. 279 | memset(pSlot, 0x00, sizeof(*pSlot)); 280 | #endif 281 | // Restore the released slot to the list. 282 | pSlot->pNext = pBlock->pFree; 283 | pBlock->pFree = pSlot; 284 | pBlock->usedCount--; 285 | 286 | // Free if unused. 287 | if (pBlock->usedCount == 0) 288 | { 289 | if (pPrev) 290 | pPrev->pNext = pBlock->pNext; 291 | else 292 | g_pMemoryBlocks = pBlock->pNext; 293 | 294 | VirtualFree(pBlock, 0, MEM_RELEASE); 295 | } 296 | 297 | break; 298 | } 299 | 300 | pPrev = pBlock; 301 | pBlock = pBlock->pNext; 302 | } 303 | } 304 | 305 | //------------------------------------------------------------------------- 306 | BOOL IsExecutableAddress(LPVOID pAddress) 307 | { 308 | MEMORY_BASIC_INFORMATION mi; 309 | VirtualQuery(pAddress, &mi, sizeof(mi)); 310 | 311 | return (mi.State == MEM_COMMIT && (mi.Protect & PAGE_EXECUTE_FLAGS)); 312 | } 313 | -------------------------------------------------------------------------------- /utils/xorstr.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 - 2021 Justas Masiulis 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #ifndef JM_XORSTR_HPP 18 | #define JM_XORSTR_HPP 19 | 20 | #if defined(_M_ARM64) || defined(__aarch64__) || defined(_M_ARM) || defined(__arm__) 21 | #include 22 | #elif defined(_M_X64) || defined(__amd64__) || defined(_M_IX86) || defined(__i386__) 23 | #include 24 | #else 25 | #error Unsupported platform 26 | #endif 27 | 28 | #include 29 | #include 30 | #include 31 | #include 32 | 33 | #define xorstr(str) ::jm::xor_string([]() { return str; }, std::integral_constant{}, std::make_index_sequence<::jm::detail::_buffer_size()>{}) 34 | #define xorstr_(str) xorstr(str).crypt_get() 35 | 36 | #ifdef _MSC_VER 37 | #define XORSTR_FORCEINLINE __forceinline 38 | #else 39 | #define XORSTR_FORCEINLINE __attribute__((always_inline)) inline 40 | #endif 41 | 42 | namespace jm { 43 | 44 | namespace detail { 45 | 46 | template 47 | XORSTR_FORCEINLINE constexpr std::size_t _buffer_size() 48 | { 49 | return ((Size / 16) + (Size % 16 != 0)) * 2; 50 | } 51 | 52 | template 53 | XORSTR_FORCEINLINE constexpr std::uint32_t key4() noexcept 54 | { 55 | std::uint32_t value = Seed; 56 | for (char c : __TIME__) 57 | value = static_cast((value ^ c) * 16777619ull); 58 | return value; 59 | } 60 | 61 | template 62 | XORSTR_FORCEINLINE constexpr std::uint64_t key8() 63 | { 64 | constexpr auto first_part = key4<2166136261 + S>(); 65 | constexpr auto second_part = key4(); 66 | return (static_cast(first_part) << 32) | second_part; 67 | } 68 | 69 | // loads up to 8 characters of string into uint64 and xors it with the key 70 | template 71 | XORSTR_FORCEINLINE constexpr std::uint64_t 72 | load_xored_str8(std::uint64_t key, std::size_t idx, const CharT* str) noexcept 73 | { 74 | using cast_type = typename std::make_unsigned::type; 75 | constexpr auto value_size = sizeof(CharT); 76 | constexpr auto idx_offset = 8 / value_size; 77 | 78 | std::uint64_t value = key; 79 | for (std::size_t i = 0; i < idx_offset && i + idx * idx_offset < N; ++i) 80 | value ^= 81 | (std::uint64_t{ static_cast(str[i + idx * idx_offset]) } 82 | << ((i % idx_offset) * 8 * value_size)); 83 | 84 | return value; 85 | } 86 | 87 | // forces compiler to use registers instead of stuffing constants in rdata 88 | XORSTR_FORCEINLINE std::uint64_t load_from_reg(std::uint64_t value) noexcept 89 | { 90 | #if defined(__clang__) || defined(__GNUC__) 91 | asm("" : "=r"(value) : "0"(value) : ); 92 | return value; 93 | #else 94 | volatile std::uint64_t reg = value; 95 | return reg; 96 | #endif 97 | } 98 | 99 | } // namespace detail 100 | 101 | template 102 | class xor_string; 103 | 104 | template 105 | class xor_string, std::index_sequence> { 106 | #ifndef JM_XORSTR_DISABLE_AVX_INTRINSICS 107 | constexpr static inline std::uint64_t alignment = ((Size > 16) ? 32 : 16); 108 | #else 109 | constexpr static inline std::uint64_t alignment = 16; 110 | #endif 111 | 112 | alignas(alignment) std::uint64_t _storage[sizeof...(Keys)]; 113 | 114 | public: 115 | using value_type = CharT; 116 | using size_type = std::size_t; 117 | using pointer = CharT*; 118 | using const_pointer = const CharT*; 119 | 120 | template 121 | XORSTR_FORCEINLINE xor_string(L l, std::integral_constant, std::index_sequence) noexcept 122 | : _storage{ ::jm::detail::load_from_reg((std::integral_constant(Keys, Indices, l())>::value))... } 123 | {} 124 | 125 | XORSTR_FORCEINLINE constexpr size_type size() const noexcept 126 | { 127 | return Size - 1; 128 | } 129 | 130 | XORSTR_FORCEINLINE void crypt() noexcept 131 | { 132 | // everything is inlined by hand because a certain compiler with a certain linker is _very_ slow 133 | #if defined(__clang__) 134 | alignas(alignment) 135 | std::uint64_t arr[]{ ::jm::detail::load_from_reg(Keys)... }; 136 | std::uint64_t* keys = 137 | (std::uint64_t*)::jm::detail::load_from_reg((std::uint64_t)arr); 138 | #else 139 | alignas(alignment) std::uint64_t keys[]{ ::jm::detail::load_from_reg(Keys)... }; 140 | #endif 141 | 142 | #if defined(_M_ARM64) || defined(__aarch64__) || defined(_M_ARM) || defined(__arm__) 143 | #if defined(__clang__) 144 | ((Indices >= sizeof(_storage) / 16 ? static_cast(0) : __builtin_neon_vst1q_v( 145 | reinterpret_cast(_storage) + Indices * 2, 146 | veorq_u64(__builtin_neon_vld1q_v(reinterpret_cast(_storage) + Indices * 2, 51), 147 | __builtin_neon_vld1q_v(reinterpret_cast(keys) + Indices * 2, 51)), 148 | 51)), ...); 149 | #else // GCC, MSVC 150 | ((Indices >= sizeof(_storage) / 16 ? static_cast(0) : vst1q_u64( 151 | reinterpret_cast(_storage) + Indices * 2, 152 | veorq_u64(vld1q_u64(reinterpret_cast(_storage) + Indices * 2), 153 | vld1q_u64(reinterpret_cast(keys) + Indices * 2)))), ...); 154 | #endif 155 | #elif !defined(JM_XORSTR_DISABLE_AVX_INTRINSICS) 156 | ((Indices >= sizeof(_storage) / 32 ? static_cast(0) : _mm256_store_si256( 157 | reinterpret_cast<__m256i*>(_storage) + Indices, 158 | _mm256_xor_si256( 159 | _mm256_load_si256(reinterpret_cast(_storage) + Indices), 160 | _mm256_load_si256(reinterpret_cast(keys) + Indices)))), ...); 161 | 162 | if constexpr (sizeof(_storage) % 32 != 0) 163 | _mm_store_si128( 164 | reinterpret_cast<__m128i*>(_storage + sizeof...(Keys) - 2), 165 | _mm_xor_si128(_mm_load_si128(reinterpret_cast(_storage + sizeof...(Keys) - 2)), 166 | _mm_load_si128(reinterpret_cast(keys + sizeof...(Keys) - 2)))); 167 | #else 168 | ((Indices >= sizeof(_storage) / 16 ? static_cast(0) : _mm_store_si128( 169 | reinterpret_cast<__m128i*>(_storage) + Indices, 170 | _mm_xor_si128(_mm_load_si128(reinterpret_cast(_storage) + Indices), 171 | _mm_load_si128(reinterpret_cast(keys) + Indices)))), ...); 172 | #endif 173 | } 174 | 175 | XORSTR_FORCEINLINE const_pointer get() const noexcept 176 | { 177 | return reinterpret_cast(_storage); 178 | } 179 | 180 | XORSTR_FORCEINLINE pointer get() noexcept 181 | { 182 | return reinterpret_cast(_storage); 183 | } 184 | 185 | XORSTR_FORCEINLINE pointer crypt_get() noexcept 186 | { 187 | // crypt() is inlined by hand because a certain compiler with a certain linker is _very_ slow 188 | #if defined(__clang__) 189 | alignas(alignment) 190 | std::uint64_t arr[]{ ::jm::detail::load_from_reg(Keys)... }; 191 | std::uint64_t* keys = 192 | (std::uint64_t*)::jm::detail::load_from_reg((std::uint64_t)arr); 193 | #else 194 | alignas(alignment) std::uint64_t keys[]{ ::jm::detail::load_from_reg(Keys)... }; 195 | #endif 196 | 197 | #if defined(_M_ARM64) || defined(__aarch64__) || defined(_M_ARM) || defined(__arm__) 198 | #if defined(__clang__) 199 | ((Indices >= sizeof(_storage) / 16 ? static_cast(0) : __builtin_neon_vst1q_v( 200 | reinterpret_cast(_storage) + Indices * 2, 201 | veorq_u64(__builtin_neon_vld1q_v(reinterpret_cast(_storage) + Indices * 2, 51), 202 | __builtin_neon_vld1q_v(reinterpret_cast(keys) + Indices * 2, 51)), 203 | 51)), ...); 204 | #else // GCC, MSVC 205 | ((Indices >= sizeof(_storage) / 16 ? static_cast(0) : vst1q_u64( 206 | reinterpret_cast(_storage) + Indices * 2, 207 | veorq_u64(vld1q_u64(reinterpret_cast(_storage) + Indices * 2), 208 | vld1q_u64(reinterpret_cast(keys) + Indices * 2)))), ...); 209 | #endif 210 | #elif !defined(JM_XORSTR_DISABLE_AVX_INTRINSICS) 211 | ((Indices >= sizeof(_storage) / 32 ? static_cast(0) : _mm256_store_si256( 212 | reinterpret_cast<__m256i*>(_storage) + Indices, 213 | _mm256_xor_si256( 214 | _mm256_load_si256(reinterpret_cast(_storage) + Indices), 215 | _mm256_load_si256(reinterpret_cast(keys) + Indices)))), ...); 216 | 217 | if constexpr (sizeof(_storage) % 32 != 0) 218 | _mm_store_si128( 219 | reinterpret_cast<__m128i*>(_storage + sizeof...(Keys) - 2), 220 | _mm_xor_si128(_mm_load_si128(reinterpret_cast(_storage + sizeof...(Keys) - 2)), 221 | _mm_load_si128(reinterpret_cast(keys + sizeof...(Keys) - 2)))); 222 | #else 223 | ((Indices >= sizeof(_storage) / 16 ? static_cast(0) : _mm_store_si128( 224 | reinterpret_cast<__m128i*>(_storage) + Indices, 225 | _mm_xor_si128(_mm_load_si128(reinterpret_cast(_storage) + Indices), 226 | _mm_load_si128(reinterpret_cast(keys) + Indices)))), ...); 227 | #endif 228 | 229 | return (pointer)(_storage); 230 | } 231 | }; 232 | 233 | template 234 | xor_string(L l, std::integral_constant, std::index_sequence) -> xor_string< 235 | std::remove_const_t>, 236 | Size, 237 | std::integer_sequence()...>, 238 | std::index_sequence>; 239 | 240 | } // namespace jm 241 | 242 | #endif // include guard -------------------------------------------------------------------------------- /externals/minhook/src/trampoline.c: -------------------------------------------------------------------------------- 1 | /* 2 | * MinHook - The Minimalistic API Hooking Library for x64/x86 3 | * Copyright (C) 2009-2017 Tsuda Kageyu. 4 | * All rights reserved. 5 | * 6 | * Redistribution and use in source and binary forms, with or without 7 | * modification, are permitted provided that the following conditions 8 | * are met: 9 | * 10 | * 1. Redistributions of source code must retain the above copyright 11 | * notice, this list of conditions and the following disclaimer. 12 | * 2. Redistributions in binary form must reproduce the above copyright 13 | * notice, this list of conditions and the following disclaimer in the 14 | * documentation and/or other materials provided with the distribution. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 18 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 19 | * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 20 | * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 21 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 22 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 23 | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 24 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 25 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 26 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 | */ 28 | 29 | #include 30 | 31 | #ifndef ARRAYSIZE 32 | #define ARRAYSIZE(A) (sizeof(A)/sizeof((A)[0])) 33 | #endif 34 | 35 | #if defined(_M_X64) || defined(__x86_64__) 36 | #include "./hde/hde64.h" 37 | typedef hde64s HDE; 38 | #define HDE_DISASM(code, hs) hde64_disasm(code, hs) 39 | #else 40 | #include "./hde/hde32.h" 41 | typedef hde32s HDE; 42 | #define HDE_DISASM(code, hs) hde32_disasm(code, hs) 43 | #endif 44 | 45 | #include "trampoline.h" 46 | #include "buffer.h" 47 | 48 | // Maximum size of a trampoline function. 49 | #if defined(_M_X64) || defined(__x86_64__) 50 | #define TRAMPOLINE_MAX_SIZE (MEMORY_SLOT_SIZE - sizeof(JMP_ABS)) 51 | #else 52 | #define TRAMPOLINE_MAX_SIZE MEMORY_SLOT_SIZE 53 | #endif 54 | 55 | //------------------------------------------------------------------------- 56 | static BOOL IsCodePadding(LPBYTE pInst, UINT size) 57 | { 58 | UINT i; 59 | 60 | if (pInst[0] != 0x00 && pInst[0] != 0x90 && pInst[0] != 0xCC) 61 | return FALSE; 62 | 63 | for (i = 1; i < size; ++i) 64 | { 65 | if (pInst[i] != pInst[0]) 66 | return FALSE; 67 | } 68 | return TRUE; 69 | } 70 | 71 | //------------------------------------------------------------------------- 72 | BOOL CreateTrampolineFunction(PTRAMPOLINE ct) 73 | { 74 | #if defined(_M_X64) || defined(__x86_64__) 75 | CALL_ABS call = { 76 | 0xFF, 0x15, 0x00000002, // FF15 00000002: CALL [RIP+8] 77 | 0xEB, 0x08, // EB 08: JMP +10 78 | 0x0000000000000000ULL // Absolute destination address 79 | }; 80 | JMP_ABS jmp = { 81 | 0xFF, 0x25, 0x00000000, // FF25 00000000: JMP [RIP+6] 82 | 0x0000000000000000ULL // Absolute destination address 83 | }; 84 | JCC_ABS jcc = { 85 | 0x70, 0x0E, // 7* 0E: J** +16 86 | 0xFF, 0x25, 0x00000000, // FF25 00000000: JMP [RIP+6] 87 | 0x0000000000000000ULL // Absolute destination address 88 | }; 89 | #else 90 | CALL_REL call = { 91 | 0xE8, // E8 xxxxxxxx: CALL +5+xxxxxxxx 92 | 0x00000000 // Relative destination address 93 | }; 94 | JMP_REL jmp = { 95 | 0xE9, // E9 xxxxxxxx: JMP +5+xxxxxxxx 96 | 0x00000000 // Relative destination address 97 | }; 98 | JCC_REL jcc = { 99 | 0x0F, 0x80, // 0F8* xxxxxxxx: J** +6+xxxxxxxx 100 | 0x00000000 // Relative destination address 101 | }; 102 | #endif 103 | 104 | UINT8 oldPos = 0; 105 | UINT8 newPos = 0; 106 | ULONG_PTR jmpDest = 0; // Destination address of an internal jump. 107 | BOOL finished = FALSE; // Is the function completed? 108 | #if defined(_M_X64) || defined(__x86_64__) 109 | UINT8 instBuf[16]; 110 | #endif 111 | 112 | ct->patchAbove = FALSE; 113 | ct->nIP = 0; 114 | 115 | do 116 | { 117 | HDE hs; 118 | UINT copySize; 119 | LPVOID pCopySrc; 120 | ULONG_PTR pOldInst = (ULONG_PTR)ct->pTarget + oldPos; 121 | ULONG_PTR pNewInst = (ULONG_PTR)ct->pTrampoline + newPos; 122 | 123 | copySize = HDE_DISASM((LPVOID)pOldInst, &hs); 124 | if (hs.flags & F_ERROR) 125 | return FALSE; 126 | 127 | pCopySrc = (LPVOID)pOldInst; 128 | if (oldPos >= sizeof(JMP_REL)) 129 | { 130 | // The trampoline function is long enough. 131 | // Complete the function with the jump to the target function. 132 | #if defined(_M_X64) || defined(__x86_64__) 133 | jmp.address = pOldInst; 134 | #else 135 | jmp.operand = (UINT32)(pOldInst - (pNewInst + sizeof(jmp))); 136 | #endif 137 | pCopySrc = &jmp; 138 | copySize = sizeof(jmp); 139 | 140 | finished = TRUE; 141 | } 142 | #if defined(_M_X64) || defined(__x86_64__) 143 | else if ((hs.modrm & 0xC7) == 0x05) 144 | { 145 | // Instructions using RIP relative addressing. (ModR/M = 00???101B) 146 | 147 | // Modify the RIP relative address. 148 | PUINT32 pRelAddr; 149 | 150 | // Avoid using memcpy to reduce the footprint. 151 | #ifndef _MSC_VER 152 | memcpy(instBuf, (LPBYTE)pOldInst, copySize); 153 | #else 154 | __movsb(instBuf, (LPBYTE)pOldInst, copySize); 155 | #endif 156 | pCopySrc = instBuf; 157 | 158 | // Relative address is stored at (instruction length - immediate value length - 4). 159 | pRelAddr = (PUINT32)(instBuf + hs.len - ((hs.flags & 0x3C) >> 2) - 4); 160 | *pRelAddr 161 | = (UINT32)((pOldInst + hs.len + (INT32)hs.disp.disp32) - (pNewInst + hs.len)); 162 | 163 | // Complete the function if JMP (FF /4). 164 | if (hs.opcode == 0xFF && hs.modrm_reg == 4) 165 | finished = TRUE; 166 | } 167 | #endif 168 | else if (hs.opcode == 0xE8) 169 | { 170 | // Direct relative CALL 171 | ULONG_PTR dest = pOldInst + hs.len + (INT32)hs.imm.imm32; 172 | #if defined(_M_X64) || defined(__x86_64__) 173 | call.address = dest; 174 | #else 175 | call.operand = (UINT32)(dest - (pNewInst + sizeof(call))); 176 | #endif 177 | pCopySrc = &call; 178 | copySize = sizeof(call); 179 | } 180 | else if ((hs.opcode & 0xFD) == 0xE9) 181 | { 182 | // Direct relative JMP (EB or E9) 183 | ULONG_PTR dest = pOldInst + hs.len; 184 | 185 | if (hs.opcode == 0xEB) // isShort jmp 186 | dest += (INT8)hs.imm.imm8; 187 | else 188 | dest += (INT32)hs.imm.imm32; 189 | 190 | // Simply copy an internal jump. 191 | if ((ULONG_PTR)ct->pTarget <= dest 192 | && dest < ((ULONG_PTR)ct->pTarget + sizeof(JMP_REL))) 193 | { 194 | if (jmpDest < dest) 195 | jmpDest = dest; 196 | } 197 | else 198 | { 199 | #if defined(_M_X64) || defined(__x86_64__) 200 | jmp.address = dest; 201 | #else 202 | jmp.operand = (UINT32)(dest - (pNewInst + sizeof(jmp))); 203 | #endif 204 | pCopySrc = &jmp; 205 | copySize = sizeof(jmp); 206 | 207 | // Exit the function If it is not in the branch 208 | finished = (pOldInst >= jmpDest); 209 | } 210 | } 211 | else if ((hs.opcode & 0xF0) == 0x70 212 | || (hs.opcode & 0xFC) == 0xE0 213 | || (hs.opcode2 & 0xF0) == 0x80) 214 | { 215 | // Direct relative Jcc 216 | ULONG_PTR dest = pOldInst + hs.len; 217 | 218 | if ((hs.opcode & 0xF0) == 0x70 // Jcc 219 | || (hs.opcode & 0xFC) == 0xE0) // LOOPNZ/LOOPZ/LOOP/JECXZ 220 | dest += (INT8)hs.imm.imm8; 221 | else 222 | dest += (INT32)hs.imm.imm32; 223 | 224 | // Simply copy an internal jump. 225 | if ((ULONG_PTR)ct->pTarget <= dest 226 | && dest < ((ULONG_PTR)ct->pTarget + sizeof(JMP_REL))) 227 | { 228 | if (jmpDest < dest) 229 | jmpDest = dest; 230 | } 231 | else if ((hs.opcode & 0xFC) == 0xE0) 232 | { 233 | // LOOPNZ/LOOPZ/LOOP/JCXZ/JECXZ to the outside are not supported. 234 | return FALSE; 235 | } 236 | else 237 | { 238 | UINT8 cond = ((hs.opcode != 0x0F ? hs.opcode : hs.opcode2) & 0x0F); 239 | #if defined(_M_X64) || defined(__x86_64__) 240 | // Invert the condition in x64 mode to simplify the conditional jump logic. 241 | jcc.opcode = 0x71 ^ cond; 242 | jcc.address = dest; 243 | #else 244 | jcc.opcode1 = 0x80 | cond; 245 | jcc.operand = (UINT32)(dest - (pNewInst + sizeof(jcc))); 246 | #endif 247 | pCopySrc = &jcc; 248 | copySize = sizeof(jcc); 249 | } 250 | } 251 | else if ((hs.opcode & 0xFE) == 0xC2) 252 | { 253 | // RET (C2 or C3) 254 | 255 | // Complete the function if not in a branch. 256 | finished = (pOldInst >= jmpDest); 257 | } 258 | 259 | // Can't alter the instruction length in a branch. 260 | if (pOldInst < jmpDest && copySize != hs.len) 261 | return FALSE; 262 | 263 | // Trampoline function is too large. 264 | if ((newPos + copySize) > TRAMPOLINE_MAX_SIZE) 265 | return FALSE; 266 | 267 | // Trampoline function has too many instructions. 268 | if (ct->nIP >= ARRAYSIZE(ct->oldIPs)) 269 | return FALSE; 270 | 271 | ct->oldIPs[ct->nIP] = oldPos; 272 | ct->newIPs[ct->nIP] = newPos; 273 | ct->nIP++; 274 | 275 | // Avoid using memcpy to reduce the footprint. 276 | #ifndef _MSC_VER 277 | memcpy((LPBYTE)ct->pTrampoline + newPos, pCopySrc, copySize); 278 | #else 279 | __movsb((LPBYTE)ct->pTrampoline + newPos, pCopySrc, copySize); 280 | #endif 281 | newPos += copySize; 282 | oldPos += hs.len; 283 | } 284 | while (!finished); 285 | 286 | // Is there enough place for a long jump? 287 | if (oldPos < sizeof(JMP_REL) 288 | && !IsCodePadding((LPBYTE)ct->pTarget + oldPos, sizeof(JMP_REL) - oldPos)) 289 | { 290 | // Is there enough place for a short jump? 291 | if (oldPos < sizeof(JMP_REL_SHORT) 292 | && !IsCodePadding((LPBYTE)ct->pTarget + oldPos, sizeof(JMP_REL_SHORT) - oldPos)) 293 | { 294 | return FALSE; 295 | } 296 | 297 | // Can we place the long jump above the function? 298 | if (!IsExecutableAddress((LPBYTE)ct->pTarget - sizeof(JMP_REL))) 299 | return FALSE; 300 | 301 | if (!IsCodePadding((LPBYTE)ct->pTarget - sizeof(JMP_REL), sizeof(JMP_REL))) 302 | return FALSE; 303 | 304 | ct->patchAbove = TRUE; 305 | } 306 | 307 | #if defined(_M_X64) || defined(__x86_64__) 308 | // Create a relay function. 309 | jmp.address = (ULONG_PTR)ct->pDetour; 310 | 311 | ct->pRelay = (LPBYTE)ct->pTrampoline + newPos; 312 | memcpy(ct->pRelay, &jmp, sizeof(jmp)); 313 | #endif 314 | 315 | return TRUE; 316 | } 317 | -------------------------------------------------------------------------------- /externals/minhook/src/hook.c: -------------------------------------------------------------------------------- 1 | /* 2 | * MinHook - The Minimalistic API Hooking Library for x64/x86 3 | * Copyright (C) 2009-2017 Tsuda Kageyu. 4 | * All rights reserved. 5 | * 6 | * Redistribution and use in source and binary forms, with or without 7 | * modification, are permitted provided that the following conditions 8 | * are met: 9 | * 10 | * 1. Redistributions of source code must retain the above copyright 11 | * notice, this list of conditions and the following disclaimer. 12 | * 2. Redistributions in binary form must reproduce the above copyright 13 | * notice, this list of conditions and the following disclaimer in the 14 | * documentation and/or other materials provided with the distribution. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 18 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 19 | * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 20 | * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 21 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 22 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 23 | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 24 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 25 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 26 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 | */ 28 | 29 | #include 30 | #include 31 | #include 32 | 33 | #include "../include/MinHook.h" 34 | #include "buffer.h" 35 | #include "trampoline.h" 36 | 37 | #ifndef ARRAYSIZE 38 | #define ARRAYSIZE(A) (sizeof(A)/sizeof((A)[0])) 39 | #endif 40 | 41 | // Initial capacity of the HOOK_ENTRY buffer. 42 | #define INITIAL_HOOK_CAPACITY 32 43 | 44 | // Initial capacity of the thread IDs buffer. 45 | #define INITIAL_THREAD_CAPACITY 128 46 | 47 | // Special hook position values. 48 | #define INVALID_HOOK_POS UINT_MAX 49 | #define ALL_HOOKS_POS UINT_MAX 50 | 51 | // Freeze() action argument defines. 52 | #define ACTION_DISABLE 0 53 | #define ACTION_ENABLE 1 54 | #define ACTION_APPLY_QUEUED 2 55 | 56 | // Thread access rights for suspending/resuming threads. 57 | #define THREAD_ACCESS \ 58 | (THREAD_SUSPEND_RESUME | THREAD_GET_CONTEXT | THREAD_QUERY_INFORMATION | THREAD_SET_CONTEXT) 59 | 60 | // Hook information. 61 | typedef struct _HOOK_ENTRY 62 | { 63 | LPVOID pTarget; // Address of the target function. 64 | LPVOID pDetour; // Address of the detour or relay function. 65 | LPVOID pTrampoline; // Address of the trampoline function. 66 | UINT8 backup[8]; // Original prologue of the target function. 67 | 68 | UINT8 patchAbove : 1; // Uses the hot patch area. 69 | UINT8 isEnabled : 1; // Enabled. 70 | UINT8 queueEnable : 1; // Queued for enabling/disabling when != isEnabled. 71 | 72 | UINT nIP : 4; // Count of the instruction boundaries. 73 | UINT8 oldIPs[8]; // Instruction boundaries of the target function. 74 | UINT8 newIPs[8]; // Instruction boundaries of the trampoline function. 75 | } HOOK_ENTRY, *PHOOK_ENTRY; 76 | 77 | // Suspended threads for Freeze()/Unfreeze(). 78 | typedef struct _FROZEN_THREADS 79 | { 80 | LPDWORD pItems; // Data heap 81 | UINT capacity; // Size of allocated data heap, items 82 | UINT size; // Actual number of data items 83 | } FROZEN_THREADS, *PFROZEN_THREADS; 84 | 85 | //------------------------------------------------------------------------- 86 | // Global Variables: 87 | //------------------------------------------------------------------------- 88 | 89 | // Spin lock flag for EnterSpinLock()/LeaveSpinLock(). 90 | volatile LONG g_isLocked = FALSE; 91 | 92 | // Private heap handle. If not NULL, this library is initialized. 93 | HANDLE g_hHeap = NULL; 94 | 95 | // Hook entries. 96 | struct 97 | { 98 | PHOOK_ENTRY pItems; // Data heap 99 | UINT capacity; // Size of allocated data heap, items 100 | UINT size; // Actual number of data items 101 | } g_hooks; 102 | 103 | //------------------------------------------------------------------------- 104 | // Returns INVALID_HOOK_POS if not found. 105 | static UINT FindHookEntry(LPVOID pTarget) 106 | { 107 | UINT i; 108 | for (i = 0; i < g_hooks.size; ++i) 109 | { 110 | if ((ULONG_PTR)pTarget == (ULONG_PTR)g_hooks.pItems[i].pTarget) 111 | return i; 112 | } 113 | 114 | return INVALID_HOOK_POS; 115 | } 116 | 117 | //------------------------------------------------------------------------- 118 | static PHOOK_ENTRY AddHookEntry() 119 | { 120 | if (g_hooks.pItems == NULL) 121 | { 122 | g_hooks.capacity = INITIAL_HOOK_CAPACITY; 123 | g_hooks.pItems = (PHOOK_ENTRY)HeapAlloc( 124 | g_hHeap, 0, g_hooks.capacity * sizeof(HOOK_ENTRY)); 125 | if (g_hooks.pItems == NULL) 126 | return NULL; 127 | } 128 | else if (g_hooks.size >= g_hooks.capacity) 129 | { 130 | PHOOK_ENTRY p = (PHOOK_ENTRY)HeapReAlloc( 131 | g_hHeap, 0, g_hooks.pItems, (g_hooks.capacity * 2) * sizeof(HOOK_ENTRY)); 132 | if (p == NULL) 133 | return NULL; 134 | 135 | g_hooks.capacity *= 2; 136 | g_hooks.pItems = p; 137 | } 138 | 139 | return &g_hooks.pItems[g_hooks.size++]; 140 | } 141 | 142 | //------------------------------------------------------------------------- 143 | static void DeleteHookEntry(UINT pos) 144 | { 145 | if (pos < g_hooks.size - 1) 146 | g_hooks.pItems[pos] = g_hooks.pItems[g_hooks.size - 1]; 147 | 148 | g_hooks.size--; 149 | 150 | if (g_hooks.capacity / 2 >= INITIAL_HOOK_CAPACITY && g_hooks.capacity / 2 >= g_hooks.size) 151 | { 152 | PHOOK_ENTRY p = (PHOOK_ENTRY)HeapReAlloc( 153 | g_hHeap, 0, g_hooks.pItems, (g_hooks.capacity / 2) * sizeof(HOOK_ENTRY)); 154 | if (p == NULL) 155 | return; 156 | 157 | g_hooks.capacity /= 2; 158 | g_hooks.pItems = p; 159 | } 160 | } 161 | 162 | //------------------------------------------------------------------------- 163 | static DWORD_PTR FindOldIP(PHOOK_ENTRY pHook, DWORD_PTR ip) 164 | { 165 | UINT i; 166 | 167 | if (pHook->patchAbove && ip == ((DWORD_PTR)pHook->pTarget - sizeof(JMP_REL))) 168 | return (DWORD_PTR)pHook->pTarget; 169 | 170 | for (i = 0; i < pHook->nIP; ++i) 171 | { 172 | if (ip == ((DWORD_PTR)pHook->pTrampoline + pHook->newIPs[i])) 173 | return (DWORD_PTR)pHook->pTarget + pHook->oldIPs[i]; 174 | } 175 | 176 | #if defined(_M_X64) || defined(__x86_64__) 177 | // Check relay function. 178 | if (ip == (DWORD_PTR)pHook->pDetour) 179 | return (DWORD_PTR)pHook->pTarget; 180 | #endif 181 | 182 | return 0; 183 | } 184 | 185 | //------------------------------------------------------------------------- 186 | static DWORD_PTR FindNewIP(PHOOK_ENTRY pHook, DWORD_PTR ip) 187 | { 188 | UINT i; 189 | for (i = 0; i < pHook->nIP; ++i) 190 | { 191 | if (ip == ((DWORD_PTR)pHook->pTarget + pHook->oldIPs[i])) 192 | return (DWORD_PTR)pHook->pTrampoline + pHook->newIPs[i]; 193 | } 194 | 195 | return 0; 196 | } 197 | 198 | //------------------------------------------------------------------------- 199 | static void ProcessThreadIPs(HANDLE hThread, UINT pos, UINT action) 200 | { 201 | // If the thread suspended in the overwritten area, 202 | // move IP to the proper address. 203 | 204 | CONTEXT c; 205 | #if defined(_M_X64) || defined(__x86_64__) 206 | DWORD64 *pIP = &c.Rip; 207 | #else 208 | DWORD *pIP = &c.Eip; 209 | #endif 210 | UINT count; 211 | 212 | c.ContextFlags = CONTEXT_CONTROL; 213 | if (!GetThreadContext(hThread, &c)) 214 | return; 215 | 216 | if (pos == ALL_HOOKS_POS) 217 | { 218 | pos = 0; 219 | count = g_hooks.size; 220 | } 221 | else 222 | { 223 | count = pos + 1; 224 | } 225 | 226 | for (; pos < count; ++pos) 227 | { 228 | PHOOK_ENTRY pHook = &g_hooks.pItems[pos]; 229 | BOOL enable; 230 | DWORD_PTR ip; 231 | 232 | switch (action) 233 | { 234 | case ACTION_DISABLE: 235 | enable = FALSE; 236 | break; 237 | 238 | case ACTION_ENABLE: 239 | enable = TRUE; 240 | break; 241 | 242 | default: // ACTION_APPLY_QUEUED 243 | enable = pHook->queueEnable; 244 | break; 245 | } 246 | if (pHook->isEnabled == enable) 247 | continue; 248 | 249 | if (enable) 250 | ip = FindNewIP(pHook, *pIP); 251 | else 252 | ip = FindOldIP(pHook, *pIP); 253 | 254 | if (ip != 0) 255 | { 256 | *pIP = ip; 257 | SetThreadContext(hThread, &c); 258 | } 259 | } 260 | } 261 | 262 | //------------------------------------------------------------------------- 263 | static VOID EnumerateThreads(PFROZEN_THREADS pThreads) 264 | { 265 | HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0); 266 | if (hSnapshot != INVALID_HANDLE_VALUE) 267 | { 268 | THREADENTRY32 te; 269 | te.dwSize = sizeof(THREADENTRY32); 270 | if (Thread32First(hSnapshot, &te)) 271 | { 272 | do 273 | { 274 | if (te.dwSize >= (FIELD_OFFSET(THREADENTRY32, th32OwnerProcessID) + sizeof(DWORD)) 275 | && te.th32OwnerProcessID == GetCurrentProcessId() 276 | && te.th32ThreadID != GetCurrentThreadId()) 277 | { 278 | if (pThreads->pItems == NULL) 279 | { 280 | pThreads->capacity = INITIAL_THREAD_CAPACITY; 281 | pThreads->pItems 282 | = (LPDWORD)HeapAlloc(g_hHeap, 0, pThreads->capacity * sizeof(DWORD)); 283 | if (pThreads->pItems == NULL) 284 | break; 285 | } 286 | else if (pThreads->size >= pThreads->capacity) 287 | { 288 | LPDWORD p = (LPDWORD)HeapReAlloc( 289 | g_hHeap, 0, pThreads->pItems, (pThreads->capacity * 2) * sizeof(DWORD)); 290 | if (p == NULL) 291 | break; 292 | 293 | pThreads->capacity *= 2; 294 | pThreads->pItems = p; 295 | } 296 | pThreads->pItems[pThreads->size++] = te.th32ThreadID; 297 | } 298 | 299 | te.dwSize = sizeof(THREADENTRY32); 300 | } while (Thread32Next(hSnapshot, &te)); 301 | } 302 | CloseHandle(hSnapshot); 303 | } 304 | } 305 | 306 | //------------------------------------------------------------------------- 307 | static VOID Freeze(PFROZEN_THREADS pThreads, UINT pos, UINT action) 308 | { 309 | pThreads->pItems = NULL; 310 | pThreads->capacity = 0; 311 | pThreads->size = 0; 312 | EnumerateThreads(pThreads); 313 | 314 | if (pThreads->pItems != NULL) 315 | { 316 | UINT i; 317 | for (i = 0; i < pThreads->size; ++i) 318 | { 319 | HANDLE hThread = OpenThread(THREAD_ACCESS, FALSE, pThreads->pItems[i]); 320 | if (hThread != NULL) 321 | { 322 | SuspendThread(hThread); 323 | ProcessThreadIPs(hThread, pos, action); 324 | CloseHandle(hThread); 325 | } 326 | } 327 | } 328 | } 329 | 330 | //------------------------------------------------------------------------- 331 | static VOID Unfreeze(PFROZEN_THREADS pThreads) 332 | { 333 | if (pThreads->pItems != NULL) 334 | { 335 | UINT i; 336 | for (i = 0; i < pThreads->size; ++i) 337 | { 338 | HANDLE hThread = OpenThread(THREAD_ACCESS, FALSE, pThreads->pItems[i]); 339 | if (hThread != NULL) 340 | { 341 | ResumeThread(hThread); 342 | CloseHandle(hThread); 343 | } 344 | } 345 | 346 | HeapFree(g_hHeap, 0, pThreads->pItems); 347 | } 348 | } 349 | 350 | //------------------------------------------------------------------------- 351 | static MH_STATUS EnableHookLL(UINT pos, BOOL enable) 352 | { 353 | PHOOK_ENTRY pHook = &g_hooks.pItems[pos]; 354 | DWORD oldProtect; 355 | SIZE_T patchSize = sizeof(JMP_REL); 356 | LPBYTE pPatchTarget = (LPBYTE)pHook->pTarget; 357 | 358 | if (pHook->patchAbove) 359 | { 360 | pPatchTarget -= sizeof(JMP_REL); 361 | patchSize += sizeof(JMP_REL_SHORT); 362 | } 363 | 364 | if (!VirtualProtect(pPatchTarget, patchSize, PAGE_EXECUTE_READWRITE, &oldProtect)) 365 | return MH_ERROR_MEMORY_PROTECT; 366 | 367 | if (enable) 368 | { 369 | PJMP_REL pJmp = (PJMP_REL)pPatchTarget; 370 | pJmp->opcode = 0xE9; 371 | pJmp->operand = (UINT32)((LPBYTE)pHook->pDetour - (pPatchTarget + sizeof(JMP_REL))); 372 | 373 | if (pHook->patchAbove) 374 | { 375 | PJMP_REL_SHORT pShortJmp = (PJMP_REL_SHORT)pHook->pTarget; 376 | pShortJmp->opcode = 0xEB; 377 | pShortJmp->operand = (UINT8)(0 - (sizeof(JMP_REL_SHORT) + sizeof(JMP_REL))); 378 | } 379 | } 380 | else 381 | { 382 | if (pHook->patchAbove) 383 | memcpy(pPatchTarget, pHook->backup, sizeof(JMP_REL) + sizeof(JMP_REL_SHORT)); 384 | else 385 | memcpy(pPatchTarget, pHook->backup, sizeof(JMP_REL)); 386 | } 387 | 388 | VirtualProtect(pPatchTarget, patchSize, oldProtect, &oldProtect); 389 | 390 | // Just-in-case measure. 391 | FlushInstructionCache(GetCurrentProcess(), pPatchTarget, patchSize); 392 | 393 | pHook->isEnabled = enable; 394 | pHook->queueEnable = enable; 395 | 396 | return MH_OK; 397 | } 398 | 399 | //------------------------------------------------------------------------- 400 | static MH_STATUS EnableAllHooksLL(BOOL enable) 401 | { 402 | MH_STATUS status = MH_OK; 403 | UINT i, first = INVALID_HOOK_POS; 404 | 405 | for (i = 0; i < g_hooks.size; ++i) 406 | { 407 | if (g_hooks.pItems[i].isEnabled != enable) 408 | { 409 | first = i; 410 | break; 411 | } 412 | } 413 | 414 | if (first != INVALID_HOOK_POS) 415 | { 416 | FROZEN_THREADS threads; 417 | Freeze(&threads, ALL_HOOKS_POS, enable ? ACTION_ENABLE : ACTION_DISABLE); 418 | 419 | for (i = first; i < g_hooks.size; ++i) 420 | { 421 | if (g_hooks.pItems[i].isEnabled != enable) 422 | { 423 | status = EnableHookLL(i, enable); 424 | if (status != MH_OK) 425 | break; 426 | } 427 | } 428 | 429 | Unfreeze(&threads); 430 | } 431 | 432 | return status; 433 | } 434 | 435 | //------------------------------------------------------------------------- 436 | static VOID EnterSpinLock(VOID) 437 | { 438 | SIZE_T spinCount = 0; 439 | 440 | // Wait until the flag is FALSE. 441 | while (InterlockedCompareExchange(&g_isLocked, TRUE, FALSE) != FALSE) 442 | { 443 | // No need to generate a memory barrier here, since InterlockedCompareExchange() 444 | // generates a full memory barrier itself. 445 | 446 | // Prevent the loop from being too busy. 447 | if (spinCount < 32) 448 | Sleep(0); 449 | else 450 | Sleep(1); 451 | 452 | spinCount++; 453 | } 454 | } 455 | 456 | //------------------------------------------------------------------------- 457 | static VOID LeaveSpinLock(VOID) 458 | { 459 | // No need to generate a memory barrier here, since InterlockedExchange() 460 | // generates a full memory barrier itself. 461 | 462 | InterlockedExchange(&g_isLocked, FALSE); 463 | } 464 | 465 | //------------------------------------------------------------------------- 466 | MH_STATUS WINAPI MH_Initialize(VOID) 467 | { 468 | MH_STATUS status = MH_OK; 469 | 470 | EnterSpinLock(); 471 | 472 | if (g_hHeap == NULL) 473 | { 474 | g_hHeap = HeapCreate(0, 0, 0); 475 | if (g_hHeap != NULL) 476 | { 477 | // Initialize the internal function buffer. 478 | InitializeBuffer(); 479 | } 480 | else 481 | { 482 | status = MH_ERROR_MEMORY_ALLOC; 483 | } 484 | } 485 | else 486 | { 487 | status = MH_ERROR_ALREADY_INITIALIZED; 488 | } 489 | 490 | LeaveSpinLock(); 491 | 492 | return status; 493 | } 494 | 495 | //------------------------------------------------------------------------- 496 | MH_STATUS WINAPI MH_Uninitialize(VOID) 497 | { 498 | MH_STATUS status = MH_OK; 499 | 500 | EnterSpinLock(); 501 | 502 | if (g_hHeap != NULL) 503 | { 504 | status = EnableAllHooksLL(FALSE); 505 | if (status == MH_OK) 506 | { 507 | // Free the internal function buffer. 508 | 509 | // HeapFree is actually not required, but some tools detect a false 510 | // memory leak without HeapFree. 511 | 512 | UninitializeBuffer(); 513 | 514 | HeapFree(g_hHeap, 0, g_hooks.pItems); 515 | HeapDestroy(g_hHeap); 516 | 517 | g_hHeap = NULL; 518 | 519 | g_hooks.pItems = NULL; 520 | g_hooks.capacity = 0; 521 | g_hooks.size = 0; 522 | } 523 | } 524 | else 525 | { 526 | status = MH_ERROR_NOT_INITIALIZED; 527 | } 528 | 529 | LeaveSpinLock(); 530 | 531 | return status; 532 | } 533 | 534 | //------------------------------------------------------------------------- 535 | MH_STATUS WINAPI MH_CreateHook(LPVOID pTarget, LPVOID pDetour, LPVOID *ppOriginal) 536 | { 537 | MH_STATUS status = MH_OK; 538 | 539 | EnterSpinLock(); 540 | 541 | if (g_hHeap != NULL) 542 | { 543 | if (IsExecutableAddress(pTarget) && IsExecutableAddress(pDetour)) 544 | { 545 | UINT pos = FindHookEntry(pTarget); 546 | if (pos == INVALID_HOOK_POS) 547 | { 548 | LPVOID pBuffer = AllocateBuffer(pTarget); 549 | if (pBuffer != NULL) 550 | { 551 | TRAMPOLINE ct; 552 | 553 | ct.pTarget = pTarget; 554 | ct.pDetour = pDetour; 555 | ct.pTrampoline = pBuffer; 556 | if (CreateTrampolineFunction(&ct)) 557 | { 558 | PHOOK_ENTRY pHook = AddHookEntry(); 559 | if (pHook != NULL) 560 | { 561 | pHook->pTarget = ct.pTarget; 562 | #if defined(_M_X64) || defined(__x86_64__) 563 | pHook->pDetour = ct.pRelay; 564 | #else 565 | pHook->pDetour = ct.pDetour; 566 | #endif 567 | pHook->pTrampoline = ct.pTrampoline; 568 | pHook->patchAbove = ct.patchAbove; 569 | pHook->isEnabled = FALSE; 570 | pHook->queueEnable = FALSE; 571 | pHook->nIP = ct.nIP; 572 | memcpy(pHook->oldIPs, ct.oldIPs, ARRAYSIZE(ct.oldIPs)); 573 | memcpy(pHook->newIPs, ct.newIPs, ARRAYSIZE(ct.newIPs)); 574 | 575 | // Back up the target function. 576 | 577 | if (ct.patchAbove) 578 | { 579 | memcpy( 580 | pHook->backup, 581 | (LPBYTE)pTarget - sizeof(JMP_REL), 582 | sizeof(JMP_REL) + sizeof(JMP_REL_SHORT)); 583 | } 584 | else 585 | { 586 | memcpy(pHook->backup, pTarget, sizeof(JMP_REL)); 587 | } 588 | 589 | if (ppOriginal != NULL) 590 | *ppOriginal = pHook->pTrampoline; 591 | } 592 | else 593 | { 594 | status = MH_ERROR_MEMORY_ALLOC; 595 | } 596 | } 597 | else 598 | { 599 | status = MH_ERROR_UNSUPPORTED_FUNCTION; 600 | } 601 | 602 | if (status != MH_OK) 603 | { 604 | FreeBuffer(pBuffer); 605 | } 606 | } 607 | else 608 | { 609 | status = MH_ERROR_MEMORY_ALLOC; 610 | } 611 | } 612 | else 613 | { 614 | status = MH_ERROR_ALREADY_CREATED; 615 | } 616 | } 617 | else 618 | { 619 | status = MH_ERROR_NOT_EXECUTABLE; 620 | } 621 | } 622 | else 623 | { 624 | status = MH_ERROR_NOT_INITIALIZED; 625 | } 626 | 627 | LeaveSpinLock(); 628 | 629 | return status; 630 | } 631 | 632 | //------------------------------------------------------------------------- 633 | MH_STATUS WINAPI MH_RemoveHook(LPVOID pTarget) 634 | { 635 | MH_STATUS status = MH_OK; 636 | 637 | EnterSpinLock(); 638 | 639 | if (g_hHeap != NULL) 640 | { 641 | UINT pos = FindHookEntry(pTarget); 642 | if (pos != INVALID_HOOK_POS) 643 | { 644 | if (g_hooks.pItems[pos].isEnabled) 645 | { 646 | FROZEN_THREADS threads; 647 | Freeze(&threads, pos, ACTION_DISABLE); 648 | 649 | status = EnableHookLL(pos, FALSE); 650 | 651 | Unfreeze(&threads); 652 | } 653 | 654 | if (status == MH_OK) 655 | { 656 | FreeBuffer(g_hooks.pItems[pos].pTrampoline); 657 | DeleteHookEntry(pos); 658 | } 659 | } 660 | else 661 | { 662 | status = MH_ERROR_NOT_CREATED; 663 | } 664 | } 665 | else 666 | { 667 | status = MH_ERROR_NOT_INITIALIZED; 668 | } 669 | 670 | LeaveSpinLock(); 671 | 672 | return status; 673 | } 674 | 675 | //------------------------------------------------------------------------- 676 | static MH_STATUS EnableHook(LPVOID pTarget, BOOL enable) 677 | { 678 | MH_STATUS status = MH_OK; 679 | 680 | EnterSpinLock(); 681 | 682 | if (g_hHeap != NULL) 683 | { 684 | if (pTarget == MH_ALL_HOOKS) 685 | { 686 | status = EnableAllHooksLL(enable); 687 | } 688 | else 689 | { 690 | FROZEN_THREADS threads; 691 | UINT pos = FindHookEntry(pTarget); 692 | if (pos != INVALID_HOOK_POS) 693 | { 694 | if (g_hooks.pItems[pos].isEnabled != enable) 695 | { 696 | Freeze(&threads, pos, ACTION_ENABLE); 697 | 698 | status = EnableHookLL(pos, enable); 699 | 700 | Unfreeze(&threads); 701 | } 702 | else 703 | { 704 | status = enable ? MH_ERROR_ENABLED : MH_ERROR_DISABLED; 705 | } 706 | } 707 | else 708 | { 709 | status = MH_ERROR_NOT_CREATED; 710 | } 711 | } 712 | } 713 | else 714 | { 715 | status = MH_ERROR_NOT_INITIALIZED; 716 | } 717 | 718 | LeaveSpinLock(); 719 | 720 | return status; 721 | } 722 | 723 | //------------------------------------------------------------------------- 724 | MH_STATUS WINAPI MH_EnableHook(LPVOID pTarget) 725 | { 726 | return EnableHook(pTarget, TRUE); 727 | } 728 | 729 | //------------------------------------------------------------------------- 730 | MH_STATUS WINAPI MH_DisableHook(LPVOID pTarget) 731 | { 732 | return EnableHook(pTarget, FALSE); 733 | } 734 | 735 | //------------------------------------------------------------------------- 736 | static MH_STATUS QueueHook(LPVOID pTarget, BOOL queueEnable) 737 | { 738 | MH_STATUS status = MH_OK; 739 | 740 | EnterSpinLock(); 741 | 742 | if (g_hHeap != NULL) 743 | { 744 | if (pTarget == MH_ALL_HOOKS) 745 | { 746 | UINT i; 747 | for (i = 0; i < g_hooks.size; ++i) 748 | g_hooks.pItems[i].queueEnable = queueEnable; 749 | } 750 | else 751 | { 752 | UINT pos = FindHookEntry(pTarget); 753 | if (pos != INVALID_HOOK_POS) 754 | { 755 | g_hooks.pItems[pos].queueEnable = queueEnable; 756 | } 757 | else 758 | { 759 | status = MH_ERROR_NOT_CREATED; 760 | } 761 | } 762 | } 763 | else 764 | { 765 | status = MH_ERROR_NOT_INITIALIZED; 766 | } 767 | 768 | LeaveSpinLock(); 769 | 770 | return status; 771 | } 772 | 773 | //------------------------------------------------------------------------- 774 | MH_STATUS WINAPI MH_QueueEnableHook(LPVOID pTarget) 775 | { 776 | return QueueHook(pTarget, TRUE); 777 | } 778 | 779 | //------------------------------------------------------------------------- 780 | MH_STATUS WINAPI MH_QueueDisableHook(LPVOID pTarget) 781 | { 782 | return QueueHook(pTarget, FALSE); 783 | } 784 | 785 | //------------------------------------------------------------------------- 786 | MH_STATUS WINAPI MH_ApplyQueued(VOID) 787 | { 788 | MH_STATUS status = MH_OK; 789 | UINT i, first = INVALID_HOOK_POS; 790 | 791 | EnterSpinLock(); 792 | 793 | if (g_hHeap != NULL) 794 | { 795 | for (i = 0; i < g_hooks.size; ++i) 796 | { 797 | if (g_hooks.pItems[i].isEnabled != g_hooks.pItems[i].queueEnable) 798 | { 799 | first = i; 800 | break; 801 | } 802 | } 803 | 804 | if (first != INVALID_HOOK_POS) 805 | { 806 | FROZEN_THREADS threads; 807 | Freeze(&threads, ALL_HOOKS_POS, ACTION_APPLY_QUEUED); 808 | 809 | for (i = first; i < g_hooks.size; ++i) 810 | { 811 | PHOOK_ENTRY pHook = &g_hooks.pItems[i]; 812 | if (pHook->isEnabled != pHook->queueEnable) 813 | { 814 | status = EnableHookLL(i, pHook->queueEnable); 815 | if (status != MH_OK) 816 | break; 817 | } 818 | } 819 | 820 | Unfreeze(&threads); 821 | } 822 | } 823 | else 824 | { 825 | status = MH_ERROR_NOT_INITIALIZED; 826 | } 827 | 828 | LeaveSpinLock(); 829 | 830 | return status; 831 | } 832 | 833 | //------------------------------------------------------------------------- 834 | MH_STATUS WINAPI MH_CreateHookApiEx( 835 | LPCWSTR pszModule, LPCSTR pszProcName, LPVOID pDetour, 836 | LPVOID *ppOriginal, LPVOID *ppTarget) 837 | { 838 | HMODULE hModule; 839 | LPVOID pTarget; 840 | 841 | hModule = GetModuleHandleW(pszModule); 842 | if (hModule == NULL) 843 | return MH_ERROR_MODULE_NOT_FOUND; 844 | 845 | pTarget = (LPVOID)GetProcAddress(hModule, pszProcName); 846 | if (pTarget == NULL) 847 | return MH_ERROR_FUNCTION_NOT_FOUND; 848 | 849 | if(ppTarget != NULL) 850 | *ppTarget = pTarget; 851 | 852 | return MH_CreateHook(pTarget, pDetour, ppOriginal); 853 | } 854 | 855 | //------------------------------------------------------------------------- 856 | MH_STATUS WINAPI MH_CreateHookApi( 857 | LPCWSTR pszModule, LPCSTR pszProcName, LPVOID pDetour, LPVOID *ppOriginal) 858 | { 859 | return MH_CreateHookApiEx(pszModule, pszProcName, pDetour, ppOriginal, NULL); 860 | } 861 | 862 | //------------------------------------------------------------------------- 863 | const char * WINAPI MH_StatusToString(MH_STATUS status) 864 | { 865 | #define MH_ST2STR(x) \ 866 | case x: \ 867 | return #x; 868 | 869 | switch (status) { 870 | MH_ST2STR(MH_UNKNOWN) 871 | MH_ST2STR(MH_OK) 872 | MH_ST2STR(MH_ERROR_ALREADY_INITIALIZED) 873 | MH_ST2STR(MH_ERROR_NOT_INITIALIZED) 874 | MH_ST2STR(MH_ERROR_ALREADY_CREATED) 875 | MH_ST2STR(MH_ERROR_NOT_CREATED) 876 | MH_ST2STR(MH_ERROR_ENABLED) 877 | MH_ST2STR(MH_ERROR_DISABLED) 878 | MH_ST2STR(MH_ERROR_NOT_EXECUTABLE) 879 | MH_ST2STR(MH_ERROR_UNSUPPORTED_FUNCTION) 880 | MH_ST2STR(MH_ERROR_MEMORY_ALLOC) 881 | MH_ST2STR(MH_ERROR_MEMORY_PROTECT) 882 | MH_ST2STR(MH_ERROR_MODULE_NOT_FOUND) 883 | MH_ST2STR(MH_ERROR_FUNCTION_NOT_FOUND) 884 | } 885 | 886 | #undef MH_ST2STR 887 | 888 | return "(unknown)"; 889 | } 890 | --------------------------------------------------------------------------------