170 lines
4.0 KiB
C++
170 lines
4.0 KiB
C++
/**
|
|
* @ref https://github.com/arishackstv/cubemod/blob/master/src/core/memory/memory_helper.h
|
|
*/
|
|
#pragma once
|
|
|
|
#include <Windows.h>
|
|
#include <Psapi.h>
|
|
#include <sstream>
|
|
#include <vector>
|
|
#include <iostream>
|
|
#include <dbghelp.h>
|
|
|
|
#define CUBE_EXE_NAME "cubeworld.exe"
|
|
|
|
class MemoryHelper
|
|
{
|
|
public:
|
|
static MODULEINFO GetModuleInfo(HMODULE module_handle)
|
|
{
|
|
MODULEINFO module_info;
|
|
GetModuleInformation(GetCurrentProcess(), module_handle, &module_info, sizeof(MODULEINFO));
|
|
|
|
return module_info;
|
|
}
|
|
|
|
static MODULEINFO GetModuleInfo(char* module)
|
|
{
|
|
return GetModuleInfo(GetModuleHandle(module));
|
|
}
|
|
|
|
static uint64_t GetCubeBase()
|
|
{
|
|
static auto cube_info = GetModuleInfo(CUBE_EXE_NAME);
|
|
return (uint64_t)cube_info.lpBaseOfDll;
|
|
}
|
|
|
|
/**
|
|
* Searches the cubeworld module for any instance of a specified string, and replaces it in memory
|
|
* @param search
|
|
* @param replace
|
|
*/
|
|
static void FindAndReplaceString(std::wstring search, std::wstring replace)
|
|
{
|
|
MODULEINFO module_info;
|
|
HMODULE module_handle = GetModuleHandle(CUBE_EXE_NAME);
|
|
if (!module_handle) return;
|
|
|
|
GetModuleInformation(GetCurrentProcess(), module_handle, &module_info, sizeof(MODULEINFO));
|
|
|
|
uint64_t base_address = (uint64_t)module_info.lpBaseOfDll;
|
|
uint64_t module_size = module_info.SizeOfImage;
|
|
|
|
auto search_cstr = search.c_str();
|
|
auto search_len = search.size();
|
|
|
|
for (uint64_t i = 0; i < module_size - search_len * 2; i++)
|
|
{
|
|
uint16_t* check_addr = (uint16_t*)(base_address + i);
|
|
|
|
bool found = true;
|
|
for (int b = 0; b < search_len; b++)
|
|
{
|
|
uint16_t pattern_byte = search_cstr[b];
|
|
uint16_t check_byte = check_addr[b];
|
|
|
|
//If any don't match its not the right pattern
|
|
if (pattern_byte != check_byte)
|
|
{
|
|
found = false;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (found)
|
|
{
|
|
//Replace it :D
|
|
PatchMemory((void*)check_addr, (void*)replace.c_str(), replace.size() * 2 + 2);
|
|
}
|
|
}
|
|
}
|
|
|
|
//Default to cubeworld module
|
|
static uint64_t FindPattern(std::string pattern, bool get_end = false)
|
|
{
|
|
return FindPattern(CUBE_EXE_NAME, pattern, get_end);
|
|
}
|
|
|
|
static uint64_t FindPattern(std::string module, std::string pattern, bool get_end = false)
|
|
{
|
|
std::vector<uint8_t> pattern_bytes;
|
|
|
|
std::istringstream iss(pattern);
|
|
for (std::string s; iss >> s;)
|
|
{
|
|
if (s == "?" || s == "??") pattern_bytes.push_back(NULL);
|
|
else pattern_bytes.push_back(std::stoi(s, 0, 16));
|
|
}
|
|
|
|
MODULEINFO module_info;
|
|
HMODULE module_handle = GetModuleHandle(module.c_str());
|
|
if (!module_handle) return 0;
|
|
|
|
GetModuleInformation(GetCurrentProcess(), module_handle, &module_info, sizeof(MODULEINFO));
|
|
|
|
uint64_t base_address = (uint64_t)module_info.lpBaseOfDll;
|
|
uint64_t module_size = module_info.SizeOfImage;
|
|
|
|
for (uint64_t i = 0; i < module_size - pattern_bytes.size(); i++)
|
|
{
|
|
uint64_t check_addr = base_address + i;
|
|
|
|
bool found = true;
|
|
for (int b = 0; b < pattern_bytes.size(); b++)
|
|
{
|
|
uint8_t pattern_byte = pattern_bytes[b];
|
|
uint8_t check_byte = *(uint8_t*)(check_addr + b);
|
|
|
|
//NULL byte can match anything
|
|
if (pattern_byte == NULL) continue;
|
|
|
|
//If any don't match its not the right pattern
|
|
if (pattern_byte != check_byte)
|
|
{
|
|
found = false;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (found)
|
|
{
|
|
if (get_end) check_addr = check_addr + pattern_bytes.size();
|
|
|
|
return check_addr;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static void PatchMemory(void* dst, void* src, uint64_t size)
|
|
{
|
|
DWORD OldProtection;
|
|
if (VirtualProtect(dst, size, PAGE_EXECUTE_READWRITE, &OldProtection))
|
|
{
|
|
memcpy(dst, src, size);
|
|
VirtualProtect(dst, size, OldProtection, &OldProtection);
|
|
}
|
|
}
|
|
|
|
template<class T>
|
|
static void PatchMemory(uint64_t dst, T src)
|
|
{
|
|
PatchMemory((void*)dst, src);
|
|
}
|
|
|
|
template<class T>
|
|
static void PatchMemory(void* dst, T src)
|
|
{
|
|
if (!dst) return;
|
|
|
|
DWORD OldProtection;
|
|
auto size = sizeof(T);
|
|
if (VirtualProtect(dst, size, PAGE_EXECUTE_READWRITE, &OldProtection))
|
|
{
|
|
memcpy(dst, &src, size);
|
|
VirtualProtect(dst, size, OldProtection, &OldProtection);
|
|
}
|
|
}
|
|
};
|