Skip to content

Instantly share code, notes, and snippets.

@jocopa3
Last active February 14, 2016 12:54
Show Gist options
  • Save jocopa3/59e99192128dd556e14d to your computer and use it in GitHub Desktop.
Save jocopa3/59e99192128dd556e14d to your computer and use it in GitHub Desktop.
#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