Files
ps4-fortniteserver/OrbisHooker/source/hook/memory.cpp
T
2026-04-23 22:01:27 +02:00

67 lines
2.2 KiB
C++

// OrbisHookah, Copyright @2026 apfelteesaft
#include "memory.h"
#include <sys/mman.h> // mmap, munmap, mprotect, MAP_ANON, MAP_PRIVATE, PROT_*
#include <string.h>
#include <stdint.h>
namespace Hookah {
// ---------------------------------------------------------------------------
// Internal helpers
// ---------------------------------------------------------------------------
// Round 'addr' down to the nearest PS4 page boundary.
static inline uintptr_t PageFloor(uintptr_t addr) {
return addr & ~(kPageSize - 1u);
}
// ---------------------------------------------------------------------------
// Public API
// ---------------------------------------------------------------------------
void* AllocateExecutable(size_t size) {
// MAP_ANON is the BSD name for MAP_ANONYMOUS; both are 0x1000 on FreeBSD.
// Combining PROT_WRITE + PROT_EXEC is required so we can write the
// trampoline bytes and then execute them without a second mprotect call.
void* mem = mmap(nullptr, size,
PROT_READ | PROT_WRITE | PROT_EXEC,
MAP_PRIVATE | MAP_ANON, -1, 0);
// mmap returns MAP_FAILED ((void*)-1) on error, not nullptr.
if (mem == reinterpret_cast<void*>(-1))
return nullptr;
return mem;
}
void FreeExecutable(void* addr, size_t size) {
if (addr && addr != reinterpret_cast<void*>(-1))
munmap(addr, size);
}
bool ProtectMemory(void* address, size_t size, int prot) {
// mprotect requires that the start address be page-aligned on PS4.
uintptr_t raw = reinterpret_cast<uintptr_t>(address);
uintptr_t aligned = PageFloor(raw);
size_t span = size + (raw - aligned); // cover the full original range
return mprotect(reinterpret_cast<void*>(aligned), span, prot) == 0;
}
bool SafeWrite(void* dst, const void* src, size_t size) {
// Temporarily open the target page for writing.
if (!ProtectMemory(dst, size, PROT_READ | PROT_WRITE | PROT_EXEC))
return false;
memcpy(dst, src, size);
// Restore to read+execute; the page no longer needs to be writable at
// runtime (only the trampoline buffer stays RWX after allocation).
ProtectMemory(dst, size, PROT_READ | PROT_EXEC);
return true;
}
} // namespace Hookah