From efba0894c4209fa193276f21ed8239c54b33720b Mon Sep 17 00:00:00 2001 From: Daniel Seiller Date: Fri, 1 Mar 2019 20:47:14 +0100 Subject: [PATCH] Added D3D8 EndScene hooking (which currently crashes the game after some time) --- ScrapHacks/.gitignore | 4 +- ScrapHacks/.vscode/settings.json | 11 +++ ScrapHacks/README.md | 11 ++- ScrapHacks/ScrapHack/D3D8_Hook.h | 76 +++++++++++++++++ ScrapHacks/ScrapHack/Hook.h | 83 +++++++++++++++---- ScrapHacks/ScrapHack/ScrapHack.cpp | 32 +++---- ScrapHacks/ScrapHack/ScrapHack.vcxproj | 8 +- .../ScrapHack/ScrapHack.vcxproj.filters | 3 + ScrapHacks/ScrapHack/Scrapland.h | 2 + 9 files changed, 193 insertions(+), 37 deletions(-) create mode 100644 ScrapHacks/.vscode/settings.json create mode 100644 ScrapHacks/ScrapHack/D3D8_Hook.h diff --git a/ScrapHacks/.gitignore b/ScrapHacks/.gitignore index 3c4efe2..b74a998 100644 --- a/ScrapHacks/.gitignore +++ b/ScrapHacks/.gitignore @@ -258,4 +258,6 @@ paket-files/ # Python Tools for Visual Studio (PTVS) __pycache__/ -*.pyc \ No newline at end of file +*.pyc + +ScrapHack/dx8/ \ No newline at end of file diff --git a/ScrapHacks/.vscode/settings.json b/ScrapHacks/.vscode/settings.json new file mode 100644 index 0000000..f2fa764 --- /dev/null +++ b/ScrapHacks/.vscode/settings.json @@ -0,0 +1,11 @@ +{ + "spellright.language": [ + "de", + "en" + ], + "spellright.documentTypes": [ + "markdown", + "latex", + "plaintext" + ] +} \ No newline at end of file diff --git a/ScrapHacks/README.md b/ScrapHacks/README.md index e2843d0..e4d7404 100644 --- a/ScrapHacks/README.md +++ b/ScrapHacks/README.md @@ -2,9 +2,14 @@ ## Usage -0. Build Project -1. Run Injector `.\Injector.exe` -2. Run Game +0. Download `DirectX.8.0a.SDK.zip` from [here](https://archive.org/download/DirectX.8.0a.SDK_includes_libs_only) +1. Extract `DirectX.SDK/8.0/include` and `DirectX.SDK/8.0/lib` to `ScrapHacks/ScrapHack/dx8/include` and `ScrapHacks/ScrapHack/dx8/lib` +2. Add include and library dirs to project +3. Build Project +4. Run Injector `.\Injector.exe ` +5. Wait for game to crash +6. Comment out `hook_d3d8()` call in `ScrapHack.cpp:DllPreInit()` +7. Rebuild and run Injector again ``` [F3 ] Unload ScrapHacks diff --git a/ScrapHacks/ScrapHack/D3D8_Hook.h b/ScrapHacks/ScrapHack/D3D8_Hook.h new file mode 100644 index 0000000..6f760fe --- /dev/null +++ b/ScrapHacks/ScrapHack/D3D8_Hook.h @@ -0,0 +1,76 @@ +#pragma once +#include +#include +uintmax_t frame = 0; +DWORD* GetVTable(void* addr) { + return (DWORD*)(*(DWORD*)addr); +} + +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; + } + +} + +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()); + Render(dev); + hook->disable(); + HRESULT ret = func(dev); + hook->enable(); + return ret; + +} + +HRESULT WINAPI H_CreateDevice(void* pDirect3D, unsigned int uiAdapter, D3DDEVTYPE pDeviceType, HWND hFocusWindow, + unsigned long ulBehaviorFlags, D3DPRESENT_PARAMETERS* pPresentationParameters, + LPDIRECT3DDEVICE8* ppReturnedDeviceInterface) { + 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); + Hook::drop(H_CreateDevice); + 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()); + 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); + 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)); + Hook::drop(H_Direct3DCreate8); + return ret; +} + +void hook_d3d8() { + Hook::module("d3d8.dll","Direct3DCreate8", H_Direct3DCreate8); +} diff --git a/ScrapHacks/ScrapHack/Hook.h b/ScrapHacks/ScrapHack/Hook.h index 8c33603..bf675f0 100644 --- a/ScrapHacks/ScrapHack/Hook.h +++ b/ScrapHacks/ScrapHack/Hook.h @@ -2,18 +2,19 @@ #include class Hook; -map> hooks; - -class Hook { +class Hook +{ private: DWORD protect; 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) { - cout << "Hooking: " << func << " -> " << detour << endl; uintptr_t dest = reinterpret_cast(detour); uintptr_t src = reinterpret_cast(func); this->orig = func; @@ -26,25 +27,77 @@ public: this->jmp_bytes[5] = 0xC3; // ret VirtualProtect(func, 16, PAGE_EXECUTE_READWRITE, &(this->protect)); memcpy(this->orig_bytes, this->orig, 1 + 4 + 1); - memcpy(this->orig, this->jmp_bytes, 1 + 4 + 1); - hooks[src]=shared_ptr(this); - } - - ~Hook() { - cout << "Unhooking: " << this->detour << " -> " << this->orig << endl; - uintptr_t src = reinterpret_cast(this->orig); - memcpy(this->orig, this->orig_bytes, 1 + 4 + 1); + VirtualProtect(func, 16, this->protect, NULL); + this->enabled = false; } + ~Hook() { + this->disable(); + } + + static void addr(void* addr, void* detour) { + cout << "Hooking: [" << addr << " -> " << detour <<"]" << endl; + uintptr_t key = reinterpret_cast(detour); + hooks[key] = make_shared(addr,detour); + hooks[key]->enable(); + } + + static void module(const char* mod, const char* func, void* detour) { + cout << "Hooking: [" << mod<<"]."< " << detour << endl; + void* addr = GetProcAddress(GetModuleHandle(mod), func); + if (addr != NULL) { + Hook::addr(addr, detour); + } + else { + cerr << "[" << mod << "]." << func << " not found!" << endl; + }; + } + + static shared_ptr get(void* func) { + uintptr_t addr = reinterpret_cast(func); + return 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 Hook::drop(addr); + } + + static size_t drop(uintptr_t addr) { + return hooks.erase(addr); + } + + static void clear() { + return hooks.clear(); + } + + void disable() { - memcpy(this->orig, this->orig_bytes, 1 + 4 + 1); + if (enabled) { + //cout << "Disabling: [" << this->orig << " <- " << this->detour << "]" << endl; + VirtualProtect(this->orig, 16, PAGE_EXECUTE_READWRITE, NULL); + memcpy(this->orig, this->orig_bytes, 1 + 4 + 1); + VirtualProtect(this->orig, 16, this->protect, NULL); + enabled = false; + } } void enable() { - memcpy(this->orig, this->jmp_bytes, 1 + 4 + 1); + if (!enabled) { + //cout << "Enabling: [" << this->orig << " -> " << this->detour << "]" << endl; + VirtualProtect(this->orig, 16, PAGE_EXECUTE_READWRITE, NULL); + memcpy(this->orig, this->jmp_bytes, 1 + 4 + 1); + VirtualProtect(this->orig, 16, this->protect, NULL); + enabled = true; + } } void* func() { return this->orig; } - }; + +map> Hook::hooks; diff --git a/ScrapHacks/ScrapHack/ScrapHack.cpp b/ScrapHacks/ScrapHack/ScrapHack.cpp index 9312b66..8c2ecd5 100644 --- a/ScrapHacks/ScrapHack/ScrapHack.cpp +++ b/ScrapHacks/ScrapHack/ScrapHack.cpp @@ -10,6 +10,11 @@ #include #include #include + +#pragma comment(lib, "d3d8.lib") +#pragma comment(lib, "d3dx8.lib") +#pragma comment(lib, "legacy_stdio_definitions.lib") + using namespace std; #include "Scrapland.h" @@ -17,8 +22,7 @@ using namespace std; #include "Structures.h" #include "Py_Utils.h" #include "Hook.h" - -#define SIZE 6 +#include "D3D8_Hook.h" HMODULE hD3D8Dll = 0; @@ -32,6 +36,7 @@ void MainLoop(HMODULE mod) cout << "[*] Starting main Loop" << endl; cout << endl; cout << "[F3 ] Unload ScrapHacks" << endl; + cout << "[F6 ] Show Alarm status" << endl; cout << "[F7 ] Set Money to 0x7fffffff" << endl; cout << "[F8 ] Dump python modules" << endl; cout << "[F10] Enable python tracing" << endl; @@ -50,17 +55,13 @@ void MainLoop(HMODULE mod) } if (key_down_norepeat(VK_F6)) { - /* - int32_t* alarm = reinterpret_cast(ptr(WORLD, { 0x1C6C })); - int16_t* alarm = reinterpret_cast(ptr(WORLD, { 0x1C6C })); - */ + + float* alarm = ptr(P_WORLD, O_ALARM); + float* alarm_grow = ptr(P_WORLD, O_ALARM_GROW); + cout << "Alarm: " << alarm[0] << " + " << alarm_grow[0] << endl; } if (key_down_norepeat(VK_F7)) { - /*========================== - mov ecx, [7FE944h] - mov edx, [ecx + 2090h] - ==========================*/ int32_t *money = ptr(P_WORLD,O_MONEY); *money = 0x7fffffff; } @@ -80,7 +81,7 @@ void MainLoop(HMODULE mod) } } SetConsoleCtrlHandler(NULL, false); - hooks.clear(); + Hook::clear(); scrap_log(0xff0000, "ScrapHacks unloaded!\n"); cout << "[+] ScrapHacks unloaded, you can now close the console!" << endl; FreeConsole(); @@ -103,9 +104,9 @@ void handle_command(const char* cmd) { return; } -int my_console(const char* cmd) { +int hooked_console(const char* cmd) { typedef int(_cdecl *t_func)(const char*); - shared_ptr hook = hooks[P_CON_HANDLER]; + shared_ptr hook = Hook::get(hooked_console); t_func func= reinterpret_cast(hook->func()); if (cmd[0] == '$') { handle_command(++cmd); @@ -118,7 +119,7 @@ int my_console(const char* cmd) { } void hook_console() { - new Hook(reinterpret_cast(P_CON_HANDLER) , my_console); + Hook::addr(reinterpret_cast(P_CON_HANDLER) , hooked_console); } @@ -127,10 +128,9 @@ void DllPreInit(HMODULE _mod) { InitConsole(); GetModuleFileName(0, mfn, 1024); Py = get_modules(P_PY_MODS); - hD3D8Dll = GetModuleHandle("d3d8.dll"); cout << "[+] ScrapHacks v0.1 Loaded in " << mfn << endl; - cout << "[*] D3D8 DLL @0x" << hD3D8Dll << endl; hook_console(); + hook_d3d8(); } void DllInit(HMODULE _mod) diff --git a/ScrapHacks/ScrapHack/ScrapHack.vcxproj b/ScrapHacks/ScrapHack/ScrapHack.vcxproj index c3d1781..6d983f1 100644 --- a/ScrapHacks/ScrapHack/ScrapHack.vcxproj +++ b/ScrapHacks/ScrapHack/ScrapHack.vcxproj @@ -72,14 +72,16 @@ true + $(VC_IncludePath);$(WindowsSDK_IncludePath);$(ProjectDir)dx8\include;$(SolutionDir)include + $(ProjectDir)dx8\lib;$(SolutionDir)lib;$(LibraryPath) true false - $(SolutionDir)include;$(IncludePath) - $(SolutionDir)lib;$(LibraryPath) + $(VC_IncludePath);$(WindowsSDK_IncludePath);$(ProjectDir)dx8\include;$(SolutionDir)include + $(ProjectDir)dx8\lib;$(SolutionDir)lib;$(LibraryPath) false @@ -129,6 +131,7 @@ true true %(AdditionalDependencies) + false @@ -150,6 +153,7 @@ + diff --git a/ScrapHacks/ScrapHack/ScrapHack.vcxproj.filters b/ScrapHacks/ScrapHack/ScrapHack.vcxproj.filters index f3af96c..962bf28 100644 --- a/ScrapHacks/ScrapHack/ScrapHack.vcxproj.filters +++ b/ScrapHacks/ScrapHack/ScrapHack.vcxproj.filters @@ -36,6 +36,9 @@ Headerdateien + + Headerdateien + diff --git a/ScrapHacks/ScrapHack/Scrapland.h b/ScrapHacks/ScrapHack/Scrapland.h index e9a4024..a55cd3f 100644 --- a/ScrapHacks/ScrapHack/Scrapland.h +++ b/ScrapHacks/ScrapHack/Scrapland.h @@ -1,6 +1,8 @@ #pragma once //OFFSETS #define O_MONEY 0x2090 +#define O_ALARM 0x1C6C +#define O_ALARM_GROW 0x1C68 //POINTERS #define P_WORLD 0x7FE944