Наверняка многие, кто в детстве любил вместе с одноклассниками играть в игры на смартфонах, знают, что практически на любую оффлайн-игру существует модифицированная версия. Обычно это мод на бесплатные покупки, много игровой валюты, открытые премиальные функции, бесконечная жизнь персонажа, иногда убийство рекламы. В каждой игре - по разному, в зависимости от того, что та предлагает. Самый широкий оплот-пристанище для таких модов - 4pda. Форум этот древнее автора данной статьи, но, безусловно, наиполезнейший для тех, кто имеет дело со внутренней кухней смартфонов в той или иной сфере. И мобильный геймхакинг - одна из них: существует даже отдельный "Клуб Читеров" - группа людей, которые по запросам модифицируют игры. Вроде как даже до сих пор туда шлют запросы, но вот сколько активных членов их круга осталось - загадка.
С детства я всегда мечтал, если не попасть в их круг, то хотя бы тоже научиться взламывать игры. И если первое - не совсем от меня зависит, то вот второе - именно то, чем мы и будем заниматься в сегодняшней мини-статье. В качестве подопытного мы возьмём одну из моих любимых игр детства -
Для начала нам необходимо вообще понять, что эта игра предлагает, и что мы можем с ней сделать.
Суть игры проста: мы должны отсреливать волны зомби, чертей, крокодилов, дровосеков, кроликов и прочей нечести, дабы пройти уровень. Из важного - у нас есть полоска HP в виде трёх сердец, у каждого подбираемого оружия есть полоска с количеством оставшихся патронов, а с убитых нами падают монеты, за которые мы можем открывать и улучшать оружие/персонажей. Кроме того, в игре есть таблица с квестами - за квесты дают опыт, за опыт мы повышаем уровень, а с новыми уровнями появляется возможность открывать всё новое.
Как человек, который довольно много играл в эту игру в своё время, скажу - вариаций оружия и персонажей для разблокировки много, и на высоких уровнях деньги и опыт копятся ну очень долго. Так что сегодня мы это дело исправим!
Для начала откроем наш APK в любом Java-декомпиляторе (я буду использовать JEB) и сразу глянем в манифест приложения:
Название интересующего нас пакета -
Изобилием классов этот пакет не блещет. Заглянем в главное активити - xtPlay:
Кроме как загрузкой вышеупомянутой библиотеки, этот активити ничем не интересен, дальше идут какие-то махинации с рекламой. В остальных активити тоже нет ничего, что походило бы на логику игры. А значит, лезем в библиотеку!
Так как игра очень старая, в ней всего две версии библиотеки: armeabi-v7a и x86. Так как с этой библиотекой дальше мы будем работать в дизассемблере, то стоит отдать предпочтение той версии, которую будет удобнее понимать, для многих - это, конечно, x86/x86-64. Я же, имея на борту IDA hex-rays для ARM, сразу начну с этой версии. Всё равно, если будет нужно, мы будем патчить все доступные версии.
Что сходу радует - здесь, в этой библиотеке расписана вообще ВСЯ логика игры. А что ещё лучше - у каждой функции есть понятное название, с объединяющей группой в виде пространства имён. Дальше всё зависит от нашей фантазии при поиске нужных! Напомню, сегодняшняя цель нашего мода - деньги и уровень для быстрой разблокировки всего. Попробуем поискать что-то, что связано с магазином:
Здесь каждая группа функций выделена на отдельную секцию магазина: уровни, оружие, персонажи - соответственно, StoreLevels, StoreWeapons и StoreCharacters. Начнём с последней - а именно с
По какой-то причине, каждая функция - просто вызов другой, уже настоящей. Причём в IDA отображаются обе, с одинаковым именем. Так что мы просто залезем во вторую:
А здесь тело уже соответствует названию: наглядно видна кривая повышающейся цены, что отвечает за прокачку персонажа. Поэтому, в теории, если мы сделаем так, чтобы эта функция всегда возвращала 0, мы не должны тратить ни монеты на покупку и прокачку. Чтобы сделать конструкцию вида
В режиме Thumb это будет выглядеть так:
Одноимённая функция, которая вызывает настоящую, тоже состоит из 2-х инструкций:
Тем более, что ADRL занимает 8 байт, мы можем её заменить на нужные нам две четырёхбайтовые инструкции! Трогать вторую инструкцию смысла нет, после патча наша функция должна выглядеть так:
Теперь попробуем собрать обратно нашу игру с новой библиотекой. Я для этих целей использую ApkTool-GUI, предварительно заменив оригинальную библиотеку на патченную:
Теперь переустановим игру и посмотрим, есть ли результат. Напоминаю, если наша задумка воплотилась, то сейчас любая прокачка персонажей должна быть бесплатной.
Получилось! Монеты не тратятся, улучшения остаются, а мы - в шоколаде! Осталось то же самое провернуть и для остальных секций магазина, там всё точно так же, по аналогии. Теперь к уровням.
Судя по структуре функций, есть отдельные функции, которые возвращают информацию обо всех предметах из секции. В каждом элементе такого массива есть отдельное поле для уровня, с которого данный предмет доступен.
А так же есть отдельные функции вида
Алгоритм тот же самый: вместо первых нескольких инструкций просто возвращаем ноль, ничего нового. Казалось бы, раз мы такие молодцы, всё же заработает? А вот хрен там!
Бесплатная прокачка == бесконечные деньги, поскольку их тратить больше не на что, тут всё прекрасно. Но вот с уровнями произошла неувязочка: видимо, предметы открываются только тогда, когда твой уровень не просто больше
Методом проб и ошибок я выяснил, что при повышении уровня разблокируется предмет, требуемый уровень которого равен полученному. Так что либо мы делаем так, чтобы они разблокировались по одному на каждом уровне, что не особо ускоряет прогресс игроку, либо ищем другой способ.
Хорошенько порывшись в функциях, я наткнулся на это чудо:
Можно сделать так, чтобы эта функция возвращала 0. Если в игре есть ограничение на максимальный уровень - в теории, должно сработать. Но если максимального уровня нет... Лучше на этот счёт не думать.
После проверки всё оказалось куда проще - игра просто вылетала при запуске. Видимо, сильно мы логику поломали этой функцией, так что меняем всё, как было и думаем дальше. А надумал я следующее: проблема не в логике, а в UI!
На этапе входа в магазин идёт отрисовка доступных для взаимодействия предметов. На этом этапе количество доступных проверяется функцией
:
А вот уровни для одноразовых абилити и персонажей прописаны в
Объясняется сиё решение разработчика наличием двух функций
Всё получилось, мы воплотили задуманное! Можно с гордостью зваться начинающим мобильным крякером =]
По аналогии сделал всё то же самое с x86-библиотекой, удалил лишние файлы, оставил небольшое пасхалко - и мод готов! Конечно, сегодняшний пример - довольно старая игра без каких-либо особых средств защиты, держащая всю логику в одной библиотеке. Но мне всё равно было интересно - это вам не ModMenuMaker'ом пользоваться по трёхминутному гайду от школьника! Какие-никакие, но серьёзные знания тут всё-таки нужны. Попробую добиться открытия темы на 4pda и таки выложить всему миру мод этой богом забытой игры...
Надеюсь, эта небольшая статья поможет вам в нашем, несомненно, нелёгком деле.
Удачного крякинга!
made 4 @rev_with_da_boys
С детства я всегда мечтал, если не попасть в их круг, то хотя бы тоже научиться взламывать игры. И если первое - не совсем от меня зависит, то вот второе - именно то, чем мы и будем заниматься в сегодняшней мини-статье. В качестве подопытного мы возьмём одну из моих любимых игр детства -
Ссылка скрыта от гостей
. Классный зомби-шутер, почему-то давно пропавший с просторов Google Play. Игра старая, последнее обновление выходило в районе 2019 года. На 4PDA присутствует уже модифицированная версия 1.25, а так же последняя 1.28, нетронутая. Её мы, ввиду актуальности, и вскроем!Для начала нам необходимо вообще понять, что эта игра предлагает, и что мы можем с ней сделать.
Суть игры проста: мы должны отсреливать волны зомби, чертей, крокодилов, дровосеков, кроликов и прочей нечести, дабы пройти уровень. Из важного - у нас есть полоска HP в виде трёх сердец, у каждого подбираемого оружия есть полоска с количеством оставшихся патронов, а с убитых нами падают монеты, за которые мы можем открывать и улучшать оружие/персонажей. Кроме того, в игре есть таблица с квестами - за квесты дают опыт, за опыт мы повышаем уровень, а с новыми уровнями появляется возможность открывать всё новое.
Как человек, который довольно много играл в эту игру в своё время, скажу - вариаций оружия и персонажей для разблокировки много, и на высоких уровнях деньги и опыт копятся ну очень долго. Так что сегодня мы это дело исправим!
Для начала откроем наш APK в любом Java-декомпиляторе (я буду использовать JEB) и сразу глянем в манифест приложения:
Название интересующего нас пакета -
net.mountainsheep.minigore2zombies
. Так же в метаданных была указана отдельная библиотека - minigore2, запоминаем. Если мы посмотрим на содержимое нашего пакета, то станет немножко неуютно:Изобилием классов этот пакет не блещет. Заглянем в главное активити - xtPlay:
Кроме как загрузкой вышеупомянутой библиотеки, этот активити ничем не интересен, дальше идут какие-то махинации с рекламой. В остальных активити тоже нет ничего, что походило бы на логику игры. А значит, лезем в библиотеку!
Так как игра очень старая, в ней всего две версии библиотеки: armeabi-v7a и x86. Так как с этой библиотекой дальше мы будем работать в дизассемблере, то стоит отдать предпочтение той версии, которую будет удобнее понимать, для многих - это, конечно, x86/x86-64. Я же, имея на борту IDA hex-rays для ARM, сразу начну с этой версии. Всё равно, если будет нужно, мы будем патчить все доступные версии.
Что сходу радует - здесь, в этой библиотеке расписана вообще ВСЯ логика игры. А что ещё лучше - у каждой функции есть понятное название, с объединяющей группой в виде пространства имён. Дальше всё зависит от нашей фантазии при поиске нужных! Напомню, сегодняшняя цель нашего мода - деньги и уровень для быстрой разблокировки всего. Попробуем поискать что-то, что связано с магазином:
Здесь каждая группа функций выделена на отдельную секцию магазина: уровни, оружие, персонажи - соответственно, StoreLevels, StoreWeapons и StoreCharacters. Начнём с последней - а именно с
StoreCharacters::getCharacterPrice()
:По какой-то причине, каждая функция - просто вызов другой, уже настоящей. Причём в IDA отображаются обе, с одинаковым именем. Так что мы просто залезем во вторую:
А здесь тело уже соответствует названию: наглядно видна кривая повышающейся цены, что отвечает за прокачку персонажа. Поэтому, в теории, если мы сделаем так, чтобы эта функция всегда возвращала 0, мы не должны тратить ни монеты на покупку и прокачку. Чтобы сделать конструкцию вида
return 0
, в ARM понадобится 2 инструкции - обнулить r0 и прыгнуть по адресу:
Код:
mov r0, #0 ; 00 00 A0 E3 (Little-Endian)
bx lr ; 1E FF 2F E1 (https://shell-storm.org/online/Online-Assembler-and-Disassembler/)
В режиме Thumb это будет выглядеть так:
Код:
movs r0, #0 ; 00 20
bx lr ; 70 47
Одноимённая функция, которая вызывает настоящую, тоже состоит из 2-х инструкций:
Тем более, что ADRL занимает 8 байт, мы можем её заменить на нужные нам две четырёхбайтовые инструкции! Трогать вторую инструкцию смысла нет, после патча наша функция должна выглядеть так:
Теперь попробуем собрать обратно нашу игру с новой библиотекой. Я для этих целей использую ApkTool-GUI, предварительно заменив оригинальную библиотеку на патченную:
Теперь переустановим игру и посмотрим, есть ли результат. Напоминаю, если наша задумка воплотилась, то сейчас любая прокачка персонажей должна быть бесплатной.
Получилось! Монеты не тратятся, улучшения остаются, а мы - в шоколаде! Осталось то же самое провернуть и для остальных секций магазина, там всё точно так же, по аналогии. Теперь к уровням.
Судя по структуре функций, есть отдельные функции, которые возвращают информацию обо всех предметах из секции. В каждом элементе такого массива есть отдельное поле для уровня, с которого данный предмет доступен.
А так же есть отдельные функции вида
getNeededLevelFor<section>()
. Что патчить - триллион полей в списке предметов или пару инструкций в нескольких функциях - думаю, для читателя очевидно.Алгоритм тот же самый: вместо первых нескольких инструкций просто возвращаем ноль, ничего нового. Казалось бы, раз мы такие молодцы, всё же заработает? А вот хрен там!
Бесплатная прокачка == бесконечные деньги, поскольку их тратить больше не на что, тут всё прекрасно. Но вот с уровнями произошла неувязочка: видимо, предметы открываются только тогда, когда твой уровень не просто больше
getNeededLevel()
, а именно равен. А так как теперь нужный уровень - нулевой, то фактически я запорол все новые предметы, сделав их неразблокируемыми))Методом проб и ошибок я выяснил, что при повышении уровня разблокируется предмет, требуемый уровень которого равен полученному. Так что либо мы делаем так, чтобы они разблокировались по одному на каждом уровне, что не особо ускоряет прогресс игроку, либо ищем другой способ.
Хорошенько порывшись в функциях, я наткнулся на это чудо:
Можно сделать так, чтобы эта функция возвращала 0. Если в игре есть ограничение на максимальный уровень - в теории, должно сработать. Но если максимального уровня нет... Лучше на этот счёт не думать.
После проверки всё оказалось куда проще - игра просто вылетала при запуске. Видимо, сильно мы логику поломали этой функцией, так что меняем всё, как было и думаем дальше. А надумал я следующее: проблема не в логике, а в UI!
На этапе входа в магазин идёт отрисовка доступных для взаимодействия предметов. На этом этапе количество доступных проверяется функцией
getVisible<section>Count()
. Причём в разных секциях разный механизм проверки предмета на доступность, но все они, в конечном итоге, смотрят на наш уровень. Интересно, что в секциях с оружием и уровнями, требуемые уровни захардкожены в память:А вот уровни для одноразовых абилити и персонажей прописаны в
is<section>Visible()
, которое под капотом вызывает get<section>Info()
:Объясняется сиё решение разработчика наличием двух функций
add<section>Item()
. Но нам всё равно: всё, что нам нужно сделать - это либо заединичить захардкоженные значения, либо занопить проверяющий переход из цикла с инкрементом. После этого заменяем библиотеки, собираем игру, устанавливаем и скрипим зубами в потугах выдержать весь груз своей офигенности:Всё получилось, мы воплотили задуманное! Можно с гордостью зваться начинающим мобильным крякером =]
По аналогии сделал всё то же самое с x86-библиотекой, удалил лишние файлы, оставил небольшое пасхалко - и мод готов! Конечно, сегодняшний пример - довольно старая игра без каких-либо особых средств защиты, держащая всю логику в одной библиотеке. Но мне всё равно было интересно - это вам не ModMenuMaker'ом пользоваться по трёхминутному гайду от школьника! Какие-никакие, но серьёзные знания тут всё-таки нужны. Попробую добиться открытия темы на 4pda и таки выложить всему миру мод этой богом забытой игры...
Надеюсь, эта небольшая статья поможет вам в нашем, несомненно, нелёгком деле.
Удачного крякинга!
made 4 @rev_with_da_boys