Содержание статьи
Итак, последняя версия приложения — 1.4.1. Разработчик приложения — Департамент информационных технологий города Москвы. Существуют версии для Android и iOS. По данным из Google Play, на текущий момент приложение установлено более чем у 50 тысяч пользователей. Обещано, что если ваш телефон не поддерживает его, то в теории вам должен быть предоставлен аппарат с уже установленным приложением. На практике, конечно, такое случается далеко не всегда и не сразу.
На сайте мэра Москвы заявлено, что «приложение при авторизации просит подтвердить номер телефона и сделать фотографию лица, а в дальнейшем фиксирует геолокацию и запрашивает фотографию посредством пуш-уведомления». С виду это действительно так, а если проигнорировать запрос на фото или выйти за пределы квартиры, будет автоматически выписан штраф. Если отказаться от установки, то принудительно поместят в обсерватор или больницу. Если удалить приложение после установки и регистрации, то будут присылать штрафы.
Конечно, ставить что-либо на свой телефон по чьему-то требованию мне не хотелось, но раз уж я был к этому принужден весьма незамысловатым способом, то надо хотя бы проверить, действительно ли приложение выполняет только заявленные функции, или там есть что-то еще.
Итак, поехали. Сразу скажу — я не гуру реверса, так что мог чего-то не заметить. Если обнаружишь что-то новое, обязательно поделись находкой в комментариях.
Смотрим трафик
Первым делом я решил проверить трафик с помощью приложения Fiddler, однако тут меня ждало разочарование. «Социальный мониторинг» устанавливает шифрованное соединение (HTTPS) с сервером mos.ru, а что там происходит дальше — так просто не понять, нужно или рутовать телефон, или пересобирать приложение. Но на рутованном аппарате приложение не работает, а пересобирать его я не рискнул, слишком высока цена ошибки — 4000 рублей за каждый пропущенный запрос на фотографию. А вдруг этот запрос придет как раз в тот момент, когда я буду с трафиком разбираться...
С помощью Fiddler и logcat удалось выяснить только то, что приложение раз в пять минут что-то отправляет на mos.ru. Что ж, придется декомпилировать и ковыряться в коде.
Декомпилируем приложение
Для декомпиляции я использовал программу JEB версии 3.17.1 производства PNF Software. На мой взгляд, это одно из лучших приложений для исследования APK, единственный его недостаток — высокая стоимость.
Приложение подписано сертификатом, сгенерированным 17 апреля 2020 года, и почему-то указан город Самара. Интересно, при чем тут Самара?
![](https://static.xakep.ru/images/e3052a9022907abe00b451007654f121/12779/ris01.png)
Первым делом смотрим, что в манифесте.
![](https://static.xakep.ru/images/e3052a9022907abe00b451007654f121/12778/ris02.png)
Версия программы — 1.4.1, имя пакета — ru.mos.socmon.
Приложение запрашивает следующие разрешения: доступ к координатам, в том числе и фоновый, доступ к камере, к интернету, состоянию сети, состоянию и изменению Wi-Fi, возможность запускать неубиваемые сервисы и добавление в список исключений оптимизации батареи (чтобы ОС не заставляла приложение экономить энергию), а также чтение и запись данных на карте памяти. Ну что же, уже неплохо — намеков на недекларированные функции пока не видно. Контакты, журнал звонков, SMS и прочее вроде не просят. Будем смотреть дальше.
Дальше видим, что приложение весьма обфусцировано. Конечно, это осложняет анализ, но попробуем.
Обычно при анализе всякой обфусцированной вирусни я поступаю так: сначала переименовываю все объявленные переменные в соответствии с их типом, то есть вместо a
, b
, c
, d
пишу intIn
, intOut
, int1
, str1
и так далее. Затем заново смотрю на код, уже становится видно, что некоторые переменные можно переименовать в counter
, i
, k
, resString
. Ну и третьим проходом после беглого анализа алгоритма переименовываю во всякие там name
, password
, hashMD5
и так далее.
То же самое и с классами. Сначала переименовываю созвучно тому, от чего класс наследуется, например activity1
или serviceHZ
, а дальше уже, изучив содержимое, даю осмысленное имя. Да, это кропотливый труд, но я не знаю, как по-другому эффективно бороться с обфускацией. В данном случае объем кода не позволяет выполнить такие переименования за разумное время, да и нет в этом особой необходимости.
Прежде чем погружаться в дебри кода, окинем взглядом используемые приложением нативные библиотеки, а именно:
- libconscrypt_jni.so — гугловская библиотека Conscrypt, поставщик безопасности Java (JSP), который реализует расширения криптографии Java (JCE) и расширения безопасных сокетов Java (JSSE). Он использует BoringSSL для предоставления криптографических примитивов и безопасности транспортного уровня (TLS) для приложений Java на Android и OpenJDK;
- libface_detector_v2_jni.so — опенсорсная библиотека libfacedetection для распознавания лиц на фото;
- libtool_checker_jni.so — библиотека из состава опенсорсного пакета rootbeer, предназначенного для проверки наличия прав root на устройстве. Чуть подробнее расскажу о ней дальше.
Беглый анализ показал, что, помимо обфусцированного кода и почти стандартных OkHttp 3, Retrofit 2 и Crashlytics, приложение использует компоненты com.redmadrobot.inputmask.helper и com.scottyab.rootbeer.
Первый компонент особого интереса не представляет, он используется для проверки ввода телефонного номера при регистрации приложения. Rootbeer же как раз проверяет «рутованность» используемого устройства: ищет определенные приложения, бинарный файл su или компоненты BusyBox.
Все, дальше вроде тянуть уже некуда, надо смотреть код. Я не буду утомлять читателя скрупулезным и занудным описанием алгоритма, тем более что из-за обфускации кода пришлось бы часто использовать слова «вероятно», «похоже» и «судя по всему», и просто расскажу своими словами.
При запуске приложение достает из настроек адрес сервера для отправки данных, интервал для отправки координат и интервал для сбора и отправки телеметрии (отметим, что эти значения можно изменить по команде с сервера). Затем проверяет наличие необходимых для работы разрешений и, если нужно, запрашивает их, а также выводит запрос на добавление в «белый список» энергосбережения, чтобы ОС не мешала работать в фоновом режиме.
if(!((activity)this).j()) {
StringBuilder v1 = k.b.a.a.a.a("package:");
v1.append(this.getPackageName());
this.startActivityForResult(new Intent("android.settings.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS", Uri.parse(v1.toString())), 3);
return;
}
Также проверяется (с помощью акселерометра), держит ли пользователь устройство в руках.
В приложении есть три основных сервиса:
- LocationService — периодически собирает координаты;
- MessagingService — отслеживает сообщения с сервера, в сообщениях могут быть новые настройки или запрос на фото пользователя;
- PeriodicJobService — собирает и отправляет телеметрию.
Приложение периодически (в моем случае раз в пять минут, но это значение может быть изменено сервером) получает координаты и телеметрию, отправляет их на сервер, а также ждет запроса на фото. Если запрос на фото пришел, то выводится уведомление и подается звуковой сигнал. Кстати, когда пользователь делает фотографию, устройство автоматически ищет лицо в области предпросмотра (см. выше про libface_detector). Пока лицо не будет найдено, фотографию отправить не получится.
В интернете попадалась информация, что у пользователя есть один час с прихода уведомления, чтобы сделать фото. В коде я никаких подтверждений этому не нашел. Если отсчет времени ведется, то это, надо думать, происходит на сервере.
Посмотрим подробнее, какие именно данные приложение отправляет на сервер.
Продолжение доступно только участникам
Вариант 1. Присоединись к сообществу «Xakep.ru», чтобы читать все материалы на сайте
Членство в сообществе в течение указанного срока откроет тебе доступ ко ВСЕМ материалам «Хакера», позволит скачивать выпуски в PDF, отключит рекламу на сайте и увеличит личную накопительную скидку! Подробнее
Вариант 2. Открой один материал
Заинтересовала статья, но нет возможности стать членом клуба «Xakep.ru»? Тогда этот вариант для тебя! Обрати внимание: этот способ подходит только для статей, опубликованных более двух месяцев назад.
Я уже участник «Xakep.ru»