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 systemu 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 systemu 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://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:
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 systemu 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ę:
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żeli 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ź.
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:
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/<></a>
This e-mail was sent by <span style="text-transform: uppercase;"><>
<></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, iż ten rodzaj zagrożenia pojawi się w przyszłych kampaniach.
Informacje dodatkowe
- Szczegółowa analiza Kaspersky’ego z 2015 roku (Emotet v2 i v3)
- Raport CERT Orange z 2014r. opisujący kampanię poprzedniej wersji Emoteta.
Analiza oparta jest na próbce c53956c95100c5c0ba342977f8fc44fcad35aabc24ec44cb12bb83eee1ed34fa
Lista skrótów MD5 modułów (widoczne 13 kwietnia):
5b2d58b4104309ee9c93b455d39c7314
722268bad0d3a2e90aa148d52c60943e
Lista adresów C&C
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:
MHwwDQYJKoZIhvcNAQEBBQADawAwaAJhAJ16QBv5Csq0eruFy4BvTcXmmIyeqUb3
vCCc8K/zOYOpL/Ww6FCdUpvPfs+RR/sLBalwtKmT14iRUaNmJdygnAKUIRWR1HNt
0rQRir0pD4QlkXlnZ9lZazTfyMV8BLCatwIDAQAB
-----END PUBLIC KEY-----
Reguły Yara:
{
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
}