Сегодня в выпуске: улучшения безопасности Android Q, обновления Android через Google Play, разбор DoS-эксплоита против почти всех смартфонов Samsung, исследование северокорейского клона игры Sim City, программирование интерфейса приложения без XML и головной боли, верификация целостности приложения, а также очередная подборка библиотек для программистов.
Queue the Hardening Enhancements, What’s New in Android Q Security — две статьи инженеров Google о сделанных в Android Q улучшениях безопасности. Основные моменты:
Fresher OS with Projects Treble and Mainline — подробности проекта Mainline, позволяющего обновлять отдельные системные компоненты Android без обновления платформы целиком.
Обновления будут распространяться в специальном формате пакетов APEX, который вместо приложения содержит в себе определенный компонент системы. В данный момент таким компонентом может быть: мультимедийный кодек, мультимедийный фреймворк, DNS-резолвер, Conscrypt Java Security Provider, Documents UI, Permission Controller, ExtServices, данные часовых поясов, ANGLE (прослойка для трансляции вызовов OpenGL ES в OpenGL, Direct3D 9/11, Desktop GL и Vulkan), Module Metadata, сетевые компоненты, Captive Portal Login и настройки сетевого доступа.
Если один из этих компонентов потребует обновления или в нем будет найдена уязвимость, Google сможет оперативно выкатить фикс в Google Play, и его получат сразу все пользователи Android Q и выше.
Интересно, что APEX не производит обновление «на живую», когда старый компонент заменяется на новый. Раздел /system
в Android недоступен для записи, поэтому APEX использует трюк с монтированием. Все файлы внутри пакета APEX находятся в образе файловой системы ext4. Когда происходит «установка» пакета, система монтирует этот образ поверх раздела /system
в режиме bind. В результате файлы пакета как бы заменяют оригинальные файлы Android, хотя в реальности все остается на своих местах. Точно такой же трюк использует Magisk для установки модификаций Android без изменения раздела /system
.
How to brick all Samsung phones — статья известного специалиста по IT-безопасности Эллиота Алдерсона (Elliot Alderson) о баге смартфонов Samsung, позволяющем стороннему разработчику залочить смартфон так, что им невозможно будет пользоваться.
Проблема заключается в приложении ContainerAgent, которое имеет ресивер SwitcherBroadcastReceiver
, принимающий среди прочих интент com.samsung.android.knox.containeragent.LocalCommandReceiver.ACTION_COMMAND
.
Декомпилировав код ресивера, можно выяснить, что при обработке интента проверяются значения com.samsung.android.knox.containeragent.LocalCommandReceiver.EXTRA_COMMAND_ID
и android.intent.extra.user_handle
. Если передать в первом 1001, а во втором 150 (идентификатор пользователя Knox User, который отвечает за защищенное хранилище данных), контейнер будет немедленно закрыт:
$ adb shell am broadcast -a com.samsung.android.knox.containeragent.LocalCommandReceiver.ACTION_COMMAND --ei "com.samsung.android.knox.containeragent.LocalCommandReceiver.EXTRA_COMMAND_ID" 1001 --ei "android.intent.extra.user_handle" 150
Если же передать 1001 и 0, произойдет немедленный переход на домашний экран:
$ adb shell am broadcast -a com.samsung.android.knox.containeragent.LocalCommandReceiver.ACTION_COMMAND --ei "com.samsung.android.knox.containeragent.LocalCommandReceiver.EXTRA_COMMAND_ID" 1002 --ei "android.intent.extra.user_handle" 0
Чтобы показать, как это можно использовать, Эллиот создал приложение, которое каждую секунду отправляет два этих интента и таким образом блокирует любые попытки использовать смартфон. Пользователь постоянно возвращается на домашний экран, а его защищенная папка, которую Samsung призывает использовать для хранения действительно важных данных, постоянно блокируется.
Reverse Engineering a North Korean Sim City Game — статья о северокорейском клоне игры Sim City, в которой внутриигровые покупки совершаются в офлайне. Интересные моменты:
Diving into Jetpack Compose — статья о новой библиотеке Jetpack Compose, представленной на Google I/O 2019. Compose позволяет описывать UI прямо в коде в декларативном стиле без необходимости править XML.
Пример приложения, написанного с использованием Compose:
class ComposeActivity : Activity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContent { CraneWrapper { MyApp() } } } @Composable fun MyApp() { MaterialTheme { Text(text = "Hello world!", style = +themeTextStyle { h3 }) } } }
Этот код создает активность в стиле Material Design с текстом «Hello World!». Функция CraneWrapper
необходима для настройки провайдеров Context, FocusManager и TextInputService. Функция MaterialTheme
настраивает цвета, стили и шрифты в соответствии с правилами Material Design.
Compose — это реактивный UI-фреймворк, существенно упрощающий работу с состояниями виджетов:
@Composable fun MyApp() { MaterialTheme { Counter() } } @Composable fun Counter() { val amount = +state { 0 } Column { Text(text = "Counter demo") Button(text = "Add", onClick = { amount.value++ }) Button(text = "Subtract", onClick = { amount.value-- }) Text(text = "Clicks: ${amount.value}") } }
Данный код создает экран с кнопками Add и Substract и текстом Text: <число>
. Нажатие любой из кнопок не только увеличивает внутреннее значение числа amount.value
, но и приводит к немедленному обновлению текстового виджета.
В качестве значения в коде +state { }
можно использовать не только числа и другие простые типы данных, можно создать и собственную модель данных:
@Model class CounterModel { var counter: Int = 0 var header = "Counter demo" fun add() { counter++ } fun subtract() { counter-- } }
Но самая интересная особенность Compose в том, что внутри он не использует стандартные виджеты и компоненты Android (View, Fragment и прочие). Вместо этого он рисует все виджеты самостоятельно, так же как это делает Flutter. Такая архитектура позволяет полностью абстрагироваться от версии Android и изменений в интерфейсе, внесенных производителями смартфонов, и получить полностью идентичный UI на любом устройстве (библиотеки поддержки Android это тоже могут, но ценой жутких костылей и необходимости допиливать вручную).
Отказ от использования стандартных виджетов Android также позволил Google создать более гибкий и современный фреймворк, многие из идей которого позаимствованы опять же из Flutter. Например, одна из ключевых идей Compose — «все есть виджет». Даже отступы для других виджетов реализуются с помощью виджета:
Padding(padding = 16.dp) { Button(text = "Say hello", onClick = { ... }) }
Это гораздо более интуитивный и понятный способ описания интерфейса.
Также одно из важных следствий описания интерфейса прямо в коде — возможность использовать любые языковые конструкции Kotlin:
Column { listOf("John", "Julia", "Alice", "Mark").forEach { Text(text = it) } }
Verify non-Google Play app installs — статья из официальной документации Google, посвященная решению проблемы, с которой столкнулись многие разработчики приложений после перехода на формат пакетов App Bundle.
Напомним, что App Bundle — это специальный формат пакета для приложений, который позволяет упаковать в один файл все возможные ресурсы и библиотеки приложения. При публикации релиза разработчик заливает App Bundle в Google Play, а тот, в свою очередь, «разрезает» бандл на множество независимых файлов APK, содержащих ресурсы и библиотеки для разных устройств. Например, файлы перевода попадают в собственные независимые пакеты, и эти пакеты устанавливаются отдельно от основного пакета приложения в зависимости от того, какой язык выбран в качестве дефолтового на устройстве пользователя.
App Bundle позволяет сократить размер приложения, не жертвуя функциональностью и не обременяя разработчика, которому иначе пришлось бы самостоятельно создавать и заливать в Google Play множество разных APK для разных платформ и устройств. Но есть одна проблема: если пользователь скачает приложение не напрямую из Google Play (например, используя специальные даунлоадеры, альтернативные маркеты, или просто достанет приложение из другого телефона), приложение может начать сбоить из-за недостающих конкретно для этого устройства файлов APK.
К счастью, у Google есть инструмент, который позволяет проверить, все ли необходимые компоненты приложения установлены на устройство. Чтобы им воспользоваться, достаточно выполнить три простых шага:
build.gradle
приложения:buildscript { dependencies { ... classpath 'com.android.tools.build:bundletool:0.9.0' } }
dependencies { ... implementation 'com.google.android.play:core:1.6.0' }
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.myapplication" > <application ... android:name="com.google.android.play.core.missingsplits.MissingSplitsDetectingApplication" > </application> ... </manifest>
Application
, сделать так:public class MyCustomApplication extends Application { @Override public void onCreate() { if (MissingSplitsManagerFactory.create(this).disableAppIfMissingRequiredSplits()) { // Skip app initialization return; } super.onCreate(); ... } }
Теперь пользователи, скачавшие приложение в обход Play Store, увидят такое сообщение:
Bohemian Wrapsody — статья о достаточно банальном в своей эффективности подходе к разработке, которым пренебрегают многие разработчики. Речь о достоинствах обертывания сторонних библиотек в кастомный API. С одной стороны, кажется, что это принесет только излишний бойлерплейт, но на самом деле, создавая врапперы, можно существенно упростить свою жизнь в будущем:
Читайте также
Последние новости