RuCore.NET

Как реверсить приложения для Android?





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

Какое приложение мы будем препарировать? Я выбрал для своих целей VK Admin — программу для управления сообществами «ВКонтакте» со смартфона. В нем не предусмотрена темная тема, поэтому мы с тобой попробуем эту тему добавить.



Разбираем

Сначала извлечем все ресурсы приложения, используя утилиту apktool — она распаковывает и запаковывает файлы пакетов APK, которые хранятся в сжатом, бинарном виде, и дизассемблирует программный код, заключенный в них.

Чтобы получить установочный пакет, можно воспользоваться Android Debugging Bridge — системой для отладки программ на устройстве. В *nix-подобных системах ADB ставится стандартно, с помощью пакетного менеджера, а в Windows — идет в составе Android Studio или Android SDK Platform Tools.

В первую очередь установим приложение из Google Play Store на смартфон, подключим его к компьютеру с помощью USB, затем воспользуемся ADB для переноса пакета приложения на компьютер и извлечем его содержимое.

 

 

$ adb shell pm path com.vk.admin

package:/data/app/com.vk.admin-Ka5KVtTbnGgxoRqnObb-pQ==/base.apk

$ adb pull /data/app/com.vk.admin-Ka5KVtTbnGgxoRqnObb-pQ==/base.apk com.vk.admin.apk

3881 KB/s (13414132 bytes in 3.374s)

$ apktool d com.vk.admin.apk

I: Using Apktool 2.4.0 on base.apk

I: Loading resource table...

I: Decoding AndroidManifest.xml with resources...

I: Regular manifest package...

I: Decoding file-resources...

I: Decoding values / XMLs…

I: Baksmaling classes.dex…

I: Copying assets and libs…

I: Copying unknown files…

I: Copying original files…

 

После этого мы получим папку com.vk.admin/, внутри которой хранится все содержимое исходного .apk, только в декодированном виде. Чтобы применить изменения, необходимо будет снова воспользоваться рядом утилит.

Сначала собери приложение обратно в пакет .apk.

 

$ apktool b com.vk.admin/

I: Using Apktool 2.4.0

I: Checking whether resources has changed…

I: Checking whether sources has changed…

I: Smaling classes folder into classes.dex…

I: Building apk file…

I: Copying unknown files/dir…

I: Built apk…

 

 

Затем необходимо подписать приложение. Это нужно, чтобы и Google Play Store, и устройство не обновляли приложение, если подписи не совпадают. Поэтому не забудь удалить приложение с телефона, прежде чем установить свое, подписанное своим ключом. Для создания подписи в первый раз нужно воспользоваться утилитой keytool (входит в Java Development Kit):

$ keytool -genkey -keyalg RSA -alias xakep -keystore ks.keystore -validity 10000 -keysize 2048

Enter keystore password:

Re-enter new password:

What is your first and last name?

  [Unknown]: Xakep User

What is the two-letter country code for this unit?

  [Unknown]: RU

Is CN=Xakep User, C=RU correct?

  [no]: yes

Enter key password for

  (RETURN if same as keystore password):

Re-enter new password:

 

Когда ты уже создал ключ, подпиши приложение.

$ jarsigner -sigalg SHA1withRSA -digestalg SHA1 -keystore ks.keystore com.vk.admin.apk xakep

Enter Passphrase for keystore:

jar signed.

После этого установи приложение на телефон.

$ adb install com.vk.admin.apk

3881 KB/s (13414132 bytes in 3.374s)

Success

 

Меняем цветовые схемы

Цвета в приложении можно настроить несколькими способами:

  • использовать встроенные цвета, к примеру @android:color/white;
  • создать палитру собственных цветов в файле colors.xml, которые затем используются в виде @color/text_primary;
  • задать цвет шестнадцатеричным кодом, главное — не забывай, что цвета в приложении записаны в формате #AARRGGBB — прозрачность на первом месте;
  • воспользоваться параметрами setTextColorsetBackgroundColor внутри кода Java или Kotlin.

Все эти варианты жизнеспособны и постоянно используются.

Рекомендую ознакомиться с документацией по байт-коду Dalvik VM.

setBackgroundColor

Для некоторых экранов приложения используется параметр setBackgroundColor(I)V, который устанавливает цвет фона. Часто это не статичные экраны, а динамические: с поддержкой скролла, различные списки и карточки.

invoke-virtual {v1, v0}, Landroid/webkit/WebView;->setBackgroundColor(I)V

Эта строка занимается изменением. Чтобы изменить цвет, нужно его записать в регистр, а затем передать в функцию вместо настоящего.

const v12, -0x1000000
#### Эквивалент 0xFF000000 — черного

invoke-virtual {v1, v12}, Landroid/webkit/WebView;->setBackgroundColor(I)V

Теперь пройдись по всем файлам и замени цвет.

Бывают случаи на порядок проще.

const v2, -0x1
#### Здесь -0x1 == 0xFFFFFFFF — белый цвет

invoke-virtual {v1, v2}, Landroid/support/v7/widget/CardView;->setBackgroundColor(I)V

Нужно просто изменить -0x1 на -0x1000000, и приложение погрузится во тьму.

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

 

setTextColor

Иногда текст, который меняется в ходе работы с приложением, может менять свой цвет. За это отвечает параметр setTextColor(I)V, второй аргумент которого можно подменить на нужный, в нашем случае — белый.

#### Меняем цвет
const p1, -0x1
#### на белый

invoke-virtual {v0, p1}, Landroid/widget/TextView;->setTextColor(I)V

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

 

Меняем функциональность приложения

Чтобы ощутить всю мощь smali, давай попробуем изменить какую-то часть приложения. Например, обойдем проверку на внутренние покупки.

Возьмем другое приложение — ISS Detector. Оно показывает положение МКС над Землей. В нем можно купить расширения: показ комет, планет, Луны, телескопа «Хаббл».

При копировании приложения на компьютер может возникнуть проблема: в составе приложения не один и не два, а целых три файла apk!

$ adb shell pm path com.runar.issdetector

package:/data/app/com.runar.issdetector-dtgy8_hlf1y-cekrg1_W-A==/base.apk

package:/data/app/com.runar.issdetector-dtgy8_hlf1y-cekrg1_W-A==/split_config.en.apk

package:/data/app/com.runar.issdetector-dtgy8_hlf1y-cekrg1_W-A==/split_config.xxhdpi.apk

Копируем все. При переустановке приложения файлы split_config.en.apk и split_config.xxhdpi.apk потеряются, а без них приложение будет вылетать. Поэтому их нужно будет переподписать: зайти в них как в архивы ZIP, удалить папку META_INF и прогнать через стандартную процедуру утилиты jarsigner. Основной же файл мы будем препарировать с помощью apktool.

Покупками в приложении занимается интерфейс IInAppBillingService. Для него прописана обертка com.runar.issdetector.util: IabHelper, IabResult, Purchase, Security, Inventory.

В этом приложении можно не идти напролом, обманывая сервис покупок. Проще заставить приложение думать, что все уже куплено. В этом нам поможет Inventory.smali.

В особо сложных случаях такой трюк провернуть не удается, и тогда приходится подменять данные, заставляя сервис ложно сообщать о совершенных покупках. Подробнее об этом можно почитать в материале компании Securing Apps (PDF).

Открыв файл, ты увидишь поле mPurchaseMap<String; Purchase>, которое содержит в себе все покупки: номер товара, сопоставленный с покупкой, которую совершил пользователь.

.field mPurchaseMap:Ljava/util/Map;
    .annotation system Ldalvik/annotation/Signature;
        value = {
            "Ljava/util/Map<",
            "Ljava/lang/String;",
            "Lcom/runar/issdetector/util/Purchase;",
            ">;"
        }
    .end annotation
.end field

Далее в коде мы видим строку hasPurchase(String sku) -> boolean, которая проверяет, совершал ли пользователь покупку. Для этого делается проверка на существование ключа sku в mPurchaseMap.

.method public hasPurchase(Ljava/lang/String;)Z
    .locals 1

    .line 45
    iget-object v0, p0, Lcom/runar/issdetector/util/Inventory;->mPurchaseMap:Ljava/util/Map;

    invoke-interface {v0, p1}, Ljava/util/Map;->containsKey(Ljava/lang/Object;)Z

    move-result p1

    return p1
.end method

А что будет, если в любом случае отдавать true?

.method public hasPurchase(Ljava/lang/String;)Z
    .locals 1

    const p1, 0x1

    return p1
.end method

Собираем приложение и устанавливаем его.

$ adb install-multiplie com.runar.issdetector.apk split_config.xxhdpi.apk split_config.en.apk

Success

 

С этого можно начать свой путь в реверс-инжиниринг.

 

Источник: https://xakep.ru/



Поделись статьей с друзьями


153 просмотров



Сообщить об опечатке

Текст, который будет отправлен нашим редакторам: