Гайд Переносим структуру из CE в C++

Vadim.dll

Известный
Автор темы
168
80
Итак, найдя структуру в Cheat Engine, неплохо бы ее перенести в C++. Можно конечно каждое значение получить по оффсету, но как по мне, это не самое лучшее решение. Сегодня я покажу, как из внешней программы получить структуру с диалогом, которую мы искали в https://blast.hk/threads/34493/ этом уроке и запихнуть ее в структуру, для удобства в использовании.

Значит имеем такую структуру в CE:
upload_2019-5-18_9-22-13.png


Суть такова, главное расположить данные в той же последовательности, что и в CE, переменные, о назначении которых мы не знаем, можно помечать как Unknown или любое другое слово.

Я например, зная несколько значений нескольких переменных перенес данную структуру таким образом:
C++:
struct Dialog {
    void* pUnkn;
    int iTextX;
    int iTextY;
    int iUnkn1[2];
    int iSizeX;
    int iSizeY;
    void* pUnkn2[3];
    int iIsActive;
    int iUnkn2;
    int iDialogID;
};

Как видим, первый у нас указатель, куда он ведет - я не знаю, поэтому пишу как pUnkn,
вторая и третья переменные - значения смещения текста по X и Y. Что делают четвертая и пятая переменные я не знаю, поэтому называю их iUnkn1[2], [2] здесь, чтобы запихнуть две эти переменные в массив, чтобы не писать их по отдельности:
C++:
int iUnkn[2]
// Смысл одинаков
int iUnkn1
int iUnkn2

Далее у нас идут размеры окна iSizeX, iSize Y, потом три неизвестных указателя, далее активен ли диалог, неизвестный int и наконец ID диалога.

Протестировать данную структуру можно следующим образом:
C++:
int main()
{
    DWORD pID = GetProcId(L"gta_sa.exe"); // Получаем ID процесса Gta sa

    HANDLE pGta = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pID); // Открываем процесс
    DWORD pSamp = (DWORD)get_module(pGta, L"samp.dll"); // Ищем библиотеку samp.dll в процессе

    DWORD structAddr; // Адрес на нашу структуру с диалогом
    ReadProcessMemory(pGta, (LPCVOID)(pSamp + 0x26E898), &structAddr, 4, 0); // Получаем адрес на нашу структуру

    Dialog dial; // Объявляем наш диалог
    ReadProcessMemory(pGta, (LPCVOID)structAddr, &dial, sizeof(Dialog), 0); // Считываем данные в нашу структуру

    cout << "Dialog ID: " << dial.iDialogID << endl;
}

По сдвигу 0x26E898 находится указатель на структуру, а не сама структура, как можно увидеть в том же CE, поэтому для начала нужно считать адрес структуры с Диалогом, а потом уже саму структуру.
Сделано это т.к указатель на эту структуру по сдвигу 0x26E898 статичен, а вот адрес самой структуры - нет, поэтому если читать сразу из адреса структуры, который вы только что нашли, то после перезахода в игру это не будет работать. Также не обязательно указывать вообще все, что находится в структуре, как можно заметить, после DialogID там есть еще несколько переменных, но если они вас не интересуют, то их можно не записывать.

Полный код:
C++:
#include <iostream>
#include <Windows.h>
#include <TlHelp32.h>
#include <tchar.h>
#include <psapi.h>

using namespace std;

DWORD GetProcId(const wchar_t* procname)
{
    PROCESSENTRY32 pe;
    HANDLE hSnap;

    pe.dwSize = sizeof(PROCESSENTRY32);
    hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, NULL);
    if (Process32First(hSnap, &pe)) {
        do {
            if (wcscmp(pe.szExeFile, procname) == 0)
                break;
        } while (Process32Next(hSnap, &pe));
    }
    return pe.th32ProcessID;
}

DWORD get_module(HANDLE hProcess, const wchar_t* name)
{
    HMODULE hMods[1024];
    DWORD cbNeeded;
    unsigned int i;


    if (EnumProcessModules(hProcess, hMods, sizeof(hMods), &cbNeeded))
    {
        for (i = 0; i < (cbNeeded / sizeof(HMODULE)); i++)
        {
            TCHAR szModName[MAX_PATH];

            if (GetModuleBaseName(hProcess, hMods[i], szModName, sizeof(szModName) / sizeof(TCHAR)))
            {
                if (wcscmp(szModName, name) == 0) return (DWORD)hMods[i];
            }
        }
    }

    CloseHandle(hProcess);

    return 0;
}

struct Dialog {
    void* pUnkn;
    int iTextX;
    int iTextY;
    int iUnkn1[2];
    int iSizeX;
    int iSizeY;
    void* pUnkn2[3];
    int iIsActive;
    int iUnkn2;
    int iDialogID;
};

int main()
{
    DWORD pID = GetProcId(L"gta_sa.exe"); // Получаем ID процесса Gta sa

    HANDLE pGta = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pID); // Открываем процесс
    DWORD pSamp = (DWORD)get_module(pGta, L"samp.dll"); // Ищем библиотеку samp.dll в процессе

    DWORD structAddr; // Адрес на нашу структуру с диалогом
    ReadProcessMemory(pGta, (LPCVOID)(pSamp + 0x26E898), &structAddr, 4, 0); // Получаем адрес на нашу структуру

    Dialog dial; // Объявляем наш диалог
    ReadProcessMemory(pGta, (LPCVOID)structAddr, &dial, sizeof(Dialog), 0); // Считываем данные в нашу структуру

    cout << "Dialog ID: " << dial.iDialogID << endl;
}

Работает на SAMP 0.3.7 R3