Last active
February 14, 2016 12:54
-
-
Save jocopa3/59e99192128dd556e14d to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <Windows.h> | |
#include <stdint.h> | |
#include <Psapi.h> | |
#include "MinHook.h" | |
// Base address | |
static uintptr_t BaseAddress; | |
HANDLE process; | |
uintptr_t SlideAddress(uintptr_t offset) { | |
return BaseAddress + offset; | |
} | |
// Structs | |
typedef void Block; | |
struct Item | |
{ | |
uintptr_t** vtable; | |
short id; | |
}; | |
struct ItemInstance | |
{ | |
short count, data; | |
uintptr_t* tag; | |
Item* item; | |
Block* block; | |
}; | |
struct FullBlock | |
{ | |
uint8_t id, data; | |
}; | |
struct BlockPos | |
{ | |
int x, y, z; | |
}; | |
struct Player | |
{ | |
char filler[408]; | |
uintptr_t* region; | |
}; | |
// Function pointers | |
static void(*setBlock)(uintptr_t*, const BlockPos&, FullBlock*, int); | |
static FullBlock*(*getBlock)(uintptr_t*, FullBlock&, const BlockPos&); | |
// Hook functions | |
static void(*growTreeTramp)(uintptr_t*, uintptr_t*, const BlockPos&, uintptr_t*); // Trampoline to original function | |
// This function will replace the original growTree function in the game | |
void growTreeHook(uintptr_t* self, uintptr_t* BlockSource, const BlockPos& pos, uintptr_t* rand) | |
{ | |
// Get what sapling was planted | |
FullBlock sapling; | |
getBlock(BlockSource, sapling, pos); | |
// Use a simple wood block with the same wood type as the sapling | |
FullBlock wood{ 5, sapling.data }; | |
// Spell out the word "Magic" | |
for (int i = 0; i < 5; i++) { | |
setBlock(BlockSource, { pos.x, pos.y + i, pos.z }, &wood, 0); | |
setBlock(BlockSource, { pos.x + 4, pos.y + i, pos.z }, &wood, 0); | |
setBlock(BlockSource, { pos.x + 8, pos.y + i, pos.z }, &wood, 0); | |
setBlock(BlockSource, { pos.x + 12, pos.y + i, pos.z }, &wood, 0); | |
} | |
for (int i = 0; i < 3; i++) { | |
setBlock(BlockSource, { pos.x + 6, pos.y + i, pos.z }, &wood, 0); | |
setBlock(BlockSource, { pos.x + 10, pos.y + 2 + i, pos.z }, &wood, 0); | |
setBlock(BlockSource, { pos.x + 14, pos.y + i, pos.z }, &wood, 0); | |
setBlock(BlockSource, { pos.x + 16, pos.y + i, pos.z }, &wood, 0); | |
setBlock(BlockSource, { pos.x + 7, pos.y + 2 * i, pos.z }, &wood, 0); | |
setBlock(BlockSource, { pos.x + 11, pos.y + 2 * i, pos.z }, &wood, 0); | |
setBlock(BlockSource, { pos.x + 14, pos.y + 2 * i, pos.z }, &wood, 0); | |
setBlock(BlockSource, { pos.x + 16 + i, pos.y, pos.z }, &wood, 0); | |
setBlock(BlockSource, { pos.x + 16 + i, pos.y + 3, pos.z }, &wood, 0); | |
} | |
setBlock(BlockSource, { pos.x + 1, pos.y + 3, pos.z }, &wood, 0); | |
setBlock(BlockSource, { pos.x + 2, pos.y + 2, pos.z }, &wood, 0); | |
setBlock(BlockSource, { pos.x + 3, pos.y + 3, pos.z }, &wood, 0); | |
setBlock(BlockSource, { pos.x + 10, pos.y, pos.z }, &wood, 0); | |
} | |
// Sets a hook on the function at the original address | |
// hookFunction will take the place of the original function | |
// trampFunction can be used to call the original function again | |
BOOL setHook(uintptr_t origAddress, uintptr_t* hookFunction, uintptr_t* trampFunction) | |
{ | |
if (MH_CreateHook((LPVOID*)SlideAddress(origAddress), (LPVOID*)hookFunction, reinterpret_cast<LPVOID*>(trampFunction)) != MH_OK) | |
{ | |
return FALSE; | |
} | |
if (MH_EnableHook((LPVOID*)SlideAddress(origAddress)) != MH_OK) | |
{ | |
return FALSE; | |
} | |
return TRUE; | |
} | |
DWORD_PTR GetProcessBaseAddress(DWORD processID); | |
BOOL init() | |
{ | |
// Get the process base address and process handle with read/write access | |
DWORD procId = GetCurrentProcessId(); | |
process = OpenProcess(PROCESS_ALL_ACCESS | PROCESS_VM_OPERATION | PROCESS_QUERY_INFORMATION, FALSE, procId); | |
BaseAddress = (uintptr_t)GetProcessBaseAddress(procId); | |
// DO NOT MOVE THIS TO DLLMain; it has to be called exactly once and DLLMain is called multiple times | |
if (MH_Initialize() != MH_OK) | |
{ | |
return FALSE; // Failed to initialize MinHook, cannot continue | |
} | |
// Functions | |
setBlock = (void(*)(uintptr_t*, const BlockPos&, FullBlock*, int)) SlideAddress(0x39A970); | |
getBlock = (FullBlock*(*)(uintptr_t*, FullBlock&, const BlockPos&)) SlideAddress(0x399860); | |
// Hooks | |
BOOL hook = TRUE; | |
hook &= setHook(0x38AC50, (uintptr_t*)&growTreeHook, (uintptr_t*)&growTreeTramp); | |
// Return the status of the hooks | |
return hook; | |
} | |
BOOL deinit() | |
{ | |
if (MH_Uninitialize() != MH_OK) | |
{ | |
return FALSE; // Could not uninitialize MinHook | |
} | |
CloseHandle(process); // Close the handle on the process | |
return TRUE; | |
} | |
// begin | |
BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) | |
{ | |
switch (ul_reason_for_call) | |
{ | |
case DLL_PROCESS_ATTACH: | |
if (!init()) | |
{ | |
CloseHandle(process); | |
return FALSE; // Could not setup properly; report to detach the DLL and quit | |
} | |
break; | |
case DLL_THREAD_ATTACH: break; | |
case DLL_THREAD_DETACH: break; | |
case DLL_PROCESS_DETACH: | |
if (!deinit()) { | |
CloseHandle(process); | |
return FALSE; | |
} | |
break; | |
} | |
return TRUE; | |
} | |
DWORD_PTR GetProcessBaseAddress(DWORD processID) | |
{ | |
DWORD_PTR baseAddress = 0; | |
HANDLE processHandle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, processID); | |
HMODULE *moduleArray; | |
LPBYTE moduleArrayBytes; | |
DWORD bytesRequired; | |
if (processHandle) | |
{ | |
if (EnumProcessModules(processHandle, NULL, 0, &bytesRequired)) | |
{ | |
if (bytesRequired) | |
{ | |
moduleArrayBytes = (LPBYTE)LocalAlloc(LPTR, bytesRequired); | |
if (moduleArrayBytes) | |
{ | |
unsigned int moduleCount; | |
moduleCount = bytesRequired / sizeof(HMODULE); | |
moduleArray = (HMODULE *)moduleArrayBytes; | |
if (EnumProcessModules(processHandle, moduleArray, bytesRequired, &bytesRequired)) | |
{ | |
baseAddress = (DWORD_PTR)moduleArray[0]; | |
} | |
LocalFree(moduleArrayBytes); | |
} | |
} | |
} | |
CloseHandle(processHandle); | |
} | |
return baseAddress; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment