Перейти к содержанию

roma912

Пользователи+
  • Постов

    223
  • Зарегистрирован

  • Посещение

  • Победитель дней

    7

Сообщения, опубликованные roma912

  1. Итак, начнем с самого начала
    Когда-то очень давно я начал играть в игру под названием Rocket League
    Импровизированая игра в футбол, где катаются машинки, со своей физикой и пр.
    Проиграв около года, все надоело и я решил посмотреть что есть у этой игры: 
    Как оказалось апи для какой-либо статистики открытого нет (Имею ввиду то, которое поддерживается официальными разработчиками)
    Ну раз нет апи, решил сделать что-то элементарное, например найти структуру игррка (в данном случае машинки)
    На данный момент у игры нет античита, хотя он тут и не нужен вовсе

    Вообщем загорелся идеей, начал пытаться найти эту структуру
    Долгое время ковырялся, ковырялся, ничего не получалось
    То ли дело во мне, то ли грабли не едут
    Посмотрел движок игры, оказалось Unreal Engine 3
    На UE3 вроде как бесполезно что-то искать руками, т.к поинтер будет с громадным количеством оффсетов и почти наверняка невалидным
    Посмотрел как реверсят игрушки на UE, и что-то не въехал с первого раза (даже с 5 не понял :DD)

    А суть была в том, что в Unreal Engine 3 можно хукнуть метод который передает все внутреигровые ф-ии которые использует в режиме реального времени
    Прочитал много статеек, посмотрел примеры и понял что хукают метод ProcessEvent
    Делают это с помощью дампа игровых классов, которые можно использовать для написания своего чита

    Собственно вот и дампер Тык
    Там уже есть заготовки для некоторые UE3, UE4 игр
    Нужная нам также имеется, осталось только сдампить

    Для дампа необходимо знать сигнатурки 
    ProcessEvent
    GlobalNames
    GlobalObjects
    Собственно вот и скомпилированный дампер
    pFOQ0HS.png

    Сам дампер это длл которая инжектится в игру, ну а сама длл и вытягивает все нужные классы для дальнейшего написания


    Теперь к написанию...

    Создаем проект, подключаем к проекту sdk которое сгенерировалось на диске С
    Подключаем все нужные инклуды и пр.

    Точка входа для нашей длл
     

    BOOL APIENTRY DllMain(HMODULE hModule,
    	DWORD ul_reason_for_call,
    	LPVOID lpReserved
    )
    {
    	switch (ul_reason_for_call)
    	{
    	case DLL_PROCESS_ATTACH:
    		AllocConsole();
    		freopen("output.log", "w", stdout);
    		printf("Dll Initialized\n");
    		DisableThreadLibraryCalls(hModule);
    		CreateThread(0, 0, MainThread, hModule, 0, 0); // creates our thread 
    		break;
    
    	case DLL_THREAD_ATTACH:
    	case DLL_THREAD_DETACH:
    	case DLL_PROCESS_DETACH:
    		break;
    	}
    	return TRUE;
    }
    

     

    В длл создаем поток который будет хукать ProcessEvent и использовать внутреигровые функции
     

    DWORD WINAPI MainThread(LPVOID param) // our main thread
    {
    	StartupApp();
    	printf("Inited\n");
    	ProcessEvent = (tProcessEvent)DetourFunction((BYTE*)ProcessEvent, (BYTE*)hkProcessEvent);
    	return false;
    }


    StartupApp метод который по сигнатуркам ищет адрес GNames, GObjects
     

    bool InitializeObjectsStore() {
    	auto address = FindPattern(GetModuleHandleW(nullptr), reinterpret_cast<const unsigned char*>(Signture), Mask);
    	if (address == -1) { return false; }
    	UObject::GObjects = reinterpret_cast<decltype(UObject::GObjects)>(*reinterpret_cast<uint32_t*>(address + 1));
    	return UObject::GObjects != nullptr;
    }
    
    bool InitializeNamesStore() {
    	auto address = FindPattern(GetModuleHandleW(nullptr), reinterpret_cast<const unsigned char*>(Signture), Mask);
    	if (address == -1) { return false; }
    	FName::GNames = reinterpret_cast<decltype(FName::GNames)>(*reinterpret_cast<uint32_t*>(address + 2));
    	return FName::GNames != nullptr;
    }


    ProcessEvent это наш хук который мы будем использовать (Как происходит хук гуглим, detours lib в помощь)

    Теперь к основной части, наш метод hProcessEvent
    Не забываем указывать Typedef 

    void __fastcall hkProcessEvent(UObject *pObject, void *edx, UFunction *pFunction, void *pParms, void *pResult);
    typedef void(__thiscall *tProcessEvent)(class UObject *, class UFunction *, void *, void *);
    tProcessEvent ProcessEvent = (tProcessEvent)FindPE();


     

    void __fastcall hkProcessEvent(UObject *pObject, void *edx, UFunction *pFunction, void *pParms, void *pResult)
    {
    	if (pFunction)
    	{
    		//Get Player*
    		if (strcmp(pFunction->GetFullName().c_str(), "Function Engine.PlayerController.PlayerTick") == 0)
    			pPlayerController = (APlayerController*)pObject;
    
    		//Get Ball*
    		if (strcmp(pFunction->GetFullName().c_str(), "Function TAGame.Ball_TA.OnRigidBodyCollision") == 0)
    			pBall = (ABall_TA*)pObject;
    
    		//Function TAGame.CarComponent_Boost_TA.EventBoostAmountChanged
    		if (strcmp(pFunction->GetFullName().c_str(), "Function TAGame.CarComponent_Boost_TA.EventBoostAmountChanged") == 0)
    		{
    			Boost = ((ACarComponent_Boost_TA_EventBoostAmountChanged_Params*)(pParms))->Boost;
    		}
    
    
    		if (strcmp(pFunction->GetFullName().c_str(), "Function Engine.Interaction.PostRender") == 0)
    		{
    			Canvas = ((UInteraction_PostRender_Params*)(pParms))->Canvas;
    			myPostRender(((UInteraction_PostRender_Params*)(pParms))->Canvas, pPlayerController, Boost);
    		}
    
    
    
    	}
    	ProcessEvent(pObject, pFunction, pParms, pResult);
    }


    Этот метод срабатывает при каждом вызове игрой какой-нибудь ф-ии, будь то отрисовка, будь то создаение машинки или же простой выход в меню
    Осталось только найти нужный нам метод и путем сравнения этой ф-ии через pFunction->GetFullName()
    Перенаправить на наш код

    В данном случае я получаю Указатели на Игрока, Мяч, UCanvas (Который рисует все что возможно в игре) и эвент EventBoostAmountChanged,
    который срабатывает когда кто-то использует на карте буст

     Перейдем к методу myPostRender который при срабатывании рисует в игре количество буста у игрока и также линию от игрока к мячику

     

    void myPostRender(UCanvas* Canvas, APlayerController* player, ACarComponent_Boost_TA* boost)
    {
    
    	//Проверка на валидность входных данных
    	if (!Canvas || !player || player->bDeleteMe || !boost || Boost->bDeleteMe || boost == NULL)
    		return;
    
    
    	try
    	{
    		if (boost)
    		{
    			
    			std::map<std::string, ACarComponent_Boost_TA*>::iterator it;
    			//Есть ли игрок уже в map
    			if (BoostMap.count(boost->Owner->GetFullName()) > 0)
    			{
    				//Обновляем игрока в map
    				it = BoostMap.find(boost->Owner->GetFullName());
    				BoostMap.erase(it);
    				BoostMap.insert(std::pair<std::string, ACarComponent_Boost_TA*>(boost->Owner->GetFullName(), boost));
    			}
    			else
    			{
    				BoostMap.insert(std::pair<std::string, ACarComponent_Boost_TA*>(boost->Owner->GetFullName(), boost));
    			}
    		}
    
    		std::map<std::string, ACarComponent_Boost_TA*>::iterator i;
    		for (i = BoostMap.begin(); i != BoostMap.end(); ++i)
    		{
    			//Опять проверяем на валидность 
    			if (!i->second->Owner || i->second->Owner->bDeleteMe || !i->second || i->second->bDeleteMe || i->second == NULL || i->second->Owner == NULL || !Canvas)
    			{
    				//Удаляем если не валиден
    				BoostMap.erase(i);
    				continue;
    			}
    			
    			//Переводим 3D Координаты игрока через Видовую матрицу Canvas->Project в 2D
    			FVector PlayerLoc = Canvas->Project(i->second->Owner->Location);
    
    
    			if (i->second->Owner->GetTeamNum() == 0) //Blue Team
    			{
    				//Проверка на то, видем ли мы на экране точку в который нужно рисовать
    				if (PlayerLoc.Z > 0)
    					DrawTextToScreen(Canvas, string("Boost Amount: ") + std::to_string((int)(i->second->CurrentBoostAmount * 100)), PlayerLoc.X + 10, PlayerLoc.Y - 30, BLUE);
    				
    			}
    			else {							//Orange Team
    				if (PlayerLoc.Z > 0)
    					DrawTextToScreen(Canvas, string("Boost Amount: ") + std::to_string((int)(i->second->CurrentBoostAmount * 100)), PlayerLoc.X + 10, PlayerLoc.Y - 30, ORANGE);
    				
    			}
    
    		}
    	}
    	catch(std::exception& e)
    	{
    		printf("Exception %s", e.what());
    	}
    }


    Итог: Разобраться в этом сразу конечно очень сложно, но методом проб и ошибок у вас должно получиться

    Ах, да, забыл показать конечный результат 
    Вот...
    Отрисовку линий я убрал в коде, но там нет ничего сложного
    Теперь мы видим количество буста у тиммейтов и противников, что вполне неплохо
    Также можно придумать множество реализаций SDK

    GPoSrT4.jpg

    • Понравилось 3
    • Плюс 3
  2. Выполнил задачку с Keygen'ом
    (Не открывайте спойлеры если хотите выполнить задачку полностью самостоятельно)

    Спойлер

    Порядок действий
    1. Запустить Keygen
    2. Запустить CR.exe
    3. Ввести ключ который сгенерировался

    mPOxJeV.png

     

    Вот результат работы, если интересен ход мыслей, то отпишешь мне в дс

     

  3. XZy7QWk.png

    Спойлер

    Сделал патчем, при вводе любого ключа в правильном формате проходится проверка и выдается зашифрованное сообщение You WIN
    xyMr2FK.png

    Собственно вот и ключ который вполне валиден и проходит все проверки

    Ну еще увеличил Sleep в конце с 2с до 10000, просто чтобы она не закрывалась
    Применил патч, вот и все)

    Если все получится, то напишу кейген как сделал partoftheworID, кстати файл от upx он же и очистил, там возникали проблемы

     

  4. 8 минут назад, MEDBEDb сказал:

    А как ты, кстати говоря, значения нашёл?

    Можно использовать всегда 1 элемент массива, и твой адрес не поменяется. Думаю так и делает тот скрипт

  5. Готово.

    Спойлер

     

    Screenshot-1.png

     

    Сделал через обход while цикла и подменой проверки
    PS DubeggerPresent лучше уже не использовать

    Положил бы под хайд, но не стоит раскрывать уж все

    download.png

    Можно и вот так :) Это уже без обхода цикла

     

  6. 1 час назад, Poligraf сказал:

    Спасибо за все комментарий.

    Учту, и да  о том что я не знаю куда лезу ну в основном ты прав, но меню я переписывал с нуля и что не что но я знаю что там делает как работает) ну немного))

    Буду смотреть видео. Удачи.

    Влезаю в тему конечно, но если бы ты переписал меню с нуля, т.е делал основной алгоритм хука записью в память, или же на ассемблере, то таких вопросов как вверху темы, не было бы :##

  7. Тебе по сути надо сделать так
    Взять какой-нибудь пустой регистр pop eax
    Потом записать туда значение  mov eax, (float) 100
    Перезаписать значение в указатель movss [rdi+offset], eax
    Освободить регистр pop eax

  8. 22 часа назад, JustHack сказал:

    также

    что нужно, то и можно

    imgui в топку ?

    в инете вагон примеров

    Примеры хука меня особо не интересуют 

    Интересует только фреймворк подобный imgui, чтобы имея хук можно было отрисовать свое меню 

  9. Вопрос состоит в том как хукается Directx 8 в отличии от 9.

    Также что можно навернуть на хук после? У imgui не нашел поддержки 8 версии для использования

    Поэтому вопрос к кодерам данного форума 
    Желательно с примерами самого хука ну и названиями библиотек

  10. 51 минуту назад, partoftheworlD сказал:

    Чит-мод работает, но возникло пару вопросов по самому языку, почитал доки, вроде он не сложнее, чем плюсы, но работает все странно.

     

    1. Вопрос, использование циклов как-то отличается от других языков к примеру python, c++? Просто используя функцию в цикле он вешает игру.

    2. Вопрос, можно ли дописать в вызываемую игрой функцию свой кусок кода, без перезаписи функции?

     

     

    Есть вариант подмены js страничного на свой, если не ошибаюсь. Но опять же надо почить насчет этого

    • Плюс 1
  11. 11 часов назад, faik003 сказал:

    Я уже выше писал, что это не совсем хук. Представим такую ситуацию: есть функция в игре, пусть будет называться tempFunc. Я провожу ее реверсинг на С++ и выношу код в функцию HookFunc, которая будет находиться в dll. Затем я нахожу место, где вызывается tempFunc и просто заменяю адрес (точнее смещение) так, чтобы произошел вызов HookFunc через dll, которую мы инжектим к игре. Мне не нужно, чтобы игра повторно вызывала оригинальную функцию, то есть tempFunc, поэтому в данной ситуации использование jump для меня избыточно. В каком-то смысле я заменяю ф-ции игры своими из dll и таким образом потихоньку "декомпилирую" игру.

    Что тогда мешает использовать точный адрес вызова? 

    Путем подмены обычного call на свой? Из длл через naked метод который как было сказано не комеилирует доп код

    • Плюс 1
  12. 2 часа назад, temtriss сказал:

     

    Не знаю, это же твоя разработка. Как там можно к ней относится? :) ИМХО свой проект, толковый всегда хочется поддерживать, развивать! 

    P.s. лично мне и бестолковые(других у меня нет) хочется развивать и улучшать) 

     

     

    Ну если толковый, то тогда лучше уже в паб выложить

    А так, для единоразовый прибыли без прочих проблем, считаю очень неплохим вариантом

     

  13. 12 часов назад, partoftheworlD сказал:

     

    Так не бывает же и так его будет проще взломать, чтобы была пиратская копия чита.

    Ну кодер может же написать единоразого и получить оплату, от этого он и выиграет
    Ему будет все равно что там дальше с читом произойдет, меньше проблем от этого

  14. 3 часа назад, Xipho сказал:

    Ну потому что логика простая. Кто напишет такой чит, то сам его и будет продавать. Зачем еще кому-то его за фиксированную сумму отдавать, чтобы тот потом куда больше заработал ))) Просто не все "продавцы" хотят это понимать.

    Нет ну можно и написать к примеру чит одноразого, и продать его к примеру за 80к+ чтобы потом не поддерживать код и не ждать клиентов как в другом варианте

  15. Предлагаю тебе не разбирать чужой код, а написать свой с нуля. 

    Для начала без каких-либо хуков и директа

    Т.е тебе понять бы алгоритм нахождения игрока, ent list, цикл перебора игроков и простенькую отрисовку линий через w2s

  16. Только что, kiwipapayamongoose сказал:

    Самому сделать? Найти координаты камеры, найти координаты голов(хитбоксы или кости) и записывать их в координаты камеры.

    Для этого ведь надо откопать entity, а потом смотреть кости.
    Конечно можно в паблике попробовать, но быстрее убьют чем найдешь нужные данные.
    Даже нет никакого полигона или сингла :((

  17. 18 минут назад, kiwipapayamongoose сказал:

    Не знаю как в этой игре, но в кс можно было в мм выходить за спектров при некоторых манипуляциях с клиентом, после этого клиент подключался к серверам зрителей, а не игровому серверу, что позволяло смотреть за всеми игроками.

    Тут такой функции нет
    Точнее наблюдать после смерти можно только за своим сквадом (аналогично pubg'у)
    Но нет ни боксов над головой, ни free look'a

  18. Ковыряю китайский недопабг для пк / телеофнов.
    Изначально хотел сделать по примеру Csgo и ее эффекта glow.

    Тут такой фишки не оказалось...
    Однако в просмотре за spectate можно увидеть все местоположения игроков на карте

    Также присутствуют боксы над самими игроками.

    Вопрос только в том, как все это ищется / переносится на обычный режим

     

     

    Map:

    Скрытый текст

    XF5-v1QHTXKUgtse6CTWMQ.jpeg

     

     

    Free Cam:

     

    Скрытый текст

    avhT_RIOSJeZ7mZDrXHY2w.jpeg

     

  19. 5 часов назад, Robit сказал:

    Так у меня ничего и не вышло (((

    У меня создаётся класс процесса, я нахожу указатель на модуль, но получить значение хотябы HP не получается.

    Найдёшь меня в дискорде, попробую помочь тебе

×
×
  • Создать...

Важная информация

Находясь на нашем сайте, Вы автоматически соглашаетесь соблюдать наши Условия использования.