Всё началось с того, как один мой друг пожаловался, что его телефон каждые несколько секунд выполняет запрос к одному и тому же приложению. Сначала я предположил, что телефон заражён вирусом, но через пару минут стало ясно, что все запросы поступали от приложения Swing VPN, которое было обычным образом установлено в телефон как VPN-сервис. Оно делало запросы к одному веб-сайту, которым мой друг никогда не пользовался, а в полезной нагрузке запроса находились конкретные данные с целью отправки запросов к конечной точке, требующей большого объёма ресурсов этого сайта.

Телефон моего друга, а позже и мои телефоны выполняли запросы к https://turkmenistanairlines.tm. Запрос отправлялся примерно каждые десять секунд и передавался на конкретно эту конечную точку поиска:

https://turkmenistanairlines.tm/tm/flights/search?_token=J8SxUX2Qwzltw4LiHsRHTCtfthgBYxf4hyI8oNly&search_type=internal&departPort=TAZ&arrivalPort=CRZ&tripType=rt&departDate=4%2F22%2F2023&arrivalDate=5%2F4%2F2023&adult=1&child=0&infant=0&is_cship=on

Точность URL чётко показывает, что это не ошибка и не способ пинговать сайт для проверки ошибок подключения к Интернету. В этой статье я докажу злоумышленные намерения создателя приложения, изучив его работу и инфраструктуру, лежащую в его основе.

Запросы

Давайте начнём с изучения запросов и посмотрим, что же происходит, когда мы запускаем Swing VPN на телефоне. Я использую реальный телефон, подключенный к компьютеру USB-проводом, и программу ‘scrcpy’ для отображения экрана телефона на экране компьютера. Это нужно, чтобы упростить создание скриншотов и при анализе без этого вполне можно обойтись.

Для начала проведём простую проверку и убедимся, что запрос, отправляемый на веб-сайт авиакомпании, действительно выполняет приложение Swing VPN. Для этого я воспользуюсь приложением для Android pcapdroid, перехватывающим все запросы приложений. Нам не нужны дополнительные плагины или приложения для просмотра подробностей о запросах, потому что для этого я использую другие инструменты. Пока наша задача заключается в том, чтобы связать каждый запрос с конкретным приложением. Стоит сказать, что в телефоне установлены только стандартные приложения Android и Swing. В этом видео pcapdroid только что установлен, я подождал, пока Google Play завершит со всей своей статикой и прочими запросами, чтобы лог не попадали ненужные нам запросы.

Из этого видео чётко понятно, что приложение Swing VPN выполняет какой-то запрос к сайту https://turkmenairlines.tm. Мы не можем точно сказать, что приложение делает нечто зловредное, но оставим это для дальнейшего анализа. Пока у нас есть доказательство того, что запросы исходят от изучаемого мной приложения, и этого достаточно. Теперь можно приступать к более глубокому изучению функциональности приложения.

Дальше нам нужно разобраться, что конкретно Swing VPN пытается сделать, отправляя эти запросы. Я использую mitmproxy для перехвата всех передаваемых данных, а потом изучу предназначение этих запросов.

В этом видео Swing VPN только что установлен из Play Store и отслеживается приложением mitmproxy. После запуска приложения, выбора языка и принятия политики конфиденциальности приложение начинает узнавать «реальный IP-адрес», выполняя запрос к Google и Bing «what+is+my+ip». Думаю, приложение просто парсит возвращаемый HTML и определяет из этих ответов IP-адрес.

Как мы увидим далее, этот запрос IP нужен, чтобы понять, какие файлы конфигурации необходимо загрузить. Приложение загружает разные конфигурации и выполняет разные действия в зависимости не только от страны и региона, но и от Интернет-провайдера региона.

После определения типа конфигурации в этом видео Swing VPN выполняет ещё пару запросов к двум разным файлам конфигурации, хранящимся в личном аккаунте Google Drive разработчика приложения. Файлы конфигурации запрашиваются с личных серверов, нескольких репозиториев Github или пары аккаунтов Google Drive. Предполагаю, что местоположение файла конфигурации определяется по времени суток, но я не стал проверять, потому что это не так важно. Как только конфигурации загружены, приложение подключается к рекламной сети для загрузки рекламы. На этом процесс инициализации приложения завершается. После этого приложение сохраняет данные в локальный кэш и начинает выполнять DDOS сайта, возвращённого из конфигурации.

А вот как приложение ведёт себя после закрытия. Оно по-прежнему пытается выполнять DDOS, хотя им не пользуются.

Из этого лога мы видим, что приложение запрашивает конкретную конечную точку: «tm/flights/search». Так как поиск рейсов — это довольно затратная задача, требующая множества ресурсов баз данных и сервера, то становится очевидным, что цель этого — подвергнуть сервер нагрузке и лишить ресурсов, чтобы обычные пользователи не смогли получить к нему доступ. И хотя выполнение одного запроса раз в десять секунд не кажется проблемой, главное для DDOS — это количество установок приложения. На июнь 2023 года его установили на Android более пяти миллионов раз, и если даже разделить на десять, то атака имеет потенциал в 500 тысяч запросов в секунду. Достаточно серьёзная нагрузка для небольшого сайта, вероятно, написанного на PHP.

Примечание: приложение не соблюдает конфиденциальность

В процессе этого маленького расследования выяснилось, что приложение не беспокоит конфиденциальность. Наверно, разработчики добавили кнопку «I Accept the privacy policy» только для того, чтобы приложение принял Play Store, но на самом деле это кнопка, которая ничего не делает. В показанном выше видео я установил свежую версию Swing VPN из Play Store, а потом вместо нажатия на «I Accept the privacy policy» я нажал на ссылку на экран «Privacy Policy». И пока я пролистывал политику конфиденциальности, приложение уже начало отправлять мои данные в рекламную сеть.

В то же время оно уже скачивало конфигурации с информацией о том, какие сайты нужно подвергнуть DDOS, и начало исполнять процедуру DDOS, пока я всё ещё читал политику конфиденциальности. Закончив читать, я пару раз нажал кнопку «назад», сообщив таким образом приложению, что я не согласен с условиями, но было уже поздно. Самого запуска приложения уже достаточно, чтобы начать действия по DDOS.

Функциональность конфигураций

Итак, мы посмотрели, как приложение выполняет действия, связанные с DDOS других сайтов. Но возможно, я просто установил другое приложение с похожей иконкой, чтобы вас обмануть. Поэтому давайте углубимся в приложение и изучим хранящиеся в нём конфигурации. Это вы можете сделать самостоятельно, чтобы убедиться, что Swing VPN — Fast VPN Proxy действительно ответственен за эти действия.

Общая информация об Android apk:

VERSION USED: swing-vpn-1-8-4.apk

APK SIZE: 32.5 MiB

INSTALL BASE ON PLAY STORE: 5+ million users

LINK TO PLAY STORE: https://play.google.com/store/apps/details?id=com.switchvpn.app&hl=en_US

ANDROID APP CREATOR: Limestone Software Solutions

LAUNCH DATE: 2020-10-06

Приложение использует две нативные библиотеки для обфускации своей работы и усложнения реверс-инжиниринга. Это файлы libnativelib.so и libbony.so. Мы воспользуемся libnativelib.so, потому что её будет достаточно для дешифрования и деобфускации данных.

Конфигурация скачивается с Github, Google Drive или собственного сайта. В своих исследованиях я проверял только Github и Google Drive, потому что этого было достаточно для проверки моей гипотезы.

Github

Давайте начнём с Github. Во-первых, есть как минимум два аккаунта Github, используемых для хранения конфигурации приложения. Я клонировал оба репозитория на случай, если кому-то понадобятся исторические данные в случае их изменения или удаления. Похоже, обоим репозиториям примерно полгода, поэтому будет неудивительно, если вскоре создадут новые репозитории. Вот эти репозитории:

https://github.com/Javaidakhtar576/swinglite_new

https://github.com/githubfunc/cocomo

Общий формат сообщения выглядит как некая закодированная строка в фигурных скобках. Во втором видео можно один пример. Вот, как это выглядит:

А вот текстовая версия одной из конфигураций, запрашиваемых при запуске.

Текстовая версия одной из конфигураций

{{{30766d755274445150474d656e6770435276786e6f15631c6056373b4f673c5935726c225378450752474d666d65704850707a6a6e48634f6355373d483b3a5631736e23527b425b54434b606a6a761955257f3a6f48624d6006303e4c6f3a5536716b715774475451444c616865754954767e3a6947664f6454306c4c693f5630756d25562f420754424e616d36724d507f7b3d6f46631a650132394c673a55367f6b7756784157554c4a34686b754e55747d6e6d13634b6051353f486e395334736e7556294257544248346837764255777e3b6b1667186656336c4c6e3a0232276f245328465751134c346c66744955277d6d6912644d6403306b4c3c3c0030746f75547a425554164a326862764c54257f366b4567496006363648683f5832276e7953284352554d48656865744855207c3d6a1166486407303a4e3b3d5630276f78577d4601514d4e616d62724d51727b3d6b47674e645530384c3a3a55362268795778435b554149676c6670185177783a6d13624d6051303a4d3f3c0030746f24567d410754174a376862754c55737f3e6b46674b6006363648683f5933226e77537d4754554d49306960754855227d3d6a1166486407303a4e6e3d5630766b735328460151444f636c65724351277e3d6b16661c6454323e4d6e3e0333746e775229475451444c616862751d54247d3c6911651b6456313d4d6a3d0331736b735328460151464e616c6b724d54277f3a6a11671f6452323e48683f5232276f755328475a511349606961751955237d38681367486051356e486e380434736b22527b425b54434b606b63764a54247e3b6f48624d6006363c48683e5432276b76572b4254554d4866686a771955277c3b6813664e655130364c3d3d5834736a20527b475b50454e346c65761855717e3b6a49661c6454323848683f5232276f745328475a511348626860744e57717d69681466406451306c4c693d0032776f78577b430255434e616d36724d507e7b3d6f46631a640333384d69380536776b7657294354554448666860764d55707c3b6947664e6457343d4966390235716b735275460154434b616866774855227e3d69496748640433394e3a3b0536226a785574430155164861683175485571793b6c4462186153343d483b390230756f78577a420254114a326832764a55247e3b6915674e640333694c3c3a0434226a2057294354554448666860714f507f793b6c1562186004343d4d6f3c0330276f2556784301551749606864774d55227f3a6b44651b6455333d4c683a5436226a715328460551134d636c66711a51777c3b69126741645c313d4d683e0530726e73567c4200541648666832764e55277f6c6b1667186006363648683f5832276e7953284200554749666960744855777d3c6b1466496452306a486e385534736b735275460155434a66686b764a55207e3d6b12674a6601336d4c6b3a5632276f245328475451444c616831751d54737d3c691466496452313b486e385534736f79577d430755474b606d36721951717f3b6b16674a645433694c3a3b0736226a7657794357544c4c3268677542552379366d13624d6051303a4c383d0730236f22527b475050454e616c6b724d54257f3a6b46671b645c323e4c6b3a5532276f245328475451444c616963751e55747c3d681466406553313f486e385534736b735275460154414a626864764a55277f696b45674c6006363648683e0332726e7757784301541049676865754a54777d38694362186106343d486e395334736e75577e425355434b676862774d51277a6e6f48631a6057373e4d6e3a5136756b71577e430651134d696c66714f5120793b694866406401303a4f6f3d0331736e77567c430156104a336964774b51277a6e6f48621f6006376948683a07367f6a2757744055554d49616962754854777f6e6947671b6557333f486e385534736a70527b465650454a656866761d55227c3c6b16661a655d33394d68385436776b765675405656114c616d37714f5074793b6d4262186455303e4c673d0333726f74577b430554424b616a6b761f54247e3b6811641c6701373e493b3e03337e6e77537d4754551748626830754856767d3c6813671c6456313d4e3b3d5631726e75557f405357474e616d36724d507e7b3d6f46631a645d333d4c383a0235246a7056284250554d49616a31751d54767c3d6b4965416051356e486e380434736b22527b4206544349606862774d54237f3a6a48661d6006363648683f5935206a72522b4306564248656966754f55777e6c6846644f6506353c4e6e3e5735706f7756784150514649666b667748567e7c3d6e49654e6101323f4f6c380032276e7953284351554c4b606861744f54737d3c6813671b6757333f486e385534736a7054784250554448326a65764954777f6e6e16671f6501316a4c673a593620697752284105574c49646a30774956277f3f6c47664b645731394f683d5832276e74527b465650454a646863754c55227e3d6a13671b6506323f4f6a395832276f2453284657504c4d616860771e56747e3f6914654e6651306b4d68380532726e72552f405b574d4f306960751e50777a3f6b16621b610430384c6e3950357f6876567b425451134c346c66754a55717e3a691267186555303a4d6e3c0533716c71557a4601514d4e616d66734b57227e376840621a670430364e663b5236756a73557d415356424b606961751951237e3b694565496551306c493f3d5132726c77557a4006544c4a666a31724d51727b3d6b146718670133394d683b0736226b77562b405057414b636c667018517778386a16664a650631384f6e3c5533776d77567c4153541148346d667749567e7c6e6a4267496107333b4c673f0535716973542e4157544048626b37754f5624783a6d13624d605130384c683e0530746e73577f420055454b606a60754f51277a6e6f48621f6701326d4c6c3a5137236a23542b400055144a616963771d55277f6e68476518665735374c6e3e0235716d23567f425055174f616861724255727d3c6a4866406006376948683a043676697657744254541748666966744e5177786c6d136418615133694d6f390234246b73567e425257444a666965774955227e3d6a4964186700373e493b3e0334276f77547e425554114c616c31714f55727d6a6a14661d655131394c693c0231726c7155794601514d4e616a65734d56717e3c6a11661c6006376948683a043676697657744254541748666966744e56757e396a1462186106343d4e6e3802337e6e725779435a55444e616c6b724d55207f376849671b6506323a4c6f3b03372469735578405651134d696c66774f50777e366814671c6403313f486e395334736f76562e410254424b616961764a54277e3c6914641c600636364868380333276923562b435154114c616c31714f54707c39691166406557303a486e385531256b73567c425454464a61686b764a55257b3d6e40631a6100373e48663e0337226b7557754357544c48666b62754854777c3a6947664e645d326a4c6d3d5230746b735328460150454e346c65774a547e7f3b6b1266186407313a4c3c3b0336246a7057754155554748676861714f507f793b6d13624d6051313a4d6c3d0030706e75567c405b54454a356962774b51277a6e6f48631a6057373e4d6f3b5836256a7456754353574548336966744f55257c3b6c1662186106343d486e395334736e745779420754464b676862744255777e3d6a4867486506363e48683f5232276e77567c475a511349666966751a5476793b6c44674a6051303a4c3d3d0730736f22567c420750454f696c65734e51277b6c6f48674a6452336b4f6e3a5136736a705328460551134d626d64714f5120793b694366406500333b4c3c3d5230746b735328460151464f636c65724351277e3d6b1267496404313f4c3a3e0333746e775229475451444c616961744f55207f6e6947671b6557343d49663e5431256b73577c430154104e616d36724d55767e3b6a15661c65013636483c3e5737256b705628430655454866686a751d54767c3d6916664f645230364d6e3d5330236f24567c430250164b67686a721954257f6b6f4567416457336e4c6d3a5037256b76537e4255554d48626966754e552478366a41671a645c306d4c693d5135276d20532e4102551449666b30734d567f7e386a40674b6504323b496e385436776822562b405457404b676a67744955737c3d6946661f665133364d3f3d5935756f795729405351144a356a32764354777b396a49671b6403323e4c693a5035716b7156784256554d4d376836754354717d3c6813664f6452306c486a3d0030746e7156784301554349636831774d54257a6b6815651f6751373a4c6b3b0337276a25562c435755444b63686b744f5471786d6b146518670634394d683c0230236e71557d435355474a666d6a774d54257b396b15671b6500333d4d683b0534256a745675435350454d676c61704f5773783b6c13621d61513239496e380435736a72527f425b55454b6168377749557f7f6c6915671f6504333949673f0232226f77552c4652514d4d616a62704f5075783b6c14621c6452303b4d693d5331756a255378460554444a306837764355257a6b6e1163416452336b4c6c3a5936706b71527c4656511748336967764255767c3a694666486553356b4c3a3d5134736b22527b425754424b676830761955257b3d6e40631a665c31394f6e3e0337736e79567a4754544d49616831714f507f793b6946671a6557313f4d6f3855347e6b27577d430055454a68686a764a55707f366a4966186403336b4c6b3a5137276a7957784301554d49606c6a7449552379366811664c605c30394c3b3d5630766f79577d430250114b606862764e54277f3c6b426248675432384c3c3a5336226a20527c410550404b60693576485624783b6a16671f6506306c4d683c5835756d2256294052554449616a30754b57247e3b6b1366186453333b4e68395137766a735275430754414a336d35754257227d6e6847621c6550303a4c6d3c0230726f79552f430755174b636862734255777f6a6a15671b6506336b4c6b3a5432236a7157744256551649616960764d55257c3b6811634c6757323e4f66395930706e73577b425355414a62686b754f55717e3d6a15624a6601303e4f3b3e0737256b7757784256564c49336964754850237c3b6811621c6457303a4d6c3d0731736e75547d425b55434a666d6a734b51227a3d6913621a610637394968380733276f7552284655511748626966744f55277c3f6916664d6657303e4d683d0335276a74527c470156414f676c62734d57237a3d6e11621a6101373a4c6b3a0537226a795675465b50164c656867751e55277d6e6911634c615334394c3c3d5130776f70562c430751134f636c61761f54247c696b49661d6453336e4d6a3f5536716a205328475a511348376861744955247d36691162186106343d4e6b3f0333756b7357744656554c4e616962774d55727b3d6e40631a645332384d6e3b5837246f24537e4702544c49666966751f55237d3c694066486550313b4c6d3d5130706f78577b425654174a326862774c51707e3b6b4763486504336a483c3a0736726a25572f4307544c49606c6b744e55707d386813661b640035694f3a3c00307e6f23567c4254511348696d30754c54767c3a6842621a6703323b4d3b3a5437256b725275415a55414a306967764f57247e3d6b14671a6455313b4c3f3d5832736c78572e420551434a306937741f50767f696944674b6552373a4d693a02367f6b77572b4307564749676936744d5570786d6947664f6557303a4d6e3d5130706f22527f420754424b636866774d54257c3f6b45661a6504366a4f6e385935746e7357294254541348336962754c55207e39694167186557356b4e6f3e0233226b77577d430154174b636b63771f547e7f3a6e47661a6504373a4c6e3a02377e6a7456284252574c4862696075485023783d6d1263186655353d496e390335736d77537b475a51454f606c61764e54277e3d6b436641640333694e6e3a5937256a70527c4653514d4d616a6270495170783b6b4863186153353d496f395930706f75577c425655434f376d66724955247f376b43674b6404366a496a3e0736776a20572c4357554649676d32704d51737d696814654e6450313c4c3f3d5631716a25562f425450454e346c65764255227e3b6b4267486404373e493b3e03342068705475475454454b376c31714f54707d386b4266486550313b486e385533256b7354744255554d4a33686b7643557f7b696e1663496100373c483d390436776a2057754302541449606c647743567179396c166341605d353f4967390433766f78562c470551434f686c67771850237a3b6f43631c6603323c4d6a3a54362269725774435457434833696071425070783a6c49624f61503539486c395732256d79557d405756104e346c67764355777f6d6b16631c665c33394c693a5336716e25532e415555404961686b7519557079366c1663406152346a496c395135716b245379465a57444a626861764e54277f366f45621b6101363b483f3f0033236e77537d4754574548356937751d55207d6e6916624e6156346a496c390434206c765629425454434a356960774c517e7d6a6815631c6103363c483f3f5833756e75542f410256144d656d60711d51757f38681567416404303a4f6b3d0330736d235629430750114f666d64734851707a3c6e13631c605331374e3d390534736879537d4756554448336830754851757f3e6912661b64013069483c390432726f79577b425554134a666c31734e507f7a3e6f44621c6055363c483f3f58327e69765729435055164961683671425070783a6c49624f61503539486e395334736d25562f

435054174a34686b764e51717a3a6f44621c6000376d4f6d3a5136706a71577e425154104c636a6a7649517578386c15624f61533436486c3f0731716e715675420057404a666865741d55777e3b6f45621b6101363b483f3f0033236e755379410657404b676a32771a51207939694266486401303a486c3f5830746f72562b425550174e636a64761854277f696b47671b6054363d496b3f5932706f75537f465651464d636c64764e55747d3f69166718640334694969380535766b24537a470550454e346c65744255717e6e6b43674b6457333d483c3f0232706f75532e470757444833686a74485424786b6d156440645d303b4d6e3d5030236f755279475b51474e336c67744e547e7e3f6b46671b675c33394c68385336776b71537e465350104d646c6a704e507379396d46644a6600333b4e383f5334246b7156754253544c4a666c67744855227f3c6b4167486052373c4e693a5037276a23577c435351474d626d65704c512278396d40631d61563539496f395135706a70537f465a56134a356865761f55727f3a6f11641d6403333a4c6b3b0336776e235274465550144c326d67704b51777e6d6843674c}}}

Код расшифровки находится в папке нативных библиотек под названием libnativelib.so. Я выполнил реверс-инжиниринг алгоритма декодирования и написал код на Python, выполняющий реверс. Скачать его можно отсюда: decode.py

Чтобы расшифровать это сообщение, сохраните его в файл, например, «data.txt» и просто запустите этот файл:

python decode.py data.txt

Декодированная строка будет помещена в stdout терминала, и если вы захотите сохранить её в файл, просто перенаправьте вывод в файл. Например:

python decode.py data.txt > data.decoded.txt

Если мы используем дешифровщик с показанным выше зашифрованным сообщением, то результат получится таким:

{
  "adsMode": "Remote",
  "adsSingleIdMode": "1",
  "summaryAdLocal": "0",
  "timeLimitedMode": "1",
  "timeLimitedConnection": "0",
  "defaultTimeLimit": "5",
  "minTimeLimit": "3",
  "extendTimeSmall": "15",
  "extendTimeBig": "30",
  "report": "1",
  "fixedServer": "1",
  "repair": "0",
  "summary": "0",
  "adsTest": "0",
  "screenMirroring": "1",
  "hotspot": "1",
  "adsDisabledFirst": "0",
  "adsDisabledPeriod": "0",
  "drawerCodeItemEnabled": "0",
  "disconnectDialogEnabled": "0",
  "summaryScreenEnabled": "0",
  "reportScreenEnabled": "0",
  "youtubeChan": "",
  "telegramChan": "",
  "livechat": "https://demolivechat.com/",
  "email": "",
  "telegram": "",
  "whatsapp": "",
  "facebook": "",
  "instagram": "",
  "twitter": "",
  "tiktok": "",
  "fakeServerList": "1",
  "fakeServerListP": "1",
  "fakeServerListPP": "1",
  "fakeServerListPPS": "0",
  "fakeServerListVIP": "0",
  "fakeServerListGP": "0",
  "gdServers": "1Wg3kZfrbbZxNz3BX1faZ1UQwPR3I3sVC",
  "gdServersTP": "1AjsNBfyj5asMmagR2JDwKDYF9jdvTgMu",
  "gdServersPP": "142dHQVc_Bmt3Cs_AZ8wZ90e54TdXQCzr",
  "gdServersPPS": "14ExZ2TZLzkfLEZSum-RkXrl8nCVSGkeO",
  "gdServersVIP": "1QkzwRzVFeYoL1vPZxn5gm4_VPAxaZbX3",
  "gdServersGP": "1SxfivoSYgBwIiLyRD8bR0Kfjy2f-lCrw",
  "ghServers": "B2_s",
  "ghServersTP": "B2_sp",
  "ghServersPP": "B2_spp",
  "ghServersPPS": "B2_spps",
  "ghServersVIP": "B2_svip",
  "ghServersGP": "B2_sgp",
  "update": {
    "enabled": "0",
    "updateVersionName": "",
    "updateForcedCode": "",
    "updateAbout": "",
    "updateMirror1": "",
    "updateMirror2": ""
  },
  "urls": {
    "enabled": "1",
    "minTime": "10",
    "maxTime": "10",
    "randCi": "1",
    "urlList": [
      {
        "url": "https://turkmenistanairlines.tm/tm/flights/search?_token=J8SxUX2Qwzltw4LiHsRHTCtfthgBYxf4hyI8oNly&search_type=internal&departPort=TAZ&arrivalPort=CRZ&tripType=rt&departDate=4%2F22%2F2023&arrivalDate=5%2F4%2F2023&adult=1&child=0&infant=0&is_cship=on",
        "method": "GET"
      },
      {
        "url": "https://turkmenistanairlines.tm/tm/flights/search?_token=J8SxUX2Qwzltw4LiHsRHTCtfthgBYxf4hyI8oNly&search_type=internal&departPort=TAZ&arrivalPort=CRZ&tripType=rt&departDate=4%2F22%2F2023&arrivalDate=5%2F4%2F2023&adult=1&child=0&infant=0&is_cship=on",
        "method": "GET"
      },
      {
        "url": "https://turkmenistanairlines.tm/tm/flights/search?_token=J8SxUX2Qwzltw4LiHsRHTCtfthgBYxf4hyI8oNly&search_type=internal&departPort=TAZ&arrivalPort=CRZ&tripType=rt&departDate=4%2F22%2F2023&arrivalDate=5%2F4%2F2023&adult=1&child=0&infant=0&is_cship=on",
        "method": "GET"
      }
    ],
    "uaList": [
      "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/111.0.0.0 Safari/537.36",
      "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/111.0.0.0 Safari/537.36",
      "Mozilla/5.0 (Windows NT 10.0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/111.0.0.0 Safari/537.36",
      "Mozilla/5.0 (Linux; Android 10) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/111.0.5563.116 Mobile Safari/537.36"
    ]
  }
}

Перейдя в раздел «urls», мы увидим ссылку на https://turkmenairlines.tm и время между запросами — 10 секунд. Это соответствует нашим предыдущим наблюдениям.

Однако в репозитории Github есть довольно много файлов со множеством разных конфигураций. Вот какие файлы есть в репозитории:

A1_c    A1_spp   A2_s    A2_spps  B1_sgp   B1_svip  B2_sp    B3_c    B3_spp    GLOBAL_s    GLOBAL_spps  IRANMCI_sgp   IRANMCI_svip    IRANTELCOM_sp    IRNCELL_c    IRNCELL_spp   RU_s    RU_spps  TEST_sgp   TEST_svip

A1_s    A1_spps  A2_sgp  A2_svip  B1_sp    B2_c     B2_spp   B3_s    B3_spps   GLOBAL_sgp  GLOBAL_svip  IRANMCI_sp    IRANTELCOM_c    IRANTELCOM_spp   IRNCELL_s    IRNCELL_spps  RU_sgp  RU_svip  TEST_sp    backup

A1_sgp  A1_svip  A2_sp   B1_c     B1_spp   B2_s     B2_spps  B3_sgp  B3_svip   GLOBAL_sp   IRANMCI_c    IRANMCI_spp   IRANTELCOM_s    IRANTELCOM_spps  IRNCELL_sgp  IRNCELL_svip  RU_sp   TEST_c   TEST_spp   main

A1_sp   A2_c     A2_spp  B1_s     B1_spps  B2_sgp   B2_svip  B3_sp   GLOBAL_c  GLOBAL_spp  IRANMCI_s    IRANMCI_spps  IRANTELCOM_sgp  IRANTELCOM_svip  IRNCELL_sp   RU_c          RU_spp  TEST_s   TEST_spps

Названия этих файлов имеют определённую структуру. Во-первых, у всех файлов есть префикс, например, A1, B1, …, GLOBAL. Это способ разбиения конфигураций по Интернет-провайдерам. Вот как они разделяются:

"B1"         | "tm"      | "State Company of Electro Communications Turkmentelecom"         |

"B2"         | "tm"      | "Telephone Network of Ashgabat CJSC;AGTS CDMA Mobile Department" |

"B3"         | "tm"      | "Altyn Asyr CJSC"                                                |

"GLOBAL"     | "default" | ""                                                               |

"RU"         | "ru"      | ""                                                               |

"IRANTELCOM" | "ir"      | ""                                                               |

"IRNCELL"    | "ir"      | "Iran Cell Service and Communication Company"                    |

"A1"         | "ae"      | ""                                                               |

"A2"         | "ae"      | "Emirates Integrated Telecommunications Company PJSC"            |

"IRANMCI"    | "ir"      | "Mobile Communication Company of Iran PLC"      |

Где «tm» — это Туркменистан, «ru» — Россия, «ir» — Иран, «ae» — Объединённые Арабские Эмираты. Нас интересуют конфигурации, заканчивающиеся на _c, что, вероятно, обозначает «configuration».

Если мы пройдёмся по всем файлам конфигурации и соберём все URL, которые DDOS-ит приложение, то получим такой список:

https://www.science.gov.tm/news/20230112news-2023-01-12/

https://www.science.gov.tm/organisations/classifier/reseach_institutes/

https://www.science.gov.tm/library/articles/article-asirow-25/

https://www.science.gov.tm/news/~Page34/

https://railway.gov.tm/

https://turkmenistanairlines.tm/tm/flights/search?_token=J8SxUX2Qwzltw4LiHsRHTCtfthgBYxf4hyI8oNly&search_type=internal&departPort=TAZ&arrivalPort=CRZ&tripType=rt&departDate=4%2F22%2F2023&arrivalDate=5%2F4%2F2023&adult=1&child=0&infant=0&is_cship=on

https://www.science.gov.tm/news/~Page25/

https://www.science.gov.tm/news/~Page9/

https://www.science.gov.tm/news/~Page36/

https://www.science.gov.tm/sci_periodicals/

https://www.science.gov.tm/anounce/

https://www.science.gov.tm/projects/mietc1/

https://www.science.gov.tm/projects/APCICT1/

https://www.science.gov.tm/projects/caren/

https://www.science.gov.tm/events/

https://www.science.gov.tm/organisations/chemical_institute/

https://www.science.gov.tm/en/news/~Page11/

https://www.science.gov.tm/en/news/20220329news-2022-03-28-1/

https://www.science.gov.tm/en/news/20220310news-2022-03-09-1/

https://www.science.gov.tm/en/news/20220123news-2022-01-22-1/

https://www.science.gov.tm/news/20230112news-2023-01-12/

В списке мы видим уже знакомую нам ссылку на turkmenistanairlines. Но другие URL тоже похожи друг на друга, все они заканчиваются на .gov.tm. Можно предположить, что это приложение пытается атаковать какие-то государственные сайты Туркменистана. Мне трудно представить, для чего кому-то понадобилось бы это делать, но мы здесь не для этого. Меня интересует техническое исследование.

Конфигурации, хранящиеся в apk

Всё вышеперечисленное можно легко удалить, тогда мы не смогли бы доказать, что этим занимается приложение. Поэтому давайте найдём доказательства того, что всё это залито в apk и криптографически подписано.

Оказалось, эта задача не так сложна. Если декомпилировать файл, распаковав его zip или инструментом наподобие apktool, то можно найти файл

res/raw/rc_g.raw

Он тоже зашифрован; его можно расшифровать скриптом decode.py, но этот файл не содержит закрывающих скобок {{{ и }}}. Поэтому чтобы декодировать файл, нам достаточно добавить "-n" в качестве второго аргумента скрипта decode.py. Не самое удобное решение, но позволяет решить нашу задачу:

python decode.py cr_g.raw.txt -n

Запустив эту команду, вы должны получить похожий файл:

{
    "configResources": [
        {
            "type": "git",
            "purpose": "config",
            "url": "https://github.com/githubfunc/cocomo/blob/main/",
            "urlExt": "",
            "entry": "green"
        },
        {
            "type": "git",
            "purpose": "config",
            "url": "https://github.com/javaidakhtar576/swinglite_new/blob/main/",
            "urlExt": "",
            "entry": "main"
        },
        {
            "type": "host",
            "purpose": "config",
            "url": "https://arpqpedacr.com/",
            "urlExt": "",
            "entry": "main"
        },
        {
            "type": "host",
            "purpose": "config",
            "url": "https://atrytgoi.com/",
            "urlExt": "",
            "entry": "main"
        },
        {
            "type": "host",
            "purpose": "config",
            "url": "https://bdefsr.com/",
            "urlExt": "",
            "entry": "main"
        },
        {
            "type": "host",
            "purpose": "config",
            "url": "https://cornchance.com/",
            "urlExt": "",
            "entry": "main"
        },
        {
            "type": "host",
            "purpose": "config",
            "url": "https://dreoapms.com/",
            "urlExt": "",
            "entry": "main"
        },
        {
            "type": "host",
            "purpose": "config",
            "url": "https://freekept.com/",
            "urlExt": "",
            "entry": "main"
        },
        {
            "type": "host",
            "purpose": "config",
            "url": "https://gquyidezfixp.com/",
            "urlExt": "",
            "entry": "main"
        },
        {
            "type": "host",
            "purpose": "config",
            "url": "https://haptpydligyh.com/",
            "urlExt": "",
            "entry": "main"
        },
        {
            "type": "host",
            "purpose": "config",
            "url": "https://hcvxm.com/",
            "urlExt": "",
            "entry": "main"
        },
        {
            "type": "host",
            "purpose": "config",
            "url": "https://hgvcp.com/",
            "urlExt": "",
            "entry": "main"
        },
        {
            "type": "host",
            "purpose": "config",
            "url": "https://jhgvu.com/",
            "urlExt": "",
            "entry": "main"
        },
        {
            "type": "host",
            "purpose": "config",
            "url": "https://mqurstd.com/",
            "urlExt": "",
            "entry": "main"
        },
        {
            "type": "host",
            "purpose": "config",
            "url": "https://mraznakgde.com/",
            "urlExt": "",
            "entry": "main"

        },
        {
            "type": "host",
            "purpose": "config",
            "url": "https://mwuth.com/",
            "urlExt": "",
            "entry": "main"
        },
        {
            "type": "host",
            "purpose": "config",
            "url": "https://net-vm-games.com/",
            "urlExt": "",
            "entry": "main"
        },
        {
            "type": "google",
            "purpose": "config",
            "url": "https://www.googleapis.com/drive/v3/files/",
            "urlExt": "?alt=media",
            "entry": "15_T7IYmov1A7Ar3jFe4SkZ4dKFpbomTf",
            "credentials": "..."
        },
        {
            "type": "google",
            "purpose": "config",
            "url": "https://www.googleapis.com/drive/v3/files/",
            "urlExt": "?alt=media",
            "entry": "13R-GC8jtz4XB-xl_IQUeL8BiS32pXB03",
            "credentials": "..."
        },
        {
            "type": "google",
            "purpose": "config",
            "url": "https://www.googleapis.com/drive/v3/files/",
            "urlExt": "?alt=media",
            "entry": "13B5sCioRZCGfBx13b9K2sRoo2XEEst0B",
            "credentials": "..."
        },
        {
            "type": "google",
            "purpose": "pin",
            "url": "https://www.googleapis.com/drive/v3/files/",
            "urlExt": "?alt=media",
            "entry": "",
            "credentials": "..."
        }
    ]
}

Я отредактировал вывод, удалив из него значение credentials, которое заменил на .... Если вам действительно нужны эти данные, то запустите скрипт самостоятельно и получите исходное значение.

Если взглянуть на вывод, то можно увидеть знакомые ссылки на Github и Google Drive, которые приложение использовало для скачивания дополнительных параметров. Эти файлы параметров являются реальной конфигурацией параметров, а также используются как механизм C&C (Command and Control) для тайного указания жертв приложения Swing VPN для DDOS-атак.

Связанные файлы

  • swinglite_new.zip — последний коммит репозитория swinglite_new repository.

  • cocomo.zip — последний коммит репозитория cocomo

  • google_drive.zip — дешифрованные файлы конфигурации одного из аккаунтов Google Drive

  • decode.py — файл для дешифровки зашифрованных конфигураций, хранящихся на Github и Google Drive

  • swing-vpn-1-8-4.apk — файл apk Swing VPN версии 1.8.4, скачанный с Play Store

Я указал только один коммит репозиториев Github, потому что они довольно велики (больше 100 МБ). Если по какой-то причине вам нужен полный репозиторий, то вы можете связаться со мной по почте, и я вышлю ссылку на скачивание полных репозиториев с историей более чем полугода коммитов.

Заключение

Судя по представленным доказательствам, можно уверенно сказать, что создатель приложения имел намерение перекрыть доступ к сервисам для обычных пользователей при помощи DDOS этих сервисов. Он использовал различные методики для обфускации и сокрытия своих злоумышленных действий, чтобы их нельзя было обнаружить. Это основная причина, по которой он отправляет запрос каждые несколько секунд: при таком количестве установок этого достаточно, чтобы перегрузить серверы, но при этом не привлечь внимание команд безопасности Play Store. Однако если по какой-то причине разработчик решит, что давления на сервис недостаточно, то он сможет с лёгкостью отправить приложениям команду и заставить их обрушить на сервисы бессмысленные запросы.

Кроме того, что это злоумышленные действия, направленные против невиновных сервисов, это ещё и очень нечестное поведение по отношению к пользователям, скачавшим приложение. Разработчик не уважает их конфиденциальность и использует телефоны пользователей в качестве ботнета. При этом он ещё и зарабатывает на пользователях, или показывая им рекламу, или ежемесячно продавая VIP-услуги. Из чистой жадности автор ещё и хочет использовать телефоны невиновных пользователей в своих преступных действиях.

Надо отдать должное команде разработчиков Swing VPN за то, что они смогли обойти меры безопасности Google PlayStore, но печально, что системы безопасности Google не могут автоматизированным образом выявлять подобные виды действий.

Комментарии (5)


  1. gazkom
    30.06.2023 06:55
    +3

    Мне кажется тут нет среди читателей модераторов googleplay. Вы в google это всё отправили?


    1. koreec
      30.06.2023 06:55
      +2

      Перевод же


    1. mayorovp
      30.06.2023 06:55
      +1

      Судя по тому что приложение уже удалено — да, он отправил.


      Однако, новое приложение с тем же названием с другого аккаунта уже создано...


  1. isitsonow
    30.06.2023 06:55
    +2

    опять "русские хакеры"? (судя по тому что в ру регионе нет целей)

    хмм


    1. freeExec
      30.06.2023 06:55
      +2

      Нет провайдеров, а не целей. Ну и если следовать вашей логике, то они так же и глобальные хакеры