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)
__pycache__/
*.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
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 <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

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>
class Hook;
map<uintptr_t, shared_ptr<Hook>> 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<uintptr_t, shared_ptr<Hook>> hooks;
public:
Hook(void* func, void* detour) {
cout << "Hooking: " << func << " -> " << detour << endl;
uintptr_t dest = reinterpret_cast<uintptr_t>(detour);
uintptr_t src = reinterpret_cast<uintptr_t>(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<Hook>(this);
VirtualProtect(func, 16, this->protect, NULL);
this->enabled = false;
}
~Hook() {
cout << "Unhooking: " << this->detour << " -> " << this->orig << endl;
uintptr_t src = reinterpret_cast<uintptr_t>(this->orig);
memcpy(this->orig, this->orig_bytes, 1 + 4 + 1);
this->disable();
}
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() {
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() {
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<uintptr_t, shared_ptr<Hook>> Hook::hooks;

View file

@ -10,6 +10,11 @@
#include <functional>
#include <Windows.h>
#include <TlHelp32.h>
#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<int32_t*>(ptr(WORLD, { 0x1C6C }));
int16_t* alarm = reinterpret_cast<int16_t*>(ptr(WORLD, { 0x1C6C }));
*/
float* alarm = ptr<float>(P_WORLD, O_ALARM);
float* alarm_grow = ptr<float>(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<int32_t>(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> hook = hooks[P_CON_HANDLER];
shared_ptr<Hook> hook = Hook::get(hooked_console);
t_func func= reinterpret_cast<t_func>(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<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();
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)

View file

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

View file

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

View file

@ -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