Added D3D8 EndScene hooking (which currently crashes the game after some time)

This commit is contained in:
Daniel S. 2019-03-01 20:47:14 +01:00
parent 7cf3ab8580
commit efba0894c4
9 changed files with 193 additions and 37 deletions

View file

@ -259,3 +259,5 @@ paket-files/
# Python Tools for Visual Studio (PTVS) # Python Tools for Visual Studio (PTVS)
__pycache__/ __pycache__/
*.pyc *.pyc
ScrapHack/dx8/

11
ScrapHacks/.vscode/settings.json vendored Normal file
View file

@ -0,0 +1,11 @@
{
"spellright.language": [
"de",
"en"
],
"spellright.documentTypes": [
"markdown",
"latex",
"plaintext"
]
}

View file

@ -2,9 +2,14 @@
## Usage ## Usage
0. Build Project 0. Download `DirectX.8.0a.SDK.zip` from [here](https://archive.org/download/DirectX.8.0a.SDK_includes_libs_only)
1. Run Injector `.\Injector.exe` 1. Extract `DirectX.SDK/8.0/include` and `DirectX.SDK/8.0/lib` to `ScrapHacks/ScrapHack/dx8/include` and `ScrapHacks/ScrapHack/dx8/lib`
2. Run Game 2. Add include and library dirs to project
3. Build Project
4. Run Injector `.\Injector.exe <Path to Scrap.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 [F3 ] Unload ScrapHacks

View file

@ -0,0 +1,76 @@
#pragma once
#include <d3d8.h>
#include <d3dx8.h>
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 = Hook::get(H_EndScene);
t_func func = reinterpret_cast<t_func>(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 = Hook::get(H_CreateDevice);
t_func func = reinterpret_cast<t_func>(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 = Hook::get(H_Direct3DCreate8);
t_func func = reinterpret_cast<t_func>(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<void*>(H_CreateDevice));
Hook::drop(H_Direct3DCreate8);
return ret;
}
void hook_d3d8() {
Hook::module("d3d8.dll","Direct3DCreate8", H_Direct3DCreate8);
}

View file

@ -2,18 +2,19 @@
#include <functional> #include <functional>
class Hook; class Hook;
map<uintptr_t, shared_ptr<Hook>> hooks; class Hook
{
class Hook {
private: private:
DWORD protect; DWORD protect;
void* orig; void* orig;
void* detour; void* detour;
bool enabled;
uint8_t orig_bytes[6]; uint8_t orig_bytes[6];
uint8_t jmp_bytes[6]; uint8_t jmp_bytes[6];
static map<uintptr_t, shared_ptr<Hook>> hooks;
public: public:
Hook(void* func, void* detour) { Hook(void* func, void* detour) {
cout << "Hooking: " << func << " -> " << detour << endl;
uintptr_t dest = reinterpret_cast<uintptr_t>(detour); uintptr_t dest = reinterpret_cast<uintptr_t>(detour);
uintptr_t src = reinterpret_cast<uintptr_t>(func); uintptr_t src = reinterpret_cast<uintptr_t>(func);
this->orig = func; this->orig = func;
@ -26,25 +27,77 @@ public:
this->jmp_bytes[5] = 0xC3; // ret this->jmp_bytes[5] = 0xC3; // ret
VirtualProtect(func, 16, PAGE_EXECUTE_READWRITE, &(this->protect)); VirtualProtect(func, 16, PAGE_EXECUTE_READWRITE, &(this->protect));
memcpy(this->orig_bytes, this->orig, 1 + 4 + 1); memcpy(this->orig_bytes, this->orig, 1 + 4 + 1);
memcpy(this->orig, this->jmp_bytes, 1 + 4 + 1); VirtualProtect(func, 16, this->protect, NULL);
hooks[src]=shared_ptr<Hook>(this); this->enabled = false;
} }
~Hook() { ~Hook() {
cout << "Unhooking: " << this->detour << " -> " << this->orig << endl; this->disable();
uintptr_t src = reinterpret_cast<uintptr_t>(this->orig);
memcpy(this->orig, this->orig_bytes, 1 + 4 + 1);
} }
static void addr(void* addr, void* detour) {
cout << "Hooking: [" << addr << " -> " << detour <<"]" << endl;
uintptr_t key = reinterpret_cast<uintptr_t>(detour);
hooks[key] = make_shared<Hook>(addr,detour);
hooks[key]->enable();
}
static void module(const char* mod, const char* func, void* detour) {
cout << "Hooking: [" << mod<<"]."<<func << " -> " << 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<Hook> get(void* func) {
uintptr_t addr = reinterpret_cast<uintptr_t>(func);
return Hook::get(addr);
}
static shared_ptr<Hook> get(uintptr_t addr) {
return hooks.at(addr);
}
static size_t drop(void* func) {
uintptr_t addr = reinterpret_cast<uintptr_t>(func);
return Hook::drop(addr);
}
static size_t drop(uintptr_t addr) {
return hooks.erase(addr);
}
static void clear() {
return hooks.clear();
}
void disable() { 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() { 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() { void* func() {
return this->orig; return this->orig;
} }
}; };
map<uintptr_t, shared_ptr<Hook>> Hook::hooks;

View file

@ -10,6 +10,11 @@
#include <functional> #include <functional>
#include <Windows.h> #include <Windows.h>
#include <TlHelp32.h> #include <TlHelp32.h>
#pragma comment(lib, "d3d8.lib")
#pragma comment(lib, "d3dx8.lib")
#pragma comment(lib, "legacy_stdio_definitions.lib")
using namespace std; using namespace std;
#include "Scrapland.h" #include "Scrapland.h"
@ -17,8 +22,7 @@ using namespace std;
#include "Structures.h" #include "Structures.h"
#include "Py_Utils.h" #include "Py_Utils.h"
#include "Hook.h" #include "Hook.h"
#include "D3D8_Hook.h"
#define SIZE 6
HMODULE hD3D8Dll = 0; HMODULE hD3D8Dll = 0;
@ -32,6 +36,7 @@ void MainLoop(HMODULE mod)
cout << "[*] Starting main Loop" << endl; cout << "[*] Starting main Loop" << endl;
cout << endl; cout << endl;
cout << "[F3 ] Unload ScrapHacks" << endl; cout << "[F3 ] Unload ScrapHacks" << endl;
cout << "[F6 ] Show Alarm status" << endl;
cout << "[F7 ] Set Money to 0x7fffffff" << endl; cout << "[F7 ] Set Money to 0x7fffffff" << endl;
cout << "[F8 ] Dump python modules" << endl; cout << "[F8 ] Dump python modules" << endl;
cout << "[F10] Enable python tracing" << endl; cout << "[F10] Enable python tracing" << endl;
@ -50,17 +55,13 @@ void MainLoop(HMODULE mod)
} }
if (key_down_norepeat(VK_F6)) if (key_down_norepeat(VK_F6))
{ {
/*
int32_t* alarm = reinterpret_cast<int32_t*>(ptr(WORLD, { 0x1C6C })); float* alarm = ptr<float>(P_WORLD, O_ALARM);
int16_t* alarm = reinterpret_cast<int16_t*>(ptr(WORLD, { 0x1C6C })); float* alarm_grow = ptr<float>(P_WORLD, O_ALARM_GROW);
*/ cout << "Alarm: " << alarm[0] << " + " << alarm_grow[0] << endl;
} }
if (key_down_norepeat(VK_F7)) if (key_down_norepeat(VK_F7))
{ {
/*==========================
mov ecx, [7FE944h]
mov edx, [ecx + 2090h]
==========================*/
int32_t *money = ptr<int32_t>(P_WORLD,O_MONEY); int32_t *money = ptr<int32_t>(P_WORLD,O_MONEY);
*money = 0x7fffffff; *money = 0x7fffffff;
} }
@ -80,7 +81,7 @@ void MainLoop(HMODULE mod)
} }
} }
SetConsoleCtrlHandler(NULL, false); SetConsoleCtrlHandler(NULL, false);
hooks.clear(); Hook::clear();
scrap_log(0xff0000, "ScrapHacks unloaded!\n"); scrap_log(0xff0000, "ScrapHacks unloaded!\n");
cout << "[+] ScrapHacks unloaded, you can now close the console!" << endl; cout << "[+] ScrapHacks unloaded, you can now close the console!" << endl;
FreeConsole(); FreeConsole();
@ -103,9 +104,9 @@ void handle_command(const char* cmd) {
return; return;
} }
int my_console(const char* cmd) { int hooked_console(const char* cmd) {
typedef int(_cdecl *t_func)(const char*); typedef int(_cdecl *t_func)(const char*);
shared_ptr<Hook> hook = hooks[P_CON_HANDLER]; shared_ptr<Hook> hook = Hook::get(hooked_console);
t_func func= reinterpret_cast<t_func>(hook->func()); t_func func= reinterpret_cast<t_func>(hook->func());
if (cmd[0] == '$') { if (cmd[0] == '$') {
handle_command(++cmd); handle_command(++cmd);
@ -118,7 +119,7 @@ int my_console(const char* cmd) {
} }
void hook_console() { void hook_console() {
new Hook(reinterpret_cast<void*>(P_CON_HANDLER) , my_console); Hook::addr(reinterpret_cast<void*>(P_CON_HANDLER) , hooked_console);
} }
@ -127,10 +128,9 @@ void DllPreInit(HMODULE _mod) {
InitConsole(); InitConsole();
GetModuleFileName(0, mfn, 1024); GetModuleFileName(0, mfn, 1024);
Py = get_modules(P_PY_MODS); Py = get_modules(P_PY_MODS);
hD3D8Dll = GetModuleHandle("d3d8.dll");
cout << "[+] ScrapHacks v0.1 Loaded in " << mfn << endl; cout << "[+] ScrapHacks v0.1 Loaded in " << mfn << endl;
cout << "[*] D3D8 DLL @0x" << hD3D8Dll << endl;
hook_console(); hook_console();
hook_d3d8();
} }
void DllInit(HMODULE _mod) void DllInit(HMODULE _mod)

View file

@ -72,14 +72,16 @@
<PropertyGroup Label="UserMacros" /> <PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<LinkIncremental>true</LinkIncremental> <LinkIncremental>true</LinkIncremental>
<IncludePath>$(VC_IncludePath);$(WindowsSDK_IncludePath);$(ProjectDir)dx8\include;$(SolutionDir)include</IncludePath>
<LibraryPath>$(ProjectDir)dx8\lib;$(SolutionDir)lib;$(LibraryPath)</LibraryPath>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<LinkIncremental>true</LinkIncremental> <LinkIncremental>true</LinkIncremental>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LinkIncremental>false</LinkIncremental> <LinkIncremental>false</LinkIncremental>
<IncludePath>$(SolutionDir)include;$(IncludePath)</IncludePath> <IncludePath>$(VC_IncludePath);$(WindowsSDK_IncludePath);$(ProjectDir)dx8\include;$(SolutionDir)include</IncludePath>
<LibraryPath>$(SolutionDir)lib;$(LibraryPath)</LibraryPath> <LibraryPath>$(ProjectDir)dx8\lib;$(SolutionDir)lib;$(LibraryPath)</LibraryPath>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<LinkIncremental>false</LinkIncremental> <LinkIncremental>false</LinkIncremental>
@ -129,6 +131,7 @@
<OptimizeReferences>true</OptimizeReferences> <OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation> <GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>%(AdditionalDependencies)</AdditionalDependencies> <AdditionalDependencies>%(AdditionalDependencies)</AdditionalDependencies>
<ImageHasSafeExceptionHandlers>false</ImageHasSafeExceptionHandlers>
</Link> </Link>
</ItemDefinitionGroup> </ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
@ -150,6 +153,7 @@
</Link> </Link>
</ItemDefinitionGroup> </ItemDefinitionGroup>
<ItemGroup> <ItemGroup>
<ClInclude Include="D3D8_Hook.h" />
<ClInclude Include="Hook.h" /> <ClInclude Include="Hook.h" />
<ClInclude Include="Py_Utils.h" /> <ClInclude Include="Py_Utils.h" />
<ClInclude Include="Structures.h" /> <ClInclude Include="Structures.h" />

View file

@ -36,6 +36,9 @@
<ClInclude Include="Hook.h"> <ClInclude Include="Hook.h">
<Filter>Headerdateien</Filter> <Filter>Headerdateien</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="D3D8_Hook.h">
<Filter>Headerdateien</Filter>
</ClInclude>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClCompile Include="stdafx.cpp"> <ClCompile Include="stdafx.cpp">

View file

@ -1,6 +1,8 @@
#pragma once #pragma once
//OFFSETS //OFFSETS
#define O_MONEY 0x2090 #define O_MONEY 0x2090
#define O_ALARM 0x1C6C
#define O_ALARM_GROW 0x1C68
//POINTERS //POINTERS
#define P_WORLD 0x7FE944 #define P_WORLD 0x7FE944