• 🚨 Ещё можно успеть на курс «OSINT: технология боевой разведки» от Академии Кодебай

    🔍 Изучите методы разведки с использованием открытых источников (OSINT) для проведения успешных атак.
    🛠️ Освойте ключевые инструменты, такие как Maltego, TheHarvester и другие.
    🧪 Пройдите практические лабораторные работы, имитирующие реальную разведку.
    🧠 Развивайте навыки, которые помогут вам стать экспертом в области информационной безопасности.

    Запись открыта до 23 мая Подробнее о курсе ...

Статья Взлом покупки в приложении или Я не хочу платить пару долларов

Дисклеймер
Данная статья впервые была опубликована мною 27 ноября 2014 года в песочнице habrahabr.ru, но удалена модераторами в тот же день. Спустя 4 года я нашёл исходники статьи и публикую её практически без изменений.
И я не стал убирать скриншоты под спойлеры, потому что на них изображён текст, который должен быть всё время на виду, так как материал очень сложен для понимания, особенно для новичков.


Недавно скачал приложение-клиент на Android для ресурса Хабрахабр. Официальный мне не понравился, так как от браузера он мало чем отличался, а второй, который был в списке поиска по Google Play, был HabraCitizen. На мою попытку авторизоваться, приложение ответило просьбой приобрести полную версию за $1.5, так же приобретение даёт возможность скачивать посты для оффлайн просмотра.

Donate


Так как нажатие на Нет отменяло авторизацию, нажал Да и увидел окошко Lucky Patcher'a с предложением получить эту покупку бесплатно. Посчитав такой подход к проблеме скучным и, оправдываясь перед совестью тем, что я небогатый студент, закрыл окошко и открыл Apktool. Разобрав HabraCitizen буквально по байтам принялся искать, где прячется вызов просьбы уменьшить счёт моего электронного кошелька.
1. Узнаём id текста с просьбой оплаты в файлах /res/values/strings.xml и /res/values/public.xml0x7f0c00d8

strings.xml
public.xml


2. Ввёл id через поиск по всем .smali файлам с помощью модифицированного мной приложения Search Thru (оригинальное пропускало «мимо ушей» файлы форматов кроме .txt, в том числе и .smali).

<скриншот утерян>

Итак, R$string и библиотека меня ничуть не интересуют, поэтому моя цель находится по адресу /smali/com/allesad/HabraCitizen/utils/i.smali. Открываем и видим:

i.smali


Формирование и отображение окошка происходит в отдельном методе, который может быть вызван из любой точки программы, ищем дальше.

3. В Smali вызов метода выглядит так:
invoke-static {p0, v0}, Lcom/allesad/HabraCitizen/utils/i;->a(Landroid/content/Context;Landroid/content/DialogInterface$OnClickListener;)V

Где p0, v0 — это параметры (если есть), com/allesad/HabraCitizen/utils/i — адрес класса, в котором вызываемый метод, a — имя вызываемого метода, (Landroid/content/Context;Landroid/content/DialogInterface$OnClickListener;)V — это что-то, связанное с каждым параметром (видно, что 2 параметра и два раза встречается ;). Важно заметить, что имена методов могут быть одинаковыми, при условии, если разное количество параметров или разные типы параметров(а).

Нам нужно найти, где вызывается метод, создающий диалоговое окно:
по запросу utils/i;->a находим вызовы метода а с двумя параметрами, то есть с
(Landroid/content/Context;Landroid/content/DialogInterface$OnClickListener;)V

utils/i;->a


DawnloadsActivity.smali и LoginActivity.smali — как раз то, за что надо платить $1.5.

4. В обоих случаях перед вызовом метода с окошком происходит какая-то проверка:

DawnloadsActivity.smali
LoginActivity.smali


А именно if-nez v0, :cond_1, что означает if not equals zero, в переводе если не равно нулю, прыгнуть на :cond_1. После замены if-nez v0, :cond_1 на if-eq v0, v0, :cond_1, что значит если v0 = v0, то перепрыгнуть вывод окошка (и, разумеется, после компиляции приложения и установки с удалением оригинала), приложение не просило пожертвовать. Иногда этого достаточно и приложения начинают радовать платными (уже бесплатными) функциями, но сразу после авторизации HabraCitizen падало с ошибкой, значит придётся ещё попотеть.

5. На скриншотах в п. 4 можно заметить ещё кое-что общее: то, откуда программа получает результат v0 для сравнения if-nez: invoke-vertual {v0}, Ljava/lang/Boolean;->booleanValue()Z, который в свою очередь берёт результат из метода
invoke-vertual {0}, Lcom/allesad/HabraCitizen/utils/e;->p()Ljava/lang/Boolean;

Где com/allesad/HabraCitizen/utils/e — класс, а p — имя метода.

6. Идём в /com/allesad/HabraCitizen/utils/e.smali и ищем метод p():

e.smali
e.smali


И видим, что в методе p() в одном месте встречаются SharedPreferences и premium_account_key, в конце которого происходит возврат результата (считывания значения premium_account_key, в данном случае там «false») действий метода туда, где он был вызван. А задав в поиск по файлу premium находим другой метод, который ничего не возвращает, но редактирует значение premium_account_key в SharedPreferences. Но чтобы давать ему что-то новое, это что-то нужно получить, в данном случае это p0. Кстати, переменные с префиксом p — параметры, получаемые при вызове данного метода. Значит, где-то происходит проверка лицензии и её результат отправляется в SharedPreferences, что нам как раз надо подделать.

7. Ищем вызов метода a(Ljava/lang/Boolean;)V (который редактирует SharedPreferences), и смотрим в удобном для понимания порядке — с третьего результата поиска по первый:

utils/e;->a
c.smali


Здесь мы видим, что будет, если мы имеем лицензию — отправка значения «true». То, что в зелёной рамочке, нужно скопировать, оно нам понадобится.

Далее второй результат:

c.smali


В нём происходит что-то, что явно не делает нам хорошо — заменяем то, что в красной рамочке тем, что скопировали ранее.

И наконец, первый результат:

c.smali
c.smali


Здесь я заметил «неприятное событие» — программа удаляет Coockie, а перед этим ряд похожих друг на друга действий, в том числе и присваивает к premium_account_key неведомое значение v1 (в самом деле false), как во втором результате. Скажу сразу, что подмена if-eqz v3, :cond_2 и if-nez v0, :cond_7, как в случае с выводом окошка, приводит к крашу приложения сразу после его запуска. Чтобы всё работало, кроме замены того, что в красной рамочке на то, что было скопировано из третьего результата, я удалил те «похожие действия», вызов метода removeAllCoockie и всё аж вплоть до :goto_3 (в данном случае это можно расценивать как логическое завершение мысли в русском языке). Вот как теперь стало:

c.smali Done


После очередной компиляции и переустановки приложения, разумеется, всё заработало без намёка на донат или падение.

Благодарю за проявленное вами терпение и упорство, необходимые для того, чтобы прочитать эту статью, и хочу заметить, что все описанные действия были совершены на смартфоне.

Несколько полезных ссылок:
  • — приложение для декомпиляции и компиляции приложений на Android устройстве
  • Search Thru — приложение для поиска текста среди текстовых файлов
  • Regex Finder - приложение для поиска по содержимому файлов, созданное мною как лучшая алтернатива Search Thru
 
Мы в соцсетях:

Обучение наступательной кибербезопасности в игровой форме. Начать игру!

Курс AD