Вылетает игра
-
Добрый день!
Есть игра, в которой я написал бота (твиновода). Он работает хорошо, за исключением вылетов.Вылеты не привязаны к действиям персонажей. Бот может проработать 5 минут, а может несколько часов. В отладчике я поймал момент вылета, там по стеку вызовов вообще не моя функция и не мой id потока. Судя по всему вылетает сама игра из за внедрения кода. Но на античит я не думаю, потому что я создавал свой сервер с чистой версией клиента - тоже самое.
Сейчас мой код устроен так: я выделяю память в процессе, записываю туда мой код, запускаю поток и жду его завершения.
Для завершения потока я пробовал использовать сначала RET, затем нашел функцию ExitThread в процессе. Разницы никакой - и так и так вылетает одинаково.Еще заметил нюанс, что на более слабом ПК вылеты происходят чаще.
У меня вот предположение, что может быть проблема решится, если я не буду создавать свой поток, а буду использовать игровой. То есть, использовать JMP на адрес моего кода, затем возвращаться обратно. Только я не понимаю как это реализовать. Какой поток надо найти чтобы так сработало? Я не понимаю, помогите!
Вот код C++:
bool ProcessReader::sendPacket(size_t size, void* packetData) { if (GameSession == 0) { std::cout << u8"GameSession не установлен.\n"; return false; } DWORD processId = pid; if (processId == 0) { std::cout << u8"Не удалось найти процесс ElementClient.exe." << std::endl; return false; } LPVOID remotePacketData = VirtualAllocEx(hProcess, NULL, size, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); if (!remotePacketData) { std::cout << u8"Не удалось выделить память в удалённом процессе." << std::endl; return false; } SIZE_T bytesWritten; if (!WriteProcessMemory(hProcess, remotePacketData, packetData, size, &bytesWritten) || bytesWritten != size) { std::cout << u8"Не удалось записать данные пакета в удалённый процесс." << std::endl; VirtualFreeEx(hProcess, remotePacketData, 0, MEM_RELEASE); return false; } DWORD sendPacketAddress = baseAddress + SENDPACKET; DWORD remoteKernel32Base = GetRemoteModuleBaseAddress(processId, L"ntdll.dll"); if (remoteKernel32Base == 0) { VirtualFreeEx(hProcess, remotePacketData, 0, MEM_RELEASE); return false; } DWORD remoteExitThreadAddr = remoteKernel32Base + RTLEXITUSERTHREAD; if (remoteExitThreadAddr == 0) { std::cout << u8"Не удалось вычислить адрес ExitThread в удалённом процессе." << std::endl; VirtualFreeEx(hProcess, remotePacketData, 0, MEM_RELEASE); return false; } // Код-стаб для вызова функции игровой, который я записываю в память. BYTE codeStub[] = { 0xB9, 0, 0, 0, 0, // mov ecx, GameSession ; ECX = GameSession 0x68, 0, 0, 0, 0, // push size ; Параметр size 0x68, 0, 0, 0, 0, // push remotePacketData ; Параметр packetData 0xB8, 0, 0, 0, 0, // mov eax, SENDPACKET_ADDRESS 0xFF, 0xD0, // call eax 0x83, 0xC4, 0x08, // add esp, 8 ; Очистка стека 0x6A, 0x00, // push 0 0xB8, 0, 0, 0, 0, // mov eax, ExitThread_ADDRESS 0xFF, 0xD0 // call eax }; // Заполняю параметры в код-стабе *(DWORD*)(codeStub + 1) = (DWORD)GameSession; // ECX = GameSession *(DWORD*)(codeStub + 6) = (DWORD)size; // Параметр size *(DWORD*)(codeStub + 11) = (DWORD)remotePacketData; // Параметр packetData *(DWORD*)(codeStub + 16) = sendPacketAddress; // Адрес функции SENDPACKET *(DWORD*)(codeStub + 28) = remoteExitThreadAddr; // Адрес функции ExitThread LPVOID remoteCode = VirtualAllocEx(hProcess, NULL, sizeof(codeStub), MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); if (!remoteCode) { std::cout << u8"Не удалось выделить память для код-стаба в удалённом процессе." << std::endl; VirtualFreeEx(hProcess, remotePacketData, 0, MEM_RELEASE); return false; } if (!WriteProcessMemory(hProcess, remoteCode, codeStub, sizeof(codeStub), &bytesWritten) || bytesWritten != sizeof(codeStub)) { std::cout << u8"Не удалось записать код-стаб в удалённый процесс." << std::endl; VirtualFreeEx(hProcess, remotePacketData, 0, MEM_RELEASE); VirtualFreeEx(hProcess, remoteCode, 0, MEM_RELEASE); return false; } HANDLE hThread = CreateRemoteThread(hProcess, NULL, 0, (LPTHREAD_START_ROUTINE)remoteCode, NULL, 0, NULL); if (!hThread) { std::cout << u8"Не удалось создать удалённый поток." << std::endl; VirtualFreeEx(hProcess, remotePacketData, 0, MEM_RELEASE); VirtualFreeEx(hProcess, remoteCode, 0, MEM_RELEASE); return false; } WaitForSingleObject(hThread, INFINITE); VirtualFreeEx(hProcess, remotePacketData, 0, MEM_RELEASE); VirtualFreeEx(hProcess, remoteCode, 0, MEM_RELEASE); CloseHandle(hThread); return true; }