1

Тема: AHK: чтение из памяти программы

Задача: считать из памяти данные, находящиеся в определенной ячейке памяти.

Проблема №1: адрес этой ячейки не постоянен.
Решение проблемы №1: нашел код на С++

Проблема №2: не могу понять как работает в этом коде функция GetDLL(), а конкретно как вообще эту функцию перевести на AHK, что бы она возвращала адрес dll.

Это сама функция из С++ кода

//Base (6F).
DWORD GetDLL(char* DllName, DWORD tPid)
{
HANDLE snapMod;
MODULEENTRY32 me32;

if (tPid == 0) return 0;
snapMod = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, tPid);
me32.dwSize = sizeof(MODULEENTRY32);

if (Module32First(snapMod, &me32)){
do{
if (strcmp(DllName,me32.szModule) == 0){
CloseHandle(snapMod);
return (DWORD) me32.modBaseAddr;
}
}while(Module32Next(snapMod,&me32));
}

CloseHandle(snapMod);
return 0;

}

Всё из того же С++ кода пример вызова этой функции для получения адреса загруженной game.dll (это библиотека используется игрой)

DWORD GameDLL = GetDLL("Game.dll",GetPID("war3.exe"));

Помогите решить проблему №2

2

Re: AHK: чтение из памяти программы

GetDLL(DllName, tPid)
{
    If tPid = 0
        Return 0

    TH32CS_SNAPMODULE = 8
    INVALID_HANDLE_VALUE = -1
    VarSetCapacity(MODULEENTRY32, 1064, 0)
    NumPut(1064, MODULEENTRY32)

    snapMod := DllCall("CreateToolhelp32Snapshot", "uint", TH32CS_SNAPMODULE
                                                 , "uint", tPid)
    If (snapMod = INVALID_HANDLE_VALUE)
        Return 0

    If DllCall("Module32First", "uint", snapMod, "uint", &MODULEENTRY32)
    {
        pszModule := &MODULEENTRY32 + 32

        If DllCall("lstrcmpi", "str", DllName, "uint", pszModule) = 0
        {
            DllCall("CloseHandle", "uint", snapMod)
            Return NumGet(MODULEENTRY32, 20)
        }

        While DllCall("Module32Next", "uint", snapMod, "uint", &MODULEENTRY32)
        {
            If DllCall("lstrcmpi", "str", DllName, "uint", pszModule) = 0
            {
                DllCall("CloseHandle", "uint", snapMod)
                Return NumGet(MODULEENTRY32, 20)
            }
        }
    }
    DllCall("CloseHandle", "uint", snapMod)
    Return 0
}

3

Re: AHK: чтение из памяти программы

Спасибо. Буду разбираться дальше.

4

Re: AHK: чтение из памяти программы

Как запустить этот код на С++?
Делал вот по этому туториалу.
Выдает ошибку

Borland C++ 5.5.1 for Win32 Copyright (c) 1993, 2000 Borland
hello.cpp:
Error E2451 hello.cpp 88: Undefined symbol 'TH32CS_SNAPPROC' in function GetPID(char *)
Error E2121 hello.cpp 88: Function call missing ) in function GetPID(char *)
Error E2268 hello.cpp 96: Call to undefined function '_stricmp' in function GetPID(char *)
*** 3 errors in Compile ***

Это содержимое .bat файла для запуска компилятора.

path C:\Borland\BCC55\bin;%path%
set include=C:\Borland\BCC55\include
set lib=C:\Borland\BCC55\lib
set app=hello
if exist %appp%.exe del %app%.exe
if exist %appp%.obj del %app%.obj
bcc32.exe -I%include% -L%lib% %app%.cpp > errout.txt

Хочу убедиться, что код на С++ работает верно, чтобы точно знать, что и на ahk это будет работать.

5

Re: AHK: чтение из памяти программы

Глубоко не разбирался, но вот в таком виде компилится:

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

using namespace std; 

void EnableDebugPriv();
DWORD GetPID (PTSTR proc);
DWORD GetDLL (PTSTR DllName, DWORD tPid);
void ClearConsole();

int main()
{
    SetConsoleTitle(TEXT("Gamestate"));
    EnableDebugPriv();
    TCHAR War3Name[32] = TEXT("Wаrсrаft III");
    HWND hWar3 = FindWindow(War3Name, NULL);

    if(!hWar3)
    {
        cout << "Please open Wаrсrаft III first." << endl;
        system( "pause" );
        return 1;
    } 

    DWORD pid;
    GetWindowThreadProcessId( hWar3, &pid );
    HANDLE hOpen = OpenProcess( PROCESS_ALL_ACCESS, false, pid );
    if( !hOpen )
    {
        cout << "Can't open Wаrсrаft III." << endl;
        system( "pause" );
        return 1;
    }

    DWORD Address = 11147656;
    DWORD Buffer;
    DWORD GameDLL = GetDLL(TEXT("Game.dll"),GetPID(TEXT("war3.exe")));
    SIZE_T BytesRead = 0;

    for (;;)
    {   
        /* Notice the GameDLL+Address: we are adding our address to the base, AA1988h, because while the base is 6F 95 % of the time, it may change for specific reasons.*/
        
        ReadProcessMemory(hOpen, (LPCVOID)(GameDLL+Address), &Buffer, 4, &BytesRead); 
        
        // If our address has value(buffer) 0, then we are not in-game:
        
        if(Buffer == 0)
        {
            cout << "Not in game" <<endl;; 
            Sleep(2000);
            ClearConsole(); 
        }       
        else
        {
            cout << "In game" <<endl; 
            Sleep(1000);
            ClearConsole(); 
        }
    }
}

// Priviledges

void EnableDebugPriv( )
{
    HANDLE hToken;
    LUID sedebugnameValue;
    TOKEN_PRIVILEGES tkp;
    OpenProcessToken( GetCurrentProcess( ), TOKEN_ADJUST_PRIVILEGES |TOKEN_QUERY, &hToken );
    LookupPrivilegeValue( NULL, SE_DEBUG_NAME, &sedebugnameValue );
    tkp.PrivilegeCount = 1;tkp.Privileges[0].Luid = sedebugnameValue;
    tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
    AdjustTokenPrivileges( hToken, false, &tkp, sizeof( tkp ), NULL, NULL );
    CloseHandle( hToken );
} 

// Get PID for process.
DWORD GetPID (PTSTR proc)
{
    BOOL working=0;
    PROCESSENTRY32 lppe= {0};
    DWORD targetPid=0;
    HANDLE hSnapshot=CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS ,0);
    
    if (hSnapshot) 
    {
        lppe.dwSize=sizeof(lppe);
        working=Process32First(hSnapshot,&lppe);
        while (working)
        {
            if (lstrcmpi(lppe.szExeFile,proc)==0)
            {
                targetPid=lppe.th32ProcessID;
                break;
            }
            working=Process32Next(hSnapshot,&lppe);
        }
    }   
    CloseHandle( hSnapshot );
    return targetPid;
}

//Base (6F).
DWORD GetDLL(PTSTR DllName, DWORD tPid)
{
    HANDLE snapMod; 
    MODULEENTRY32 me32;
    
    if (tPid == 0) return 0;
    snapMod = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, tPid); 
    me32.dwSize = sizeof(MODULEENTRY32); 
    
    if (Module32First(snapMod, &me32))
    { 
        do {
            if (lstrcmpi(DllName,me32.szModule) == 0)
            { 
                CloseHandle(snapMod); 
                return (DWORD) me32.modBaseAddr; 
            }
        } while(Module32Next(snapMod,&me32));
    }   
    CloseHandle(snapMod); 
    return 0;
} 

void ClearConsole()
{
    HANDLE hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);
    COORD coord = {0, 0};
    DWORD count;
    CONSOLE_SCREEN_BUFFER_INFO csbi;
    if(GetConsoleScreenBufferInfo(hStdOut, &csbi))
    {
        FillConsoleOutputCharacter(hStdOut, (TCHAR) 32, csbi.dwSize.X * csbi.dwSize.Y, coord, &count);
        FillConsoleOutputAttribute(hStdOut, csbi.wAttributes, csbi.dwSize.X * csbi.dwSize.Y, coord, &count );
        SetConsoleCursorPosition(hStdOut, coord);
    }
    return;
}

Также обратите внимание, что в батнике опечатка — определяется переменная app, а дальше используется appp.

6

Re: AHK: чтение из памяти программы

Еще раз спасибо.