Модификация игры 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 код:
Показать скриншот:Развернуть ↓Ищем его Показать скриншот:Развернуть ↓Теперь переходим на LABEL_28 и снова ищем 0x113. Найдя это сообщения можно увидеть что оно просто сбрасывает переменную в 0. И это никак не может относится к проверки фокуса окна. Показать скриншот:Развернуть ↓Вернемся к функции sub_5D4CC0 в которой создавалось окно и куда-то записывался результат выполнения функции GetActiveWindow. И переименуем переменную dwNewLong на THIS. Так как это адрес объекта который управляет созданием окна. На скриншоте показано как это я определил. Показать скриншот:Развернуть ↓Помним что класс передается окну указатель на самого себя PHP код:
PHP код:
Вначале находим получение указателя класса PHP код:
Ищем смещение 0x53E, то есть наша переменная активности окна. Долго искать не пришлось, вот что я нашел PHP код:
Код:
.text:005D14B7 xor ecx, ecx Давайте попробуем. Для того чтобы нам узнать какие байты нам нужно прописать запустим 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 Изменим нашу функцию PHP код:
Видим что в фокусе находится окно проводника, но в игре паузы нет. Показать скриншот:Развернуть ↓На этом все:) Отвечу на все ваши вопросы:) Следующая часть будет не менее интересней этой:) Так же сделал репозиторий с исходным кодом проекта. GitHub Если нужен исходник: PlantsVsZombies.rar 1 часть 2 часть |
Текущее время: 19:08. Часовой пояс GMT +3. |
Powered by vBulletin® Version 3.8.6
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd. Перевод: zCarot