在注入的 DLL 中访问内存¶
当你试图从注入的 DLL 访问游戏内存时,进程句柄和 API 函数反而碍事。由于游戏与所有注入它的代码共享相同的内存空间,你可以从注入代码直接访问游戏内存。例如,要从注入代码访问 DWORD 值,你可以写:
DWORD
这只是把内存地址 adr 类型转换为 DWORD* 并解引用该指针得到一个 DWORD。像这样就地类型转换没问题,但如果像 Windows API 包装器一样抽象和泛化这些函数,你的内存访问代码会更干净。从注入代码内部访问内存的通用函数看起来像这样:
template<typename T>
T readMemory(LPVOID adr) {
return *((T*)adr);
}
template<typename T>
void writeMemory(LPVOID adr, T val) {
*((T*)adr) = val;
}
使用这些模板就像使用第一百二十三页「编写模板化的内存访问函数」下的函数一样。这里有一个示例:
这些调用与第一百二十四页清单 6-6 中的调用几乎相同;它们只是不需要把进程句柄作为参数,因为它们是从进程内部调用的。你可以通过创建第三个模板化函数 pointMemory() 让这个方法更灵活,如下所示:
这个函数跳过内存读取的解引用步骤,直接给你指向数据的指针。从那里,你可以通过自己解引用该指针读写内存,像这样:
DWORD* pValue = pointMemory<DWORD>(adr); // 指向
DWORD value = *pValue; // “读取”
(*pValue)++; // 递增并“写入”
有了 pointMemory() 这样的函数,你可以消除对 readMemory() 和 writeMemory() 的调用。你仍然需要提前找到 adr,但从那里,读取值、更改值并写回的代码会更容易理解。