内存 Patch

读写、NOP、跳转重定向与可逆修改

shared/Patch.h · plugin::patch

大多数写入 API 的 vp 默认为 true(内部 VirtualProtect)。改代码前先 GetRaw 备份,关闭功能时写回备份。

可逆

可开关的修改务必保存原始字节或数值,不要把「默认值」写死在还原路径里。

写 NOP

Nop / NopRestore

Nop 写入 0x90NopRestore 还原 SDK 记录的那一次 Nop。

static void Nop(uintptr_t address, size_t size, bool vp = true);
static void NopRestore(uintptr_t address, bool vp = true);

读写 1 字节

SetChar / GetChar 族
static void SetChar(uintptr_t address, char value, bool vp = true);
static void SetUChar(uintptr_t address, unsigned char value, bool vp = true);
static char GetChar(uintptr_t address, bool vp = true);
static unsigned char GetUChar(uintptr_t address, bool vp = true);

读写 2 字节

SetShort / GetShort 族
static void SetShort(uintptr_t address, short value, bool vp = true);
static void SetUShort(uintptr_t address, unsigned short value, bool vp = true);
static short GetShort(uintptr_t address, bool vp = true);
static unsigned short GetUShort(uintptr_t address, bool vp = true);

读写 4 字节整数

SetInt / GetInt 族
static void SetInt(uintptr_t address, uintptr_t value, bool vp = true);
static void SetUInt(uintptr_t address, uintptr_t value, bool vp = true);
static uintptr_t GetInt(uintptr_t address, bool vp = true);
static uintptr_t GetUInt(uintptr_t address, bool vp = true);

读写 float

SetFloat / GetFloat

改倍率等浮点配置时:先备份再写,关闭时还原。

static void SetFloat(uintptr_t address, float value, bool vp = true);
static float GetFloat(uintptr_t address, bool vp = true);

读写指针

SetPointer / GetPointer

按指针宽度读写。

static void SetPointer(uintptr_t address, injector::memory_pointer_raw value, bool vp = true);
static void* GetPointer(uintptr_t address, bool vp = true);

模板读写 POD

Set / Get(模板)

任意 POD 类型读写。

template <typename T>
static void Set(uintptr_t address, T value, bool vp = true);

template <typename T>
static T Get(uintptr_t address, bool vp = true);

读写原始字节

SetRaw / GetRaw

任意长度字节块。修改代码路径前务必备份。

static void SetRaw(uintptr_t address, void* value, size_t size, bool vp = true);
static void GetRaw(uintptr_t address, void* ret, size_t size, bool vp = true);

重定向 call / jump

RedirectCall / RedirectJump / RedirectShortJump

改写 E8 call、E9 跳转或短跳。address 指向 指令本身 的起始地址。

static void RedirectCall(uintptr_t address, injector::memory_pointer_raw func, bool vp = true);
static void RedirectJump(uintptr_t address, injector::memory_pointer_raw func, bool vp = true);
static void RedirectShortJump(uintptr_t address, injector::memory_pointer_raw dest = nullptr, bool vp = true);

替换函数入口

ReplaceFunction / ReplaceFunctionCall

入口整体替换,或只替换 call 点。

static void ReplaceFunction(uintptr_t address, void* func, bool vp = true);
static void ReplaceFunctionCall(uintptr_t address, void* func, bool vp = true);

写 ret 返回

PutRetn / PutRetn0 / PutRetn1

写入返回指令。Retn0 / Retn1 会先让函数返回 0 / 1。BytesToPop 用于 stdcall 清栈。

static void PutRetn(uintptr_t address, unsigned short BytesToPop = 0, bool vp = true);
static void PutRetn0(uintptr_t address, unsigned short BytesToPop = 0, bool vp = true);
static void PutRetn1(uintptr_t address, unsigned short BytesToPop = 0, bool vp = true);

解析跳转目标

TranslateCallOffset / TranslateJumpOffset

解析 E8 / E9 的目标地址。若该处不是对应 opcode,结果为空。

template <typename T>
static T TranslateCallOffset(uintptr_t address);

template <typename T>
static T TranslateJumpOffset(uintptr_t address);

批量改多地址

同一操作可对一组地址执行。

template <typename T>
static void Set(std::vector<uintptr_t> const& addresses, T value, bool vp = true);
static void SetFloat(std::vector<uintptr_t> const& addresses, float value, bool vp = true);
static void Nop(std::vector<uintptr_t> const& addresses, size_t size, bool vp = true);
static void RedirectCall(std::vector<uintptr_t> const& addresses, /* ... */, bool vp = true);
static void RedirectJump(std::vector<uintptr_t> const& addresses, /* ... */, bool vp = true);

On this page