1

Тема: AHK: Чтение памяти из процесса.

Добрый день. Изучаю AHK самоучением. Но тут столкнулся с проблемой, которую открытием готового скрипта и последующему изучению не разрешить (тот же самый sampUDF). Есть к примеру Приложение (Игра) и я хочу найти тот же самый Hp. Колдовал с CE, но так дельного ничего и не получилось, ибо даже применить найденный процесс/проверить нормально не могу.
На lua для этой игры (css v34) нашел подобный код.


client = getBaseAddr("client.dll")
engine = getBaseAddr("engine.dll")
myNameAddr = readmem(engine+0x3B9F24,4)
tAddr = readmem(client+0x4D300C,4)+0x1450
radar = readmem(client+0x510C80,4)
no = 0x38 --name
ho = 0x5C --health
xo = 0x60 --x pos
...

И там еще куча таких же скриптов, но получают они все эти переменные примерно одинаково. Каков алгоритм моих действий, если я хочу создать функцию получающую тот же самый Hp после запуска игры?

2

Re: AHK: Чтение памяти из процесса.

Никогда не приходилось читать память вручную, но если я правильно понимаю то:


pid := getPID()
hGame := openProcess(pid)
client := getModuleBaseAddress("client.dll", hGame)
engine := getModuleBaseAddress("engine.dll", hGame)


openProcess(dwPID, dwRights = 0x1F0FFF) {
    hProcess := DllCall("OpenProcess", "UInt", dwRights
                        , "int",  0
                        , "UInt", dwPID
                        , "Uint")
    if(hProcess == 0) {
        ErrorLevel := ERROR_OPEN_PROCESS
        return 0
    }
    
    ErrorLevel := ERROR_OK
    return hProcess
}

getPID() {
    local dwPID := 0
    WinGet, dwPID, PID, ahk_class Grand theft auto San Andreas ; тут класс окна вашей игры определяется через win spy
    return dwPID
}

getModuleBaseAddress(sModule, hProcess) {
    if(!sModule) {
        ErrorLevel := ERROR_MODULE_NOT_FOUND
        return 0
    }
    
    if(!hProcess) {
        ErrorLevel := ERROR_INVALID_HANDLE
        return 0
    }
    
    dwSize = 1024*4                    ; 1024 * sizeof(HMODULE = 4)
    VarSetCapacity(hMods, dwSize)    
    VarSetCapacity(cbNeeded, 4)        ; DWORD = 4
    dwRet := DllCall(    "Psapi.dll\EnumProcessModules"
                        , "UInt", hProcess
                        , "UInt", &hMods
                        , "UInt", dwSize
                        , "UInt*", cbNeeded
                        , "UInt")
    if(dwRet == 0) {
        ErrorLevel := ERROR_ENUM_PROCESS_MODULES
        return 0
    }
    
    dwMods := cbNeeded / 4            ; cbNeeded / sizeof(HMDOULE = 4)
    i := 0
    VarSetCapacity(hModule, 4)        ; HMODULE = 4
    VarSetCapacity(sCurModule, 260)    ; MAX_PATH = 260
    while(i < dwMods) {
        hModule := NumGet(hMods, i*4)
        DllCall("Psapi.dll\GetModuleFileNameEx"
                , "UInt", hProcess
                , "UInt", hModule
                , "Str", sCurModule
                , "UInt", 260)
        SplitPath, sCurModule, sFilename
        if(sModule == sFilename) {
            ErrorLevel := ERROR_OK
            return hModule
        }
        i := i + 1
    }
    
    ErrorLevel := ERROR_MODULE_NOT_FOUND
    return 0
}

Посмотрите через читенджин в каком формате хранятся данные по этим адресам и используйте соответствующую функцию из того же UDF. Правда все вышенаписанное может оказаться в корне неверным, повторюсь: я никогда не читал память и мои знания лишь поверхностны.

Когда вы говорите что не можете сделать, вам всего-лишь не хватает фантазии придумать какой-нибудь костыль.