Фаззинг системных сервисов Андроид
🥷 Приветствую друзья!
Содержание:
Введение:
Android - ведущая операционная система на международном рынке смартфонов. Его основа - открытый исходный код, однако каждый производитель волен применять к нему свои собственные настройки. Все эти дополнения представляют собой дополнительную поверхность атаки, которая может меняться от одной модели телефона к другой.
Системные сервисы:
Вся служебная логика в Android основана на одном принципе: изоляция между процессами обеспечивается довольно строго. Он поддерживается многими существующими механизмами ядра Linux, которые не всегда используются в других дистрибутивах, а именно пользователями, группами, возможностями POSIX и SELinux. Например, непривилегированное приложение не имеет доступа к драйверам, но все равно требует аппаратной или системной поддержки для большинства классических приложений для смартфонов! Примером, который мы подробнее рассмотрим позже, является необходимость выполнения основных задач по воспроизведению звука.
Как и для многих операционных систем, команда Android разработала специальный механизм для работы с сервисами. Он называется Binder. Благодаря его поддержке сервисы можно рассматривать как средства межпроцессного взаимодействия (IPC), предоставляемые привилегированными процессами. Если вы уже разрабатывали для Android, значит, вы использовали эту функцию через Android Framework, который на самом деле частично является системными сервисами, замаскированными под удобный и стандартизированный API.
Не все сервисы построены одинаково.
Их первое отличие - это происхождение:
Подавляющее большинство исходит из базы Android, платформы Android с открытым исходным кодом (AOSP), поэтому их код находится в свободном доступе.
Некоторые из них являются настройками, добавленными конструкторами, и обычно имеют закрытый исходный код.
Некоторые из них изначально взяты из AOSP, но были изменены конструктором. Как правило, они дополняются новыми транзакциями, которые, как и полностью новые сервисы, являются с закрытым исходным кодом.
Разработчики также имеют возможность внедрять сервисы в свои приложения. В данном случае мы не будем говорить о системных сервисах, но, тем не менее, они создаются и становятся доступными аналогичными методами.
Второй момент - это разнообразие языков, используемых для программирования сервисов. Кроме того, интерфейс и заглушки, представленные в предыдущем разделе, не всегда написаны “от руки”. Android имеет свой собственный язык определения интерфейса (IDL), удивительно названный AIDL для Android IDL! Разработчики могут использовать его для описания сервиса и его транзакции, затем код автоматически генерируется с помощью серверной части на выбранном ими языке. По сей день существуют:
2 бэкэнда C++: один для AOSP/system и один для Native Development Kit (NDK)/app services.
Начиная со Snow Cone, серверной части Rust.
Binder:
IPCS для системных служб работают через Binder по очень стандартизированной процедуре:
Каждый вызов помечается как транзакция, идентифицируемая номером внутри группы, называемой интерфейсом.
Во время транзакции запрашиваемый процесс можно рассматривать как сервер. Он ранее зарегистрировал узел для каждого экземпляра любого интерфейса, который он предоставляет. С другой стороны, вызывающий процесс можно рассматривать как клиент. Он заранее получил ссылку на целевой узел.
Содержимое транзакции сортируется в посылку. Это означает, что в клиентском процессе вызову транзакции предшествует некоторый код сериализации. Напротив, серверный процесс начинает свою часть транзакции с десериализации.
Итак, как все это работает на практике? Этот механизм связывания фактически включен как заглушками (в пользовательском пространстве), так и драйвером (в пространстве ядра). Заглушки выполняют задачи связи и сериализации как на клиенте, так и на сервере, в то время как работа драйвера в основном двоякая:
Это обеспечивает передачу данных между процессами. Каждый из них взаимодействует с псевдоустройством, обычно /dev/binder, которое доступно в пределах их границ изоляции.
Он ведет некоторый учет узлов и ссылок, которые мы вызвали, для каждого процесса.
Сбор информации, фаззинг:
Чтобы добыть информацию по службе, вы должны иметь возможность вызвать эту службу. Тем не менее, как подробно описано выше, вам необходимо заранее получить ссылку на интерфейс.
Первое, что нужно знать, - это то, что в посылке можно передавать ссылки на сервисы вместе с упорядоченными данными. Это означает, что обычный способ получить ссылку - это просто получить ее через ответ другой транзакции! Отлично, теперь это проблема курицы и яйца… К счастью, для запуска цепочки существует специальная системная служба, называемая Service Manager, и каждый процесс автоматически получает ссылку на нее. Другие службы могут регистрироваться таким образом, чтобы любой процесс мог запросить у менеджера служб ссылку на них. Задействованный процесс проиллюстрирован ниже. Таким образом, такие услуги легко доступны, и мы можем называть их услугами высшего уровня.
Напротив, существуют вложенные службы, которые сами не регистрируются в Service Manager. Возможно, удастся разобраться с ними, обратившись в какую-нибудь службу высшего уровня. И цепочка продолжается, переходя к более глубоким услугам. Сервисы, которые могут быть объединены в приложения, являются примером таких вложенных сервисов: они зарегистрированы в ActivityManager, который сам по себе является сервисом верхнего уровня.
❓ Остались вопросы? - @golden_hpa