Всё началось с того, как один мой друг пожаловался, что его телефон каждые несколько секунд выполняет запрос к одному и тому же приложению. Сначала я предположил, что телефон заражён вирусом, но через пару минут стало ясно, что все запросы поступали от приложения 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 не могут автоматизированным образом выявлять подобные виды действий.