Итак, найдя структуру в Cheat Engine, неплохо бы ее перенести в C++. Можно конечно каждое значение получить по оффсету, но как по мне, это не самое лучшее решение. Сегодня я покажу, как из внешней программы получить структуру с диалогом, которую мы искали в https://blast.hk/threads/34493/ этом уроке и запихнуть ее в структуру, для удобства в использовании.
Значит имеем такую структуру в CE:
Суть такова, главное расположить данные в той же последовательности, что и в CE, переменные, о назначении которых мы не знаем, можно помечать как Unknown или любое другое слово.
Я например, зная несколько значений нескольких переменных перенес данную структуру таким образом:
Как видим, первый у нас указатель, куда он ведет - я не знаю, поэтому пишу как pUnkn,
вторая и третья переменные - значения смещения текста по X и Y. Что делают четвертая и пятая переменные я не знаю, поэтому называю их iUnkn1[2], [2] здесь, чтобы запихнуть две эти переменные в массив, чтобы не писать их по отдельности:
Далее у нас идут размеры окна iSizeX, iSize Y, потом три неизвестных указателя, далее активен ли диалог, неизвестный int и наконец ID диалога.
Протестировать данную структуру можно следующим образом:
По сдвигу 0x26E898 находится указатель на структуру, а не сама структура, как можно увидеть в том же CE, поэтому для начала нужно считать адрес структуры с Диалогом, а потом уже саму структуру.
Сделано это т.к указатель на эту структуру по сдвигу 0x26E898 статичен, а вот адрес самой структуры - нет, поэтому если читать сразу из адреса структуры, который вы только что нашли, то после перезахода в игру это не будет работать. Также не обязательно указывать вообще все, что находится в структуре, как можно заметить, после DialogID там есть еще несколько переменных, но если они вас не интересуют, то их можно не записывать.
Полный код:
Работает на SAMP 0.3.7 R3
Значит имеем такую структуру в CE:
Суть такова, главное расположить данные в той же последовательности, что и в 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