W zeszłym roku opublikowano artykuł opisujący kulisy „prawie udanego ataku” gangu ransomware o nazwie Spacecolon na jedną z polskich firm, a pół roku później temat gangu rozwinął ESET w swojej publikacji. Metody wykorzystywane w ataku nie cechowały się zbytnim wyrafinowaniem poza tym, że operatorzy używali autorskich narzędzi napisanych w języku Delphi, które nie były wykrywane przez oprogramowanie antywirusowe. Według informacji przedstawionych przez ESET przestępcy wybierali ofiary przypadkowo. Wśród nich znalazła się polska instytucja rządowa, firmy sektora prywatnego z Izraela, Brazylii, Turcji, Tajlandii oraz szkoła w Meksyku.
Obserwując ślady kolejnych włamań, postanowiłem zebrać informacje o rabusiach, ich infrastrukturze i utrudnić im trochę życie. W dalszej części artykułu przekonasz się, jak mi poszło.
Zaszyfrowana zawartość złośliwego oprogramowania
Analiza wsteczna złośliwych próbek na potrzeby obsługi incydentu jest wykonywana z reguły w ścisłym rygorze czasowym, tak aby szybko pozyskać kluczowe informacje o napastniku. W związku z tym skupia się ona przede wszystkim na pozyskaniu wskaźników kompromitacji (ang. Indicatior of Compromise, IoC), takich jak domeny, adresy IP itp., ułatwiających identyfikację przejętych urządzeń oraz kont.
Moja analiza miała charakter postincydentalny, dlatego mogłem zbadać mniej oczywiste elementy próbek, takie jak algorytm szyfrowania. Twórcy opisanych narzędzi umieścili szyfrogramy w formie tekstowej (ASCII) w postaci szestnastkowej, więc odpowiednie wyrażenie regularne i grep wystarczył, aby zebrać szyfrogramy, które następnie odszyfrowałem.
W rezultacie uzyskałem następujące adresy URI:
hxxp://195[.]123.246.5/list.txt
hxxps://3[.]76.107.228/list.txt
hxxp://195[.]123.246.5:8080/fileupload
hxxp://195[.]123.246.5:8080/fileupload2
hxxp://195[.]123.246.5/mimi/a.php?task=u
hxxp://195[.]123.246.5/mimi/a.php?task=p
Plik list.txt
zgodnie z informacjami z pierwotnego artykułu zawierał listę dodatkowych narzędzi dla operatora złośliwego oprogramowania, a pozostałe 4 adresy prowadziły do aplikacji umiejscowionych w infrastrukturze przestępców.
Aplikacja fileupload
pozwalała zgodnie ze swoją nazwą wysyłać pliki, a linki zawierające /mimi/
w nazwie zwracały pustą odpowiedź. Prawdziwa rola obu aplikacji pozostawała jednak zagadką, do czasu kiedy wykorzystałem reguły YARA, aby pozyskać z serwisu Virustotal inne wersje tej próbki, a wraz z nimi prawdziwą perełkę. Natrafiłem na podejrzany plik umieszczony w archiwum ZIP, które najprawdopodobniej stanowiło materiał dowodowy zebrany w toku obsługi innego incydentu.
Plik eines.zip
zawierał zarówno złośliwe oprogramowanie w charakterystycznej (opisanej w oryginalnym artykule) ścieżce %USERPROFILE%\Music
, jak i inne opisane wcześniej narzędzia i skrypty. W archiwum znalazły się również następujące pliki:
lsa.file
– zrzut pamięci procesu lsass z kontrolera domenyDC1-FS
lastlog.txt
– logi uruchomienia programu mimikatz na zrzucie pamięciHOW TO RECOVERY FILES.TXT
– notatka z okupem
Analizując wspomniane pliki, przyjąłem hipotezę, zgodnie z którą aplikacja fileupload
służy do wysyłania zrzutu pamięci procesu lsass na serwer kontrolowany przez przestępców. W celu minimalizacji ryzyka wykrycia mimikatza jest on uruchamiany zdalnie, a odszyfrowane poświadczenia prezentuje operatorowi aplikacja /mimi/
. Oględziny plików pozwoliły mi z łatwością odnaleźć przedsiębiorstwo, które dołączyło do grona ofiar gangu.
Rozpoznałem następujące typy aplikacji:
http://ip/tools
– repozytorium narzędzi przestępców (opendir
)http://ip:8080/fileupload
– formularz do wysyłania zrzutów pamięci procesu lsasshttp://ip/mimi/a?task=u
– lista skompromitowanych kont (na podst. lsass)http://ip/mimi/a?task=p
– odpowiadające im hasła
Adresy IP serwerów były zmieniane przy każdej rekompilacji złośliwych narzędzi.
Aby potwierdzić swoje przypuszczenia, zautomatyzowałem pobieranie treści z adresów listujących wykradzione poświadczenia i czekałem na kolejne ofiary gangu.
Historia szwajcarskiego dealera aut
Pewnego dnia serwer przestępców zwrócił następujące dane:
Jasnym stało się, że kolejna firma jest już krok od zaszyfrowania. Pośród poświadczeń rozpoznałem nazwę domeny AD oraz konto o nazwie IWAM_USR
, które było tworzone przez przestępców w poprzednich włamaniach, więc najwidoczniej gang miał już pełny dostęp do kontrolera domeny. Ofiarę można było łatwo ustalić na podstawie nazwy domeny, był nią szwajcarski dealer samochodów luksusowych. Firma zatrudniała kilkadziesiąt osób, pośród których próżno było znaleźć pracowników IT. Pomocny okazał się szwajcarski CERT, który błyskawicznie przyjął zgłoszenie i podjął próbę kontaktu z dealerem, mimo że zdarzenie zostało wykryte w niedzielę w trakcie przerwy na lancz.
Fakt kompromitacji kontrolera domeny wskazywał raczej na ponury początek tygodnia dla pracowników. O dziwo, następnego dnia dostałem od CERT-u informacje, że incydent został potwierdzony, a stosunkowo wczesna reakcja najprawdopodobniej uratuje większość zasobów przed szyfrowaniem.
Niestety firma zdecydowała nie dzielić się żadnymi szczegółami związanymi z przebiegiem incydentu, więc sposób uzyskania pierwszego dostępu do sieci pozostawał dla mnie zagadką. Postanowiłem dalej monitorować wykradzione poświadczenia.
Mapowanie infrastruktury przestępców
Pomimo że pozyskiwanie informacji na temat serwerów z próbek złośliwego oprogramowania przynosiło dobre rezultaty, zależało mi na rozszerzeniu moich źródeł przy wykorzystaniu narzędzi takich jak Censys lub Shodan. Przestępcy nie dbali o ograniczanie dostępu z niezaufanej adresacji, więc serwisy skanujące publicznie dostępne hosty powinny zbierać o nich pewne informacje.
Zgodnie z przedstawionymi wyżej informacjami, przestępcy utrzymywali usługę http/https, opartą o serwer WAMP i dość standardowy certyfikat x509. Sama usługa, jak i certyfikat, nie przejawiały żadnych wyjątkowych właściwości i śledzenie ich mechanizmami takimi jak JA3S było niepraktyczne.
Usługa „uploadu” zrzutów pamięci wydawała się bardziej obiecująca, w prawdzie nie wspierała protokołu TLS, ale zwracane przez serwer źródło strony było zawsze jednakowe:
<form action="fileupload" method="post" enctype="multipart/form-data">
<input type="file" name="filetoupload"><br><input type="submit"></form>
Zarówno Censys, jak i Shodan pozwalają przeszukiwać swoje bazy danych w oparciu o hasz zwracanego źródła strony. W przypadku Censys jest to SHA1 odpowiedzi serwera (bez nagłówków HTTP), Shodan wykorzystuje zaś hasz MurmurHash3. Wartości tych funkcji skrótu można wyliczyć przy użyciu aplikacji CyberChef:
- SHA1:
4a1cf7c044be2ca4253887576190ba980abcc611
, - Murmur3:
1629558153
.
Oba serwisy dostarczyły tylko garść wyników, a przy założeniu, że ten sam adres wykorzystywany jest do świadczenia wszystkich 3 aplikacji, wystarczyło poszukać np. pliku list.txt
.
Na tym etapie mojego śledztwa dysponowałem już możliwością pozyskiwania nowych próbek na bieżąco z serwisu Virustotal oraz solidnym sposobem wyszukiwania nowopowstałych serwerów przestępców. Ostatnim krokiem była automatyzacja wykorzystująca API Virustotala, Censysa i Shodana, która pozwoliła mi spokojnie śledzić kolejne kroki gangu.
Próba atrybucji
Kiedy oceniłem, że mam solidny wgląd w bieżące działania grupy, moją uwagę wciąż przyciągał algorytm szyfrowania. Zawsze fascynuje mnie tendencja przestępców do wykorzystywania nietypowych, napisanych na kolanie algorytmów szyfrujących. Prawdopodobnie ma to na celu utrudnienie analizy lub jest przykładem niskich umiejętności deweloperów, którzy nie potrafią wykorzystać gotowych bibliotek kryptograficznych. Dla mnie jest to szansa na wyodrębnienie nietypowego kodu i poszukiwanie innych próbek, które go współdzielą w nadziei na odnalezienie innych „narzędzi zbrodni”.
MUL = 0xd201 #dec: 53761
ADD = 0x7f6a #dec: 32618
def decode(encoded: str, key = 0x0639) -> str:
decoded = b""
for ch in bytearray.fromhex(encoded):
xorVal = key >> 8 & 0xff
decoded += chr(ch ^ xorVal).encode("utf-8")
key += ch
key = (key * MUL + ADD) & 0xffff
return decoded.decode("utf-8")
Powyżej przedstawiłem rekonstrukcję szyfru w formie skryptu języka Python. Pierwszym wnioskiem, jaki się nasuwa po jego przestudiowaniu, jest to, że efektywna długość klucza wynosi 16 bitów, ponieważ w ostatnim kroku zmienna przechowująca klucz wygasza wszystkie bity poza 16 najmniej znaczącymi. Oznacza to, że szyfrogramy będzie można odszyfrować bez znajomości klucza, próbując po kolei wszystkie 2^16 kluczy – zadanie proste dla współczesnego komputera. Zainteresowały mnie również stałe MUL
i ADD
wykorzystywane w tej samej instrukcji do modyfikacji klucza przy każdym wykonaniu pętli. Postanowiłem przeszukać internet pod kątem tych wartości i pierwszym wynikiem Google było pytanie na stackoverflow zadane przez użytkownika o pseudonimie maxfax.
Obecność stałych w formie dziesiętnej, jak również rzut okiem na algorytm potwierdza, że mamy do czynienia z oryginalnym kodem szyfrującym. Pozostałe pytania zadane przez użytkownika pozwoliły mi potwierdzić, że raczej słabo operuje językiem angielskim i nie jest wybitnym programistą, ale w żaden inny sposób nie łączyły go ze złośliwym oprogramowaniem.
Nadszedł czas, by stworzyć odpowiednią sygnaturę ujawniającą algorytm w pliku wykonywalnym. W tym celu zlokalizowałem odpowiedni fragment kodu binarnego próbki, który wykonywał kolejne kroki szyfru.
Powyższa ilustracja przedstawia kod maszynowy będący odpowiednikiem pętli for
, która odpowiedzialna jest za deszyfrowanie wartości znak po znaku. Jest do dobry kandydat na stworzenie wzorca. W celu stworzenia reguły YARA, pozwalającej na śledzenie kodu, można wykorzystać plugin Ghidry o nazwie YaraGhidraGUIScript.
Skrypt umożliwia maskowanie adresów oraz wartości skalarnych, które są wykorzystywane w toku wykonywania kodu maszynowego. Dzięki temu wzorzec wykorzystywany w regule YARA dopasuje próbkę, w której algorytm nieznacznie różni się od oryginału (adresami lub zdefiniowanymi stałymi), ale zachowuje oryginalną logikę. Wartości zaznaczone kolorem fioletowym (lub znakami zapytania we wzorcu) będą ignorowane. Wytworzoną w ten sposób regułę można wykorzystać w procesie wyszukiwania wstecz (ang. retro hunt) w serwisach UnpacMe lub Virustotal.
Postanowiłem wykorzystać UnpacMe w wersji darmowej i przeszukałem zbiór plików za okres 12 tygodni wstecz, w rezultacie czego otrzymałem 14 próbek zawierających ciąg odpowiadający mojej regule YARA. Jedna z próbek okazała się inną wersją złośliwego oprogramowania wykorzystywaną przez tę grupę, ale ciekawszym znaleziskiem okazały się pozostałe pliki. Były to różne aplikacje użytkowe (od odtwarzacza muzyki po notatnik) wytworzone i podpisane kluczem firmy Vovsoft.
Na pierwszy rzut oka odnalezione pliki nie były złośliwe, jednak najprawdopodobniej współdzieliły omawiany algorytm szyfrujący. Odwiedziłem więc stronę internetową firmy Vovsoft, na której można było kupić wspomniane aplikacje, a dodatkowo skontaktować się z ich autorem, ponieważ najprawdopodobniej wszystkie aplikacje rozwija ten sam człowiek. Czy maxfax i Fatih to ta sama osoba? Czy któryś z nich rozwija złośliwe oprogramowanie dla gangu Spacecolon? Nie ma na to dowodów, a aktywność grupy w ostatnich miesiącach spadła. Być może słaby OPSEC grupy sprawił, że część jej członków zmieniła miejsce zakwaterowania na dłużej. Powyższy artykuł dowodzi, jak wiele informacji można pozyskać z jednej tylko próbki złośliwego oprogramowania, kiedy śledztwo wesprze się narzędziami takimi jak Censys czy Virustotal.
Aktualizacja: Problemowi przyjrzał się też ESET, który w dwóch publikacjach szczegółowo przeanalizował zagrożenie – polecamy lekturę. Na podstawie ustaleń zespołu ESET skorygowaliśmy także fragment o atrybucji zagrożenia.
Dziękuję Pawłowi za jego pomoc w zbieraniu informacji związanych z opisaną grupą przestępczą.
Komentarze
Mają rozmach……Ale autor artykułu ma większy.
Wooow! Niezła akcja i nieźle się czytało!
Adamie H., zatwierdzam tego autora! ;) Wincyj!
Fantastyczny tekst :)
Nie jest pewny ale każdy złodziej zostawia ślady nawet IT fajnie się czytało pozdrawiam
Słaby opsec, to jak u mnie. Fajny artykuł.
Moim zdaniem wskazanie w artykule persony dewelopera z Turcji, tylko na podstawie współdzielonego fragmentu kodu ze Stackoverflow jest zbyt daleko idące, a nawet nieodpowiedzialne. Jest to prawdopodobnie zwykły przypadek. Co innego gdyby algorytm był rzeczywiście autorski. Kiepskie rozumowanie ze strony autora.