Модификация игры ASM/C++ Часть 3.

Тема в разделе "Уроки, Создание читов и трейнеров, исходники", создана пользователем RedYu, 25 июл 2016.

  1. Оффлайн

    RedYu

    На форуме с:
    25 июл 2016
    Сообщения:
    6
    Симпатии:
    4
    Баллы:
    2
    Пол:
    Мужской
    Всем, привет!
    После первых двух частей где мы подготавливали свою DLL к боюsmile-z, в этой части я обещал что будет очень интересно.
    А именно будет представлен сам процесс модификации, а именно мы будем в IDA Pro искать нам нужные функции и редактировать их.

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

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


    FixGame.h
    PHP:
    #pragma once

    class FixGame
    {
        
    FixGame() {};
        ~
    FixGame() {};
    public:
        static 
    void Initialize(void);
    };
    FixGame.cpp
    PHP:
    #include "stdafx.h"
    #include "FixGame.h"


    void FixGame::Initialize(void)
    {
        
    //:D
        
    int x == 5;
    }
    Теперь запустим игру и попробуем что-то внутри нее изменитьsmile-z

    [​IMG]

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


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


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


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

    [​IMG]

    Теперь мы видим дизассемблированый код этой функции 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. Пробуем пропатчить нашу игруsmile-z

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

    PHP:
    void FixGame::Initialize(void)
    {
        
    BYTE bytes[] = { 0xB10x010x90 };
        
    WriteMemoryBYTES(0x005D14BDbytes3);
    }
    Компилируем и пробуем поставить игру на паузуsmile-z

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


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

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

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

    Если нужен исходник:
    PlantsVsZombies.rar
    --- Добавлено, 26 июл 2016, Дата первого сообщения: 25 июл 2016 ---
    https://www.virustotal.com/ru/file/...b6842f3b2b7730102c2b06a6/analysis/1469530551/
     
    Rango нравится это.
  2.  

Поделиться этой страницей

Уважаемый пользователь!

Мы обнаружили, что вы блокируете показ рекламы на нашем сайте.

Просим внести его в список исключения или отключить AdBlock.

Наши материалы предоставляются БЕСПЛАТНО и единственным доходом является реклама.

Спасибо за понимание!