Здравствуйте, начал заниматься геймхакингом с лета и за все это время очень мало продвинулся, моей конечной целью являлось вызвать одну игровую функцию. Вот такой у меня был к этому подход:
Что я делал?
Использовал минхук для подключения к моей функции, затем хукал эту функцию, перехватывал ее аргументы и передавал их в переменные, затем я вызывал нужную мне функцию с этими переменными в качестве аргументов, все бы ничего, но я сталкиваюсь с такой проблемой, функция, которую я вызываю содержит 3 аргумента, 1 указатель на класс(всегда постоянный), 2 тип сообщения которое я эмулирую, 3 метод инфо(всегда 0). Вот как функция выглядит в дампе(это IL2CPP, сама игра x86):
{
"Address": 3252048,
"Name": "Game.Managers.ConnectionManager.ConnectionManager$$SendMessage",
"Signature": "void Game_Managers_ConnectionManager_ConnectionManager__SendMessage (Game_Managers_ConnectionManager_ConnectionManager_o* __this, ServerDefinitions_NetworkMessage_o* message, const MethodInfo* method);",
"TypeSignature": "viii"
}
Когда я вызываю саму функцию, все проходит успешно, но потом мне стоит повыполнять по истечению некоторого времени(не долго, может минуту или чуть больше) в игре различные действия, как я понял, меняется ее 2 аргумент, т.е. ServerDefinitions_NetworkMessage_o* message
, вот этот аргумент меняется, сложно предугадать когда именно, я вызываю эту функцию и моя игра крашается. Я приложил скрипт, которым я хукаю, а позже вызываю эту самую функцию и скриншот того, как она вызывается внутри игры(вид из CE) c нужными параметрами(P.S:Не смотрите на адреса(переменная uintptr_t SetOffset = 0x343D60;
и адрес в дампе и тот, который на скрине), там некоторые для старой версии игры, а некоторые для новой):
#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
// Windows Header Files
#include <windows.h>
#include <iostream>
#include <MinHook.h>
#pragma comment(lib, "libMinHook.x86.lib")
//Globals
HINSTANCE DllHandle;
uintptr_t base = (uintptr_t)GetModuleHandle(NULL);
uintptr_t GameAssembly = (uintptr_t)GetModuleHandle(L"GameAssembly.dll");
uintptr_t SetOffset = 0x343D60;
DWORD* fisrtarg;
DWORD* secondarg;
DWORD* thirdarg;
// hooks
typedef bool(__cdecl* build)(DWORD* __this, DWORD* BuildingDef, DWORD* method);
build buildcall;
build pBuild = nullptr;
build pBuildTarget = reinterpret_cast<build>(GameAssembly+SetOffset); // function pointer before hook
bool __cdecl build_h(DWORD* __this, DWORD* BuildingDef, DWORD* method) {
fisrtarg = __this;
secondarg = BuildingDef;
thirdarg = method;
std::cout << fisrtarg << " " << BuildingDef << " " << method << " " << std::endl;
std::cout << "Values gotten!!!" << std::endl;
return true;
}
DWORD __stdcall EjectThread(LPVOID lpParameter) {
Sleep(100);
FreeLibraryAndExitThread(DllHandle, 0);
return 0;
}
void shutdown(FILE* fp, std::string reason) {
MH_Uninitialize();
std::cout << reason << std::endl;
Sleep(1000);
if (fp != nullptr)
fclose(fp);
FreeConsole();
CreateThread(0, 0, EjectThread, 0, 0, 0);
return;
}
DWORD WINAPI Menue(HINSTANCE hModule) {
AllocConsole();
FILE* fp;
freopen_s(&fp, "CONOUT$", "w", stdout); //sets cout to be used with our newly created console
MH_STATUS status = MH_Initialize();
if (status != MH_OK)
{
std::string sStatus = MH_StatusToString(status);
shutdown(fp, "Minhook init failed!");
return 0;
}
if (MH_CreateHook(reinterpret_cast<void**>(pBuildTarget), &build_h, reinterpret_cast<void**>(&pBuild)) != MH_OK) {
shutdown(fp, "CreateHook failed!");
return 1;
}
std::cout << "Waiting for actions..." << std::endl;
bool enablePeekMessage = false;
bool enableReload = false;
while (true) {
Sleep(50);
if (GetAsyncKeyState(VK_INSERT) & 1) {
break;
}
if (GetAsyncKeyState(VK_HOME) & 1) {
enableReload = !enableReload;
if (enableReload) {
std::cout << "Build hook enabled" << std::endl;
if (MH_EnableHook(reinterpret_cast<void**>(pBuildTarget)) != MH_OK) {
shutdown(fp, "Reload: EnableHook failed!");
return 1;
}
}
else {
std::cout << "Build hook disabled" << std::endl;
if (MH_DisableHook(reinterpret_cast<void**>(pBuildTarget)) != MH_OK) {
shutdown(fp, "Reload: DisableHook failed!");
return 1;
}
}
}
if (GetAsyncKeyState(VK_F2) & 1) {
buildcall = (build)(GameAssembly + SetOffset);
buildcall(fisrtarg, secondarg, thirdarg);
}
}
shutdown(fp, "Byby");
return 0;
}
BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
DllHandle = hModule;
CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)Menue, NULL, 0, NULL);
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
Обращаюсь на надежде на то, что мне кто-то объяснит, как передавать во второй аргумент какой-нибудь "константный" адрес, чтобы он всегда отрабатывал и игра не завершалась сбоем.