Рекомендуем почитать:
Сегодня в выпуске: бэкдор в смартфонах Huawei, исследование устройства защищенной среды исполнения в смартфонах Samsung, простой и надежный способ зашифровать данные приложения, оптимизация приложения для Chrome OS, объяснение разницы между val и const val в Kotlin, а также новые инструменты пентестинга и большая подборка библиотек для разработчиков.
Huawei’s Undocumented APIs — A Backdoor to Reinstall Google Services — статья разработчика Magisk о том, как Huawei удалось реализовать систему установки сервисов Google Play на недавно выпущенный Huawei Mate 30.
Напомним, что в результате развязанной президентом Трампом торговой войны США и Китая Google была вынуждена разорвать действующие соглашения с компанией Huawei. В результате Huawei больше не может легально устанавливать приложения Google на свои устройства.
Казалось бы, приложения, в том числе Google Play, всегда можно доустановить из сторонних источников. Однако для их работы необходимы сервисы и библиотеки Google, которые должны быть частью прошивки и не могут быть установлены отдельно.
Huawei оказалась в безвыходной ситуации, но энтузиасты быстро выяснили, что в Сети можно найти приложение LZPlay, которое магическим образом установит все необходимые компоненты на устройство, причем его разлочка или рутинг не понадобятся.
Никак иначе, кроме как с помощью скрытого API, реализованного Huawei, или уязвимости, LZPlay работать не мог, и Джон Ву (John Wu), разработчик Magisk, решил выяснить, так ли это.
Оказалось, что LZPlay использует ряд специфичных для Huawei разрешений:
<uses-permission android:name="com.huawei.permission.sec.MDM_APP_MANAGEMENT"/> <uses-permission android:name="com.huawei.permission.sec.MDM_INSTALL_SYS_APP"/> <uses-permission android:name="com.huawei.permission.sec.MDM_INSTALL_UNDETACHABLE_APP"/> <uses-permission android:name="com.huawei.systemmanager.permission.ACCESS_INTERFACE"/>
Документация сообщает, что отдельные из этих разрешений предназначены для использования функции MDM, при помощи которой компании контролируют устройства своих сотрудников. Но документация ничего не говорит о двух разрешениях, которые, судя по названиям, нужны для установки системных приложений:
<uses-permission android:name="com.huawei.permission.sec.MDM_INSTALL_SYS_APP"/> <uses-permission android:name="com.huawei.permission.sec.MDM_INSTALL_UNDETACHABLE_APP"/>
Учитывая то, что системный раздел в новых устройствах Huawei всегда подключается в режиме «только чтение», эти разрешения позволяют дать любому стороннему приложению привилегии системных. По сути, это бэкдор.
Но самое интересное, что использовать эти API могут только приложения, подписанные специальным ключом Huawei. Другими словами, Huawei не только знала о существовании приложения LZPlay, но и одобрила его, выдав разработчикам ключ для подписи.
Breaking Samsung’s ARM TrustZone — рассказ об уязвимостях, найденных в реализации TrustZone в смартфонах Samsung. Презентация интересна не столько самими уязвимостями, сколько подробностями о внутренностях системы.
Система TrustZone представляет собой выделенную среду исполнения внутри ARM-совместимых чипсетов, логически не связанную с основной средой исполнения, где работает операционная система смартфона и пользовательские приложения. Android использует TrustZone для запуска систем шифрования и обработки сенситивной информации, которая должна быть защищена от третьих лиц. К TrustZone имеет доступ только ограниченный набор привилегированных сервисов, а хранимая ей информация зашифрована и лежит в недоступной для основной системы памяти.
В случае с Samsung внутри TrustZone работает либо операционная система Kinibi, разработанная компанией Trustonic (Samsung Galaxy S3–S9), либо система TEEGRIS, за авторством инженеров самой Samsung (Samsung Galaxy S10). В презентации речь идет только о Kinibi. Интересные факты:
AndroidX: Security library — рассказ о новой Jetpack-библиотеке androidx.security, содержащей удобные и простые инструменты для шифрования данных приложения.
Библиотека включает в себя два основных класса:
Пользоваться библиотекой очень просто. Подключаем библиотеку с помощью Gradle:
implementation "androidx.security:security-crypto:1.0.0-alpha02"
Затем создаем ключи шифрования (библиотека автоматически сохранит их в KeyStore, который в современных телефонах использует защищенную среду TEE):
val keyGenParameterSpec = MasterKeys.AES256_GCM_SPEC val masterKeyAlias = MasterKeys.getOrCreate(keyGenParameterSpec)
Далее создаем объект класса EncryptedSharedPreferences:
val sharedPrefs = EncryptedSharedPreferences.create( ИМЯ_ФАЙЛА, masterKeyAlias, context, EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV, EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM )
Все, теперь sharedPrefs
можно использовать вместо стандартного объекта SharedPreferences
для хранения и извлечения настроек. Все они будут автоматически зашифрованы с помощью ключа, который не удастся узнать, даже получив права root на устройстве.
To val, or to const val, that is the question — заметка о различиях между val
и const val
в Kotlin.
Возьмем следующий пример:
val FANCY_VAL = 1 const val FANCY_CONST_VAL = 2
Обе эти переменные немодифицируемые, но вторая объявлена с ключевым словом const
в начале. Что это значит на деле? Во-первых, FANCY_VAL
станет приватной переменной, для доступа к которой будет создан геттер. Это можно увидеть, если скомпилировать код и затем декомпилировать его в Java:
public final class ConstValKt { private static final int FANCY_VAL = 1; public static final int FANCY_CONST_VAL = 2; public static final int getFANCY_VAL() { return FANCY_VAL; } }
Во-вторых, переменная FANCY_CONST_VAL
будет заинлайнена, то есть компилятор заменит все полученные значения этой переменной на само значение. Это тоже можно увидеть, если написать код, использующий эти переменные, а затем скомпилировать и декомпилировать его.
Оригинальный код:
public static void main(String[] args) { System.out.println(ConstValKt.get_FANCY_VAL()); System.out.println(ConstValKt.MY_FANCY_CONST_VAL); }
Декомпилированный код:
public static void main(String[] var0) { System.out.println(ConstValKt.getFANCY_VAL()); System.out.println(2); }
Вывод: const val
позволяет оптимизировать код, избавившись от ненужных геттеров и обращений к переменным.
Optimizing Android app experiences for Chrome OS — статья разработчиков Chrome OS о том, что нужно сделать, чтобы Android-приложение стало удобным для пользователей Chrome OS. Основные моменты:
override fun onKeyUp(code: Int, ev: KeyEvent?): Boolean { return when (code) { KeyEvent.KEYCODE_J -> { // Обрабатываем нажатие true } else -> super.onKeyUp(code, ev) } }
Следует иметь в виду, что ноутбуки на Chrome OS оснащены специальной клавишей «Обновить» (код кнопки: KEYCODE_REFRESH
). В Android-приложениях эта кнопка по умолчанию обновляет SwipeRefreshLayout
.
Тачпад. Пользователи Chrome OS ожидают, что свайп двумя пальцами по тачпаду будет проматывать экран. Это поведение автоматически распространяется на Android-приложения, но если необходимо обрабатывать эти действия раздельно, то следует игнорировать MotionEvent
с состоянием кнопок, равным нулю (event.getButtonState() == 0
).
NDK. Если Android-приложение использует нативные библиотеки для платформы ARM, Chrome OS будет применять x86-транслятор для запуска кода библиотеки. Это снижает производительность, поэтому разработчику следует включать в приложение библиотеки для платформ ARM, x86 и AMD64.
Разметка. Android уже давно позволяет использовать разную разметку и метод навигации в зависимости от ориентации и размера экрана. Поддержка разных устройств и положений экрана автоматически сделает приложение более удобным в использовании на устройствах с Chrome OS. Также стоит сделать обработчик смены разрешения в колбэке onConfigurationChanged
на случай, если пользователь подключит внешний монитор.
10 New Android Kotlin Libraries You Should Check Out This Winter — подборка из десяти новых, написанных на Kotlin библиотек:
Читайте также
Последние новости