Взаимодействие с Android Market
В предыдущем посте я сказал, что GTalkService вовлечен в процесс установки приложений из Android Marketa. Это вообще интересная история. Тут тоже есть интересные нюансы. Рассмотрим для начала этапы, которые проходит пользователь для установки программы из маркета:
- Запуск Android Market.
- Поиск нужной приложения для установки.
- Нажатие на кнопку «install».
- Подтверждение необходимых для приложения привилегий.
- Закачка и установка приложения.
После этого у пользователя в панели оповещений выводятся сообщения о загрузке и установке приложения. Все просто и прозрачно, но… Если посмотреть на процесс изнутри, то все происходит несколько сложнее. Если первые четыре шага выполняются приложением Android Market, то за пятый (самый важный] этап отвечает совершенно другой компонент системы, а именно уже знакомый GTalkService. Схема работы выглядит следующим образом:
- Пользователь кликает на кнопку установки приложения в Android Markete.
- Приложение отправляет POST – запрос на серверы Android Market.
- Серверы Android Market отправляют информацию о запросе на установку приложения системе C2DM.
- Серверы C2DM отправляют смартфону пользователя сообщение INSTALL_ASSET через подключение GTalkService.
- Компонент GTalkService принимает сообщение INSTALL_ASSET и активирует Vending – компонент.
- Vending – компонент скачивает АРК – пакет приложения и, в конце концов, устанавливает приложение.
Первое, что вызывает интерес —это, конечно же, POST – запрос, который передается на сервер. Раз его может отправить Android Market, то, возможно, это сможем сделать и мы с помощью специального приложения? Попробуем разобраться. Перехваченный запрос выглядит следующим образом:
POST /market/api/ApiRequest HTTP/1.1 Content – Length: 524 Content – Type: application/x – www – form – urlencoded Host: android.clients.google.com Connection: Keep – Alive User – Agent: Android – Market/2 ; gzip version=2&request=CuACCvYBRFFBQUFL0EFBQU3vZWVEVGo4eGV40VR 3aW9…
Все банально, кроме параметра request, в котором очевидно и прячется все интересное. Зная Google, легко можно предположить, что это данные, упакованные в фирменную структуру protobuf code, google.com/p/protobufl и кодированные после этого в base64.Так и есть. Декодировав хэш и распаковав структуру, получаем данные запроса:
i (1: “DQAAAK8AAABoeeDTj8xex9TIio…” 2: 013: “- 606db3000d480d63″)2(10 (1: “353999319718585473″))
Уже что-то, но есть проблема: мы не знаем, за что отвечает тот или иной параметр. Скорее всего, это некоторые идентификаторы девайса, информация о платформе, некоторые данные для авторизации и, конечно же, идентификатор запрашиваемого из Marketa приложения. Тут надо сказать, что для многих структур protobuf, которые участвуют в работе с Android Market, доступно описание, составленное энтузиастами в результате реверсинга. А на сайте code.gooale.com/p/android – market – api даже выложен коллективно написанный API, позволяющий запрашивать различные данные из маркета (описание, иконки программ и т.д.]. Правда, данных о структуре запроса на установку приложений там нет. Зато реверсинг выполнил известный исследователь Android – платформы Джон Оберхейд, который впоследствии реализовал интересную атаку, о которой я и хочу тебе рассказать. Итак, структура запроса в сокращенном виде выглядит так:
message InstallRequest ( optional string appld = 1;)message RequestContext (required string authToken = 1; required string androidld = 4; optional string deviceAndSdkVersion = 5;
Большинство полей из запроса могут быть извлечены из самого девайса (например, язык интерфейса, версия системы и т.д.]. Но только не параметры appld и authToken:
appld —является уникальным идентификатором приложения в Android Markete. Этот идентификатор нигде не отображается, поэтому единственный способ его получить —запросить приложение из Android Marketa и отснифать трафик, вытащив из protobuf – структуры его идентификатор.
authToken —это токен системы ClientLogin, с помощью которого серверы Android Marketa могут провести аутентификацию твоего запроса.
Если authToken остается в секрете, то проспуфить запрос не выйдет. Но ты можешь заметить, что раз он есть у девайса, значит, в каком-то месте системы он все-таки хранится.
Именно! Такое хранилище называется Account Manager и является важным компонентом платформы Android, предоставляющем данные для аутентификации. Например, если какое-то приложение хочет запостить в Twitter сообщение, то ему необязательно знать логин и пароль для Twitter – аккаунта —оно может запросить токен из AcountManager, который позволит ему отправить твит. Так вот в этом же самом месте хранится и authToken, используемый для взаимодействия с серверами Android Market. Но самое смешное из всей этой истории, что извлечь его можно буквально несколькими строчками кода:
AccountManager accountManager = AccountManager.get; Account acct = getAccount; accountManager.getAuthToken(acct, “android”, false, new GetAuthTokenCallbackQ, null);
Что это значит? Получается, что у нас есть все данные, чтобы составить protobuf – структуру, которую я привел выше, и сконструировать POST – запрос для отправки на серверы Android Market. Если запрос будет корректным, то на устройство через GTalkService будет, соответственно, отправлено сообщение INSTALL_ASSET, что приведет к установке указанного нами приложения! А поскольку система устроена так, что разрешение на установку пользователь отдает еще до отправки запроса, то его вообще никто и ни о чем не будет спрашивать. И приложение установится в систему со всеми необходимыми разрешениями!