我想对@Adam Rosenfield的回答进行一些详细说明。我将以英雄联盟为例。
为了打开进程(获取句柄),我们需要它的PID(进程ID)。我们可以通过窗口句柄(HWND)来实现,因为通常已知窗口的标题。
//You will need to change this the name of the window of the foreign process
HWND WindowHandle = FindWindow(nullptr, L"League of Legends (TM) Client");
DWORD PID;
GetWindowThreadProcessId(WindowHandle, &PID);
PVOID hProcess = OpenProcess(PROCESS_VM_READ | PROCESS_QUERY_INFORMATION, 0, PID);
现在我们能够获取进程的句柄,让我们继续。
HMODULE Module = GetModule();
DWORD BaseAddress = (DWORD)Module;
GetModule函数
HMODULE GetModule()
{
HMODULE hMods[1024];
HANDLE pHandle = GetHandle();
DWORD cbNeeded;
unsigned int i;
if (EnumProcessModules(pHandle, hMods, sizeof(hMods), &cbNeeded))
{
for (i = 0; i < (cbNeeded / sizeof(HMODULE)); i++)
{
TCHAR szModName[MAX_PATH];
if (GetModuleFileNameEx(pHandle, hMods[i], szModName, sizeof(szModName) / sizeof(TCHAR)))
{
wstring wstrModName = szModName;
wstring wstrModContain = L"League of Legends.exe";
if (wstrModName.find(wstrModContain) != string::npos)
{
CloseHandle(pHandle);
return hMods[i];
}
}
}
}
return nullptr;
}
就我个人而言,我喜欢编写两个单独的函数,一个用于获取句柄,另一个用于获取模块。
这样我们就成功地获取了外部进程的基地址。
ReadProcessMemory()
。它的hProcess
参数可以是从OpenProcess()
获取的HANDLE
。它的lpBaseAddress
参数是相对于被访问的进程的,所以你不需要计算它,如果你知道它是什么,就硬编码它,例如:hProcess = OpenProcess(...); ReadProcessMemory(hProcess, (void*)0x011F9B08, ...);
。 - Remy Lebeau