Sprawdzamy, jak działa trojan z maili "od DHL". Są groźne nowości
Dostałeś maila o zwrocie od DHL i kliknąłeś? Jeśli stało się to w ostatnich dniach, nie przejmuj się. Przeanalizowaliśmy go i daliśmy znać, komu trzeba. Jest już nieszkodliwy.
Bardzo częstą opinią dotyczącą wiadomości z wirusami w plikach Microsoft Office jest stwierdzenie, że nie warto zajmować się takimi bzdurami. Że przecież nikt nie otworzy tak kiepsko podrobionych wiadomości. A nawet jeśli otworzy, to na pewno nie zezwoli na uruchamianie zawartości aktywnej, przed którą chroni krzykliwy żółty pasek "nie rób tego".
Tymczasem według tegorocznego badania Agencji Badań Rynku i Opinii SW Research, 30 proc. Polaków nie wie, co to phishing. Ba - kolejne 32%... nie jest pewne, czy wie.Dlatego postanowiliśmy wziąć na tapet ostatnią kampanię makrami pakietu Office w tle.
Takie maile są częstym problemem w firmach, a niektórych niuansów technicznych nie da się wytłumaczyć żadnym szkoleniem. Ponadto, podejście "nie otwierać żadnych podejrzanych wiadomości" to mrzonka i prosty sposób na sparaliżowanie biznesu, porównywalny w swych stratach do uruchomienia wirusa.
Skuteczność takich ataków phishingowych widać po tym, że opłaca się tworzyć kolejne jej warianty. To, co było wysyłane przez ostatnie kilka dni, jest w dodatku dowodem na to, że opłaca się inwestować również ze wzrost złożoności pierwszej części ataku, czyli dokumentu. Nie minął dzień od naszego artykułu o usprawnieniach w dostarczaniu wirusów, a na polskich skrzynkach pocztowych rozpanoszył się wirus znacznie, znacznie bardziej skomplikowany od wszystkich swoich poprzednich wcieleń.
Etap I: nowy dokument
Atak w dalszym ciągu jest oparty o mechanizm makr pakietu Office. Korzysta on jednak z pewnej intrygującej cechy podsystemu makr, dzięki której zapoznanie się z jego treścią jest niemożliwe.
Makro dokumentu pakietu Microsoft Office jest tak naprawdę... projektem programistycznym Visual Studio '98! To nie pomyłka. Środowisko programowania makr, uruchamiające edytor Visual Basic, to odpowiednio zaadaptowany wariant antycznego programu Microsoft Development Environment w ponad dwudziestoletniej wersji. W programie tym założony zostaje nowy projekt języka Visual Basic. Nie jest to jednak ten sam Visual Basic, który jest dziś obecny w pakiecie .NET Framework.
Język ten, zwany VB.NET, jest następcą innego, klasycznego języka, jakim był Visual Basic 6.0. Rozwój VB6 zatrzymał się w 1998 roku, a jego nowa wersja, VB.NET, nosiła numer 7.0, celem podkreślenia, że nowy język oznacza zerwanie z przeszłością. Klasyczne projekty w VB były już niemożliwe do założenia w nowym Visual Studio, a pakiet Office miał otrzymać mechanizm migracji makr napisanych w VB do VB.NET.
Z tym, że nigdy nie miało to miejsca. Model programowania makr, podobnie jak sam dokument Office, jest zbyt mocno zanurzony w koncepcjach innego środowiska obiektowego, czyli COM. Przeniesienie obiektów COM do środowiska .NET jest nietrywialne, dlatego Microsoft wylądował z koniecznością dalszego wspierania klasycznego języka Visual Basic i swojego IDE z 1998 roku. Jest ono dosłownie przekompilowywane z roku na rok i trwa w stanie zamrożenia. Wersja języka VB używanego w nim to obecnie 7.1.
Projekt Visual Studio '98 nie może jednak zostać zapisany w sposób klasyczny w postaci zbioru plików *.vbp, *.frm i *.bas. Muszą one być zawarte wewnątrz dokumentu. Ponieważ format Microsoft Office XML (DOCX, XLSX...) jeszcze wtedy nie istniał, projekt ten jest umieszczany wewnątrz dokumentu jako binarny "blob OLE". W podobny sposób jest on umieszczany w dokumentach XLSX. Po ich rozpakowaniu, w ładnej strukturze katalogów i plików XML, znajduje się element "vbaProject.bin". Jego rozpakować się już nie da.
Można go tylko przeglądać wewnątrz wbudowanego w Office okrojonego Visual Studio. Niestety, okazało się, że istnieje możliwość uszkodzenia strumienia OLE z makrem. Tak, aby kod był niemożliwy do przeglądania, ale wciąż działający. Właśnie z takim przypadkiem mamy tu do czynienia.
Na szczęście, istnieje pakiet oletools, napisany w języku Python 2, dzięki któremu da się rozłożyć strumień OLE na pliki, a następnie dołączyć je do samodzielnie stworzonego dokumentu, celem zapoznania z treścią.
Tym razem jest tylko jeden plik z kodem, w dodatku mało zaciemnionym, dzięki czemu da się przeczytać, jak działa (gdy wreszcie da się do wyświetlić!). Makro zaczyna się urokliwym testem:
If Application.LanguageSettings.LanguageID(msoLanguageIDUI) = 1045
Then Shell payload()
End If
Numer 1045 to identyfikator języka dla Polski. Co oznacza, że żaden inny kraj nie zostałby zaatakowany niniejszym dokumentem. Następnie, dla wartości z komórek w wierszach od 5 do 8 w kolumnach D i E, uruchamiany jest nieprzeciętnie skomplikowany translator, wyciągający bardzo długie polecenie.
Etap II: PowerShell
Polecenie to uruchamia, jak zwykle, PowerShella, ale czyni to w nowy sposób. Otóż nowy proces da się wywołać również poprzez instrumentację WMI. Przestrzeń WMI zawiera podprzestrzeń "Process", a ona z kolei, metodę "Create", przyjmującą jako parametr polecenie do wykonania. Jeżeli więc ktoś szukał Office'a wywołującego PowerShella, bez obaw! Excel wywołał tutaj niegroźny "WMIC.EXE", a więc program podpisany przez Microsoft, wszystko w porządku.
Z tym, że ten niewinny WMIC.EXE następnie uruchomił PowerShella. Co on robi? Otóż:
$decoded = [Io.MemoryStream][Convert]::FromBase64String($payloadString)
$decompressed = New-Object IO.Compression.DeflateStream( $decoded, [IO.Compression.CompressionMode]::Decompress )
$convertedToStream = New-Object System.IO.StreamReader( $decompressed, [Text.Encoding]::ASCII)
$convertedToString = $convertedToStream.ReadToEnd()
$convertedToString | Invoke-Expression
Tą bardzo ciekawą metodą, wymagającą długiego przygotowania, wyłuskiwany jest kod zaklęty w kodowaniu base64. Kod ten jest... skompresowanym strumieniem surowym pamięci(!), który następnie jest dekompresowany, rozkładany na łańcuch tekstowy ASCII i wywoływany jako kod PowerShella.
Korzystanie ze strumieni w taki sposób pozwala przechowywać w pamięci skompresowane dane bez konieczności zapisywania ich na dysk. Scenariusze użycia takiej metody są jednak drastycznie odmienne od przechowywania małych fragmentów kodu. Taka metoda zaciemnienia jest zupełnie nowa.
Etap III: kolejny PowerShell
Rozłożony kod ($convertedToString) okazał się... robić to samo, co poprzedni, ale w jeszcze bardziej zaciemniony sposób: dekompresuje on strumień pamięci i wywołuje jako kod. Co jest owym kodem? Otóż kolejny PowerShell! To już było coś zupełnie niespotykanego.
Niestety, otrzymany wynalazek był tak strasznie zaciemniony, że nawet rozłożenie go na poprawny, niezaciemniony kod, nie pozwalało łatwo stwierdzić, co tak naprawdę robi. Wiadomo było, że pobiera nowy plik z serwera pod domeną kupioną na początku miesiąca, odpytując serwer za pomocą unikatowego żądania stworzonego z numeru seryjnego dysku twardego. Istotnie, zależnie od numeru dysku, otrzymywany plik był inny.
Etap IV: jeszcze jeden PowerShell
Żeby otrzymać wynikowy plik, należało uruchomić skrypt, jego rozkładanie po kawałku było już niemożliwe. Z pomocą przyszedł tu PowerShell na Linuksa, gdzie przeprowadzanie eksperymentów nie wiązało się z ryzykiem wykonania szkodliwego kodu. Co więc dzieje się z pobranym plikiem? Okazuje się on być strumieniem tekstowym, ale niezapisanym w base64. Pozornie to nonsensowny łańcuch drukowalnych znaków ASCII. Funkcja dopiero przerabia go na base64, dokonując substytucji znaków i przesunięć bitowych.
Otrzymany kod base64, przetłumaczony na dane źródłowe, dalej okazuje się być plikiem binarnym! Ale to jeszcze nie nasz wirus. To po prostu plik skompresowany algorytmem GZip. Co ciekawe, PowerShell potrafi dekompresować pliki i obiekty(!) skompresowane przez GZip, na Windowsie również. Skorzystano tu z owej mało znanej funkcji, w dodatku bez zapisywania pliku na dysk (żaden nowy binarny plik jeszcze nie pojawił się u ofiary).
Odpakowanie pliku pozwala znowu otrzymać plik tekstowy. Zawiera on jednak bardzo dużo powtórzonych łańcuchów, które są z niego usuwane. Łańcuch ten jest odmienny dla każdego nowego pobranego pliku. Usunięcie go pozwala dokopać się wreszcie do bardzo długiego base64. PowerShell ma go zapisać do pliku *.vbe i wykonać domyślną operację Eksploratora, jaką w ich przypadku jest... wykonanie kodu.
Etap V: Brusha Loader
Tutaj nowości powoli się kończą. Skrypt VBE, który udało się wykopać z wnętrza pobranego dziwadła to już zwykły downloader, działajacy tak samo, jak w przypadku ostatniej dystrybucji Emoteta. Skrypt okresowo prosi zdalny serwer o próbkę kodu i wykonuje ją, zaciągając komputer do botnetu.
Tym razem Brusha Loader nie wykonuje kodu od razu. Dokonuje on przejęcia konsoli Zarządzanie Komputerem, aby dokonać podniesienia uprawnień do poziomu Administratora i dopiero wtedy próbuje. Ponownie przed czymś takim uchroni nas podniesienie suwaka Kontroli Konta Użytkownika na samą górę, co jest zawsze dobrym pomysłem.
W końcu wśród pobranych plików znajduje się DLL z właściwym trojanem. Nie jest to jednak ani Emotet ani Danabot, tylko coś jeszcze nowszego.
Etap VI: nowy trojan
Trojan naturalnie wykrywa uruchomienie w maszynie wirtualnej na którymś etapie swojego działania, ponieważ kończy pracę dość szybko, ale nie od razu. Możliwe, że usiłuje ukryć się przed automatycznymi analizatorami, działając z opóźnieniem, poprzez dodanie się do listy automatycznego uruchomienia.
Wiadomo jednak, że wstrzykuje się do innych procesów, gwarantując sobie trwałą pracę oraz możliwość kamuflowania swojego działania pod innymi nazwami. Dzięki temu może prowadzić szkodliwe działania jako np. Explorer.exe, co nie wzbudza podejrzeń na liście procesów.
Takiego wirusa da się znaleźć na dysku (pobrano wszak plik DLL), ale o wiele trudniej wykryć go w działaniu. Jeżeli kogoś interesuje, w jaki sposób możliwe jest infekowanie cudzych procesów w systemie oferującym ochronę pamięci, polecam zapoznanie się z mechanizmem "process hollowing" (drążenie procesów), opisanym w ramach konferencji Black Hat.
Przyszłość
Plik został zgłoszony do CERT-u. Kilka godzin później dostępne już było obwieszczenie, informujące o zagrożeniu. Choć skala zaciemnienia rośnie z każdym tygodniem, a mechanizmy indywidualizacji ataku stają się coraz bardziej rozbudowane, kilka elementów pozostaje niezmiennych. Trudno całkowicie wyeliminować zawartość binarną, w postaci pobranego pliku DLL. Oznacza to, że nawet nieobecność na liście procesów nie oznacza braku śladów. Zaktualizowany skaner w pewnym momencie natknie się na taki plik i włączy alarm. Być może wkrótce czekają nas bezplikowe wirusy, jak to miało miejsce lata temu, w czasach dyskietek?