Модификация игры ASM/C++ Часть 3. - Форум администраторов игровых серверов
Форум администраторов игровых серверов StormWall - Защита от DDos атак
Регистрация Мнения Справка Пользователи Календарь Все разделы прочитаны
Вернуться   Форум администраторов игровых серверов > Полезное / Common > Программирование / Programming

Программирование / Programming
Ищете помощи в написании программы, есть сложность в выполнении задания (в институте и т.д.), пожалуйста, спросите у нас в данном форуме и мы обязательно вам поможем. При поддержке: Рейтинг серверов самых популярных online-игр

Ответ
Опции темы
Непрочитано 27.07.2016, 14:22   #1
Аватар для VOLKyiv
Пользователь

Автор темы (Топик Стартер) Модификация игры ASM/C++ Часть 3.

Всем, привет!
После первых двух частей где мы подготавливали свою DLL к бою, в этой части я обещал что будет очень интересно.
А именно будет представлен сам процесс модификации, а именно мы будем в IDA Pro искать нам нужные функции и редактировать их.

Создадим класс FixGame.

И объявим статическую функцию Initialize
Эта функция будет главной, внутри её мы будем писать изменения. И она будет вызываться внутри DllInitializer.

FixGame.h:
Свернуть ↑Развернуть ↓


FixGame.cpp:
Свернуть ↑Развернуть ↓


Теперь запустим игру и попробуем что-то внутри нее изменить


При создании скриншота я заметил что игра переходит в режим паузы, когда я перехожу в другое приложение.



И в качестве примера сейчас попробуем это убрать. Запускаем IDA Pro. Переходим на вкладку Imports.
И ищем WINAPI функции связаны с фокусом окна.



Далее двойной щелчок по функции GetFocus для того чтобы увидеть где она размещена в памяти. Теперь нам нужно найти где она вызывается, правой кнопкой мыши по названию функции.



И выбираем Jump to xref to operand... IDA Pro покажет где эта функция вызывается, в нашем случае только 1 раз в функции sub_602410. Нажимаем снова два раза на название чтобы нас переместили в то месте где она вызывается.


Теперь мы видим дизассемблированый код этой функции sub_602410. Нажимаем кнопку F5, чтобы увидеть приближенный к С++ код.



Поставим вот здесь breakpoint для того чтобы определить здесь ли нам нужно патчить или нет. И запускаем игру в IDA Pro. Пытаемся поставить игру на паузу.



Видим что игра стоит на паузе, но breakpoint не сработал, значит это не та функция которая нам нужна. Да и если посмотреть выше, то это функция для какого-то левого окна.



Погуглив я нашел что можно определять фокус окна с помощью функции GetActiveWindow, проделываем то же самое что и с GetFocus.



Видим что здесь намного больше адресов где она вызывается, ну что же, нам нужно каждый проверить. Просто ставим breakpoint и ставим игру на паузу, пока не сработает breakpoint.

Когда я проверил все функции, я увидел в последней то что при запуске игры, игра записывает результат выполнения в какую-то переменную. Значит это значение анализируется в другом месте. Посмотрев эту функцию sub_5D4CC0
Можно сделать вывод о том что здесь создается главное окно игры. Здесь можно увидеть то что игра передает созданному окну указатель на класс создателя.



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



Найдем функцию WndProc, которая указывается при регистрации класса окна.
В нашем случае зарегистрирован класс с наименованием MainWindow. Попробуем найти его регистрацию. Откроем вспомогательное окно в IDA Pro, Strings.



Попробуем найти все места где упоминаются MainWindow. Всё точно так же как и с поиском функций.

И вот мы видим функцию WndProc. Зайдем внутрь её. Для того чтобы найти наш таймер. С помощью Visual Studio узнаем номер сообщения

PHP код:
WM_TIMER 0x113 


Ищем его



Теперь переходим на LABEL_28 и снова ищем 0x113. Найдя это сообщения можно увидеть что оно просто сбрасывает переменную в 0. И это никак не может относится к проверки фокуса окна.



Вернемся к функции sub_5D4CC0 в которой создавалось окно и куда-то записывался результат выполнения функции GetActiveWindow. И переименуем переменную dwNewLong на THIS. Так как это адрес объекта который управляет созданием окна.
На скриншоте показано как это я определил.



Помним что класс передается окну указатель на самого себя

PHP код:
SetWindowLongA(*(HWND *)(THIS 884), -21THIS);
SetWindowLongA(*(HWND *)(THIS 0x374), -21THIS);
884 0x374 
Видим куда записывается состояние окна

PHP код:
*(_BYTE *)(THIS 0x53E) = GetActiveWindow() == *(HWND *)(THIS 0x374); 
И возвращаемся к WndProc
Вначале находим получение указателя класса

PHP код:
v38 GetWindowLongA(hWnd, -21); 
То есть v38, это тот же THIS что и в функции создания окна.
Ищем смещение 0x53E, то есть наша переменная активности окна. Долго искать не пришлось, вот что я нашел

PHP код:
if ( v38 && !*(_BYTE *)(v38 0x581) && hWnd == *(HWND *)(v38 0x374) )
    *(
_BYTE *)(v38 0x53E) = wParam != 0
То есть пока идут сообщения окну, значит оно активно, как только будет 0, это значит что окно вне фокуса, посмотрим на дизассемблированый код этого участка.

Код:
.text:005D14B7                 xor     ecx, ecx
.text:005D14B9                 cmp     [ebp+wParam], 0
.text:005D14BD                 setnz   cl
.text:005D14C0                 mov     edx, [ebp+var_4]
.text:005D14C3                 mov     [edx+53Eh], cl
Что можно здесь сделать, так это заменить setnz cl, на mov cl, 1.

Давайте попробуем. Для того чтобы нам узнать какие байты нам нужно прописать запустим Cheat Engine, и подключимся к нашей игре, и откроем Memory View.

Перейдем по адресу 005D14BD и видим все ту же инструкцию, только Cheat Engine вместо z пишет e, на самом деле это одно и то же. (Не важно) Главное мы видим рядом что эта инструкция занимает 3 байта, теперь нажмем правой кнопкой и нажмем Assemble.



Напишем mov cl, 1. И нажмем YES чтобы забить оставшиеся байты нопами. Сейчас увидите почему соглашаемся. Новая инструкция занимает всего 2, и для того чтобы не испортить приложение, нужно оставшийся байт занопить.

Главное мы теперь знаем какие байты нам нужно писать.

Код:
PlantsVsZombies.exe+1D14B9 - 83 7D 10 00           - cmp dword ptr [ebp+10],00
PlantsVsZombies.exe+1D14BD - B1 01                 - mov cl,01
PlantsVsZombies.exe+1D14BF - 90                    - nop 
PlantsVsZombies.exe+1D14C0 - 8B 55 FC              - mov edx,[ebp-04]
А это B1 01 90. Пробуем пропатчить нашу игру

Изменим нашу функцию

PHP код:
void FixGame::Initialize(void)
{
    
BYTE bytes[] = { 0xB10x010x90 };
    
WriteMemoryBYTES(0x005D14BDbytes3);

Компилируем и пробуем поставить игру на паузу
Видим что в фокусе находится окно проводника, но в игре паузы нет.



На этом все Отвечу на все ваши вопросы

Следующая часть будет не менее интересней этой

Так же сделал репозиторий с исходным кодом проекта.
GitHub

Если нужен исходник:
PlantsVsZombies.rar

1 часть
2 часть
VOLKyiv вне форума Ответить с цитированием
Сказали спасибо:
Ответ

Метки
модификация игры, создание чита


Здесь присутствуют: 1 (пользователей: 0 , гостей: 1)
 
Опции темы

Ваши права в разделе
Вы не можете создавать новые темы
Вы не можете отвечать в темах
Вы не можете прикреплять вложения
Вы не можете редактировать свои сообщения

BB коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.

Быстрый переход

Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Модификация игры ASM/C++ Часть 2. VOLKyiv Программирование / Programming 0 27.07.2016 14:04
Модификация игры ASM/C++ Часть 1. VOLKyiv Программирование / Programming 0 27.07.2016 13:59
Визуальная часть игры Ajax52 Документация 5 04.01.2012 21:10
Часть Клиента и часть серверная DRAGYN Lineage II 3 20.02.2011 00:25


© 2007–2020 «Форум администраторов игровых серверов»
Защита сайта от DDoS атак — StormWall
Работает на Булке неизвестной версии с переводом от zCarot
Текущее время: 06:21. Часовой пояс GMT +3.

Вверх