В настоящее время я работаю над функцией телепортации для игрового тренера. Я нашел правильные статические адреса, содержащие число с плавающей точкой:
изображение адресов со смещениями
Этот адрес указывает на мою X-координату. Теперь я пытаюсь изменить свою X-координату (с плавающей точкой) с помощью процесса чтения / записи. Но что бы я ни делал, это не работает (у меня нет проблем с изменением нормальных целых). Я хочу заменить значение с плавающей точкой, которую я выбрал раньше.
Может кто-нибудь дать мне подробный пример, как я могу это сделать?
заранее спасибо
1) получить базовый адрес процесса — Получение базового адреса процесса
hprocess — дескриптор, передайте туда возвращенное значение openprocesshttps://msdn.microsoft.com/en-us/library/windows/desktop/ms684320(v=vs.85).aspx)
2) добавить смещение ‘teleport’ к базовому адресу
3) записать заданное значение в память процесса
HANDLE hProcess = openProcess(processId); //you also need to pass desired mode, use read & write
DWORD dwBaseAddress = getBaseAddress(hProcess):
DWORD dwPositionAddress = dwBaseAddress + POSITION_OFFSET;
float newPosition = 123.5;
WriteProcessMemory(hProcess, dwPositionAddress, &newPosition, sizeof(float));
вам нужно проверить на наличие ошибок, это просто псевдокод, чтобы дать вам представление о том, что вам нужно сделать, также убедитесь, что вы управляете своим тренером как администратор и имеете доступ к памяти игры
Вы должны прочитать указатель и добавить, что указывает его относительные смещения, чтобы добраться до адреса телепортации.
Ты можешь использовать WriteProcessMemory () записывать в память процесса напрямую и ReadProcessMemory () читать по памяти.
Но в случае, если вы читаете два три указатель уровня это станет громоздким подходом для этого.
Поэтому я рекомендую использовать Game Trainer или библиотека для взлома памяти читать / писать указатель легко.
вы могли бы использовать GTLibc гAME TRainer Libray для C / C ++.
GTLibc Библиотека игровых тренеров
или вы можете использовать библиотеку взлома игр Memory.dll для C #.
Memory.dll
Readprocessmemory и writeprocessmemory были бы относительно простыми, но лучшим вариантом является внедрение DLL в целевой процесс для скорости и простоты. Вы можете вручную почтить с помощью *
или используйте предпочтительный метод и настройте классы с подходящими размерами, чтобы вам не приходилось обрабатывать смещения одинаково. Проверьте Reclass.NET для автоматизации этого.
class unk3{
public:
char pad_001[0x10];
float location;
}
class unk2{
public:
unk3* m_unk3;
}
class unk1{
public:
char pad_001[0x78];
unk2* m_unk2;
}
Затем объявите экземпляр с вашим статическим смещением и считывайте / записывайте в него, как будто это ваша собственная память.
unk1* p_unk1 = (unk1*)(uintptr_t*)(OFFSET);
p_unk1->m_unk2->m_unk3->location = 300f;
Если вы хотите выйти на улицу, вам сначала нужно открыть дескриптор процесса.
void attach(LPCSTR WindowName) {
HWND hWindow = FindWindowA(NULL, WindowName);
if (hWindow)
{
GetWindowThreadProcessId(hWindow, &Proc_ID);
hProcess = OpenProcess(PROCESS_VM_READ | PROCESS_VM_WRITE | PROCESS_VM_OPERATION/*PROCESS_ALL_ACCESS*/, FALSE, Proc_ID);
HANDLE hModule = INVALID_HANDLE_VALUE;
MODULEENTRY32 ePoint;
hModule = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, Proc_ID);
ePoint.dwSize = sizeof(MODULEENTRY32);
Module32First(hModule, &ePoint);
base = (DWORD*)ePoint.modBaseAddr;
CloseHandle(hModule);
}
}
Тогда я бы порекомендовал настроить шаблоны для чтения / записи для вас.
template <class T>
T read(DWORD_PTR Address){
T buffer;
ReadProcessMemory(this->hProcess, (LPCVOID)Address, &buffer, sizeof(buffer), NULL);
return buffer;
}
Тогда почти такой же метод написания. Тогда исполнение будет:
DWORD_PTR p_unk1 = mem.read<DWORD_PTR>(OFFSET);
DWORD_PTR p_unk2 = mem.read<DWORD_PTR>(p_unk1 + 0x78);
DWORD_PTR p_unk3 = mem.read<DWORD_PTR>(p_unk2);
float location = mem.read<float>(p_unk3 + 0x10);
Вместо того, чтобы просто готовить sizeof (DWORD_PTR) и читать каждый элемент в классе, лучше, если вы сделаете что-то вроде этого:
class unk3{
public:
char pad_001[0x10];
float location;
}
class unk2{
public:
DWORD_PTR m_unk3;
}
class unk1{
public:
char pad_001[0x78];
DWORD_PTR m_unk2;
}
Заменить каждый класс * на DWORD_PTR
Затем выполните это с
unk1 p_unk1 = mem.read<unk1>(OFFSET);
unk2 p_unk2 = mem.read<unk2>(p_unk1.m_unk2);
unk3 p_unk3 = mem.read<unk3>(p_unk2.m_unk3);
float location = p_unk3.Location;
Для тех, кто задается вопросом, написание этого пути сделано:
mem.write<float>(p_unk2 + offsetof(unk3, location), value);
Внутренне делать это значительно лучше, меньше хлопот. Обратите внимание на ваш вопрос, writeprocessmemory просто пихает байты, это не заботится о типе. Вы, вероятно, передаете адрес целого числа в качестве буфера для записи, когда int и float по-разному кодируются с прямым порядком байтов. Убедитесь, что вы объявили его как float, или, что еще лучше, используйте шаблон. Или даже лучше, просто напишите dll 🙂