![](https://habrastorage.org/getpro/habr/post_images/652/8f8/687/6528f8687ec814cb2ae33bfc63f46f97.jpg)
Возможно, кто-то из вас заметил, что Google на 1 апреля добавила в приложение Google Maps для Android и iOS интерактивную игру «Змейка».
Специалисты Check Point обычно заняты исследованием последних киберугроз, но здесь очень увлеклись этой игрой, правда, сильно расстраивались из-за проигрышей… поэтому возникла логичная мысль: почему бы её не взломать!
Таким образом, наши самые озорные сотрудники начали думать над обратной разработкой приложения с помощью удалённой отладки. В общем, у них получилось, и вскоре мы успешно выполнили задачу никогда не проигрывать — и даже добавили простой ИИ, который сам играет в игру.
![](https://habrastorage.org/getpro/habr/post_images/b62/c71/fc4/b62c71fc418fcb097b52c4245eeb4d6c.jpg)
![](https://habrastorage.org/getpro/habr/post_images/865/187/d2b/865187d2b602ab168bdfafd147e64598.png)
В этой заметке подробно опишем хак.
Сначала мы открыли приложение на виртуальном устройстве через Genymotion и запустили «Змейку», которая находится в меню в правом верхнем углу.
Похоже, что игра отображается в WebView, поэтому мы запустили удалённую отладку в инструментах разработчика Chrome:
![](https://habrastorage.org/getpro/habr/post_images/513/35d/b2a/51335db2aeb6fec60fce9f3b15ad8dc5.png)
Затем перешли на сайт и нашли на вкладке с исходниками файл v18.js, а в нём несколько интересных функций.
Во-первых, функция fa() инициирует поле размером 20×20:
this.height = this.width = 20;
Наша главная цель — найти и изменить функцию, которая определяет, когда змейка врезается в стену или в себя, чтобы отключить возможность проигрыша. Переменные width и height представляют размеры игрового поля, поэтому мы поискали width и height внутри исходного кода и нашли функцию F(a, b):
![](https://habrastorage.org/getpro/habr/post_images/7db/875/4aa/7db8754aa46203e12e8cc609cd7c106e.png)
Похоже, F(a, b) проверяет, находятся ли координаты тела змеи в пределах поля. Один из вариантов — полностью удалить условия в функции, чтобы она всегда возвращала истину, тем самым переводя нас в «режим Бога», где мы можем проходить сквозь стены, не умирая.
Для этого мы нажали кнопку Inspect в удалённой консоли и изменили функцию F(a, b) на следующую:
![](https://habrastorage.org/getpro/habr/post_images/21e/14d/452/21e14d452d2b31afdec5ca293cc2eb86.png)
Теперь мы можем проходить сквозь стены:
![](https://habrastorage.org/getpro/habr/post_images/5e1/7c8/27d/5e17c827d93c1e9dffbc3e73c9be1998.png)
Рис. 1. Режим Бога
Это всё очень хорошо, но нам по-прежнему придётся играть, самостоятельно подбирая людей, чтобы зарабатывать очки. Следующий хак решит эту проблему.
В стеке вызовов много вызовов функции wa(a). Если изучить эту функцию, то мы увидим, что она рекурсивна и отвечает за запрос кадров анимации. wa(a) вызывает функции xa(a, b) и ya(a), которые отображают игровые фигуры (поезд, люди) и поле, соответственно.
Рассмотрим функцию xa(a, b):
![](https://habrastorage.org/getpro/habr/post_images/bd0/524/984/bd052498424b070f1927505e064bb65c.png)
Она принимает два аргумента: 'a' и 'b'. Первый является частью глобальной переменной Q, которая содержит интересную информацию о нашей игре, включая массив, который представляет собой игровое поле (рис. 2), где мы видим поезд (М), людей и объекты (K). Функция также вычисляет счёт и сохраняет его в c.i, что также эквивалентно Q.b.
![](https://habrastorage.org/getpro/habr/post_images/342/6db/729/3426db7294084bde0b602e57ac0a9b71.png)
Рис. 2. Массив игрового поля
Данный массив соответствует такому полю:
![](https://habrastorage.org/getpro/habr/post_images/70a/08f/84e/70a08f84e4494a9b822c72b3d33ebc2e.png)
Рис. 3. Игровое поле
xa(a) также обращается к функции sa(a) на рис. 4, которая генерирует случайные координаты при каждом создании нового человека. Если вызывать функцию более одного раза, то можно создать сколько угодно людей (рис. 5).
![](https://habrastorage.org/getpro/habr/post_images/182/38f/358/18238f358816860cf2de195f0428b335.png)
Рис. 4. Вызов функции sa(a)
Как здесь:
![](https://habrastorage.org/getpro/habr/post_images/c8f/c01/d3b/c8fc01d3b7c183913a11a30183772a47.png)
Рис. 5. Вызов функции с созданием любого количества людей на карте
Обратите внимание, что даже если вызывать sa(a) более одного раза и забирать человека, счёт не меняется. При подборе пассажира вызывается функция ka(a, b) на рис. 6. Таким образом, её нужно изменить, чтобы при каждом вызове она добавляла 10 очков и обновляла счёт на экране.
![](https://habrastorage.org/getpro/habr/post_images/e96/091/159/e9609115944b21a2e324b99c46d9c094.png)
Рис. 6. Обновлённая функция
Координаты каждой части поезда указаны в Q.b.o.b, где первый элемент представляет собой первый вагончик в поезде.
![](https://habrastorage.org/getpro/habr/post_images/4e6/d8e/0ea/4e6d8e0ea5fc7dc12186a5a27ee63f08.png)
Рис. 7. Массив вагончиков
Это понадобится для создания простого ИИ. Начнём с его логики:
![](https://habrastorage.org/getpro/habr/post_images/d25/e30/214/d25e30214681ad9d0469982f9a596830.jpg)
Рис. 8. Логика ИИ
Змейка представляет собой машину состояний (конечный автомат):
- На X=19 идём вниз, пока не доберёмся до Y=19.
- На X=19 и Y=19 идём влево до X=0.
- Переходим к машине состояний для зигзагов:
- Вверх на одну клетку и направо до X=18.
- Вверх на одну клетку и налево до X=0.
- Назад к шагу А.
- На Y=0 идём направо до X=19.
- Возвращаемся к шагу 1.
Полный код опубликован на GitHub.
Видео: