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

0

Мне нужен базовый адрес 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 ;
  • 2
    lpszModuleName отсутствует lpszModuleName '\0' в конце.
  • 0
    @halex спасибо, сейчас проверю
Показать ещё 13 комментариев
Теги:
winapi

1 ответ

1

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

  • 0
    Сравнение строк несколько хрупкое. Он соответствует любому имени модуля, содержащему .exe , например myapp.exe.resources.dll . Поддержка UNICODE тоже не помешает.
  • 0
    @IInspectable: Да - остальное предназначено почти исключительно как демонстрация того, как использовать эти функции.
Показать ещё 1 комментарий

Ещё вопросы

Сообщество Overcoder
Наверх
Меню