从".exe" + 偏移中读取内存?

Reading memory from ".exe" + offset?

本文关键字:读取 内存 exe      更新时间:2023-10-16

我正在使用WinAPI的ReadProcessMemory()从游戏中读取一些"隐藏"信息。

我已经用作弊引擎找到了静态指针,但我不知道如何从中读取。作弊引擎给了我一个类似的指针:"mygame.exe"+1C50

我真的是WinAPI的新手,如何将"mygame.exe"+1C50转换为可以用ReadProcessMemory()读取的地址?

编辑:我试图简化这个问题,但我想我应该首先给出完整的代码。所以我在这里使用静态地址和多级指针,但我仍然无法获得基地址或w/e。

这是我的作弊引擎地址的完整代码和图片:

#include <iostream>
#include <windows.h>
#include <tlhelp32.h>
using namespace std;
HANDLE GetProcessHandle(const char *procName);
int main()
{
    const char *procName = "prism3d.exe";
    HANDLE hProc = GetProcessHandle(procName);
    if (hProc) {
     /* This works if I use the dynamic address (f.e. 0x02C2C4DC),
        but it changes every time I restart the game.
        I need to use the static address (prism3d.exe+A1C) to get
        the dynamic address for my "nuke".
      */
        float nuke;
        ReadProcessMemory(hProc, (void*)0x02C2C4DC, &nuke, 4, 0);
        cout << nuke;
    }
    CloseHandle(hProc);
    return 0;
}
HANDLE GetProcessHandle(const char *procName)
{
    HANDLE hProc = NULL;
    PROCESSENTRY32 pe32;
    pe32.dwSize = sizeof(PROCESSENTRY32);
    HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
    if (Process32First(hSnapshot, &pe32)) {
        do {
            if (!strcmp(pe32.szExeFile, procName)) {
                hProc = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pe32.th32ProcessID);
                break;
            }
        } while (Process32Next(hSnapshot, &pe32));
    }
    CloseHandle(hSnapshot);
    return hProc;
}

编辑2:以下是我如何尝试读取我的核弹值,但它给了我随机数,每次我重新启动游戏时都会有所不同(有时是0,有时是324324324,等等):

if (hProc) [
    DWORD baseAddr = (DWORD)GetModuleHandle(procName) + 0xA1C50; // also tried this with GetModuleHandle(NULL)
    DWORD mainAddr;
    ReadProcessMemory(hProc, (void*)(baseAddr + 0x111C), &mainAddr, 4, 0);
    // Nuke
    float nuke;
    DWORD nukeAddr;
    ReadProcessMemory(hProc, (void*)(mainAddr + 0x48), &nukeAddr, 4, 0);
    ReadProcessMemory(hProc, (void*)nukeAddr, &nuke, 4, 0);
    cout << nuke;
}

基偏移量通常是内存中模块的开始,您可以使用GetModuleHandle(它返回的地址是内存中PE的开始)来获得它。我之所以这么说,是因为一些约定定义了相对于代码部分开头的基础,然后您需要从PE中读取

您可以执行以下操作:

UINT_PTR addr = (UINT_PTR)GetModuleHandle("game.dll") + 0x1C50;
ReadProcessMemory(hProc,(void*)addr,pBuffer,nSize,&BytesRead);

以上仅适用于您在目标进程的地址空间中运行(通过dll注入)的情况,要通过远程进程(如您的示例所示)执行此操作,您需要枚举处理模块以获得您感兴趣的模块的有效句柄。

MSDN在这里有一个例子,对它进行一点重构,您可以创建一个函数来检查名称,如果匹配,则返回HMODULE,强制转换它将为您提供模块基地址。