diff --git a/hook.cpp b/hook.cpp deleted file mode 100644 index 3b06168..0000000 --- a/hook.cpp +++ /dev/null @@ -1,42 +0,0 @@ -#include "hook.hpp" - -namespace hook -{ - //--- default constructor - detour::detour(void* addr_to_hook, void* jmp_to_addr) - : hook_addr((std::uintptr_t)addr_to_hook), detour_addr((std::uintptr_t)jmp_to_addr) - { - //finish the shellcode by adding the address to jmp to - *(uintptr_t*)(jmp_code + OFFSET_TO_ADDRESS) = (std::uintptr_t)jmp_to_addr; - //save old bytes - memcpy(org_bytes, (void*)hook_addr, JMP_CODE_SIZE); - //install the hook. - install(); - } - - detour::~detour() - {uninstall();} - - void detour::install() - { - //install the hook. - write_to_readonly((void *)hook_addr, jmp_code, JMP_CODE_SIZE); - hook_installed = true; - } - - void detour::uninstall() - { - //write the original bytes back. - write_to_readonly((void *)hook_addr, org_bytes, JMP_CODE_SIZE); - hook_installed = false; - } - - uintptr_t detour::hook_address() - {return hook_addr;} - - uintptr_t detour::detour_address() - {return detour_addr;} - - bool detour::installed() - {return hook_installed;} -} \ No newline at end of file diff --git a/hook.hpp b/hook.hpp index f22135b..2ff094b 100644 --- a/hook.hpp +++ b/hook.hpp @@ -1,51 +1,97 @@ #pragma once #include #include +#include #include -#define JMP_CODE_SIZE 14 -#define OFFSET_TO_ADDRESS 0x2 +#if _M_IX86 + #define OFFSET_TO_ADDRESS 0x1 +#elif _M_X64 + #define OFFSET_TO_ADDRESS 0x2 +#endif namespace hook { + static void write_to_readonly(void* addr, void* data, int size) + { + DWORD old_flags; + VirtualProtect((LPVOID)addr, size, PAGE_READWRITE, &old_flags); + memcpy((void*)addr, data, size); + VirtualProtect((LPVOID)addr, size, old_flags, &old_flags); + } + class detour { public: - detour(void* addrToHook, void* jmpTo); - ~detour(); - void install(); - void uninstall(); - bool installed(); - uintptr_t hook_address(); - uintptr_t detour_address(); + detour(void* addr_to_hook, void* jmp_to, bool enable = true) + : hook_addr(addr_to_hook), detour_addr(jmp_to) + { + //setup hook + memcpy( + jmp_code + OFFSET_TO_ADDRESS, + &jmp_to, + sizeof(jmp_to) + ); + //save bytes + memcpy( + org_bytes, + hook_addr, + sizeof(org_bytes) + ); + if(enable) + install(); + } + + void install() + { + write_to_readonly(hook_addr, jmp_code, sizeof(jmp_code)); + hook_installed.exchange(true); + } + void uninstall() + { + write_to_readonly(hook_addr, org_bytes, sizeof(org_bytes)); + hook_installed.exchange(false); + } + + ~detour() { uninstall(); } + bool installed() { return hook_installed; } + void* hook_address() { return hook_addr; } + void* detour_address() { return detour_addr; } private: - bool hook_installed{ false }; - uintptr_t hook_addr, detour_addr; - unsigned char jmp_code[JMP_CODE_SIZE] = { - 0x48, 0xb8, //movabs rax, &jmpTo - 0x0, //jmpTo address will be here in these 0's + std::atomic hook_installed{ false }; + void *hook_addr, *detour_addr; + +#if _M_IX86 + /* + 0: b8 ff ff ff ff mov eax, 0xffffffff + 5: ff e0 jmp eax + */ + unsigned char jmp_code[7] = { + 0xb8, 0x0, 0x0, 0x0, 0x0, + 0xFF, 0xE0 + }; +#elif _M_X64 + /* + 0: 48 c7 c0 ff ff ff ff mov rax,0xffffffffffffffff + 7: ff e0 jmp rax + */ + unsigned char jmp_code[12] = { + 0x48, 0xb8, + 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, - 0x0, 0x0, - 0xff, 0xe0, //jmp rax - 0x90, 0x90 //nop, nop + 0x0, + 0x0, + 0xff, 0xe0 }; - char org_bytes[JMP_CODE_SIZE]; +#endif + std::uint8_t org_bytes[sizeof(jmp_code)]; }; - static std::map> hooks{}; - - __forceinline void write_to_readonly(void* addr, void* data, int size) - { - DWORD old_flags; - VirtualProtect((LPVOID)addr, size, PAGE_READWRITE, &old_flags); - memcpy((void*)addr, data, size); - VirtualProtect((LPVOID)addr, size, old_flags, &old_flags); - } + static std::map> hooks{}; /* Author: xerox @@ -53,16 +99,16 @@ namespace hook Create Hook without needing to deal with objects */ - __forceinline void install(void* addr_to_hook, void* jmp_to_addr) { - + static void make_hook(void* addr_to_hook, void* jmp_to_addr, bool enable = true) + { if (!addr_to_hook) return; - hooks.insert({ - (std::uintptr_t)addr_to_hook, + addr_to_hook, std::make_unique( addr_to_hook, - jmp_to_addr + jmp_to_addr, + enable )} ); } @@ -73,11 +119,11 @@ namespace hook Enable hook given the address to hook */ - __forceinline void enable(void* addr) + static void enable(void* addr) { if (!addr) return; - hooks.at((std::uintptr_t)addr)->install(); + hooks.at(addr)->install(); } /* @@ -86,11 +132,11 @@ namespace hook Disable hook givent the address of the hook */ - __forceinline void disable(void* addr) + static void disable(void* addr) { if (!addr) return; - hooks.at((std::uintptr_t)addr)->uninstall(); + hooks.at(addr)->uninstall(); } @@ -100,10 +146,10 @@ namespace hook Remove hook completely from vector */ - __forceinline void remove(void* addr) + static void remove(void* addr) { if (!addr) return; - hooks.erase((std::uintptr_t)addr); + hooks.erase(addr); } } \ No newline at end of file diff --git a/main.cpp b/main.cpp index 3df330f..23e26b9 100644 --- a/main.cpp +++ b/main.cpp @@ -10,33 +10,47 @@ BOOL HookWriteFile( LPOVERLAPPED lpOverlapped ) { - //this will change the output to "shithooked!\n" - - memset((void *)lpBuffer, NULL, nNumberOfBytesToWrite); - memcpy((void*)lpBuffer, "shithooked!?\n", sizeof("shithooked!\n")); + const char* shithooked = "shithooked!?"; hook::disable(&WriteFile); - BOOL result = WriteFile(hFile, lpBuffer, nNumberOfBytesToWrite, lpNumberOfBytesWritten, lpOverlapped); + BOOL result = WriteFile( + hFile, + shithooked, + nNumberOfBytesToWrite, + lpNumberOfBytesWritten, + lpOverlapped + ); hook::enable(&WriteFile); return result; } int main() { - hook::install( + //make hook + hook::make_hook( &WriteFile, - &HookWriteFile + &HookWriteFile, + false // you can choose not to install it yet ); - OFSTRUCT ofstruct; - OpenFile("output.txt", &ofstruct, OF_CREATE); - HFILE result = OpenFile("output.txt", &ofstruct, OF_READWRITE); + //make file + OFSTRUCT ofstruct{}; + auto result = std::unique_ptr, decltype(&CloseHandle)>( + (HANDLE)(OpenFile( + "output.txt", + &ofstruct, + OF_READWRITE | OF_CREATE + )), &CloseHandle + ); - while (true) + if (reinterpret_cast(result.get()) != HFILE_ERROR) { - Sleep(1000); - char aString[] = "Hello world!\n"; - WriteFile((HANDLE)result, aString, sizeof(aString), NULL, NULL); + // we can enable it after we open the file + hook::enable(&WriteFile); + + //write to file + const char aString[] = "Hello world!\n"; + WriteFile(result.get(), aString, sizeof(aString), NULL, NULL); } } diff --git a/shithook.sln b/shithook.sln new file mode 100644 index 0000000..f77b49a --- /dev/null +++ b/shithook.sln @@ -0,0 +1,31 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.29519.181 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "shithook", "shithook.vcxproj", "{E5255EE2-A83E-4455-99E3-B5D236B76D36}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {E5255EE2-A83E-4455-99E3-B5D236B76D36}.Debug|x64.ActiveCfg = Debug|x64 + {E5255EE2-A83E-4455-99E3-B5D236B76D36}.Debug|x64.Build.0 = Debug|x64 + {E5255EE2-A83E-4455-99E3-B5D236B76D36}.Debug|x86.ActiveCfg = Debug|Win32 + {E5255EE2-A83E-4455-99E3-B5D236B76D36}.Debug|x86.Build.0 = Debug|Win32 + {E5255EE2-A83E-4455-99E3-B5D236B76D36}.Release|x64.ActiveCfg = Release|x64 + {E5255EE2-A83E-4455-99E3-B5D236B76D36}.Release|x64.Build.0 = Release|x64 + {E5255EE2-A83E-4455-99E3-B5D236B76D36}.Release|x86.ActiveCfg = Release|Win32 + {E5255EE2-A83E-4455-99E3-B5D236B76D36}.Release|x86.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {8D42E5D0-475A-4EA5-94EA-1ADB1F46CBF1} + EndGlobalSection +EndGlobal diff --git a/shithook.vcxproj b/shithook.vcxproj new file mode 100644 index 0000000..df6c359 --- /dev/null +++ b/shithook.vcxproj @@ -0,0 +1,170 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + + + + + + + 16.0 + {E5255EE2-A83E-4455-99E3-B5D236B76D36} + Win32Proj + shithook + 10.0 + + + + Application + true + v142 + Unicode + false + + + Application + false + v142 + true + Unicode + false + + + Application + true + v142 + Unicode + false + + + Application + false + v142 + true + Unicode + false + + + + + + + + + + + + + + + + + + + + + true + + + true + $(SolutionDir)$(Configuration)\ + $(Configuration)\ + + + false + + + false + $(SolutionDir)$(Configuration)\ + $(Configuration)\ + + + + + + Level3 + true + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + stdcpp17 + + + Console + true + + + + + + + Level3 + true + _DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + stdcpp17 + + + Console + true + + + + + + + Level3 + true + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + stdcpp17 + + + Console + true + true + true + + + + + + + Level3 + true + true + true + NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + stdcpp17 + + + Console + true + true + true + + + + + + \ No newline at end of file diff --git a/shithook.vcxproj.filters b/shithook.vcxproj.filters new file mode 100644 index 0000000..8d61e76 --- /dev/null +++ b/shithook.vcxproj.filters @@ -0,0 +1,23 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;hm;inl;inc;ipp;xsd + + + + + Source Files + + + + + Header Files + + + \ No newline at end of file diff --git a/shithook.vcxproj.user b/shithook.vcxproj.user new file mode 100644 index 0000000..88a5509 --- /dev/null +++ b/shithook.vcxproj.user @@ -0,0 +1,4 @@ + + + + \ No newline at end of file