使用 ReadProcessMemory 从进程读取相对于基址的地址

Reading an address relative to the base address from a process with ReadProcessMemory

本文关键字:地址 相对于 读取 ReadProcessMemory 进程 使用      更新时间:2023-10-16
几年前

,我做了一些记忆阅读的东西,主要是为了好玩。当时的标准是32位。

我已经修改了现有代码以在 x64 系统上运行,但似乎无法读取相对于进程基址的地址。我的日常工作并不涉及低级编程,所以我很生疏。

简而言之:我想读取一个内存地址,相对于进程的基址,这样我就可以做一些有用的事情。

在作弊引擎中,我可以使用:

哇-64.exe + 0x173D390

阅读我的地址没有问题。

尝试模拟时,我可以确定(我认为成功(进程基址。但是,当我尝试从指针读取"地址"时,我总是收到0xCCCCCCCC。显然有些不对劲,但我正在努力寻找如何进一步调试它......

#include "stdafx.h"
#include <iostream>
#include <string>
#include <windows.h>
#include <psapi.h>
using namespace std;
UINT_PTR GetProcessBaseAddress(DWORD processID, HANDLE *processHandle);
int main()
{
    HWND WindowHandle = FindWindow(nullptr, L"World of Warcraft");
    DWORD PID;
    GetWindowThreadProcessId(WindowHandle, &PID);
    HANDLE      processHandle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, PID);
    if (processHandle == 0) {
        cout << "Could not open process";
        return 1;
    }
    UINT_PTR BaseAddress = GetProcessBaseAddress(PID, &processHandle);
    UINT_PTR PlayerBaseAddress = (BaseAddress + 0x173D390);
    UINT_PTR PlayerBase;
    ReadProcessMemory(processHandle, (void *)PlayerBaseAddress, &PlayerBase, sizeof(PlayerBase, 0));

    cout << "Process base: " << hex << BaseAddress << ", Player Base Address: " << hex << PlayerBaseAddress << ", Actual address: " << hex << PlayerBase << "n";
    system("PAUSE");
    return 0;
}

UINT_PTR GetProcessBaseAddress(DWORD processID, HANDLE *processHandle)
{
    DWORD_PTR   baseAddress = 0;
    HMODULE     *moduleArray;
    LPBYTE      moduleArrayBytes;
    DWORD       bytesRequired;
    if (*processHandle)
    {
        if (EnumProcessModulesEx(*processHandle, NULL, 0, &bytesRequired, 0x02))
        {
            if (bytesRequired)
            {
                moduleArrayBytes = (LPBYTE)LocalAlloc(LPTR, bytesRequired);
                if (moduleArrayBytes)
                {
                    unsigned int moduleCount;
                    moduleCount = bytesRequired / sizeof(HMODULE);
                    moduleArray = (HMODULE *)moduleArrayBytes;
                    if (EnumProcessModulesEx(*processHandle, moduleArray, bytesRequired, &bytesRequired, 0x02))
                    {
                        baseAddress = (DWORD_PTR)moduleArray[0];
                    }
                    LocalFree(moduleArrayBytes);
                }
            }
        }
        CloseHandle(*processHandle);
    }
    return baseAddress;
}

编辑控制台实际输出

Process base: 7ff7395d0000, Player Base Address: 7ff73ad0d390, Actual address: cccccccccccccccc

感谢 RbMm,我不小心在 GetProcessBaseAddress 中留下了对 CloseHandle(( 的调用。删除它并将其放在 main(( 中解决了问题。

该程序似乎仅在VS中的"发布"模式下才能正确执行。


如果您只想获取EXE的基址,则不需要枚举所有进程模块。 EXE始终是进程中的第一个模块 - 因此足够的查询只有一个:

ULONG GetProcessBaseAddress(HANDLE hProcess, HMODULE* phmod)
{
    ULONG cb;
    return EnumProcessModulesEx(hProcess, phmod, sizeof(HMODULE), &cb, LIST_MODULES_DEFAULT) ? 0 : GetLastError();
}

并像这样使用

        union {
            HMODULE hmod;
            ULONG_PTR BaseAddress;
        };
        ULONG err = GetProcessBaseAddress(h, &hmod);
        if (!err)
        {
            DbgPrint("%pn", BaseAddress + 0x173D390 );
        }