Tag: analiza

Atak Petya & Mischa

Data publikacji: 28/06/2017, Kamil Frankowicz

Duet Petya & Mischa jest na rynku ransomware od końcówki 2015 roku. Po sukcesie ataku WannaCry, ostatni wariant został wzbogacony o funkcje propagacji wewnątrz sieci za pomocą exploita EternalBlue, PsExec oraz Windows Management Instrumentation Command-line (WMIC).

Wczorajsza kampania uderzyła przede wszystkim w sieci ukraińskie (dostawca energii Ukrenergo, system monitoringu promieniowania elektrowni w Czarnobylu oraz producent samolotów Antonov) oraz rosyjskie.

W przypadku Polski otrzymaliśmy tylko jedno potwierdzone zgłoszenie, lecz innymi kanałami udało się ustalić kilka zainfekowanych firm.

Czytaj więcej

Analiza złośliwego oprogramowania Emotet v4

Data publikacji: 24/05/2017, Paweł Srokosz

Wstęp

Emotet jest modularnym koniem trojańskim, który po raz pierwszy został zaobserwowany w czerwcu 2014 roku przez Trend Micro. Ten rodzaj złośliwego oprogramowania jest ściśle powiązany z innymi rodzajami, takimi jak Geodo, Bugat czy Dridex, które uznawane są za warianty należące do jednej rodziny.

Zadebiutował jako zaawansowany banker – u swych początków wykorzystywany był do wykradania pieniędzy z kont zainfekowanych ofiar. Jego początkowa wersja była wymierzona w klientów niemieckich i austriackich banków. Przejmowanie kont odbywało się z użyciem techniki Man-in-the-Browser, polegającej na przejęciu kontroli nad przeglądarką i przechwytywaniu komunikacji sieciowej przez podsłuchiwanie wywołań odpowiednich funkcji systemowych.

W kolejnej wersji (v2) arsenał Emoteta został uzupełniony o automatyczne wyprowadzanie pieniędzy z kont przy pomocy systemów ATS (Automatic Transfer System) (dokładniejszy opis tej techniki można znaleźć na 20 stronie raportu CERT Polska z 2013 r.). Jest to sposób powszechnie wykorzystywany również w innych bankerach, m.in. w ISFB (Gozi) i Tinbie.

Na początku kwietnia 2017r. zaobserwowaliśmy szeroką kampanię spamową, w której były dystrybuowane fałszywe maile pochodzące rzekomo od firmy kurierskiej DHL. Maile zawierały odnośnik prowadzący do nieznanego wcześniej, nowego wariantu złośliwego oprogramowania znanego pod nazwą Emotet.

W przypadku tej kampanii, zmiany w kodzie oprogramowania, a także w sposobie komunikacji z serwerami Command&Control wskazywały, iż mamy do czynienia z Emotetem w wersji 4. Z tego względu postanowiliśmy szczegółowo przeanalizować to zagrożenie.

Czytaj więcej

Analiza Sage 2.0

Data publikacji: 14/02/2017, Jarosław Jedynak

logo

Wstęp

Sage jest nową rodziną ransomware, wariantem CryLockera. Obecnie jest rozprowadzany przez tych samych aktorów, którzy zazwyczaj rozsyłają Cerbera, Locky’ego oraz Sporę.

Głównym wektorem infekcji jest malspam i złośliwe załączniki. Emaile z kampanii są puste, bez żadnego tekstu i zawierają jedynie plik .zip. W załączniku znajduje się złośliwy dokument programu Word z makrem pobierającym i instalującym ransomware.

Po uruchomieniu ransomware’u zostaje pokazane okno UAC Windowsa, które jest wyświetlane w pętli do momentu, aż użytkownik ostatecznie zgodzi się na nadanie praw administracyjnych aplikacji.

Na końcu rozpoczynany jest proces szyfrowania i pliki są przetwarzane:

Wiadomość z żądaniem okupu kieruje nas do panelu w sieci Tor, ale zanim możemy się zalogować musimy rozwiązać captchę:

W końcu jesteśmy witani przez „przyjazny użytkownikowi” panel:

Można nawet porozmawiać z twórcami malware (ale nie testowaliśmy tej opcji):

Co ciekawe, próbka nie usuwa się z systemu po infekcji, ale kopiuje się do folderu %APPDATA%\Roaming, i szyfruje wszystkie pliki ponownie po każdym restarcie komputera (do momentu aż zostanie zapłacony okup).

Analiza techniczna

Po tym krótkim wprowadzeniu, skoncentrujemy się bardziej na stronie technicznej, ponieważ Sage 2.0 nie jest zupełnie wtórną rodziną i kilka rzeczy nadaje się do opisania.

Główna funkcja programu wygląda tak:

Jak widzimy, po drodze wiele rzeczy jest sprawdzanych i komputer jest identyfikowany na kilka sposobów. Ciekawsze rzeczy jakie znaleźliśmy to m.in.:

Parametr służący do debugowania

Prawdopodobnie nie wszystko w kodzie działało od razu jak trzeba, ponieważ istnieje w nim parametr (przekazywany z linii poleceń) służący do testowania działania konfiguracji malware’u:

I rzeczywiście, jeśli zostanie przekazany, robi to co powinien:

Prawdopodobnie twórca zapomniał usunąć ten fragment kodu z ostatecznej wersji, bo funkcja ta jest bezużyteczna poza okresem programowania.

Sprawdzenie języka

Twórcy Sage’a 2.0 lubią niektóre kraje bardziej niż inne:

Funkcja ta sprawdza layouty klawiatury użytkownika:

    • next == 0x23 -> białoruski
    • next == 0x3F -> kazachski
    • next == 0x19 -> rosyjski
    • next == 0x22 -> ukraiński
    • next == 0x43 -> uzbecki
    • next == 0x85 -> sacha (jakucki)

Niestety, język polski nie trafił na listę wyjątków Sage’a w obecnej wersji. Może w przyszłości?

Namierzanie użytkownika

Sage próbuje poznać lokalizację swojego hosta odpytując maps.googleapis.com z aktualnym SSID sieci Wi-Fi oraz adresem MAC:

Plik kanarka

Przed szyfrowaniem próbka sprawdza czy istnieje specjalny plik:

Dzięki temu twórcy malware nie muszą się przejmować przypadkowym uruchomieniem swojego dzieła i zaszyfrowaniem własnego dysku. Ale jeśli plik nie zostanie znaleziony, szyfrowanie jest rozpoczynane.

Lista szyfrowanych rozszerzeń

Nie są szyfrowane oczywiście pliki – tylko te z rozszerzeniami pasującymi do whitelisty:

Szyfrowanie

Jak zwykle to najciekawsza część kodu każdego ransomware. Sage 2.0 szczególnie wyróżnia się pod tym względem, ponieważ szyfruje pliki korzystając z kryptografii krzywych eliptycznych.

Do szyfrowania użyta została krzywa eliptyczna postaci y^2 = x^3 + 486662x^x + x, z punktem bazowym x=9, określona nad ciałem skończonym zdefiniowanym przez liczbę pierwszą p = 2^255 – 19. Te wartości nie są wybrane przypadkowo – ta krzywa jest zwana również Curve25519 i należy do jednych z najnowocześniejszych współczesnych metod szyfrowania. Nie tylko jest to jedna z najszybszych krzywych eliptycznych, ale jest też mniej podatna na słabe generatory losowości. Została zaprojektowana przy uwzględnieniu możliwych ataków kanałem bocznym (side channel), unika wielu potencjalnych problemów implementacyjnych oraz (prawdopodobnie) nie ma backdoora stworzonego przez żadną trzyliterową agencję.

Klucz publiczny używany podczas generacji współdzielonego sekretu jest zapisany na stałe w próbce. Dokładny kod wygląda tak (struktury i funkcje nazwane przez nas):

Jest to prawidłowa implementacja protokołu krzywych eliptycznych Diffiego-Hellmana (ECDH), ale ponieważ klucze prywatne nie są nigdzie zapisywane, sekret może odzyskać jedynie strona będąca w posiadaniu klucza prywatnego serwera.

Funkcja ta może wyglądać skomplikowanie, ale prawie wszystkie jej składowe to funkcje opakowujące prymityw ECC – nazwany przez nas CurveEncrypt. Na przykład szukanie pasującego klucza publicznego to po prostu mnożenie przez punkt bazowy (który jest równy 9, czyli jeden bajt 9 i 31 zer):

Liczenie współdzielonego sekretu jest bardzo podobne, ale zamiast stałego punktu bazowego używamy klucza publicznego:

Z powodu własności Curve25519, konwertowanie między sekwencją dowolnych losowych bajtów i kluczem prywatnym jest bardzo proste – wystarczy maskować kilka bitów i ustawić jeden:

Dodatkowo z tego powodu generowanie klucza prywatnego jest trywialne (wystarczy wylosować 32 bajty i skonwertować je do klucza prywatnego):

To wszystko jeśli chodzi o generowanie klucza. Co z szyfrowaniem plików? Użyty jest algorytm ChaCha (to chyba pierwsza rodzina szyfrująca tym algorytmem, mimo że Petya używa bardzo zbliżonego algorytmu Salsa20), a klucz ChaCha jest dopisywany do końca pliku, po zaszyfrowaniu za pomocą Curve25519:

Gdzie funkcja AppendFileKeyInfo dokleja na koniec danych zaszyfrowany klucz oraz klucz publiczny:

Nie wiemy czemu została użyta ChaCha zamiast AES – prawdopodobnie to tylko próba wyróżnienia się albo paranoja przed wyimaginowanymi tylnymi furtkami agencji rządowych.

Podsumowując, istnieją dwa zbiory kluczy plus jedna para kluczy na każdy zaszyfrowany plik:

Kiedy ransomware kończy swoje operacje, znamy tylko my_public, sh_public, fl_shared, a potrzebujemy odzyskać chachakey żeby zdeszyfrować plik – nie zrobimytego bez znajomości prywatnych części.

Ten schemat szyfrowania jest dobrze przemyślany, ponieważ umożliwia szyfrowanie offline – nie ma potrzeby łączyć się z C&C i negocjowania kluczy szyfrujących. Wystarczy klucz publiczny, zapisany na stałe w programie. Zakładając że twórcy złośliwego oprogramowania nie popełnili drastycznych błędów implementacyjnych (a nie mamy powodu podejrzewać żeby to zrobili), odzyskanie zaszyfrowanych plików jest niemożliwe. Oczywiście zawsze jest możliwość, że klucze szyfrujące zostaną wcześniej upublicznione przez kogoś.

Dodatkowe informacje

Reguły Yara:

Hashe (sha256):

    • sample 1, 362baeb80b854c201c4e7a1cfd3332fd58201e845f6aebe7def05ff0e00bf339
    • sample 2, 3b4e0460d4a5d876e7e64bb706f7fdbbc6934e2dea7fa06e34ce01de8b78934c
    • sample 3, ccd6a495dfb2c5e26cd65e34c9569615428801e01fd89ead8d5ce1e70c680850
    • sample 4, 8a0a191d055b4b4dd15c66bfb9df223b384abb75d4bb438594231788fb556bc2
    • sample 5, 0ecf3617c1d3313fdb41729c95215c4d2575b4b11666c1e9341f149d02405c05

Więcej materiałów:

Nymaim atakuje ponownie

Data publikacji: 30/01/2017, Jarosław Jedynak

logo

Wstęp

Nymaim nie jest nową rodziną złośliwego oprogramowania – pierwszy raz został napotkany w 2013 roku. Wtedy był wykorzystywany jedynie jako dropper, używany głównie do dystrybucji TorrentLockera.

W lutym 2016 ponownie stał się popularny, po tym jak do jego kodu zostały dołączone fragmenty kodu ISFB, który wcześniej wyciekł. Zyskał wtedy przydomek „Goznym”. Ta inkarnacja Nymaima była dla nas szczególnie interesująca, ponieważ zyskała możliwości bankera i stała się poważnym zagrożeniem w Polsce. Z tego powodu przeprowadziliśmy dokładną analizę tego zagrożenia i byliśmy w stanie śledzić aktywność Nymaima od tamtego czasu.

Przez ostatnie dwa miesiące, wiele rzeczy się zmieniło. Przede wszystkim, sieć fast-flux nazywana „Avalanche” (wykorzystywana intensywnie przez Nymaima) została wyłączona na skutek skoordynowanych działań organów ścigania kilku krajów. Przez prawie dwa tygodnie Nymaim był zupełnie nieaktywny, a do dzisiaj jest cieniem tego czym był jeszcze niedawno. Mimo że jest ciągle aktywny w Niemczech (z nowymi injectami), dopiero niedawno powrócił do Polski.

Obfuskacja kodu

Ten temat został już dobrze opisany przez innych badaczy, ale ciągle jest na tyle interesujący, że warto o nim wspomnieć.

Kod Nymaima jest bardzo mocno zaciemniony za pomocą autorskiego narzędzia – do tego stopnia, że analiza jest prawie niemożliwa. Na przykład typowy kod wygląda tak:

Zostało tu użytych wiele technik utrudniających analizę, więc omówimy je po kolei:

Po pierwsze, rejestry procesora nie są umieszczane bezpośrednio na stosie, ale jest używana do tego pomocnicza funkcja push_cpu_register. Na przykład push_cpu_register(0x53) jest równoważna push ebx, a push_cpu_register(0x50) to push eax. Stałe odpowiadające rejestrom zmieniły się przynajmniej raz między wersjami, ale kolejność jest zawsze ta sama:

. register constant
0 eax 0x50
1 ecx 0x51
2 ebx 0x52
3 edx 0x53
4 esp 0x54
5 ebp 0x55
6 esi 0x56
7 edi 0x57

Dodatkowo, większość stałych jest obfuskowana. Na przykład mov eax, 25 może zostać zmienione na:

Stała użyta w przykładzie to 8CBFB5DA, ale to nie żadna reguła – to po prostu losowy dword, wygenerowany tylko na potrzeby zaciemnienia kilku stałych (zmienia się zawsze z wersji na wersję). Ważne jest tylko to, że po tej operacji rejestr eax będzie miał wartość taką jaką chcemy.

Poza xor_eax_with_X są też analogiczne podobne funkcje: sub_*_from_eax and add_*_to_eax.

Ostatecznie, przepływ sterowania jest mocno zmodyfikowany. Jest bardzo dużo metod wykorzystanych do utrudnienia analizy, ale wszystkie sprowadzają się do prostej podmiany: call X i jmp X są transformowane do przynajmniej dwóch operacji push i skoku gdzieś. Ta metoda jest bardzo podobna do technik wykorzystywanych przy ukrywaniu zmiennych – np. zamiast użyć adresu 0x42424242, skok wykonywany jest do funkcji detour z parametrami 0x40404040 oraz 0x02020202. W asemblerze, zamiast:

będziemy widzieć coś w rodzaju:

Istnieje też sprytna wariacja tej metody, gdzie detour zamiast dwóch argumentów przyjmuje jeden – wtedy kod maszynowy za opkodem call jest wykorzystywany jako stała (inaczej mówiąc, detour używa adresu powrotu wrzuconego przez call jako wskaźnika do drugiej stałej).

Podsumowując, poprzednio wklejony przetworzony kod może być interpretowany w ten sposób:

Dysponując tą wiedzą, stworzyliśmy własny deobfuskator. Było to dość dawno temu i od tego czasu pojawiły się też inne rozwiązania. Nasze narzędzie niekoniecznie działa najlepiej, ale ma kilka unikalnych (z tego co wiemy) funkcji, których potrzebujemy, np. odzyskiwanie importów i deszyfrowanie zaszyfrowanych napisów.

Inne narzędzia to na przykład mynaim i ida-patchwork.

Tak czy inaczej, za pomocą naszego narzędzia jesteśmy w stanie całkiem dobrze oczyścić kod:

Ale to nie wszystko co potrafi obfuskator Nymaima. Na przykład zewnętrzne funkcje nie są wywoływane bezpośrednio, zamiast tego używany jest skomplikowany wrapper:

Ten wrapper wrzuca hash z nazwy funkcji na stos i skacze do kolejnego (mimo że użyty jest opkod call, nigdy nie wykonywany jest ret to tego adresu):

Drugi dispatcher wrzuca hash nazwy dll na stos i skacze do pomocniczej funkcji:

Ostatecznie wykonywany jest prawdziwy dispatcher:

Dodatkowo prawdziwy adres powrotu z API jest obfuskowany – wskazuje on na call ebx gdzieś w bibliotece ntdll, a prawdziwy adres powrotu znajduje się wtedy w ebx. Większość narzędzi zupełnie sobie z tym nie radzi. Bardzo utrudnia to śledzenie wykonania kodu.

Ale to nie wszystko. Tak jak widzieliśmy, krótkie stałe są obfuskowane przy pomocy prostych operacji matematycznych, ale co z dłuższymi stałymi, takimi jak np. napisy? Twórcy złośliwego oprogramowania również na to mają odpowiedź. Prawie wszystkie napisy użyte w programie są przechowywane w specjalnej sekcji danych. Kiedy Nymaim potrzebuje jednej z nich, używa specjalnej funkcji, którą nazwaliśmy encrypted_memcpy. Jest dość prosta w swoim działaniu:

Samo memcpy_and_decrypt też nie jest skomplikowane. Nasza wersja tej funkcji w Pythonie ma jedynie kilka linijek kodu:

Potrzebujemy tylko wyciągnąć stałe użyte do deszyfrowania (różnią się między programami) – są ukryte w tych kawałkach kodu.

(Te funkcje nigdy nie są zaciemniane, więc możemy wyciągnąć te stałe za pomocą prostego pattern matchingu).

Ale ukrywanie stałych to nie wszystko – okazjonalnie szyfrowany jest również kod. Nie zdarza się to często, ale kilka krytycznych funkcji jest przechowywanych w postaci zaszyfrowanej cały czas, poza chwilą ich wywołania. Dość ciekawe podejście, trzeba przyznać.

Zostawiając temat obfuskacji za sobą, co więcej możemy powiedzieć o Nymaimie:

Statyczna konfiguracja

Po potraktowaniu deobfuskatorem kod jest znacznie prostszy do analizy i możemy zająć się bardziej interesującymi rzeczami. Po pierwsze, chcielibyśmy wyciągnąć statyczną konfigurację z próbek, szczególnie rzeczy takie jak:

    • adresy serwerów C&C
    • hashe DGA
    • klucze używane do szyfrowania
    • wersję malware
    • inne rzeczy potrzebne do nawiązania komunikacji

Okazuje się to być trudniejsze niż się wydaje – ponieważ te informacje nie są przechowywane podobnie jak zwykłe stałe, a wykorzystywany jest inny mechanizm. Na szczęście, tym razem algorytm szyfrowania jest prosty:

Musimy tylko wywołać funkcję nymaim_config_crypt na początku zaszyfrowanej statycznej konfiguracji.

Pozostaje ostatnia rzecz – jak znaleźć miejsce gdzie zaczynają się szukane dane? Spróbowaliśmy kilku metod (dopasowywanie kodu, charakterystyczne miejsca itp.), ale nie były wystarczająco niezawodne jak na nasze potrzeby. Dlatego użyliśmy najprostszego możliwego rozwiązania – próbujemy deszyfrować zaczynając od każdego możliwego miejsca w pamięci. Dodając do tego kilka trywialnych heurystyk (przewidywanie wielkości i zawartości wyniku), jest to dość szybkie rozwiązanie (poniżej 1s na typowym programie) i działa zawsze.

Co znajduje się w zdeszyfrowanej konfiguracji? Wynikowa struktura jest dość prosta w parsowaniu. Składa się z wielu następujących po sobie kawałków danych, z których każdy ma swój typ, długość i dane (poza brakiem paddingu jest to format zgodny z RIFF (Resource Interchange File Format), chociaż raczej nie był to cel twórców):

Graficznie wygląda to mniej więcej tak:

Kawałki te są położone jeden po drugim:

Więc możemy szybko przejść przez nie wszystkie w kilku linijkach języka Python:

Fragment funkcji process_chunk (gdzie hash to typ)

Po wstępnym parsowaniu wynik wygląda tak:

static config example

(Swoją drogą, w tym artykule typy kawałków – chunków są reprezentowane w kolejności bajtów, czyli big endian)

W bardziej czytelnej dla człowieka postaci po interpretacji ciekawych fragmentów:

static config example

Przebieg infekcji

Jest więcej niż jeden gatunek Nymaimów. W tym momencie rozróżniamy trzy rodzaje:

    • dropper – pierwszy Nymaim, który jest wykonywany w systemie. To jedyny typ rozprowadzany bezpośrednio do ofiar (na przykład przez złośliwe załączniki).
    • payload – moduł odpowiedzialny za większość operacji – na przykład web injecty. Pobierany przez payload.
    • bot_peer – moduł odpowiedzialny za komunikację P2P. Próbuje też zostać supernodem w botnecie.

To wszysto jedna rodzina malware – wszystkie współdzielą ten sam kod, ten sam obfuskator, ten sam format konfiguracji, ten sam protokół sieciowy i te same metody szyfrowania. Różnią się tylko kilkoma specjalizowanymi funkcjami.

Rola droppera jest prosta. Robi najpierw kilka testów, na przykład:

    • Upewnia się, że nie jest wirtualizowany/inkubowany
    • Porównuje obecną datę z „terminem ważności” zapisanym w konfiguracji
    • Sprawdza czy DNS działa poprawnie, odpytując serwery DNS o adresy microsoft.com i google.com

Jeśli coś jest nie tak, dropper zamyka się i proces infekcji komputera nie zachodzi.Szczególnie drugi test przeszkadza w analizie, ponieważ żeby zainfekować komputer trzeba mieć świeżą próbkę Nymaima – starsze programy nie zadziałają. Nawet jeśli dokona się patchowania tego sprawdzania w programie, jest to walidowane również po stronie serwera i payload nie będzie pobrany.

Żeby pobrać więcej danych od Nymaima, musimy znać adres IP peera albo C&C. Konfiguracja statyczna zawiera między innymi dwie przydatne tu informacje:

    • IP servera DNS (zawsze jest to 8.8.8.8 i 8.8.4.4).
    • Nazwa domeny serwera C&C (na przykład ejdqzkd.com albo sjzmvclevg.com).

Nymaim odpytuje o te domeny, ale zwrócone odpowiedzi nie są prawdziwymi adresami serwera C&C – są używane w kolejnym algorytmie żeby wyciągnąć faktyczne adresy IP. Nie będziemy reprodukować tutaj kodu, ale istnieje bardzo dobry artykuł na ten temat, opublikowany przez Talos. Kod samego DGA można znaleźć tutaj:

https://github.com/vrtadmin/goznym/blob/master/DGA_release.py

Kiedy dropper zdobywa adres serwera C&C, rozpoczyna prawdziwą komunikację. Pobiera kilka dodatkowych programów:

    • Payload – moduł odpowiedzialny za injecty. Łączy się z botnetem P2P, ale tylko pasywnie.
    • Opcjonalny bot (próbuje otwierać porty na routerze i stać się aktywnym elementem botnetu. Jeśli się to nie uda, usuwa się z systemu).
    • Kilka dodatkowych binarek (służących np. do wykradania haseł).

DGA

Payload bardzo różni się od droppera w kwestii komunikacji sieciowej:

    • Nie ma zapisanych na stałe domen
    • Ale ma zaimplementowane DGA
    • Oraz komunikację P2P

Algorytm DGA użyty tutaj jest prosty – znaki są generowane jeden po drugim, przy wykorzystaniu prostej pseudo-losowej funkcji (wariacji xorshifta). Początkowy stan DGA zależy wyłącznie od ziarna (ang. seed) przechowywanego w statycznej konfiguracji, więc możemy łatwo przewidzieć wartości DGA dla dowolnej próbki. Dodatkowo badacze z Talos wykonali przeszukiwanie metodą bruteforce prawidłowych seedów, upraszczając generowanie poprawnych domen jeszcze bardziej.

P2P

Po pierwsze, dlaczego podejrzewamy że Nymaim faktycznie korzysta z komunikacji P2P?

Zauważyliśmy że jedna z analizowanych binarek zachowuje się zauważalnie inaczej niż inne. Odpakowaliśmy ją wtedy i rozpoczęliśmy analizę. Szybko znaleźliśmy wiele rzeczy, które wyraźnie sugerowały komunikację P2P. Na przykład zaszyfrowane napisy, które typowo odpowiadają za dodawanie wyjątków do firewalla Windows:

Inne podejrzane zachowanie to otwieranie portów na routerze przy wykorzystaniu UPNP. W ten sposób pozwala zainfekowanym urządzeniom na całym świecie połączyć się do siebie.

Ostatecznie coś jeszcze bardziej wyróżniającego się. Zaobserwowaliśmy już wcześniej, że malware prezentuje się jako nginx w nagłówku Server. Skąd pochodzi ten nagłówek? Okazuje się, że prosto z samego Nymaima:

Zaimplementowaliśmy tracker botnetu, o którym napiszemy więcej za chwilę. Z informacji, które wyciągnęliśmy wynika, że Nymaim to jeden botnet, ale z geolokalizowanymi injectami. Na przykład injecty pobrane z Polski i z USA różnią się, ale możemy stwierdzić że napisane są przez tych samych aktorów. Rozkład adresów IP na świecie jest bardzo podobny do tego co ustalili inni badacze (poza tym że znaleźliśmy więcej węzłów w Polsce, a mniej w USA niż inni, ale to prawdopodobnie dlatego że nasze badania koncentrowały się na naszym obszarze działania).

49.9% (~7.5k) dostępnych publicznie węzłów, które znaleźliśmy znalazło się w Polsce, 30% (~4.5k) w Niemczech, a 15.7% (~2.2k) w USA.

Protokół sieciowy

Kolejną rzeczą do opisania jest protokół wykorzystywany przez Nymaim do komunikacji. To przykład typowego żądania sieciowego:

    • Wartośc nagłówka Host jest brana ze statycznej konfiguracji
    • Nazwa zmiennej POST i ścieżka w URL są randomizowane i nie mają znaczenia
    • Wartośc zmiennej POST to zaszyfrowane zapytanie (zakodowany dodatkowo za pomocą base64)
    • User-Agent i reszta nagłówków jest generowana przez WinHTTP (więc nagłówki nie są zbyt unikalne i nie da się rozpoznawać łatwo Nymaima za pomocą płytkiej analizy ruchu sieciowego).

A to typowa odpowiedź:

    • Tak naprawdę to oczywiście nie nginx, tylko zapisane na stałe nagłówki
    • Wszystko poza sekcją danych jest zapisane w programie
    • Dane to zaszyfrowany request

Zaszyfrowana wiadomość ma bardzo specyficzny format: Dolna połowa pierwszego bajtu jest równa długości soli, a dolna połowa drugiego bajtu jest równa długości paddingu. Wszystko pomiędzy solą a paddingiem to zaszyfrowana za pomocą algorytmu RC4 wiadomość. Kluczem jest klucz sklejony z solą.

Po przeprowadzeniu analizy tego algorytmu możemy łatwo go odwrócić:

Po odszyfrowaniu wiadomości ponownie dostajemy format bardzo podobny do statycznej konfiguracji (tzn.sekwencja następujących po sobie kawałków danych – chunki):

Każdy kawałek ma swój typ, długość i właściwe dane:

Możemy przetworzyć zaszyfrowaną wiadomość używając praktycznie takiego samego kodu jak ten do statycznej konfiguracji:

I to właściwie cały kod potrzebny do parsowania wiadomości. Każdy typ chunka ma inną zawartość i musi być przetwarzany w trochę inny sposób.

Co ciekawe, wiadomości trzeba parsować rekurencyjnie, ponieważ niektóre typy chunków zawierają kolejne, zagnieżdżone listy, które mogą z kolei zawierać kolejne listy itd. Niestety, żeby dostać się do najciekawszych danych, musimy pokonać jeszcze jedną warstwę – szyfrowanie i kompresję. Niektóre typy chunków są zaszyfrowane za pomocą kolejnego mechanizmu. Takie chunki na końcu danych mają specjalny nagłówek, podpisany za pomocą RSA. Po zdeszyfrowaniu (technicznie: po zdjęciu cyfrowego podpisu, bo robimy to kluczem publicznym) znajdujemy tam md5 i długość zaszyfrowanych danych – i przede wszystkim klucz użyty do zaszyfrowania właściwych danych:

Po zdeszyfrowaniu (za pomocą algorytmu Serpent), trafiamy na kolejną warstwę – dane są skompresowane przy pomocy APLIB32. Ta struktura jest bardzo podobna do tej używanej przez ISFB – najpierw mamy magiczny dword ‚ARCH’, później długość skompresowanych danych, dalej długość skompresowanych danych, a na końcu CRC32.

Ponownie z pomocą funkcji w języku Python możemy szybko poradzić sobie z tym problemem:

Korzystając z tej funkcji, nareszcie udało nam się zdeszyfrować wszystkie interesujące rzeczy przekazywane z serwera, w szczególności dodatkowe binarki, filtry sieciowe, oraz webinjecty.

Komunikacja

Przykładowe żądanie, po parsowaniu, może wyglądać tak:

Jak widać, przekazywane jest wiele danych identyfikujących komputer i trochę informacji o aktualnym stanie. Odpowiedzi potrafią być bardzo długie, ale dla uproszczenia przedstawmy jedną z prostszych opcji:

Zainfekowana maszyna poznaje swój publiczny adres IP, porty i adresy IP swoich peerów oraz aktywną domenę C&C. Dodatkowo dostaje polecenie spania kilkadziesiąt sekund (minimalnie 90 sekund podczas gdy rozsyłane są aktualizacje, 280 sekund kiedy nic się nie dzieje).

Lista typów chunków które rozumiemy i jesteśmy w stanie parsować:

typ krótki opis
ffd5e56e fingerprint 1
014e2be0 fingerprint 2 + aktualny czas
f77006f9 fingerprint 3
22451ed7 CRC32 ostatnio otrzymanych chunków be8ec514 i 0282aa05
b873dfe0 flaga mówiąca czy serwer jest aktywny
0c526e8b zagnieżdżona lista chunków (należy zdeszyfrować używając nymaim_config_crypt, odpakować APLIB32 i sparsować)
875c2fbf niezaszyfrowany program wykonywalny
08750ec5 zagnieżdżona lista chunków (należy zdeszyfrować używając nymaim_config_crypt, odpakować APLIB32 i sparsować)
1f5e1840 web injecty (należy zdeszyfrować Serpentem, odpakować APLIB32, sparsować format injectów ISFB)
76daea91 handshake, którego używa dropper podczas nawiązywania połączenia
be8ec514 lista adresów IP peerów
138bee04 lista adresów IP peerów
1a701ad9 zaszyfrowana binarka (należy zdeszyfrować algorytmem Serpent, odpakować APLIB32, zapisać)
30f01ee5 zaszyfrowana binarka (należy zdeszyfrować algorytmem Serpent, odpakować APLIB32, zapisać)
3bbc6128 zaszyfrowana binarka (należy zdeszyfrować algorytmem Serpent, odpakować APLIB32, zapisać)
39bc61ae zaszyfrowana binarka (należy zdeszyfrować algorytmem Serpent, odpakować APLIB32, zapisać)
261dc56c zaszyfrowana binarka (należy zdeszyfrować algorytmem Serpent, odpakować APLIB32, zapisać)
a01fc56c zaszyfrowana binarka (należy zdeszyfrować algorytmem Serpent, odpakować APLIB32, zapisać)
76fbf55a padding
cae9ea25 zagnieżdżona lista chunków (należy zdeszyfrować używając nymaim_config_crypt, odpakować APLIB32 i sparsować)
0282aa05 zagnieżdżona lista chunków (należy zdeszyfrować używając nymaim_config_crypt, odpakować APLIB32 i sparsować)
d2bf6f4a informacje o stanie bota
41f2e735 filtry sieciowe
1ec0a948 filtry sieciowe
18c0a95e filtry sieciowe
3d717c2e filtry sieciowe
8de8f7e6 termin ważności? (nie jesteśmy pewni zastosowania, zawsze jest kilka dni naprzód od aktualnej)
3e5a221c lista dodatkowych binarek które zostały pobrane
5babb165 handshake używany przez payload podczas nawiązywania połączenia
b84216c7 publiczne IP zainfekowanej maszyny
cb0e30c4 liczba sekund, które ma spać zainfekowana maszyna
f31cc18f CRC32 dodatkowych zainfekowanych binarek
920f2f0c web injecty (należy zdeszyfrować algorytmem Serpent, odpakować APLIB32, sparsować format injectów ISFB)
930f2f0c web injecty (należy zdeszyfrować algorytmem Serpent, odpakować APLIB32, sparsować format injectów ISFB)

To już wydaje się być dużo, a i tak pomijaliśmy większość chunków których nawet nie próbowaliśmy analizować (np. zignorowaliśmy większość czterobajtowych bloków, albo tych które zawsze były równe zero).

Po ekstrakcji wszystkiego z komunikacji, możemy w końcu popatrzeć na injecty. Na przykład polskie:

(304 różne injecty, na dzień pisania tego artykułu)

Albo te z USA:

(393 różne injecty, na dzień pisania artykułu)

Inne zasoby

Regułki Yara:

Hashe (md5):

    • Payload 2016-10-20, 9d6cb537d65240bbe417815243e56461, wersja 90032
    • Dropper 2016-10-20, a395c8475ad51459aeaf01166e333179, wersja 80018
    • Payload 2016-10-05, 744d184bf8ea92270f77c6b2eea28896, wersja 90019
    • Payload 2016-10-04, 6b31500ddd7a55a8882ebac03d731a3e, wersja 90012
    • Dropper 2016-04-12, cb3d058a78196e5c80a8ec83a73c2a79, wersja 80017
    • Dropper 2016-04-09, 8a9ae9f4c96c2409137cc361fc5740e9, wersja 80016

Repozytorium z naszymi narzędziami: nymaim-tools

Materiały dodatkowe:

Evil: prosty ransomware, napisany w języku JavaScript

Data publikacji: 18/01/2017, Jarosław Jedynak

hacker-1944688_960_720

Evil: prosty ransomware, napisany w języku JavaScript

Wstęp

Evil jest nową odmianą ransomware, którą pierwszy raz zaobserwowaliśmy ósmego stycznia 2017 roku – wtedy został nam zgłoszony pierwszy incydent z nią związany. Było to wtedy zupełnie nowe zagrożenie i nie było na jego temat żadnych informacji dostępnych publicznie. Nie mieliśmy też żadnych próbek do analizy.

Pierwszą działającą próbkę zdobyliśmy dzień później, dziewiątego stycznia. W tym artykule opiszemy w skrócie naszą analizę i wnioski. Od tamtej porty dostaliśmy relatywnie dużo raportów o infekcji, więc istnieje ryzyko, że ta rodzina stanie się większym zagrożeniem w przyszłości.

Evil nie ma żadnego panelu służącego do deszyfrowania (podobnie jak np. CryptoMix) – zamiast tego dostarczany jest adres email twórców, pod który należy się skontaktować.

Czytaj więcej

Analiza techniczna rodziny CryptoMix/CryptFile2

Data publikacji: 04/01/2017, Jarosław Jedynak

skull and crossbones malware

Kampania

CryptoMix to kolejna rodzina ransomware która próbuje zdobyć pieniądze dla swoich twórcow przez szyfrowanie plików ofiar i wymuszanie na nich okupu za odszyfrowanie ich.
Do niedawna była znana bardziej jako CryptFile2, ale z nieznanych nam powodów została rebrandowana i teraz jest rozpoznawalna jako CryptoMix.
Została zaobserwowana niedawno jako malware serwowane przez Rig-V exploit kit.

Ten malware wyróżnia się na tle innych popularnych odmian, ale niekoniecznie pozytywnie.

Czytaj więcej

TorrentLocker: złośliwa faktura za telefon

Data publikacji: 24/10/2016, Paweł Srokosz

Na początku października otrzymaliśmy zgłoszenie o kolejnej kampanii spamowej, wymierzonej w klientów sieci Play i dystrybuującej oprogramowanie ransomware. Rozsyłane maile mają postać fałszywych faktur, z załączonym skryptem JS, który pobiera i uruchamia złośliwe oprogramowanie, znane pod nazwą TorrentLocker (określanym również jako Crypt0L0cker).

Czytaj więcej