From 3a9ab5424007633d14abc960e3b16e2340027d4b Mon Sep 17 00:00:00 2001 From: Daniel Seiller Date: Mon, 4 Mar 2019 15:11:47 +0100 Subject: [PATCH] Update Notes Clean up DLL-Injector code Fix Crash in DX8 EndScene Hook Update Hook.c to change whole page protection instead of first few bytes Add Hashtable parser and dumper Add keyboard shortcut to toggle DX8 overlay Add VMT Hooking (currently not working) Add Cleanup function that gets called on DLL-Unload --- NOTES.md | 3 +- ScrapHacks/Injector/Injector/Injector.cpp | 62 ++++++------- ScrapHacks/ScrapHack/D3D8_Hook.h | 83 ++++++++++------- ScrapHacks/ScrapHack/Hook.h | 35 ++++--- ScrapHacks/ScrapHack/ScrapHack.cpp | 67 +++++++++++--- ScrapHacks/ScrapHack/ScrapHack.vcxproj | 1 + .../ScrapHack/ScrapHack.vcxproj.filters | 3 + ScrapHacks/ScrapHack/Scrapland.h | 2 + ScrapHacks/ScrapHack/Structures.h | 18 +++- ScrapHacks/ScrapHack/VMT_Hook.h | 91 +++++++++++++++++++ ScrapHacks/ScrapHack/dllmain.cpp | 4 + ScrapHacks/Scrapland_Tools.sln | 6 ++ 12 files changed, 275 insertions(+), 100 deletions(-) create mode 100644 ScrapHacks/ScrapHack/VMT_Hook.h diff --git a/NOTES.md b/NOTES.md index 2ac61ba..59243ca 100644 --- a/NOTES.md +++ b/NOTES.md @@ -65,7 +65,7 @@ Points to GameState struct ## Entity Hash Table -Hashfunction used: [strhash](http://www.cs.ecu.edu/karl/3300/spr16/Notes/DataStructure/hashtable.html) +Hashfunction used: [PJW](https://en.wikipedia.org/wiki/PJW_hash_function) (Same parameters as the example implementation) Entry format: @@ -81,6 +81,7 @@ Data format: | ------ | ----------- | -------------------- | | 0x0 | void** | Virtual Method Table | | 0x4 | const char* | name as string | +| 0x14 | void* | pointer to self | | 0x28 | float[3] | Position | # File Formats diff --git a/ScrapHacks/Injector/Injector/Injector.cpp b/ScrapHacks/Injector/Injector/Injector.cpp index f235d2c..040a863 100644 --- a/ScrapHacks/Injector/Injector/Injector.cpp +++ b/ScrapHacks/Injector/Injector/Injector.cpp @@ -156,7 +156,7 @@ bool Injected(DWORD PID) return HasModule(PID, DLL_NAME); } -void InjectDll(DWORD PID, bool do_resume = false) +void InjectDll(DWORD PID) { HANDLE hRemThread, hProc; const char *dll_name = DLL_NAME; @@ -175,42 +175,34 @@ void InjectDll(DWORD PID, bool do_resume = false) if (HasModule(PID, dll_name)) { cout << "[*] DLL already Loaded" << endl; - } - else + CloseHandle(hProc); + return; + }; + if (!fexists(dll_full_path)) { - if (!fexists(dll_full_path)) - { - cout << "[!] DLL file not found!" << endl; - return; - } - HINSTANCE hK32 = LoadLibraryA("kernel32"); - cout << "[*] Getting Address of LoadLibrary" << endl; - LPVOID LoadLibrary_Address = (LPVOID)GetProcAddress(hK32, "LoadLibraryA"); - FreeLibrary(hK32); - cout << "[+] LoadLibrary is at " << LoadLibrary_Address << endl; - cout << "[*] Allocating " << strlen(dll_full_path) << " Bytes of Memory" << endl; - LPVOID mem = VirtualAllocEx(hProc, NULL, strlen(dll_full_path), MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); - if (mem == NULL) - { - cout << "[!] Could not Allocate Memory: " << GetLastErrorAsString() << endl; - return; - } - cout << "[*] Writing DLL Name to Process Memory at " << mem << endl; - WriteProcessMemory(hProc, mem, dll_full_path, strlen(dll_full_path), 0); - cout << "[*] Creating Thread to Load DLL" << endl; - if (do_resume) - { - hRemThread = CreateRemoteThread(hProc, 0, 0, (LPTHREAD_START_ROUTINE)LoadLibrary_Address, mem, CREATE_SUSPENDED, 0); - ResumeThread(hRemThread); - } - else - { - hRemThread = CreateRemoteThread(hProc, 0, 0, (LPTHREAD_START_ROUTINE)LoadLibrary_Address, mem, 0, 0); - } - cout << "[*] Waiting for DLL to load" << endl; - WaitForSingleObject(hRemThread, INFINITE); - CloseHandle(hRemThread); + cout << "[!] DLL file not found!" << endl; + CloseHandle(hProc); + return; } + HINSTANCE hK32 = LoadLibraryA("kernel32"); + cout << "[*] Getting Address of LoadLibrary" << endl; + LPVOID LoadLibrary_Address = (LPVOID)GetProcAddress(hK32, "LoadLibraryA"); + FreeLibrary(hK32); + cout << "[+] LoadLibrary is at " << LoadLibrary_Address << endl; + cout << "[*] Allocating " << strlen(dll_full_path) << " Bytes of Memory" << endl; + LPVOID mem = VirtualAllocEx(hProc, NULL, strlen(dll_full_path), MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); + if (mem == NULL) + { + cout << "[!] Could not Allocate Memory: " << GetLastErrorAsString() << endl; + return; + } + cout << "[*] Writing DLL Name to Process Memory at " << mem << endl; + WriteProcessMemory(hProc, mem, dll_full_path, strlen(dll_full_path), 0); + cout << "[*] Creating Thread to Load DLL" << endl; + hRemThread = CreateRemoteThread(hProc, 0, 0, (LPTHREAD_START_ROUTINE)LoadLibrary_Address, mem, 0, 0); + cout << "[*] Waiting for DLL to load" << endl; + WaitForSingleObject(hRemThread, INFINITE); + CloseHandle(hRemThread); cout << "[*] Closing Process Handle" << endl; CloseHandle(hProc); return; diff --git a/ScrapHacks/ScrapHack/D3D8_Hook.h b/ScrapHacks/ScrapHack/D3D8_Hook.h index 6f760fe..7b658f0 100644 --- a/ScrapHacks/ScrapHack/D3D8_Hook.h +++ b/ScrapHacks/ScrapHack/D3D8_Hook.h @@ -5,72 +5,89 @@ uintmax_t frame = 0; DWORD* GetVTable(void* addr) { return (DWORD*)(*(DWORD*)addr); } +bool overlay = false; +LPD3DXFONT m_pFont; +HFONT hFont; +HBRUSH hBrush; +D3DCOLOR color = D3DCOLOR_XRGB(255, 0, 0); +RECT Rect = { 0,0,0,0 }; +D3DRECT panel; void Render(LPDIRECT3DDEVICE8 dev) { - char text[MAX_PATH]; - LPD3DXFONT m_pFont; - HFONT hFont; - RECT Rect={0,0,0,0}; - D3DCOLOR color = D3DCOLOR_XRGB(255, 0, 0); - hFont = CreateFont(50, 0, 0, 0, FW_BOLD, 0, 0, 0, ANSI_CHARSET, 0, 0, 0, 0, "Verdana"); - D3DXCreateFont(dev, hFont, &m_pFont); - snprintf(text, MAX_PATH, "Frame: %d", ++frame); - if (m_pFont) { - m_pFont->Begin(); - m_pFont->DrawTextA(text, -1, &Rect, DT_CALCRECT, 0); - m_pFont->DrawTextA(text, -1, &Rect, DT_LEFT, color); - m_pFont->End(); - m_pFont->Release(); - m_pFont = nullptr; + if (!overlay) { + return; } - + char text[MAX_PATH]; + snprintf(text, MAX_PATH, "Frame: [%lld]\nTest", ++frame); + if (m_pFont == nullptr) { + D3DXCreateFont(dev, hFont, &m_pFont); + CloseHandle(hFont); + } + m_pFont->Begin(); + m_pFont->DrawTextA(text, -1, &Rect, DT_CALCRECT, 0); + + dev->Clear(0, NULL, D3DCLEAR_ZBUFFER, D3DCOLOR_ARGB(25, 0, 0, 0),0.5,0); + + m_pFont->DrawTextA(text, -1, &Rect, DT_LEFT, color); + m_pFont->End(); } HRESULT WINAPI H_EndScene(LPDIRECT3DDEVICE8 dev) { typedef HRESULT(WINAPI *t_func)(LPDIRECT3DDEVICE8); shared_ptr hook = Hook::get(H_EndScene); - t_func func = reinterpret_cast(hook->func()); + _asm push esi; + _asm pushad; Render(dev); hook->disable(); - HRESULT ret = func(dev); + HRESULT ret = hook->func()(dev); hook->enable(); + _asm popad; + _asm pop esi; return ret; - } HRESULT WINAPI H_CreateDevice(void* pDirect3D, unsigned int uiAdapter, D3DDEVTYPE pDeviceType, HWND hFocusWindow, unsigned long ulBehaviorFlags, D3DPRESENT_PARAMETERS* pPresentationParameters, LPDIRECT3DDEVICE8* ppReturnedDeviceInterface) { + _asm push esi; + _asm pushad; typedef HRESULT(WINAPI *t_func)(void*, unsigned int, D3DDEVTYPE, HWND, unsigned long, D3DPRESENT_PARAMETERS*, LPDIRECT3DDEVICE8*); shared_ptr hook = Hook::get(H_CreateDevice); - t_func func = reinterpret_cast(hook->func()); hook->disable(); - HRESULT ret = func(pDirect3D, uiAdapter, pDeviceType, hFocusWindow, ulBehaviorFlags, pPresentationParameters, ppReturnedDeviceInterface); - cout << "Ret:" << ret << endl; - DWORD *vtable = GetVTable(ppReturnedDeviceInterface[0]); - cout << "Dev VTable @ " << vtable << endl; - cout << "Dev VTable[35]: " << (void*)(vtable[35]) << endl; // EndScene - Hook::addr((void*)vtable[35], H_EndScene); + HRESULT ret = hook->func()(pDirect3D, uiAdapter, pDeviceType, hFocusWindow, ulBehaviorFlags, pPresentationParameters, ppReturnedDeviceInterface); + cout << "CreateDevice ->" << ret << endl; + void* EndScene = reinterpret_cast(GetVTable(ppReturnedDeviceInterface[0])[35]); + cout << "EndScene @ " << EndScene << endl; // EndScene + Hook::addr(EndScene, H_EndScene); Hook::drop(H_CreateDevice); + _asm popad; + _asm pop esi; + return ret; } LPDIRECT3D8 WINAPI H_Direct3DCreate8(unsigned int SDKVersion) { typedef LPDIRECT3D8(_stdcall *t_func)(unsigned int); shared_ptr hook = Hook::get(H_Direct3DCreate8); - t_func func = reinterpret_cast(hook->func()); + + _asm push esi; + _asm pushad; + hook->disable(); - D3DPRESENT_PARAMETERS D3D_Present_Param = { 0,0,D3DFMT_UNKNOWN,0,D3DMULTISAMPLE_NONE,D3DSWAPEFFECT_DISCARD,0,1,0,D3DFMT_UNKNOWN,0,0,0 }; - LPDIRECT3D8 ret = func(SDKVersion); + LPDIRECT3D8 ret = hook->func()(SDKVersion); cout << "D3D8-Create: " << SDKVersion << " -> " << ret << endl; - DWORD *vtable = GetVTable(ret); - cout << "ID3D8 VTable @ " << vtable << endl; - cout << "ID3D8 VTable[15]: " << (void*)(vtable[15]) << endl; // CreateDevice - Hook::addr((void*)vtable[15], reinterpret_cast(H_CreateDevice)); + void *CreateDevice = reinterpret_cast(GetVTable(ret)[15]); + cout << "CreateDevice @ " << CreateDevice << endl; // CreateDevice + Hook::addr(CreateDevice, H_CreateDevice); Hook::drop(H_Direct3DCreate8); + _asm popad; + _asm pop esi; + return ret; } void hook_d3d8() { + hFont = CreateFont(20, 0, 0, 0, FW_BOLD, 0, 0, 0, ANSI_CHARSET, 0, 0, 0, 0, "Verdana"); + hBrush = CreateSolidBrush(D3DCOLOR_ARGB(25, 0, 0, 0)); Hook::module("d3d8.dll","Direct3DCreate8", H_Direct3DCreate8); } diff --git a/ScrapHacks/ScrapHack/Hook.h b/ScrapHacks/ScrapHack/Hook.h index bf675f0..64e719e 100644 --- a/ScrapHacks/ScrapHack/Hook.h +++ b/ScrapHacks/ScrapHack/Hook.h @@ -1,19 +1,18 @@ #pragma once #include -class Hook; - class Hook { private: - DWORD protect; + MEMORY_BASIC_INFORMATION mbi; void* orig; void* detour; bool enabled; uint8_t orig_bytes[6]; uint8_t jmp_bytes[6]; static map> hooks; - + public: + Hook(void* func, void* detour) { uintptr_t dest = reinterpret_cast(detour); uintptr_t src = reinterpret_cast(func); @@ -25,16 +24,18 @@ public: this->jmp_bytes[3] = (dest >> 16) & 0xff; this->jmp_bytes[4] = (dest >> 24) & 0xff; this->jmp_bytes[5] = 0xC3; // ret - VirtualProtect(func, 16, PAGE_EXECUTE_READWRITE, &(this->protect)); + VirtualQuery(func, &mbi, sizeof(mbi)); + VirtualProtect(mbi.BaseAddress, mbi.RegionSize, PAGE_EXECUTE_READWRITE, &mbi.Protect); memcpy(this->orig_bytes, this->orig, 1 + 4 + 1); - VirtualProtect(func, 16, this->protect, NULL); + VirtualProtect(mbi.BaseAddress, mbi.RegionSize, mbi.Protect, NULL); this->enabled = false; } ~Hook() { + cout << "Unhooking: [" << this->orig << " <- " << this->detour << "]" << endl; this->disable(); } - + static void addr(void* addr, void* detour) { cout << "Hooking: [" << addr << " -> " << detour <<"]" << endl; uintptr_t key = reinterpret_cast(detour); @@ -72,31 +73,35 @@ public: } static void clear() { + cout << "Clearing Hooks" << endl; + for (pair> h : hooks) { + h.second->disable(); + } return hooks.clear(); } - void disable() { if (enabled) { //cout << "Disabling: [" << this->orig << " <- " << this->detour << "]" << endl; - VirtualProtect(this->orig, 16, PAGE_EXECUTE_READWRITE, NULL); + VirtualProtect(mbi.BaseAddress, mbi.RegionSize, PAGE_EXECUTE_READWRITE, NULL); memcpy(this->orig, this->orig_bytes, 1 + 4 + 1); - VirtualProtect(this->orig, 16, this->protect, NULL); + VirtualProtect(mbi.BaseAddress, mbi.RegionSize, mbi.Protect, NULL); enabled = false; } } void enable() { if (!enabled) { //cout << "Enabling: [" << this->orig << " -> " << this->detour << "]" << endl; - VirtualProtect(this->orig, 16, PAGE_EXECUTE_READWRITE, NULL); + VirtualProtect(mbi.BaseAddress, mbi.RegionSize, PAGE_EXECUTE_READWRITE, NULL); memcpy(this->orig, this->jmp_bytes, 1 + 4 + 1); - VirtualProtect(this->orig, 16, this->protect, NULL); + VirtualProtect(mbi.BaseAddress, mbi.RegionSize, mbi.Protect, NULL); enabled = true; } } - - void* func() { - return this->orig; + + template + T func() { + return reinterpret_cast(this->orig); } }; diff --git a/ScrapHacks/ScrapHack/ScrapHack.cpp b/ScrapHacks/ScrapHack/ScrapHack.cpp index 8c2ecd5..409011c 100644 --- a/ScrapHacks/ScrapHack/ScrapHack.cpp +++ b/ScrapHacks/ScrapHack/ScrapHack.cpp @@ -22,6 +22,7 @@ using namespace std; #include "Structures.h" #include "Py_Utils.h" #include "Hook.h" +#include "VMT_Hook.h" #include "D3D8_Hook.h" HMODULE hD3D8Dll = 0; @@ -30,29 +31,58 @@ bool initialized = false; bool running = true; HMODULE mod = 0; +void dump_ht(HashTable* ht) { + size_t cnt = 0; + for (size_t i = 0; i < ht->size; ++i) { + HashTableEntry* ent = ht->chains[i]; + if (ent != NULL) { + cout << i << ": "; + while (ent != NULL) { + ++cnt; + cout << ent->name; + if (ent->next) { + cout << " -> "; + }; + ent = ent->next; + } + cout << endl; + } + } + cout << cnt << " Entities" << endl; + return; +} + void MainLoop(HMODULE mod) { Sleep(100); cout << "[*] Starting main Loop" << endl; cout << endl; cout << "[F3 ] Unload ScrapHacks" << endl; + cout << "[F5 ] Show Overlay" << endl; cout << "[F6 ] Show Alarm status" << endl; cout << "[F7 ] Set Money to 0x7fffffff" << endl; cout << "[F8 ] Dump python modules" << endl; + cout << "[F9 ] Dump Entity hashtable" << endl; cout << "[F10] Enable python tracing" << endl; cout << "[ F ] \"Handbrake\" (*Will* crash the game after some time!)" << endl; while (running) { Sleep(100); - if (key_down_norepeat(VK_F10)) - { - scrap_exec("dbg.settrace()"); - } + while (key_down('F')) { scrap_exec("dbg.brake()"); } + if (key_down_norepeat(VK_F3)) + { + break; + } + + if (key_down_norepeat(VK_F5)) + { + overlay = !overlay; + } if (key_down_norepeat(VK_F6)) { @@ -75,17 +105,16 @@ void MainLoop(HMODULE mod) } } } - if (key_down_norepeat(VK_F3)) + + if (key_down_norepeat(VK_F9)) { + HashTable *ht = ptr(P_WORLD,O_HASHTABLE); + dump_ht(ht); + } + if (key_down_norepeat(VK_F10)) { - break; + scrap_exec("dbg.settrace()"); } } - SetConsoleCtrlHandler(NULL, false); - Hook::clear(); - scrap_log(0xff0000, "ScrapHacks unloaded!\n"); - cout << "[+] ScrapHacks unloaded, you can now close the console!" << endl; - FreeConsole(); - PostQuitMessage(0); FreeLibraryAndExitThread(mod, 0); } @@ -107,13 +136,12 @@ void handle_command(const char* cmd) { int hooked_console(const char* cmd) { typedef int(_cdecl *t_func)(const char*); shared_ptr hook = Hook::get(hooked_console); - t_func func= reinterpret_cast(hook->func()); if (cmd[0] == '$') { handle_command(++cmd); return 0; } hook->disable(); - int ret=func(cmd); + int ret= hook->func()(cmd); hook->enable(); return ret; } @@ -122,7 +150,6 @@ void hook_console() { Hook::addr(reinterpret_cast(P_CON_HANDLER) , hooked_console); } - void DllPreInit(HMODULE _mod) { char mfn[1024]; InitConsole(); @@ -151,4 +178,14 @@ void DllInit(HMODULE _mod) DispatchMessage(&msg); } return; +} + +void DllUnload(HMODULE _mod) { + SetConsoleCtrlHandler(NULL, false); + Hook::clear(); + scrap_log(0xff0000, "ScrapHacks unloaded!\n"); + cout << "[+] ScrapHacks unloaded, you can now close the console!" << endl; + FreeConsole(); + PostQuitMessage(0); + return; } \ No newline at end of file diff --git a/ScrapHacks/ScrapHack/ScrapHack.vcxproj b/ScrapHacks/ScrapHack/ScrapHack.vcxproj index 6d983f1..31c19a7 100644 --- a/ScrapHacks/ScrapHack/ScrapHack.vcxproj +++ b/ScrapHacks/ScrapHack/ScrapHack.vcxproj @@ -154,6 +154,7 @@ + diff --git a/ScrapHacks/ScrapHack/ScrapHack.vcxproj.filters b/ScrapHacks/ScrapHack/ScrapHack.vcxproj.filters index 962bf28..042a2e6 100644 --- a/ScrapHacks/ScrapHack/ScrapHack.vcxproj.filters +++ b/ScrapHacks/ScrapHack/ScrapHack.vcxproj.filters @@ -39,6 +39,9 @@ Headerdateien + + Headerdateien + diff --git a/ScrapHacks/ScrapHack/Scrapland.h b/ScrapHacks/ScrapHack/Scrapland.h index a55cd3f..08d6b44 100644 --- a/ScrapHacks/ScrapHack/Scrapland.h +++ b/ScrapHacks/ScrapHack/Scrapland.h @@ -1,8 +1,10 @@ #pragma once + //OFFSETS #define O_MONEY 0x2090 #define O_ALARM 0x1C6C #define O_ALARM_GROW 0x1C68 +#define O_HASHTABLE 0x4 //POINTERS #define P_WORLD 0x7FE944 diff --git a/ScrapHacks/ScrapHack/Structures.h b/ScrapHacks/ScrapHack/Structures.h index 850f63b..df3affb 100644 --- a/ScrapHacks/ScrapHack/Structures.h +++ b/ScrapHacks/ScrapHack/Structures.h @@ -1,5 +1,5 @@ #pragma once - +struct HashTableEntry; struct Vector3 { float x; float y; @@ -32,3 +32,19 @@ struct Module PyMod *mod; map methods; }; + +struct Entity { + void* VMT; + +}; + +struct HashTable { + uint32_t size; + HashTableEntry** chains; +}; + +struct HashTableEntry { + Entity* data; + const char* name; + HashTableEntry* next; +}; \ No newline at end of file diff --git a/ScrapHacks/ScrapHack/VMT_Hook.h b/ScrapHacks/ScrapHack/VMT_Hook.h new file mode 100644 index 0000000..1759cc8 --- /dev/null +++ b/ScrapHacks/ScrapHack/VMT_Hook.h @@ -0,0 +1,91 @@ + +#pragma once +class VMT_Hook +{ +private: + MEMORY_BASIC_INFORMATION mbi; + void* orig; + void* detour; + DWORD* vtable; + size_t ord; + bool enabled; + static map> hooks; + static DWORD* GetVTable(void* addr) { + return (DWORD *)*(DWORD *)addr; + }; + + +public: + + VMT_Hook(void* obj, size_t ord, void* detour) { + this->vtable = GetVTable(obj); + this->detour = detour; + this->orig = reinterpret_cast(vtable[ord]); + this->ord = ord; + this->enabled = false; + + VirtualQuery(&this->vtable[this->ord], &mbi, sizeof(mbi)); + cout << "Hooking: " << this->vtable << "[" << this->ord << "]: (" << this->orig << " -> " << this->detour << ")" << endl; + } + + ~VMT_Hook() { + cout << "Unhooking: " << this->vtable << "[" << this->ord << "]: (" << this->orig << " -> " << this->detour << ")" << endl; + this->disable(); + } + + static void create(void* obj, size_t ord, void* detour) { + uintptr_t key = reinterpret_cast(detour); + hooks[key] = make_shared(obj,ord, detour); + hooks[key]->enable(); + } + + static shared_ptr get(void* func) { + uintptr_t addr = reinterpret_cast(func); + return VMT_Hook::get(addr); + } + + static shared_ptr get(uintptr_t addr) { + return hooks.at(addr); + } + + static size_t drop(void* func) { + uintptr_t addr = reinterpret_cast(func); + return VMT_Hook::drop(addr); + } + + static size_t drop(uintptr_t addr) { + return hooks.erase(addr); + } + + static void clear() { + return hooks.clear(); + } + + void disable() { + if (enabled) { + cout << "Disabling: " << this->vtable << "[" << this->ord << "]: (" << this->orig << " -> " << this->detour<<")" << endl; + VirtualProtect(mbi.BaseAddress, mbi.RegionSize, PAGE_EXECUTE_READWRITE, NULL); + this->vtable[ord] = reinterpret_cast(this->orig); + VirtualProtect(mbi.BaseAddress, mbi.RegionSize, mbi.Protect, NULL); + enabled = false; + } + } + void enable() { + if (!enabled) { + cout << "Enabling: " << this->vtable << "[" << this->ord << "]: (" << this->orig << " -> " << this->detour <<")" << endl; + VirtualProtect(mbi.BaseAddress, mbi.RegionSize, PAGE_EXECUTE_READWRITE, NULL); + this->vtable[ord] = reinterpret_cast(this->detour); + VirtualProtect(mbi.BaseAddress, mbi.RegionSize, mbi.Protect, NULL); + enabled = true; + } + } + + template + T func() { + return reinterpret_cast(this->orig); + } + +}; + +map> VMT_Hook::hooks; + diff --git a/ScrapHacks/ScrapHack/dllmain.cpp b/ScrapHacks/ScrapHack/dllmain.cpp index 6fab88b..b11b433 100644 --- a/ScrapHacks/ScrapHack/dllmain.cpp +++ b/ScrapHacks/ScrapHack/dllmain.cpp @@ -2,6 +2,8 @@ #define DLL_EXPORT extern "C" __declspec(dllexport) void DllInit(HMODULE); void DllPreInit(HMODULE); +void DllUnload(HMODULE); + BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, @@ -16,6 +18,8 @@ BOOL APIENTRY DllMain(HMODULE hModule, hThread = CreateThread(NULL, NULL, (LPTHREAD_START_ROUTINE)DllInit, hModule, 0, 0); break; case DLL_PROCESS_DETACH: + DllUnload(hModule); + break; case DLL_THREAD_ATTACH: case DLL_THREAD_DETACH: break; diff --git a/ScrapHacks/Scrapland_Tools.sln b/ScrapHacks/Scrapland_Tools.sln index 3c2d8c4..f526d15 100644 --- a/ScrapHacks/Scrapland_Tools.sln +++ b/ScrapHacks/Scrapland_Tools.sln @@ -9,24 +9,30 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Injector", "Injector\Inject EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU Debug|x64 = Debug|x64 Debug|x86 = Debug|x86 + Release|Any CPU = Release|Any CPU Release|x64 = Release|x64 Release|x86 = Release|x86 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution + {72CB1B9E-50C7-4010-BEAD-82FACF87A87A}.Debug|Any CPU.ActiveCfg = Debug|Win32 {72CB1B9E-50C7-4010-BEAD-82FACF87A87A}.Debug|x64.ActiveCfg = Debug|x64 {72CB1B9E-50C7-4010-BEAD-82FACF87A87A}.Debug|x64.Build.0 = Debug|x64 {72CB1B9E-50C7-4010-BEAD-82FACF87A87A}.Debug|x86.ActiveCfg = Debug|Win32 {72CB1B9E-50C7-4010-BEAD-82FACF87A87A}.Debug|x86.Build.0 = Debug|Win32 + {72CB1B9E-50C7-4010-BEAD-82FACF87A87A}.Release|Any CPU.ActiveCfg = Release|Win32 {72CB1B9E-50C7-4010-BEAD-82FACF87A87A}.Release|x64.ActiveCfg = Release|x64 {72CB1B9E-50C7-4010-BEAD-82FACF87A87A}.Release|x64.Build.0 = Release|x64 {72CB1B9E-50C7-4010-BEAD-82FACF87A87A}.Release|x86.ActiveCfg = Release|Win32 {72CB1B9E-50C7-4010-BEAD-82FACF87A87A}.Release|x86.Build.0 = Release|Win32 + {7C91C225-D95C-4B7A-9251-0CE358BAF556}.Debug|Any CPU.ActiveCfg = Debug|Win32 {7C91C225-D95C-4B7A-9251-0CE358BAF556}.Debug|x64.ActiveCfg = Debug|x64 {7C91C225-D95C-4B7A-9251-0CE358BAF556}.Debug|x64.Build.0 = Debug|x64 {7C91C225-D95C-4B7A-9251-0CE358BAF556}.Debug|x86.ActiveCfg = Debug|Win32 {7C91C225-D95C-4B7A-9251-0CE358BAF556}.Debug|x86.Build.0 = Debug|Win32 + {7C91C225-D95C-4B7A-9251-0CE358BAF556}.Release|Any CPU.ActiveCfg = Release|Win32 {7C91C225-D95C-4B7A-9251-0CE358BAF556}.Release|x64.ActiveCfg = Release|x64 {7C91C225-D95C-4B7A-9251-0CE358BAF556}.Release|x64.Build.0 = Release|x64 {7C91C225-D95C-4B7A-9251-0CE358BAF556}.Release|x86.ActiveCfg = Release|Win32