A C++17 header-only library for Windows targeting game hacking and reverse engineering workflows.
Drop it into any project via CMake — no compilation step required.
| OS | Windows (x86 / x64) |
| C++ Standard | C++17 or later |
| CMake | 3.16 or later |
include(FetchContent)
FetchContent_Declare(
GHCore
GIT_REPOSITORY https://github.com/Bourdon94m/GHCore.git
GIT_TAG main
)
FetchContent_MakeAvailable(GHCore)
target_link_libraries(your_target PRIVATE GHCore)git submodule add https://github.com/Bourdon94m/GHCore.git third_party/GHCoreadd_subdirectory(third_party/GHCore)
target_link_libraries(your_target PRIVATE GHCore)Copy the src/ folder into your project and add the include path to your build system.
Include everything at once:
#include "GHCore.hpp"Or include only what you need:
#include "Memory/Memory.hpp"
#include "Memory/Scan.hpp"
#include "Process/Process.hpp"
#include "Hooks/VmtHook.hpp"
#include "Hooks/DetourHook.hpp"
#include "Hooks/IatHook.hpp"
#include "Inject/Inject.hpp"
#include "Utils/Utils.hpp"Read and write memory in the current process or a remote one.
// Internal (same process)
int hp = GHCore::Memory::Read<int>(address);
GHCore::Memory::Write<int>(address, 100);
// Safe read — won't crash on invalid pages
int val;
if (GHCore::Memory::SafeRead<int>(address, val)) { ... }
// Multi-level pointer chain
uintptr_t final = GHCore::Memory::FollowPointer(base, { 0x30, 0x10, 0x4C });
// External (remote process)
int remoteHp = GHCore::Memory::ReadEx<int>(hProcess, address);
GHCore::Memory::WriteEx<int>(hProcess, address, 100);
// Page protection & allocation
GHCore::Memory::Unprotect(address, size);
uintptr_t remoteMem = GHCore::Memory::AllocEx(hProcess, 0x1000);
GHCore::Memory::FreeEx(hProcess, remoteMem);IDA-style pattern scanning with a rich result type.
// Scan a loaded module
auto result = GHCore::Scan::FindInModule(nullptr, "48 89 5C 24 ?? 57 48 83 EC ??");
// Scan a specific PE section
auto result = GHCore::Scan::FindInSection(nullptr, ".text", "48 8B 05 ?? ?? ?? ??");
// Scan a raw range
auto result = GHCore::Scan::Find(base, size, "CC CC CC");
// Find all occurrences
auto all = GHCore::Scan::FindAll(base, size, "CC CC CC");ScanResult helpers:
if (result) {
uintptr_t off = result.Offset(+3); // address ± offset
uintptr_t rip = result.ResolveRip(3, 7); // resolve RIP-relative displacement
uintptr_t deref = result.Deref(); // dereference pointer at address
float value = result.Read<float>(0x8); // read typed value at address + offset
}Process and module enumeration utilities.
DWORD pid = GHCore::Process::GetPidByName(L"game.exe");
HANDLE hProc = GHCore::Process::Open(pid);
// Module bases
uintptr_t base = GHCore::Process::GetModuleBase(); // current exe
uintptr_t remoteBase = GHCore::Process::GetModuleBaseEx(hProc, L"test.exe"); // remote
// List modules and threads
auto modules = GHCore::Process::GetModules(hProc);
auto threads = GHCore::Process::GetThreadIds(pid);
// Resolve a RIP-relative instruction
uintptr_t target = GHCore::Process::ResolveRip(instrAddr, 3, 7);Inline JMP trampoline hook. Works on both x86 and x64. Allocates a trampoline so the original function can still be called.
using tMessageBox = int(WINAPI*)(HWND, LPCSTR, LPCSTR, UINT);
int WINAPI MyMessageBox(HWND hWnd, LPCSTR text, LPCSTR caption, UINT type) {
// call original
return hook.CallOriginal<tMessageBox>(hWnd, text, "Hooked!", type);
}
GHCore::Hook::DetourHook hook;
hook.Install(reinterpret_cast<uintptr_t>(&MessageBoxA),
reinterpret_cast<uintptr_t>(&MyMessageBox));
// ...
hook.Remove();Replace a virtual function slot directly in an object's vtable.
// Save the original and patch slot 2
void* original = GHCore::Hook::VmtHook::Hook(pObject, 2, &MyVirtFunc);
// Restore
GHCore::Hook::VmtHook::Unhook(pObject, 2, original);Patch an entry in a module's Import Address Table. Intercepts calls to a Windows API without modifying the function itself.
GHCore::Hook::IatHook iatHook;
iatHook.Install(nullptr, "MessageBoxA", &MyMessageBoxA);
// Call the real function through the saved original
auto orig = iatHook.Original<decltype(&MessageBoxA)>();
orig(nullptr, "text", "caption", MB_OK);
iatHook.Remove();Three DLL / shellcode injection strategies.
HANDLE hProc = GHCore::Process::Open(pid);
// Classic LoadLibrary via CreateRemoteThread
GHCore::Inject::LoadLibrary(hProc, L"C:\\payload.dll");
// Raw shellcode
GHCore::Inject::Shellcode(hProc, shellcode, sizeof(shellcode));
// APC injection (fires on alertable threads)
GHCore::Inject::Apc(hProc, pid, L"C:\\payload.dll");Thread-safe logger with optional console window and file output. Useful when running as an injected DLL.
auto& log = GHCore::Utils::Logger::Get();
log.AllocConsole("My Tool"); // open a console window
log.OpenFile("log.txt"); // also write to file
log.SetMinLevel(GHCore::Utils::LogLevel::Debug);
log.Debug("debug message");
log.Info("info message");
log.Warning("something odd");
log.Error("something broke");Output format: [HH:MM:SS][LEVEL] message
GHCore/
├── src/
│ ├── GHCore.hpp ← single include
│ ├── Memory/
│ │ ├── Memory.hpp
│ │ └── Scan.hpp
│ ├── Process/
│ │ └── Process.hpp
│ ├── Hooks/
│ │ ├── DetourHook.hpp
│ │ ├── VmtHook.hpp
│ │ └── IatHook.hpp
│ ├── Inject/
│ │ └── Inject.hpp
│ ├── Utils/
│ │ └── Utils.hpp
│ └── example/
│ └── main.cpp
└── CMakeLists.txt
GHCore is header-only — there's no .lib to generate or link. Just include the headers!
The example can be built to see how to use the library:
cmake -S . -B build
cmake --build buildThis generates example.exe in build/Debug/ (or build/Release/).
To skip building the example:
cmake -S . -B build -DGHCORE_BUILD_EXAMPLE=OFFThis project is provided for educational purposes. Use responsibly and only on software you own or have explicit permission to modify.