Мне нужен базовый адрес exe «tibia.exe». Это то, что я получил до сих пор, но это не работает. Всегда возвращается 0
,
В чем дело?
DWORD MainWindow::getBaseAddress(DWORD dwProcessIdentifier)
{
TCHAR lpszModuleName[] = {'t','i','b','i','a','.','e','x','e','\0'}; //tibia.exe
HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE,
dwProcessIdentifier);
DWORD dwModuleBaseAddress = 0;
if(hSnapshot != INVALID_HANDLE_VALUE)
{
MODULEENTRY32 ModuleEntry32;
ModuleEntry32.dwSize = sizeof(MODULEENTRY32);
if(Module32First(hSnapshot, &ModuleEntry32))
{
do
{
if( wcscmp(ModuleEntry32.szModule, lpszModuleName) == 0)
{
dwModuleBaseAddress = (DWORD)ModuleEntry32.modBaseAddr;
break;
}
}
while(Module32Next(hSnapshot, &ModuleEntry32));
}
CloseHandle(hSnapshot);
}
return dwModuleBaseAddress;
}
//Call it here
tibiaWindow = FindWindow( L"TibiaClient", NULL);
DWORD PID;
GetWindowThreadProcessId( tibiaWindow, &PID );
DWORD baseAddress = getBaseAddress( PID );
if( baseAddress == 0 )
return false ;
Возможно, это только потому, что я использовал их до того, как ToolHelp32 был доступен (по крайней мере, в операционных системах на базе NT), но я склонен использовать функции PSAPI для такого рода задач. Используя их, код будет выглядеть так:
#include <windows.h>
#include <string>
#include <psapi.h>
#include <iostream>
int main(int argc, char **argv) {
HANDLE process = GetCurrentProcess();
if (argc != 1)
process = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, false, atoi(argv[1]));
HMODULE handles[2048];
DWORD needed;
EnumProcessModules(process, handles, sizeof(handles), &needed);
for (int i = 0; i < needed / sizeof(handles[0]); i++) {
MODULEINFO info;
char name[1024];
GetModuleBaseName(process, handles[i], name, sizeof(name));
if (std::string(name).find(".exe") != std::string::npos) {
GetModuleInformation(process, handles[i], &info, sizeof(info));
std::cout << name << ": " << info.lpBaseOfDll << "\n";
break;
}
}
}
В нынешнем виде это позволит вам ввести идентификатор процесса в командной строке и показать адрес загрузки первого модуля, который он найдет в этом процессе, с именем, включающим «.exe». Если вы не укажете идентификатор процесса, он будет искать в своем собственном процессе (демонстрирует, как работают функции, но в остальном практически бесполезен).
Используя ToolHelp32 или PSAPI, вы сталкиваетесь с аналогичным ограничением: вам нужно скомпилировать его в 64-битный исполняемый файл, чтобы он мог «видеть» другие 64-битные процессы (т. Е. При компиляции в виде 32-битного кода, они видят только другие 32-битные процессы).
Есть также некоторые процессы (например, CSRSS.exe), которые ни один не сможет успешно открыть / перечислить. Насколько я знаю, те же процессы будут успешными / неудачными с PSAPI против ToolHelp32.
PSAPI имеет один неловкость по сравнению с ToolHelp32: иметь дело (хорошо) с процессами, которые имеют много модулей, неуклюже (в лучшем случае). Ты звонишь EnumProcessModules
и, если вы не предоставили место для достаточного количества модулей, для параметра «Нужно» будет установлено пространство, необходимое для количества модулей в нем. Есть условие гонки: между временем, которое возвращается, и временем, когда вы звоните EnumProcessModules
Опять же, процесс мог загрузить больше DLL, так что второй вызов мог завершиться неудачно таким же образом.
На данный момент я только предположил, что ни один процесс не будет использовать более 2048 модулей. Чтобы быть действительно правильным, у вас должен быть цикл while (или, возможно, цикл do / while), который начинается с нуля, вызовы EnumProcessModules
чтобы выяснить, сколько места требуется, выделите его (возможно, с небольшим дополнительным объемом в случае, если он загружает больше библиотек DLL) и повторяйте, пока это не удастся.
Других решений пока нет …