Получение базового адреса не работает

Мне нужен базовый адрес 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 ;

0

Решение

Возможно, это только потому, что я использовал их до того, как 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) и повторяйте, пока это не удастся.

1

Другие решения

Других решений пока нет …