Всем, привет!
После первых двух частей где мы подготавливали свою DLL к бою, в этой части я обещал что будет очень интересно.
А именно будет представлен сам процесс модификации, а именно мы будем в IDA Pro искать нам нужные функции и редактировать их.
Создадим класс FixGame.
И объявим статическую функцию Initialize
Эта функция будет главной, внутри её мы будем писать изменения. И она будет вызываться внутри DllInitializer.
[Ссылки могут видеть только зарегистрированные пользователи. ]
Далее двойной щелчок по функции GetFocus для того чтобы увидеть где она размещена в памяти. Теперь нам нужно найти где она вызывается, правой кнопкой мыши по названию функции.
[Ссылки могут видеть только зарегистрированные пользователи. ]
И выбираем Jump to xref to operand... IDA Pro покажет где эта функция вызывается, в нашем случае только 1 раз в функции sub_602410. Нажимаем снова два раза на название чтобы нас переместили в то месте где она вызывается.
[Ссылки могут видеть только зарегистрированные пользователи. ]
Поставим вот здесь breakpoint для того чтобы определить здесь ли нам нужно патчить или нет. И запускаем игру в IDA Pro. Пытаемся поставить игру на паузу.
[Ссылки могут видеть только зарегистрированные пользователи. ]
Видим что игра стоит на паузе, но breakpoint не сработал, значит это не та функция которая нам нужна. Да и если посмотреть выше, то это функция для какого-то левого окна.
[Ссылки могут видеть только зарегистрированные пользователи. ]
Видим что здесь намного больше адресов где она вызывается, ну что же, нам нужно каждый проверить. Просто ставим breakpoint и ставим игру на паузу, пока не сработает breakpoint.
Когда я проверил все функции, я увидел в последней то что при запуске игры, игра записывает результат выполнения в какую-то переменную. Значит это значение анализируется в другом месте. Посмотрев эту функцию sub_5D4CC0
Можно сделать вывод о том что здесь создается главное окно игры. Здесь можно увидеть то что игра передает созданному окну указатель на класс создателя.
[Ссылки могут видеть только зарегистрированные пользователи. ]
Ниже можно увидеть что создается таймер возможно он проверяет находится ли окно в фокусе, и у него последний параметр равен 0, то есть таймер обрабатывается в WndProc.
[Ссылки могут видеть только зарегистрированные пользователи. ]
Найдем функцию WndProc, которая указывается при регистрации класса окна.
В нашем случае зарегистрирован класс с наименованием MainWindow. Попробуем найти его регистрацию. Откроем вспомогательное окно в IDA Pro, Strings.
[Ссылки могут видеть только зарегистрированные пользователи. ]
Теперь переходим на LABEL_28 и снова ищем 0x113. Найдя это сообщения можно увидеть что оно просто сбрасывает переменную в 0. И это никак не может относится к проверки фокуса окна.
[Ссылки могут видеть только зарегистрированные пользователи. ]
Вернемся к функции sub_5D4CC0 в которой создавалось окно и куда-то записывался результат выполнения функции GetActiveWindow. И переименуем переменную dwNewLong на THIS. Так как это адрес объекта который управляет созданием окна.
На скриншоте показано как это я определил.
То есть пока идут сообщения окну, значит оно активно, как только будет 0, это значит что окно вне фокуса, посмотрим на дизассемблированый код этого участка.
Что можно здесь сделать, так это заменить setnz cl, на mov cl, 1.
Давайте попробуем. Для того чтобы нам узнать какие байты нам нужно прописать запустим Cheat Engine, и подключимся к нашей игре, и откроем Memory View.
Перейдем по адресу 005D14BD и видим все ту же инструкцию, только Cheat Engine вместо z пишет e, на самом деле это одно и то же. (Не важно) Главное мы видим рядом что эта инструкция занимает 3 байта, теперь нажмем правой кнопкой и нажмем Assemble.
[Ссылки могут видеть только зарегистрированные пользователи. ]
Напишем mov cl, 1. И нажмем YES чтобы забить оставшиеся байты нопами. Сейчас увидите почему соглашаемся. Новая инструкция занимает всего 2, и для того чтобы не испортить приложение, нужно оставшийся байт занопить.
Главное мы теперь знаем какие байты нам нужно писать.