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
|
## 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:
|
Entry format:
|
||||||
|
|
||||||
|
@ -81,6 +81,7 @@ Data format:
|
||||||
| ------ | ----------- | -------------------- |
|
| ------ | ----------- | -------------------- |
|
||||||
| 0x0 | void** | Virtual Method Table |
|
| 0x0 | void** | Virtual Method Table |
|
||||||
| 0x4 | const char* | name as string |
|
| 0x4 | const char* | name as string |
|
||||||
|
| 0x14 | void* | pointer to self |
|
||||||
| 0x28 | float[3] | Position |
|
| 0x28 | float[3] | Position |
|
||||||
|
|
||||||
# File Formats
|
# File Formats
|
||||||
|
|
|
@ -156,7 +156,7 @@ bool Injected(DWORD PID)
|
||||||
return HasModule(PID, DLL_NAME);
|
return HasModule(PID, DLL_NAME);
|
||||||
}
|
}
|
||||||
|
|
||||||
void InjectDll(DWORD PID, bool do_resume = false)
|
void InjectDll(DWORD PID)
|
||||||
{
|
{
|
||||||
HANDLE hRemThread, hProc;
|
HANDLE hRemThread, hProc;
|
||||||
const char *dll_name = DLL_NAME;
|
const char *dll_name = DLL_NAME;
|
||||||
|
@ -175,42 +175,34 @@ void InjectDll(DWORD PID, bool do_resume = false)
|
||||||
if (HasModule(PID, dll_name))
|
if (HasModule(PID, dll_name))
|
||||||
{
|
{
|
||||||
cout << "[*] DLL already Loaded" << endl;
|
cout << "[*] DLL already Loaded" << endl;
|
||||||
}
|
CloseHandle(hProc);
|
||||||
else
|
return;
|
||||||
|
};
|
||||||
|
if (!fexists(dll_full_path))
|
||||||
{
|
{
|
||||||
if (!fexists(dll_full_path))
|
cout << "[!] DLL file not found!" << endl;
|
||||||
{
|
CloseHandle(hProc);
|
||||||
cout << "[!] DLL file not found!" << endl;
|
return;
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
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;
|
cout << "[*] Closing Process Handle" << endl;
|
||||||
CloseHandle(hProc);
|
CloseHandle(hProc);
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -5,72 +5,89 @@ uintmax_t frame = 0;
|
||||||
DWORD* GetVTable(void* addr) {
|
DWORD* GetVTable(void* addr) {
|
||||||
return (DWORD*)(*(DWORD*)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) {
|
void Render(LPDIRECT3DDEVICE8 dev) {
|
||||||
char text[MAX_PATH];
|
if (!overlay) {
|
||||||
LPD3DXFONT m_pFont;
|
return;
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
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) {
|
HRESULT WINAPI H_EndScene(LPDIRECT3DDEVICE8 dev) {
|
||||||
typedef HRESULT(WINAPI *t_func)(LPDIRECT3DDEVICE8);
|
typedef HRESULT(WINAPI *t_func)(LPDIRECT3DDEVICE8);
|
||||||
shared_ptr<Hook> hook = Hook::get(H_EndScene);
|
shared_ptr<Hook> hook = Hook::get(H_EndScene);
|
||||||
t_func func = reinterpret_cast<t_func>(hook->func());
|
_asm push esi;
|
||||||
|
_asm pushad;
|
||||||
Render(dev);
|
Render(dev);
|
||||||
hook->disable();
|
hook->disable();
|
||||||
HRESULT ret = func(dev);
|
HRESULT ret = hook->func<t_func>()(dev);
|
||||||
hook->enable();
|
hook->enable();
|
||||||
|
_asm popad;
|
||||||
|
_asm pop esi;
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
HRESULT WINAPI H_CreateDevice(void* pDirect3D, unsigned int uiAdapter, D3DDEVTYPE pDeviceType, HWND hFocusWindow,
|
HRESULT WINAPI H_CreateDevice(void* pDirect3D, unsigned int uiAdapter, D3DDEVTYPE pDeviceType, HWND hFocusWindow,
|
||||||
unsigned long ulBehaviorFlags, D3DPRESENT_PARAMETERS* pPresentationParameters,
|
unsigned long ulBehaviorFlags, D3DPRESENT_PARAMETERS* pPresentationParameters,
|
||||||
LPDIRECT3DDEVICE8* ppReturnedDeviceInterface) {
|
LPDIRECT3DDEVICE8* ppReturnedDeviceInterface) {
|
||||||
|
_asm push esi;
|
||||||
|
_asm pushad;
|
||||||
typedef HRESULT(WINAPI *t_func)(void*, unsigned int, D3DDEVTYPE, HWND, unsigned long, D3DPRESENT_PARAMETERS*, LPDIRECT3DDEVICE8*);
|
typedef HRESULT(WINAPI *t_func)(void*, unsigned int, D3DDEVTYPE, HWND, unsigned long, D3DPRESENT_PARAMETERS*, LPDIRECT3DDEVICE8*);
|
||||||
shared_ptr<Hook> hook = Hook::get(H_CreateDevice);
|
shared_ptr<Hook> hook = Hook::get(H_CreateDevice);
|
||||||
t_func func = reinterpret_cast<t_func>(hook->func());
|
|
||||||
hook->disable();
|
hook->disable();
|
||||||
HRESULT ret = func(pDirect3D, uiAdapter, pDeviceType, hFocusWindow, ulBehaviorFlags, pPresentationParameters, ppReturnedDeviceInterface);
|
HRESULT ret = hook->func<t_func>()(pDirect3D, uiAdapter, pDeviceType, hFocusWindow, ulBehaviorFlags, pPresentationParameters, ppReturnedDeviceInterface);
|
||||||
cout << "Ret:" << ret << endl;
|
cout << "CreateDevice ->" << ret << endl;
|
||||||
DWORD *vtable = GetVTable(ppReturnedDeviceInterface[0]);
|
void* EndScene = reinterpret_cast<void*>(GetVTable(ppReturnedDeviceInterface[0])[35]);
|
||||||
cout << "Dev VTable @ " << vtable << endl;
|
cout << "EndScene @ " << EndScene << endl; // EndScene
|
||||||
cout << "Dev VTable[35]: " << (void*)(vtable[35]) << endl; // EndScene
|
Hook::addr(EndScene, H_EndScene);
|
||||||
Hook::addr((void*)vtable[35], H_EndScene);
|
|
||||||
Hook::drop(H_CreateDevice);
|
Hook::drop(H_CreateDevice);
|
||||||
|
_asm popad;
|
||||||
|
_asm pop esi;
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
LPDIRECT3D8 WINAPI H_Direct3DCreate8(unsigned int SDKVersion) {
|
LPDIRECT3D8 WINAPI H_Direct3DCreate8(unsigned int SDKVersion) {
|
||||||
typedef LPDIRECT3D8(_stdcall *t_func)(unsigned int);
|
typedef LPDIRECT3D8(_stdcall *t_func)(unsigned int);
|
||||||
shared_ptr<Hook> hook = Hook::get(H_Direct3DCreate8);
|
shared_ptr<Hook> hook = Hook::get(H_Direct3DCreate8);
|
||||||
t_func func = reinterpret_cast<t_func>(hook->func());
|
|
||||||
|
_asm push esi;
|
||||||
|
_asm pushad;
|
||||||
|
|
||||||
hook->disable();
|
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 = hook->func<t_func>()(SDKVersion);
|
||||||
LPDIRECT3D8 ret = func(SDKVersion);
|
|
||||||
cout << "D3D8-Create: " << SDKVersion << " -> " << ret << endl;
|
cout << "D3D8-Create: " << SDKVersion << " -> " << ret << endl;
|
||||||
DWORD *vtable = GetVTable(ret);
|
void *CreateDevice = reinterpret_cast<void*>(GetVTable(ret)[15]);
|
||||||
cout << "ID3D8 VTable @ " << vtable << endl;
|
cout << "CreateDevice @ " << CreateDevice << endl; // CreateDevice
|
||||||
cout << "ID3D8 VTable[15]: " << (void*)(vtable[15]) << endl; // CreateDevice
|
Hook::addr(CreateDevice, H_CreateDevice);
|
||||||
Hook::addr((void*)vtable[15], reinterpret_cast<void*>(H_CreateDevice));
|
|
||||||
Hook::drop(H_Direct3DCreate8);
|
Hook::drop(H_Direct3DCreate8);
|
||||||
|
_asm popad;
|
||||||
|
_asm pop esi;
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
void hook_d3d8() {
|
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);
|
Hook::module("d3d8.dll","Direct3DCreate8", H_Direct3DCreate8);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,19 +1,18 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
#include <functional>
|
#include <functional>
|
||||||
class Hook;
|
|
||||||
|
|
||||||
class Hook
|
class Hook
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
DWORD protect;
|
MEMORY_BASIC_INFORMATION mbi;
|
||||||
void* orig;
|
void* orig;
|
||||||
void* detour;
|
void* detour;
|
||||||
bool enabled;
|
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;
|
static map<uintptr_t, shared_ptr<Hook>> hooks;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
Hook(void* func, void* detour) {
|
Hook(void* func, void* detour) {
|
||||||
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);
|
||||||
|
@ -25,16 +24,18 @@ public:
|
||||||
this->jmp_bytes[3] = (dest >> 16) & 0xff;
|
this->jmp_bytes[3] = (dest >> 16) & 0xff;
|
||||||
this->jmp_bytes[4] = (dest >> 24) & 0xff;
|
this->jmp_bytes[4] = (dest >> 24) & 0xff;
|
||||||
this->jmp_bytes[5] = 0xC3; // ret
|
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);
|
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;
|
this->enabled = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
~Hook() {
|
~Hook() {
|
||||||
|
cout << "Unhooking: [" << this->orig << " <- " << this->detour << "]" << endl;
|
||||||
this->disable();
|
this->disable();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void addr(void* addr, void* detour) {
|
static void addr(void* addr, void* detour) {
|
||||||
cout << "Hooking: [" << addr << " -> " << detour <<"]" << endl;
|
cout << "Hooking: [" << addr << " -> " << detour <<"]" << endl;
|
||||||
uintptr_t key = reinterpret_cast<uintptr_t>(detour);
|
uintptr_t key = reinterpret_cast<uintptr_t>(detour);
|
||||||
|
@ -72,31 +73,35 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
static void clear() {
|
static void clear() {
|
||||||
|
cout << "Clearing Hooks" << endl;
|
||||||
|
for (pair<uintptr_t,shared_ptr<Hook>> h : hooks) {
|
||||||
|
h.second->disable();
|
||||||
|
}
|
||||||
return hooks.clear();
|
return hooks.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void disable() {
|
void disable() {
|
||||||
if (enabled) {
|
if (enabled) {
|
||||||
//cout << "Disabling: [" << this->orig << " <- " << this->detour << "]" << endl;
|
//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);
|
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;
|
enabled = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
void enable() {
|
void enable() {
|
||||||
if (!enabled) {
|
if (!enabled) {
|
||||||
//cout << "Enabling: [" << this->orig << " -> " << this->detour << "]" << endl;
|
//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);
|
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;
|
enabled = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void* func() {
|
template<typename T>
|
||||||
return this->orig;
|
T func() {
|
||||||
|
return reinterpret_cast<T>(this->orig);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -22,6 +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 "VMT_Hook.h"
|
||||||
#include "D3D8_Hook.h"
|
#include "D3D8_Hook.h"
|
||||||
|
|
||||||
HMODULE hD3D8Dll = 0;
|
HMODULE hD3D8Dll = 0;
|
||||||
|
@ -30,29 +31,58 @@ bool initialized = false;
|
||||||
bool running = true;
|
bool running = true;
|
||||||
HMODULE mod = 0;
|
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)
|
void MainLoop(HMODULE mod)
|
||||||
{
|
{
|
||||||
Sleep(100);
|
Sleep(100);
|
||||||
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 << "[F5 ] Show Overlay" << endl;
|
||||||
cout << "[F6 ] Show Alarm status" << 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 << "[F9 ] Dump Entity hashtable" << endl;
|
||||||
cout << "[F10] Enable python tracing" << endl;
|
cout << "[F10] Enable python tracing" << endl;
|
||||||
cout << "[ F ] \"Handbrake\" (*Will* crash the game after some time!)" << endl;
|
cout << "[ F ] \"Handbrake\" (*Will* crash the game after some time!)" << endl;
|
||||||
|
|
||||||
while (running)
|
while (running)
|
||||||
{
|
{
|
||||||
Sleep(100);
|
Sleep(100);
|
||||||
if (key_down_norepeat(VK_F10))
|
|
||||||
{
|
|
||||||
scrap_exec("dbg.settrace()");
|
|
||||||
}
|
|
||||||
while (key_down('F'))
|
while (key_down('F'))
|
||||||
{
|
{
|
||||||
scrap_exec("dbg.brake()");
|
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))
|
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);
|
FreeLibraryAndExitThread(mod, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -107,13 +136,12 @@ void handle_command(const char* cmd) {
|
||||||
int hooked_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 = Hook::get(hooked_console);
|
shared_ptr<Hook> hook = Hook::get(hooked_console);
|
||||||
t_func func= reinterpret_cast<t_func>(hook->func());
|
|
||||||
if (cmd[0] == '$') {
|
if (cmd[0] == '$') {
|
||||||
handle_command(++cmd);
|
handle_command(++cmd);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
hook->disable();
|
hook->disable();
|
||||||
int ret=func(cmd);
|
int ret= hook->func<t_func>()(cmd);
|
||||||
hook->enable();
|
hook->enable();
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -122,7 +150,6 @@ void hook_console() {
|
||||||
Hook::addr(reinterpret_cast<void*>(P_CON_HANDLER) , hooked_console);
|
Hook::addr(reinterpret_cast<void*>(P_CON_HANDLER) , hooked_console);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void DllPreInit(HMODULE _mod) {
|
void DllPreInit(HMODULE _mod) {
|
||||||
char mfn[1024];
|
char mfn[1024];
|
||||||
InitConsole();
|
InitConsole();
|
||||||
|
@ -151,4 +178,14 @@ void DllInit(HMODULE _mod)
|
||||||
DispatchMessage(&msg);
|
DispatchMessage(&msg);
|
||||||
}
|
}
|
||||||
return;
|
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>
|
</ItemDefinitionGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClInclude Include="D3D8_Hook.h" />
|
<ClInclude Include="D3D8_Hook.h" />
|
||||||
|
<ClInclude Include="VMT_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" />
|
||||||
|
|
|
@ -39,6 +39,9 @@
|
||||||
<ClInclude Include="D3D8_Hook.h">
|
<ClInclude Include="D3D8_Hook.h">
|
||||||
<Filter>Headerdateien</Filter>
|
<Filter>Headerdateien</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClInclude Include="VMT_Hook.h">
|
||||||
|
<Filter>Headerdateien</Filter>
|
||||||
|
</ClInclude>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClCompile Include="stdafx.cpp">
|
<ClCompile Include="stdafx.cpp">
|
||||||
|
|
|
@ -1,8 +1,10 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
//OFFSETS
|
//OFFSETS
|
||||||
#define O_MONEY 0x2090
|
#define O_MONEY 0x2090
|
||||||
#define O_ALARM 0x1C6C
|
#define O_ALARM 0x1C6C
|
||||||
#define O_ALARM_GROW 0x1C68
|
#define O_ALARM_GROW 0x1C68
|
||||||
|
#define O_HASHTABLE 0x4
|
||||||
|
|
||||||
//POINTERS
|
//POINTERS
|
||||||
#define P_WORLD 0x7FE944
|
#define P_WORLD 0x7FE944
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
struct HashTableEntry;
|
||||||
struct Vector3 {
|
struct Vector3 {
|
||||||
float x;
|
float x;
|
||||||
float y;
|
float y;
|
||||||
|
@ -32,3 +32,19 @@ struct Module
|
||||||
PyMod *mod;
|
PyMod *mod;
|
||||||
map<string, PyMethodDef*> methods;
|
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)
|
#define DLL_EXPORT extern "C" __declspec(dllexport)
|
||||||
void DllInit(HMODULE);
|
void DllInit(HMODULE);
|
||||||
void DllPreInit(HMODULE);
|
void DllPreInit(HMODULE);
|
||||||
|
void DllUnload(HMODULE);
|
||||||
|
|
||||||
|
|
||||||
BOOL APIENTRY DllMain(HMODULE hModule,
|
BOOL APIENTRY DllMain(HMODULE hModule,
|
||||||
DWORD ul_reason_for_call,
|
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);
|
hThread = CreateThread(NULL, NULL, (LPTHREAD_START_ROUTINE)DllInit, hModule, 0, 0);
|
||||||
break;
|
break;
|
||||||
case DLL_PROCESS_DETACH:
|
case DLL_PROCESS_DETACH:
|
||||||
|
DllUnload(hModule);
|
||||||
|
break;
|
||||||
case DLL_THREAD_ATTACH:
|
case DLL_THREAD_ATTACH:
|
||||||
case DLL_THREAD_DETACH:
|
case DLL_THREAD_DETACH:
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -9,24 +9,30 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Injector", "Injector\Inject
|
||||||
EndProject
|
EndProject
|
||||||
Global
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
|
Debug|Any CPU = Debug|Any CPU
|
||||||
Debug|x64 = Debug|x64
|
Debug|x64 = Debug|x64
|
||||||
Debug|x86 = Debug|x86
|
Debug|x86 = Debug|x86
|
||||||
|
Release|Any CPU = Release|Any CPU
|
||||||
Release|x64 = Release|x64
|
Release|x64 = Release|x64
|
||||||
Release|x86 = Release|x86
|
Release|x86 = Release|x86
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
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.ActiveCfg = Debug|x64
|
||||||
{72CB1B9E-50C7-4010-BEAD-82FACF87A87A}.Debug|x64.Build.0 = 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.ActiveCfg = Debug|Win32
|
||||||
{72CB1B9E-50C7-4010-BEAD-82FACF87A87A}.Debug|x86.Build.0 = 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.ActiveCfg = Release|x64
|
||||||
{72CB1B9E-50C7-4010-BEAD-82FACF87A87A}.Release|x64.Build.0 = 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.ActiveCfg = Release|Win32
|
||||||
{72CB1B9E-50C7-4010-BEAD-82FACF87A87A}.Release|x86.Build.0 = 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.ActiveCfg = Debug|x64
|
||||||
{7C91C225-D95C-4B7A-9251-0CE358BAF556}.Debug|x64.Build.0 = 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.ActiveCfg = Debug|Win32
|
||||||
{7C91C225-D95C-4B7A-9251-0CE358BAF556}.Debug|x86.Build.0 = 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.ActiveCfg = Release|x64
|
||||||
{7C91C225-D95C-4B7A-9251-0CE358BAF556}.Release|x64.Build.0 = Release|x64
|
{7C91C225-D95C-4B7A-9251-0CE358BAF556}.Release|x64.Build.0 = Release|x64
|
||||||
{7C91C225-D95C-4B7A-9251-0CE358BAF556}.Release|x86.ActiveCfg = Release|Win32
|
{7C91C225-D95C-4B7A-9251-0CE358BAF556}.Release|x86.ActiveCfg = Release|Win32
|
||||||
|
|
Loading…
Reference in a new issue