Четене на памет от .exe + отместване?

Използвам ReadProcessMemory() на WinAPI, за да прочета малко "скрита" информация от игра.

Използвах Cheat Engine, за да открия статичните указатели, но не знам как да чета от тях. Cheat Engine ми дава насока към нещо подобно: "mygame.exe"+1C50

Наистина съм нов в WinAPI, как да конвертирам "mygame.exe"+1C50 в адрес, който мога да прочета с ReadProcessMemory()?

РЕДАКТИРАНЕ: Опитах се да опростя проблема, но предполагам, че трябваше просто да дам пълния код на първо място. Така че работя със статични адреси и многостепенни указатели тук, но все още съм заседнал с получаването на основния адрес или w/e.

Ето пълния код и снимка на моя адрес на cheat engine:

#include <iostream>
#include <windows.h>
#include <tlhelp32.h>

using namespace std;

HANDLE GetProcessHandle(const char *procName);

int main()
{
    const char *procName = "prism3d.exe";
    HANDLE hProc = GetProcessHandle(procName);
    if (hProc) {

     /* This works if I use the dynamic address (f.e. 0x02C2C4DC),
        but it changes every time I restart the game.
        I need to use the static address (prism3d.exe+A1C) to get
        the dynamic address for my "nuke".
      */
        float nuke;
        ReadProcessMemory(hProc, (void*)0x02C2C4DC, &nuke, 4, 0);
        cout << nuke;

    }
    CloseHandle(hProc);
    return 0;
}

HANDLE GetProcessHandle(const char *procName)
{
    HANDLE hProc = NULL;
    PROCESSENTRY32 pe32;
    pe32.dwSize = sizeof(PROCESSENTRY32);
    HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
    if (Process32First(hSnapshot, &pe32)) {
        do {
            if (!strcmp(pe32.szExeFile, procName)) {
                hProc = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pe32.th32ProcessID);
                break;
            }
        } while (Process32Next(hSnapshot, &pe32));
    }
    CloseHandle(hSnapshot);
    return hProc;
}

Редактиране 2: Ето как се опитах да прочета стойността на моя nuke, но ми дава произволни числа, различни всеки път, когато рестартирам играта (понякога е 0, понякога 324324324 и т.н...):

if (hProc) [

    DWORD baseAddr = (DWORD)GetModuleHandle(procName) + 0xA1C50; // also tried this with GetModuleHandle(NULL)
    DWORD mainAddr;
    ReadProcessMemory(hProc, (void*)(baseAddr + 0x111C), &mainAddr, 4, 0);

    // Nuke
    float nuke;
    DWORD nukeAddr;
    ReadProcessMemory(hProc, (void*)(mainAddr + 0x48), &nukeAddr, 4, 0);
    ReadProcessMemory(hProc, (void*)nukeAddr, &nuke, 4, 0);
    cout << nuke;
}

person Skamah One    schedule 31.07.2013    source източник
comment
Трябва да намерите основния адрес на game.dll и след това да добавите 1C50.   -  person Mats Petersson    schedule 31.07.2013


Отговори (1)


Базовото отместване обикновено е началото на модула в паметта, можете да го получите с GetModuleHandle (адресът, който това връща, е началото на PE в паметта). Казвам общо, защото някои конвенции дефинират основата спрямо началото на кодовата секция, която след това трябва да прочетете от PE.

можете да направите нещо като следното:

UINT_PTR addr = (UINT_PTR)GetModuleHandle("game.dll") + 0x1C50;
ReadProcessMemory(hProc,(void*)addr,pBuffer,nSize,&BytesRead);

Горното работи само ако работите в адресното пространство на процеса, който сте насочили (чрез инжектиране на dll), за да направите това чрез отдалечен процес (както показва вашият пример), трябва да изброите модулите за обработка, за да получите валиден манипулатор за модула, който ви интересува.

MSDN има пример за това тук, преработвайки го малко, можете да създадете функция, която проверява името и връща HMODULE, ако съвпада, като кастингът ще ви даде основния адрес на модула.

person Necrolis    schedule 31.07.2013
comment
Не работи, просто ми дава някакви странни номера, а не правилните адреси :/ Редактирах въпроса, вече имам .exe статичен указател - person Skamah One; 31.07.2013
comment
@SkamahOne проверихте ли дали адресните CE отчети са относителни към файла или секцията с код? и какви точно са странните числа? - person Necrolis; 31.07.2013
comment
Не, как да проверя това...? Имам указател със стойност "mygame.exe" + 1C50, който сочи към друг адрес, опитвам се да получа другия адрес. И само няколко огромни цели числа, 17512325403 и т.н. - person Skamah One; 31.07.2013
comment
@SkamahOne това огромно цяло число е адресът, ReadProcessMemory ще направи само едно ниво на индиректност, така че ще трябва да го използвате няколко пъти, за да следвате указателите - person Necrolis; 31.07.2013
comment
@SkamahOne: Току-що разбрах, че не работите в адресното пространство на процеса, така че GetModuleHandle ще се провали, вижте моята актуализация - person Necrolis; 31.07.2013
comment
Това наистина трябва да е приетият отговор. Аз също използвам CE и той дава адрес спрямо модул. Винаги използвам GetModuleHandle() + отместване, както предлага Necrolis, но го правя от инжектирана DLL (също както предлага Necrolis). Този отговор е правилен; Skamah One не работи в същото адресно пространство, което Necrolis също адресира. - person benbotto; 03.05.2016