Как взломать приложения для Android при помощи отладчика

На сегодняшний день существует огромное количество разнообразных методов и способов взлома приложений для операционной системы андроид. Все они по-своему хороши и интересны, но важно одно — правильно разбираться в схеме их работы, иначе вас ожидает провал или «нечто страшное»))) Сейчас предлагаю поговорить о взломе приложений для андроид при помощи отладчика т.к. данный способ помогает тщательно разобраться в поведении работы приложений и выявить их слабые места для дальнейшего воздействия.

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

Во все времена лучший способ сделать это состоял в использовании отладчика. Но есть одна проблема: у вас нет исходников, а без них отладчик мало полезен в вашем деле. Зато у вас есть возможность декомпилировать приложение в Java (нередко только частично) или в достаточно высокоуровневый (в сравнении с машинным кодом) код smali, который всегда будет полностью корректным.

Так что в целом алгоритм ваших действий будет выглядеть так: достать подопытное приложение из устройства; дизассемблировать его, выставляя флаги отладки; собрать обратно и установить на устройство; импортировать декомпилированный или дизассемблированный код в Android Studio; запустить отладку, будто это наше приложение.

<h2 style=»text-align: left;»>Флаги отладки</h2>

Андроид устроен таким образом, что не позволит подключиться с помощью отладчика к приложению, которое этого не хочет. А факт «желания» определяется флагом отладки, который представляет собой простую строку в файле АndroidManifest.xml приложения.

Поэтому первое, что мы должны сделать, — это разобрать приложение, выставить флаг отладки в значение true и собрать обратно. Проще всего это сделать с помощью утилиты apktool. Просто натравливаем ее на подопытное приложение, и готово:

$ java -jar apktool.jar d app.apk

В текущем каталоге появится подкаталог app (ну или как назывался пакет с приложением).

Далее переходим в него и видим несколько файлов и каталогов. Нам они еще пригодятся, а пока открываем файл АndroidManifest.xml в текстовом редакторе и находим строку, начинающуюся с <application. Это тег application, который описывает приложение в целом. Именно к нему мы должны добавить атрибут android:debuggable=»true». Просто вставь его сразу после application:

<application android:debuggable="true" ...

Теперь приложение необходимо запаковать и подписать:

$ java -jar apktool.jar b app
$ java -jar sign.jar app.apk

Утилиту sign можно найти на GitHub. После этого приложение можно установить на устройство.

<h2 style=»text-align: left;»>Процесс декомпиляции и дизассемблирования</h2>

Дизассемблерный листинг приложения у нас уже есть, мы получили его, разобрав приложение с помощью apktool. Мы можем импортировать его в Android Studio и начать отладку. Но лучше все-таки попытаться получить исходники Java, гораздо более легкие в чтении.

А для этого приложение необходимо декомпилировать. Сделать это можно с помощью нескольких различных инструментов, но я предпочитаю использовать декомпилятор Jadx. Он хорошо переваривает код, имеет средства деобфускации и активно развивается.

Теперь скачиваем Jadx, запускаем, выбираем apk-файл приложения. Откроется главное окно приложения. Слева будут пакеты, справа исходники. Лучше сразу проверить их корректность (действительно ли получился читаемый Java-код), а затем можно экспортировать их с помощью меню File → Save as gradle project.

<h2 style=»text-align: left;»>Android Studio и процесс отладки</h2>

А теперь экспортированные исходники необходимо импортировать в Android Studio (да, у вас должна быть установлена и настроена среда разработки). Делается это с помощью меню File → Open → New Project → Import Project. Затем выбираем каталог с исходниками и в ответ на все вопросы нажимаем «Далее».

Если все пройдет успешно, исходники будут импортированы и вы увидите их в главном окне Android Studio. Опять же лучше сразу пройтись по файлам и проверить их корректность. В 99,9% случаев вы увидите множество подчеркиваний и выделений красным: в понимании среды разработки исходники полны ошибок. Это абсолютно нормально, так как декомпилированный код так или иначе не должен быть пригоден для компиляции.

Активируйте на смартфоне режим отладки по USB (Настройки → О телефоне → восемь тапов по номеру сборки), подключите его к компу. В Android Studio нажмите кнопку Attach debugger to Android process (она находится рядом с кнопками запуска и остановки приложения), чтобы подключиться к смартфону и приложению.

Если снизу появилась панель дебаггера — вы на коне. Следующий шаг — расставить брейк-пойнты в тех местах приложения, которые вы хотите исследовать. Сделаем это на примере простейшего crackme-one, который записывает строку в файл, а вам нужно узнать содержимое этой строки. Он хранит строку в открытом виде, но мы представим, что он расшифровывает ее только во время записи и поэтому мы должны поймать момент этой записи, чтобы вычленить уже расшифрованную, но еще не записанную строку.

Ну и с чего же нам начать? Для начала выясним, с какой активности начинается исполнение приложения. В данном случае это опять же бессмысленно в силу простоты crackme, но в больших приложениях пригодится. Найти исходник нужной активности можно с помощью файла АndroidManifest.xml. Вот как выглядит описание главной активности в crackme:

<activity android:label="@string/app_name" android:name="com.reoky.crackme.challengeone.activities.ChallengeActivity">
    <intent-filter>
        <action android:name="android.intent.action.MAIN"/>
        <category android:name="android.intent.category.LAUNCHER"/>
    </intent-filter>
</activity>

Обратите внимание на 3 и 4 строки. Они означают, что именно с этой активности начнется исполнение приложения (на самом деле таких активностей может быть несколько, но это редкость). Также обратите внимание на следующую строку:

android:name="com.reoky.crackme.challengeone.activities.ChallengeActivity

Можно сказать, это полный «путь» до активности, включая все имена покетов. Именно по такому пути вы найдете ее в исходниках, загруженных в Android Studio.

Открыв исходник этой активности в Android Studio, вы заметите его крайнюю простоту. По сути это окно с переключателем табов, а содержимое табов располагается внутри фрагментов в пакете/каталоге fragments. Переходим в него и видим ChallengeOneFragment. Он как раз и содержит поле ввода ответа и кнопку для записи файла. Внимательно прочитав исходник, замечаем, что в качестве колбэка для этой кнопки используется ChallengeOneFragmentOnClickListener, определенный в одноименном файле в каталоге listeners.

Открываем этот файл и среди прочих видим такие строки:

OutputStreamWriter outputStreamWriter = new OutputStreamWriter(parent.getContext().openFileOutput("ANSWER", 1));
outputStreamWriter.write("poorly-protected-secret");
outputStreamWriter.flush();
outputStreamWriter.close();

Вот мы и взломали crackme, искомая строка: «poorly-protected-secret». Но постойте, мы же договорились, что представим будто строка зашифрована и мы не можем ее увидеть. Вот здесь нам и нужен дебаггер: соль в том, чтобы поставить брейк-пойнт на вторую строку приведенного выше листинга и после этого запустить приложение. Когда исполнение приложения дойдет до этой точки, оно будет остановлено, а мы с помощью консоли дебаггера сможем прочитать аргумент вызова write (который уже должен быть расшифрован перед записью).

Итак, открываем исходник в Android Studio, находим нужную строку и кликаем рядом с номером этой строки. Строка подсвечивается красным, сигнализируя об установке брейк-пойнта. Наверняка вы не сразу сможете установить корректный брейк-пойнт (тот, который будет отмечен галочкой), потому что исходники, скорее всего, не будут соответствовать коду приложения. По этой же причине вам  придется действовать вслепую, когда исполнение приложение дойдет до брейк-пойнта. При переходе к следующей строке дебаггер будет кидать вас в совершенно неверные куски кода, постоянно сообщая, что код некорректный.

Выхода из этой ситуации два: либо продвигаться на ощупь, либо вместо декомпилированного Java-кода загрузить в Android Studio дизассемблированный код smali, который просто технически не может быть некорректным.

<h2 style=»text-align: left;»>Использование дизассемблированного кода</h2>

Дизассемблированный код приложения у нас уже есть. Мы получили его, когда разбирали приложение с помощью apktool. Проблема только в том, что Android Studio в своем стандартном варианте хоть и умеет подсвечивать код smali, но не способна «работать» с этим кодом. Другими словами, мы сможем прочитать код smali, но не сможем установить брейк-пойнты.

Чтобы это исправить, нужен сторонний плагин smalidea, а общая последовательность действий будет выглядеть так: скачаем плагин smalidea; импортируем плагин в Android Studio: Settings → Plugins → Install plugin from disk; импортируем каталог с разобранным приложением точно так же, как мы это делали в случае декомпилированного кода; в боковой панели кликнем на Android и выберем Project Files, чтобы увидеть все файлы и каталоги проекта; кликнем правой кнопкой на каталоге smali и выбираем Mark directory as → Sources root.

Как и в случае с Java-кодом, нужный нам код находится в listeners/ChallengeOneFragmentOnClickListener. В этот раз код намного длиннее и запутаннее, но, используя ранее полученный Java-исходник, вы легко найдете нужное место, а именно 246-ю строку:

invoke-virtual {v4, v8}, Ljava/io/OutputStreamWriter;->write(Ljava/lang/String;)V

Ставьте на нее брейк-пойнт, запускайте приложение и, когда оно остановится, посмотрите на окно дебаггера. В нем будет состояние текущего и других объектов. Нажимая F7, вы заставите дебаггер выполнить следующую строку с переходом внутрь вызываемой функции (в нашем случае outputStreamWriter.write(«poorly-protected-secret») ). Оказавшись внутри нее, вы сможете просмотреть содержимое ее аргумента, а именно искомую строку. В данном случае ее видно и до перехода в функцию, но, если бы она была зашифрована, этот метод помог бы выяснить реальное значение.

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

Материал, представленный в процессе статьи, несёт исключительно ознакомительный характер.

Click to rate this post!
[Total: 4 Average: 4.3]

Leave a reply:

Your email address will not be published.