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
This commit is contained in:
parent
3976fdea37
commit
3a9ab54240
12 changed files with 275 additions and 100 deletions
3
NOTES.md
3
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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 = Hook::get(H_EndScene);
|
||||
t_func func = reinterpret_cast<t_func>(hook->func());
|
||||
_asm push esi;
|
||||
_asm pushad;
|
||||
Render(dev);
|
||||
hook->disable();
|
||||
HRESULT ret = func(dev);
|
||||
HRESULT ret = hook->func<t_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 = 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);
|
||||
HRESULT ret = hook->func<t_func>()(pDirect3D, uiAdapter, pDeviceType, hFocusWindow, ulBehaviorFlags, pPresentationParameters, ppReturnedDeviceInterface);
|
||||
cout << "CreateDevice ->" << ret << endl;
|
||||
void* EndScene = reinterpret_cast<void*>(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 = Hook::get(H_Direct3DCreate8);
|
||||
t_func func = reinterpret_cast<t_func>(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<t_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));
|
||||
void *CreateDevice = reinterpret_cast<void*>(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);
|
||||
}
|
||||
|
|
|
@ -1,19 +1,18 @@
|
|||
#pragma once
|
||||
#include <functional>
|
||||
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<uintptr_t, shared_ptr<Hook>> hooks;
|
||||
|
||||
|
||||
public:
|
||||
|
||||
Hook(void* func, void* detour) {
|
||||
uintptr_t dest = reinterpret_cast<uintptr_t>(detour);
|
||||
uintptr_t src = reinterpret_cast<uintptr_t>(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<uintptr_t>(detour);
|
||||
|
@ -72,31 +73,35 @@ public:
|
|||
}
|
||||
|
||||
static void clear() {
|
||||
cout << "Clearing Hooks" << endl;
|
||||
for (pair<uintptr_t,shared_ptr<Hook>> 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<typename T>
|
||||
T func() {
|
||||
return reinterpret_cast<T>(this->orig);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -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<HashTable>(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 = Hook::get(hooked_console);
|
||||
t_func func= reinterpret_cast<t_func>(hook->func());
|
||||
if (cmd[0] == '$') {
|
||||
handle_command(++cmd);
|
||||
return 0;
|
||||
}
|
||||
hook->disable();
|
||||
int ret=func(cmd);
|
||||
int ret= hook->func<t_func>()(cmd);
|
||||
hook->enable();
|
||||
return ret;
|
||||
}
|
||||
|
@ -122,7 +150,6 @@ void hook_console() {
|
|||
Hook::addr(reinterpret_cast<void*>(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;
|
||||
}
|
|
@ -154,6 +154,7 @@
|
|||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="D3D8_Hook.h" />
|
||||
<ClInclude Include="VMT_Hook.h" />
|
||||
<ClInclude Include="Hook.h" />
|
||||
<ClInclude Include="Py_Utils.h" />
|
||||
<ClInclude Include="Structures.h" />
|
||||
|
|
|
@ -39,6 +39,9 @@
|
|||
<ClInclude Include="D3D8_Hook.h">
|
||||
<Filter>Headerdateien</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="VMT_Hook.h">
|
||||
<Filter>Headerdateien</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="stdafx.cpp">
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
#pragma once
|
||||
|
||||
struct HashTableEntry;
|
||||
struct Vector3 {
|
||||
float x;
|
||||
float y;
|
||||
|
@ -32,3 +32,19 @@ struct Module
|
|||
PyMod *mod;
|
||||
map<string, PyMethodDef*> methods;
|
||||
};
|
||||
|
||||
struct Entity {
|
||||
void* VMT;
|
||||
|
||||
};
|
||||
|
||||
struct HashTable {
|
||||
uint32_t size;
|
||||
HashTableEntry** chains;
|
||||
};
|
||||
|
||||
struct HashTableEntry {
|
||||
Entity* data;
|
||||
const char* name;
|
||||
HashTableEntry* next;
|
||||
};
|
91
ScrapHacks/ScrapHack/VMT_Hook.h
Normal file
91
ScrapHacks/ScrapHack/VMT_Hook.h
Normal file
|
@ -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<uintptr_t, shared_ptr<VMT_Hook>> 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<void*>(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<uintptr_t>(detour);
|
||||
hooks[key] = make_shared<VMT_Hook>(obj,ord, detour);
|
||||
hooks[key]->enable();
|
||||
}
|
||||
|
||||
static shared_ptr<VMT_Hook> get(void* func) {
|
||||
uintptr_t addr = reinterpret_cast<uintptr_t>(func);
|
||||
return VMT_Hook::get(addr);
|
||||
}
|
||||
|
||||
static shared_ptr<VMT_Hook> get(uintptr_t addr) {
|
||||
return hooks.at(addr);
|
||||
}
|
||||
|
||||
static size_t drop(void* func) {
|
||||
uintptr_t addr = reinterpret_cast<uintptr_t>(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<DWORD>(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<DWORD>(this->detour);
|
||||
VirtualProtect(mbi.BaseAddress, mbi.RegionSize, mbi.Protect, NULL);
|
||||
enabled = true;
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T func() {
|
||||
return reinterpret_cast<T>(this->orig);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
map<uintptr_t, shared_ptr<VMT_Hook>> VMT_Hook::hooks;
|
||||
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue