Zespół CERT Polska przeanalizował nowe próbki powiązane z kampanią FvncBot wymierzoną w polskich użytkowników internetu. Poniższy opis został oparty na wariancie kampanii wykorzystującej wizerunek Spółdzielczej Grupy Bankowej.
Podstawowe informacje
Omawiane próbki są hostowane pod adresem ruvofech.it[.]com. Sposób dystrybucji plików nie został jeszcze zidentyfikowany na moment tworzenia tej analizy.
Aplikacja opisana jako Token U2F Mobilna Ochrona SGB informuje użytkownika o konieczności instalacji dodatkowego Play Component, a następnie prowadzi go poprzez proces instalacji dodatkowego modułu opisanego jako Android V.28.11. Ofiara jest następnie nakłaniana do zezwolenia na uruchomienie funkcji ułatwień dostępu pod pretekstem uaktualnienia systemu (System Update). W kolejnym kroku wspomniany moduł rejestruje się na serwerze przestępców i wysyła informacje o zainfekowanym urządzeniu.
Przebieg infekcji
Z perspektywy ofiary ciąg wydarzeń odtworzony podczas dynamicznej analizy próbki wygląda następująco:
Użytkownik uruchamia aplikację wykorzystującą wizerunek SGB i na ekranie startowym widzi komunikat o konieczności instalacji Play Component oraz tekst nakłaniający go do uruchomienia procesu instalacji dzięki guzika Install Component.
System Android przywołuje menu kontekstowe adekwatne dla instalacji aplikacji z nieznanych źródeł (Install unknown apps). Użytkownik widzi informację o instalacji Android V.28.11. Po instalacji modułu, guzik "instalacji" zmienia się w "aktywację" (Activate). Wciśnięcie go powoduje wyświetlenie menu ustawień (Setup Required), które informuje użytkownika o konieczności wyrażenia zgody na uruchomienie funkcji ułatwień dostępu.
Po uruchomieniu usługi, aplikacja wyświetla komunikat All Systems Operational. Każda próbka w tej kampanii używa wizerunku innego banku.
Głównym motywem socjotechnicznym obserwowanej kampanii jest właśnie opisany wyżej podział - widoczna fasada z logotypem i szatą graficzną banku ma na celu zwabienie użytkownika w pułapkę, ale nie odpowiada za samo szkodliwe działanie. Tym zajmuje się zainstalowany za jej pomocą moduł, który ukrywa się za informacjami przypominającymi systemowe komunikaty Androida.
Co przyniosła analiza próbki?
- Istnieje zewnętrzna paczka danych com.junk.knock, określana mianem Token U2F Mobilna Ochrona SGB.
- W następnym kroku ładowany jest instalator z /data/user/0/com.junk.knock/app_tell/tWyWeG.txt używając DexClassLoader.
- Załadowany instalator odpakowuje assets/apk/payload_grass.apk, czyli drugi moduł odpowiedzialny za główny element ataku.
- Instalator korzysta z core://setup by przekierować ofiarę do kolejnego etapu infekcji.
- Drugi etap jest spakowany pod com.core.town i określany jako Android V.28.11.
- Plik APK com.core.town stanowi kolejną warstwę, która ukrywa dodatkowy wsad w zagnieżdżonym zasobie o nazwie qkcCg.jpg.
- Ukryty zasób jest przekształcany dzięki procesu podobnego do RC4 wprowadzanego przez sDjCM i przekształca się w finalną wersję modułu.
- Podczas uruchomienia moduł rejestruje urządzenie pod adresem https://jeliornic.it.com/api/v1/devices/register i otrzymuje dane dostępowe unikalne dla danego urządzenia.
Jak się chronić?
- Pobieraj aplikacje bankowe jedynie z zaufanych źródeł takich jak Google Play Store lub App Store.
- Jeśli otrzymujesz połączenie telefoniczne rzekomo ze swojego banku, w którym rozmówca informuje o potencjalnym zagrożeniu, rozłącz się i oddzwoń na numer znaleziony na oficjalnej stronie banku. Pozwala to uniknąć oszustw opartych na spoofingu CLI.
- Traktuj wszelkie instrukcje wymagające manualnej instalacji "komponentu bezpieczeństwa" lub "komponentu uruchomienia" spoza oficjalnego sklepu jako podejrzane i potencjalnie niebezpieczne.
- Jeśli aplikacja prosi o zgodę na instalację z nieznanych źródeł (Install unknown apps), a następnie o dostęp do funkcji ułatwień dostępu, traktuj to jako ostateczny sygnał ostrzegawczy.
Analiza techniczna
Każda aplikacja na Androida posiada plik manifestu: AndroidManifest.xml. W tym przypadku, już analiza tego pliku pokazuje, iż zewnętrzna aplikacja korzystająca z wizerunku SGB jest zaprojektowana do współpracy z dodatkowym pakietem com.core.town i komunikacji z jego dostawcą.
Manifest i przynęty
Treści wyświetlane na urządzeniu ofiary nie są przypadkowe - są zgodne z procesem asystowanej instalacji danego operatora:
Etap 1, wczytywanie: prywatna ścieżka + DexClassLoader
Zewnętrzna klasa aplikacji inicjalizuje prywatne foldery i nazwy plików wykorzystanych podczas wykonywania programu:
Dekoduje także kolejne etapy zawartości i przekazuje kontrolę do asystenta wczytywania (reflective loader helper):
Mechanizm wczytywania jest podany wprost (DexClassLoader):
A dynamiczna analiza próbki potwierdza dokładną ścieżkę wywołania:
Etap 2, instalacja: payload_grass.apk i śledzenie ofiary
Załadowany instalator (com.gallery.oppose) przechowuje wiele ważnych wartości w formie Base64+XOR. Po odkodowaniu ujawniają:
- target package: com.core.town
- setup URI: core://setup
- tracking endpoint: https://jeliornic.it.com/api/v1/tracking/events
- build ID: h8zskxh6kjv
Sam dekoder jest bardzo prosty:
Instalator weryfikuje czy funkcje ułatwień dostępu są już uruchomione:
Zapisuje zagnieżdżony plik .APK i uruchamia instalację:
Po instalacji przekazuje kontrolę do kolejnego etapu dzięki deep linku:
Na tym etapie również akcje użytkownika są przesyłane do serwera atakującego. Dane zawierają build ID, package name, wersję aplikacji, ID urządzenia, wersję systemu Android i model urządzenia:
Instalator wprost monitoruje spełnienie co najmniej poniższych warunków:
Etap 2: com.core.town
Zagnieżdżony plik APK nie jest jedynie atrapą mającą na celu odciągnięcie uwagi. Jego manifest deklaruje implant oparty na usługach ułatwień dostępu, mechanizmy persystencji, przechwytywanie ekranu, wiadomości oparte na Firebase, a także dostawcę wykorzystywanego przez instalator.
Profil dostępności jest celowo bardzo szeroki:
Poniższe ciągi jasno pokazują sposób zamaskowania drugiego etapu jako rzekomego komponentu systemowego:
Najważniejszym odkryciem jest to, iż com.core.town sam w sobie jest kolejnym modułem ładującym. Jego klasa Application nie tylko uruchamia usługi, ale także ładuje inny ukryty plik o nazwie qkcCg.jpg.
Funkcja attachBaseContext() tworzy wewnętrzną ścieżkę dla wspomnianego pliku i wykonuje się jedynie po jego skutecznym wypakowaniu:
Wypakowanie ukrytego etapu: qkcCg.jpg
Fragment wyciągnięty z classes7.dex wskazuje, iż qkcCg.jpg nie jest plikiem graficznym w klasycznym rozumieniu. Wczytywanie korzysta z prostej warstwy dekodującej i zahardkodowanego klucza:
Zawiera także prosty dekoder na bazie XOR wykorzystywany do odzyskiwania nazw metod:
Samo przekształcenie korzysta z this.m.getBytes() a następnie wykonuje podobną do RC4 pętlę:
Analiza offline potwierdziła, iż zastosowanie RC4 z kluczem sDjCM do pierwotnej wersji pliku qkcCg.jpg skutkuje uzyskaniem archwium ZIP zawierającego finalną wersję classes.dex.
Cechy szkodliwego oprogramowania
Ostatni etap po wypakowaniu odpowiada za adekwatną część zachowania opisywanego modułu. On również wykorzystuje paczkę com.core.town, ale nie służy już tylko do setupu.
Accessibility-based remote control
Ostateczna wersja RemoteAccessibilityService wykonuje otrzymywane wiadomości z instrukcjami przekładając je na wstrzyknięcie gestów i w efekcie akcje globalne:
Wstrzyknięcie poleceń dotykowych następuje dzięki dispatchGesture():
Akcje globalne również widać tutaj:
Binarny dekoder wiadomości przychodzących po protokole Websocket potwierdza, iż są to akcje uruchamiane zdalnie przez operatora oprogramowania:
Przechwytywanie tekstu i wejścia klawiatury
Moduł przechwytuje zmiany tekstu z edytowalnych pól i zapisuje zarówno pierwotne, jak i zedytowane wartości:
Każde zdarzenie jest dodawane także do kanału event/log:
Przechwytywany jest także bzepośrednio TYPE_VIEW_TEXT_CHANGED:
Przechwytywanie interfejsu użytkownika
Usługa tworzy pełną reprezentację wyświetlanego ekranu w pliku JSON, zawierającą tekst, opis zawartości, identyfikatory widoków, granice na ekranie, role oraz elementy podrzędne:
Wyeksportowana metoda zwraca zserializowane drzewo wraz z wymiarami ekranu:
Nakładki i wstrzyknięcia zawartości sieciowej
Operator może wyświetlać poprzez moduł adresy URL, zawartość HTML, wygasić ekran lub nałożyć nakładkę:
Zestaw instrukcji FCM wprost wspiera klikalne nakładki i aktualizacje ich zadań:
Ścieżka nakładek pozwala też na wstrzyknięcie spersonalizowanego JavaScript do zawartości WebView w celu zachowania widoczności pól wprowadzania danych przy otwartej klawiaturze - zachowanie charakterystyczne dla nakładek służacych do przechwytywania danych logowania.
Strumieniowanie ekranu i sesje WebSocket
Moduł może także poprosić o dostęp do MediaProjection i uruchomić usługę przechwytywania ekranu działającą na pierwszym planie:
FCM wspiera też sesje websocketowe:
Metoda przyjmuje adres websocketu i klucz do API:
Klient websocketowy jest zbudowany na bazie OkHttp i dodaje X-API-Key gdy jest aktywny:
Ze źródeł można także odczytać protokół kontrolny, poniżej przykłady:
- 1 -> touch/gesture events
- 2 -> key events
- 3 -> swipe vector
- 15 -> overlay mode (black, html, url, loading)
- 18 -> clipboard injection
- 22 -> open a settings page
- 23 -> launch another application
- 24 -> end session
Fragment wspomnianego dekodera:
Dodatkowe funkcje pomocnicze
Ostatni etap zawiera także następujące funkcje:
- upload_apps
- request_permissions
- start_polling
- stop_polling
- start_heartbeat
- stop_heartbeat
- show_settings
- wake_with_activity
- show_notification
- configure_logging
Poszczególne komendy są widoczne także w switchu odpowiadającym za obsługę komunikatów FCM (Firebase Cloud Messaging):
Rejestracja urządzenia podczas wykonania programu
Analiza dynamiczna potwierdza wnioski ze statycznej:
Zaobserwowany ruch do serwera:
- https://jeliornic.it.com/api/v1/tracking/events
- https://jeliornic.it.com/api/v1/devices/register
- https://jeliornic.it.com/api/v1/devices/device_bf43438cc5236391/events/batch
Zaobserwowane wartości rejestracji urządzenia:
- device_id = device_bf43438cc5236391
- api_key = ak_c5JNf4OUUSGytz0DpmR9fGbxtjtSR0BCoDtrPj7CS8Y
- adres IP backendu zaobserwowany w trakcie sesji: 104.21.59.199
Zaobserwowane nagłówki uwierzytelniające:
- X-API-Key: ak_c5JNf4OUUSGytz0DpmR9fGbxtjtSR0BCoDtrPj7CS8Y
- X-Device-ID: device_bf43438cc5236391
Bazowy (statyczny) URL serwera jest zagnieżdżony bezpośrednio w ostatnim etapie kodu. Moduł odczytuje stałą z adresem przy pomocy dekodera opartego na XOR i klucza zext0sup3bei25jm:
Zdekodowana wartość:
- https://jeliornic.it.com
Proces rejestracji urządzenia jest wskazany wprost w źródłach:
Po rejestracji dane dostępowe do serwera są przechowywane lokalnie:
Do uwierzytelniania w komunikacji HTTP wykorzystano zarówno nagłówek X-API-Key jak i X-Device-ID:
Ten sam klient HTTP jest używany do odpytywania o polecenia, heartbeatów i wsadowego wysyłania zdarzeń:
Podsumowanie
Analizowaną próbkę można opisać jako wielomodułowe narzędzie do zdalnego sterowania zainfekowanym urządzeniem i nie jest to typowa fałszywa aplikacja banku. Przynęta w postaci wykorzystania wizerunku SGB, instalator, widoczna paczka Android V.28.11 i ukryty plik qkcCg.jpg są częścią ekosystemu, który umożliwia adwersarzowi pełny dostęp do urządzenia.
Inne próbki analizowane przez CERT Polska w podobnych kampaniach wykorzystują ten sam schemat: przynęta z logotypem banku, instalator, przekazanie sterowania do com.core.town, rejestracja urządzenia pod jeliornic.it.com i wykorzystanie mechanizmu ułatwień dostępu do zwiększenia możliwości aplikacji. Wariant z wizerunkiem banku SGB stanowi zatem kolejną odsłonę kampanii FvncBot.
Wskaźniki infekcji (IoC)
Identyfikatory plików i etapów
- nazwa zewnętrznej próbki: sgb.apk
- SHA-256 zewnętrznej próbki: 96b47838ba48b881f4b8e007c5b8c2963db516556865695848ee252571fe5893
- zewnętrzna paczka: com.junk.knock
- ścieżka loadera w czasie wykonania: /data/user/0/com.junk.knock/app_tell/tWyWeG.txt
- SHA-256 instalatora w czasie wykonania: 91a22dcd68500e33ee0aa45d40dc00df58bc1d8e3559a273ff1ab8c3d2d94486
- dołączona wewnętrzna nazwa apk: payload_grass.apk
- SHA-256 dołączonego apk: b4708b853ff64530776e8179a748b7e9469eb88491bceaffe3bf16cfe366d75a
- wewnętrzna nazwa paczki: com.core.town
- ukryty zasób: qkcCg.jpg
- SHA-256 ukrytego zasobu: 3d980d21f116bd499bdd0b52b570cbb4ddcbf47aa2dd96b5aae43dbce51f6249
- klucz do odszyfrowania ukrytego zasobu: sDjCM
- SHA-256 końcowo wyodrębnionego pliku DEX: 56c28cda7650e6d9287b8c260594bc759f9f7b47cf74b27ad914de0a57b315c6
Infrastruktura sieciowa
- bazowy URL backendu: https://jeliornic.it.com
- endpoint służący do śledzenia: https://jeliornic.it.com/api/v1/tracking/events
- endpoint służący do rejestracji: https://jeliornic.it.com/api/v1/devices/register
- wzorzec endpointu pobierania poleceń: /api/v1/devices/<device_id>/commands?status=pending&limit=10
- endpoint do wysyłki paczek zdarzeń: /api/v1/devices/<device_id>/events/batch
- endpoint heartbeat (utrzymania połączenia): /api/v1/devices/<device_id>/heartbeat
- wzorzec endpointu sprawdzania statusu polecenia: /api/v1/commands/<command_id>/status
- adres IP backendu zaobserwowany podczas analizy dynamicznej: 104.21.59.199










