Взламываем игру-головоломку «Сапер»

Intro

Холодным зимним вечером, начитавшись статей об исследовании различного ПО и насмотревшись различного рода видео про взломы игр и прочее, у меня вдруг тоже возникло желание повозиться под дебагерром с чем-нибудь интересным. Крякингом я занимаюсь сравнительно давно, поэтому практический опыт имеется. Поначалу я, как и многие, просто искал различные CrackME в сети и взламывал их с целью обучения, затем перешел на взломы платных приложений(поиск/подбор ключей) и написание различного рода KeyGen`ов. В данный момент «набиваю руку» и пытаюсь оттачивать мастерство взлома.
Ну да ладно, это лирическое отступление от сути. Теперь определимся с некоторыми деталями.

В данной статье главным объектом внимания для нас будет компьютерная игра «Сапер».
Исследование и последующая отладка приложения происходят под Windows 7 x64 (реализация игры «Сапер» отличается в различных версиях OS Windows).

В качестве дизассемблера будем использовать встроенный дебаггер CheatEngine. Мне он нравится своей простотой и изящностью, некоторые вещи в нем делаются гораздо легче, чем, например, в OllyDBG.

Окей, c деталями разобрались, приступим же к делу!

Наверняка, почти каждый, кто использует Windows, когда-либо имел дело с игрой «Сапер». В «семерке» игра выглядит так:



Это стандартное поле( в данном случае 16x16 клеток ). Мы будем ломать игру на среднем уровне сложности, т.е на уровне «Любитель». В общем-то для уровней сложности «Новичок» и «Профессионал» эта статья также будет актуальна, ничего кроме времени, количества мин и размеров поля не изменится.

1 этап

Итак, открываем наш CheatEngine( в дальнейшем будет использоваться сокращение CE ) и аттачимся к процессу игры:



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

1) Вводим в поле «Value» первоначальное количество открытых клеток, т.е ноль, нажимаем на «First Scan»
2) Переходим в игру и кликаем на случайной клетке, после переходим в CE и в поле «Scan Type» выбираем «Increased Value»(значение увеличилось), жмем «Next Scan»

Делаем похожие действия, пока не найдем то самое, заветное значение:



Мы отыскали адрес, в котором хранится другой адрес, который, в свою очередь, хранит статическое значение.
Добавляем значение в «AddressList». Теперь если немного поиграть в игру, можно будет заметить, что значение меняется.

Теперь ищем asm-инструкцию, которая как-то взаимодействует с данным значением( меняет, читает ):



Открываем игру и еще немного играем, затем видим такую картину:



Ага, очень интересно :) Особенный интерес представляют 1 и 3 инструкции, так как они во-первых пишут в память, а во вторых они схожи и в общем счете выполняются целых 3 раза! Вот мы и переходим в дебаггер, выделив 1 или 3 инструкцию и нажав на кнопку «Show Disassembler».

Так, так, так, все становится интереснее и интереснее! Особый интерес представляет вот эта цепочка с заверщающим сравнением( cmp ):



Если повесим «бряк» на сравнение «cmp edx,eax», то при возврате в игру и попытке кликнуть на клетку, бряк сработает. При чем, как при клике на клетку с миной, так и при клике на обычную клетку. А что это значит? А значит это то, что где-то здесь происходит «распознавание» того, что находится под в закрытой клетке: пустота, мина или цифра. Пробуем изменить это значение на какое-либо бессмысленно сравнение, например, на такое:



Здесь, как некоторые поняли, главная задача — активация процессорного флага «Z», которая происходит в случае, если оба операнда инструкции CMP эквивалентны.
Возвращаемся в игру и кликаем по какой-либо закрытой клетке. В итоге:



Хах, прикольно! Оказывается, это была проверка " на выигрывание игры ", которая происходит при каждом клике по клетке поля, что в общем-то логично. Уже неплохо, но мы ведь хотим именно играть, минуя все мины, а не тупо выигрывать игру при открытии первой же клетки поля, верно? Так что, продолжаем наше исследование.

2 этап

Во втором этапе взлома мы постараемся выяснить, что является «переломным моментом» при распознавании «нутра» клетки, на которую пришелся клик. Ок, снова идем в CE и проделываем те же операции, что и в первом этапе, разве что дебажить код не требуется. Видим уже знакомую последовательность инструкций:



Попытаемся отыскать границы функции( блока инструкций ), в которой мы находимся в данный момент( где находится инструкция ):



Ага, и что же мы видим:



Нас визуально перекинуло в начало текущей функции. Это нам пока что еще ни о чем важном не говорит, но если поразмыслить, обдумать, все что имеем, то можем прийти к выводу, что данная функция может быть как-либо связана с графикой игры, например. К такому выводу можно прийти, исходя из 1 этапа, где мы отыскали проверку игры «на выигрывание», что, скорее всего, сказывается на отрисовке поля. Ладно, проверим эту теорию. Спускаемся от начала функции немного вниз, где вскоре обнаружим весьма интересную инструкцию:



Это первое сравнение в данной функции… Хм, попробуем поставить бряк на инструкцию, затем переходим в игру:



Мы не можем перейти в игру. Почему? Да потому что наша теория подтвердилась! Эта функция и правда связана с графикой игры. При каждой активации окна и прочем взаимодействии с игровым интерфейсом вызывается эта функция, а в ней установлен BreakPoint на сравнении => активировать окно и «Сапёрить» мы не сможем, пока не снимем бряк. Снимаем его. Есть вероятность, что данное сравнение играет ключевую роль в последующем поведении всей функции. Попробуем изменить данное сравнение на бессмысленно сравнение, чтобы флаг процессора «Z» активировался, как это было сделано в первом этапе:



Размер новой инструкции( 2 байта ) в 2 раза меньше, чем тот, что был изначально( 4 байта ), следовательно, добавились инструкции «nop» в 1 байт, чтобы «Занопалось» оставшееся пространство в 2 байта. Переходим в игру и пытаемся играть. Тыкаем по клеткам, натыкаемся на мину, и… ничего не произошло! Хм, не удивительно. Ладно, попробуем не включать, а выключать флаг процессора «Z». Для этого надо заменить сравнение на такое, чтобы два сравниваемых элемента никогда не были равными. Для этого восстанавливаем изначальную инструкцию:

cmp dword ptr [rax+38],01

и изменяем сравнение содержимого указателя, например, на сравнение с отрицательным числом( с -1 ):



Теперь возвращаемся в игру и начинаем «саперить». При клике на некоторые области, они отрисовываются с некоторым запозданием, или их «нутро» отрисовывается лишь со второго раза. Оно и верно, ведь мы нагло влезли в графическую функцию и беспощадно отдебажили её :). Зато при клике на «опасные области» с минами ничего не происходит вообще!
Результат:



Профит :) Мы хакнули игру «Сапер» из стандартного комплекта игр от Microsoft.

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

Похожие публикации

AdBlock похитил этот баннер, но баннеры не зубы — отрастут

Подробнее
Реклама

Комментарии 38

    +21
    Картинки в BMP? o___O

    Сконвертируйте в PNG и перезалейте на habrastorage.org
      0
      Пользовался тем, что было «под рукой» :)
        +4
        Эээ? Paint больше 10 лет умеет работать с png, а в win7 даже предлагает по-умолчанию.
          +7
          Ок, я уже исправляю это недоразумение.
      +1
      В сапере карта мин хранится в двумерном массиве. Достаем массив из памяти процесса, и рисуем все что угодно на канве его окна в нужных местах))

      Есть одно условие еще. Если человек первым же кликом попадает мину, то ее местоположение меняется.
        –6
        В ассемблере нет понятия «двумерного массива», нет даже понятия «массива». Есть лишь«указатели». Отследить все указатели на положение мин достаточно сложно, поэтому я пока этим даже не занимался. Зато мне удалось обнаружить функцию, отвечающую за отображение всех мин( при проигрыше ). Возможно, в следующих статьях поведаю об этом.
          0
          Я уверен, автор предыдущего поста и имел в виду это. Небольшой намёк: данные скорее всего хранятся рядом, а, быть может, и даже в виде 1-мерного массива.
            +3
              0
              Не, этого не видел. Кстати, спасибо)
                0
                Именно эту нет, видел и другие статьи с похожим результатом на delphi
                  0
                  Даже такое было ;)
                  habrahabr.ru/post/131117/
                +4
                Если человек первым же кликом попадает мину, то ее местоположение меняется.
                Я всегда был уверен, что поле заполняется минами только после первого клика.
                +2
                Читер! Ату его, ату!
                Что, не осилили в минёра выиграть?
                :)
                  0
                  Суть не в этом.
                    +10
                    Конечно не в этом.
                    И даже не в полном отсутствии у вас чувства юмора.
                      0
                      o__O это был юмор? Не распознал, что ж…
                  +4
                  А мне понравился пост. Никогда в эту тему не влезал, но сейчас почитал с интересом. У автора легкий понятный язык, тема похоже из первых рук. Ничего не приобрел, но прочитал с удовольствием.
                    +3
                    Наконец-то я выиграю в сапёра.
                      +1
                      Перерисовывал как-то на вин95(вроде) карты в солитёре попиксельно, редактируя программу в нортон командере. Это было сложно:)
                        +4
                        У меня в детстве с желания пройти игрушку до конца (и отсутствия infinite life в загрузчике ;) ) началась эпопея по взлому игр. Как сейчас помню — www.worldofspectrum.org/infoseekid.cgi?id=0009438 Что самое характерное, если бы на этой первой не получилось, то возможно и не пытался бы больше, но ощущение того, что ты сам нашёл как это всё обессмертить давало какое-то ощущение эйфории. Потом были самописные искатели последовательностей байт( это нужно было для поиска типа — «а если жизнь хранится не числом а сразу символами… а что если жизнь уменьшается не DEC а через SUB....» и т.д.), выдиратели спрайтов и музыки с плеерами и много чего ещё. И ведь всё без инета :) Как умудрялись…
                        Вот только сейчас уже ничего этого не хочется :( И времени нет и понимаю, что тех ощущений уже не вернуть…
                          +4
                          1. Запустите сапер.

                          2. Установите курсор в область с игрой.

                          3. Наберите «XYZZY» и нажмите Shift-Enter и Enter. В верхнем левом углу экрана должна появиться белая точка. При наведении курсора на мину точка будет менять свой цвет на черный.

                          4. Вот и все. Наслаждайтесь возможностью никогда не взрываться, играя в Сапер!
                            0
                            Помню когда-то делал возможность сохранятся с помощью внедрения библиотеки. Тогда в меню появлялись Open, Save.
                              +1
                              А я помню, как изменял сапёра, чтобы куда ни ткни — либо всегда мина, либо всегда её нет. Скачать тут.
                                0
                                Да, такую вещь можно провернуть. В процессе исследования «Сапера» также выяснилось, что координаты мин задаются после первого клика по клетке поля игры( я, например, этого не знал, так как ранее не играл в сапера ). Соответственно, с этим можно что-либо сделать :)
                                  0
                                  Здесь же: «нутро» первой клетки, по которой пришелся клик также определяется после щелчка мыши по ней.
                                • НЛО прилетело и опубликовало эту надпись здесь
                                    +1
                                    у меня не получилось взломать даже калькулятор :(
                                    http://www.youtube.com/watch?v=i7RJhn5EBXQ
                                    +1
                                    Дежавю…
                                      +5
                                      — Ваше хобби?
                                      — Крякинг
                                      — Продемонстрировать можете?
                                      — Кря-кря
                                      • НЛО прилетело и опубликовало эту надпись здесь
                                          0
                                          Ну здесь всё равно, получение неправомерного доступа. Статья 272, как она есть =)
                                            0
                                            Ассемблерный код исполняется на моем компьютере, в моем процессоре ( кэп), следовательно, без них кода не существует вовсе. Из этого следует, что АССЕМБЛЕРНЫЙ код также принадлежит мне, т.е моему процессору( по крайней мере, в данный момент ), из чего, наконец, следует то, что менять код я могу так, как мне вздумается( он же мой ).А вот распространять взломанное — уже другое дело.

                                            P.S И, да, код игры «Сапера» вряд ли охраняемый( как гласит 272 статья)… по крайней мере, машинный код.
                                              0
                                              Вы внимательно читали EULA на MS Windows? ;)
                                                0
                                                Его ведь никто никогда не читает :) Разве существуют такие люди, которые читают лицензионное соглашение, тем более ВНИМАТЕЛЬНО !?
                                                  +1
                                                  Вы всё равно не поверите.
                                                  0
                                                  А вы внимательно читали статью 1280 ГКРФ «Свободное воспроизведение программ для ЭВМ и баз данных. Декомпилирование программ для ЭВМ»?
                                                    0
                                                    Ну и какой же из пунктов данной статьи подход под действия автора?
                                                    Что-то не наблюдаю тут «исправления ошибок» или «взаимодействия с программами»
                                                      +1
                                                      Пункт 2 же, «изучать, исследовать и испытывать функционирование».

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

                                          Самое читаемое