Preorder drugiego tomu książki sekuraka: Wprowadzenie do bezpieczeństwa IT. -15% z kodem: sekurak-book

Deobfuskacja JavaScript – część trzecia

09 września 2015, 09:40 | Teksty | 1 komentarz
W trzeciej części serii o deobfuskacji JavaScriptu zajmiemy się omówieniem dodatkowych narzędzi, które mogą być stosowane równolegle do omawianego wcześniej JSDetox.

Dla przypomnienia: pierwsza część cyklu o deobfuskacji JavaScript, druga część.

Przypomnijmy sobie zatem zobfuskowany JavaScript, który służył nam za przykład w pierwszej części artykułu

<script>
eval(function(p,a,c,k,e,d){e=function(c){return c.toString(36)};if(!''.replace(/^/,String)){while(c--){d[c.toString(a)]=k[c]||c.toString(a)}k=[function(e){return d[e]}];e=function(){return'\\w+'};c=1};while(c--){if(k[c]){p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c])}}return p}('g 6=["\\t\\u\\j","\\w\\n\\f\\j","\\i\\k\\h","\\q\\9\\9\\k","\\r\\l\\l\\8\\8\\8\\i","\\h\\m\\o\\f\\9\\s\\m\\v"];g 7=[6[0],6[1],6[2],6[3],6[4],6[5]];a=7[0];b=7[1];c=7[2];d=7[3];e=7[4];p[7[5]]=d+e+a+b+c;',33,33,'||||||_0x3725|_0x64df|x77|x74||||||x61|var|x6C|x2E|x6B|x70|x2F|x6F|x72|x63|document|x68|x3A|x69|x73|x65|x6E|x75'.split('|'),0,{}))
</script>

Ten sam kod spróbujemy przetestować na dwóch innych narzędziach, które znane są z możliwości analizy JavaScriptu. Następnie przetestujemy również jedno zobfuskowane przekierowanie do Exploit Kitu oraz obfuskowany JavaScript w kampanii phishingowej. Do dzieła!

Revelo

Na stronie Kahu Security możemy pobrać Windowsowy program Revelo. Według opisu program potrafi przeprowadzić deobfuskacje używając różnych technik oraz posiada wbudowany upiększacz kodu, proxy oraz firewall. Brzmi obiecująco. Przejdźmy zatem do analizy kodu z pierwszego listingu.

Foto1. Revelo bez problemu radzi sobie z przykładowym zobfuskowanym kodem

Foto1. Revelo bez problemu radzi sobie z przykładowym zobfuskowanym kodem

Efekt będzie bardziej niż zadowalający. Wystarczy załadować wybrany kod, otoczyć go tagami <script> i uruchomić przyciskiem execute. Revelo sprawnie symuluje uruchomienie JavaScriptu i informuje użytkownika, że skrypt próbuje uzyskać dostęp do strony www.sekurak.pl. Tool od Kahu Security pozwala także modyfikować kod w trakcie emulacji, co może przydać się w trakcie analizy bardziej zaawansowanych skryptów. Przykładem może być opcja “Redirect Eval to Action”, która wyłuska kod przesyłany do funkcji eval() i przedstawi go użytkownikowi w zakładce Results (funkcjonalność zbliżona do Show Code -> Send to Analyze w JSDetox).

Zobaczmy jak Revelo sprawdzi się analizując prawdziwy malware.

UWAGA! Złośliwy kod powinien być analizowany w wirtualnym, izolowanym środowisku.

Za przykład posłuży nam tym razem Nuclear Exploit Kit. Pliki zip z kilkoma podsłuchanymi transmisjami możemy pobrać ze strony http://malware-traffic-analysis.net/2015/07/30/index.html. W tej analizie skupimy się na skrypcie, który znajduje się w 146. pakiecie pliku 2015-07-29-BizCN-gate-actor-Nuclear-EK-traffic.pcap.

Ładujemy zatem plik do Revelo, dodajemy tagi <script> (można zrobić to automatycznie z poziomu górnego menu Options), klikamy Execute i przy odrobinie szczęścia otrzymamy okienko pop-up z adresem url, do którego dostać się próbuje złośliwy skrypt. Ta sama informacja pojawi się również w zakładce Traffic Log oraz Traffic Detail. Jeśli zechcemy symulacje powtórzyć możemy jeszcze raz kliknąć w przycisk execute lecz… tym razem nic się nie wydarzy. Aby dowiedzieć się skąd wynika ten stan rzeczy przejdźmy do zakładki Tools. W okienku Session Cookies pojawiła się wartość “gKYCABxdieSkjDTL”, której wcześniej tam nie było. Jeśli wyszukamy jej w zobfuskowanym kodzie możemy śmiało stwierdzić, że oryginalny JavaScript sprawdza zawartość pewnego pliku cookie zanim przekieruje użytkownika na złośliwą stronę www.

Foto2. Ustanowione przez Revelo cookie sesyjne. Pod spodem widoczny oryginalny kod JS z zaznaczonymi fragmentami, gdzie owe cookie się pojawia

Foto2. Ustanowione przez Revelo cookie sesyjne. Pod spodem widoczny oryginalny kod JS z zaznaczonymi fragmentami, gdzie owo cookie się pojawia

Spróbujmy zatem “upiększyć” kod, na co pozwala wbudowany w Revelo formater kodu. Okienko upiększacza wywołujemy z zakładki Tools, a po odpowiednim sformatowaniu kod możemy przesłać do głównego okna przy pomocy przycisku “Copy to Main”. Co ciekawe Revelo na swój sposób próbuje zmienić również tagi <script> wstawiając niepotrzebne spacje i modyfikując je do postaci < script >, czego potem nie potrafi zinterpretować.

Foto3. Upiększanie kodu wewnątrz Revelo. Zaznaczony przerobiony tag <script>, który po upiększeniu staje się nieczytelny dla emulatora JS.

Foto3. Upiększanie kodu wewnątrz Revelo. Zaznaczony przerobiony tag <script>, który po upiększeniu staje się nieczytelny dla emulatora JS.

Po upiększeniu możemy wyszukać wspomnianego ciągu „gKYCABxdieSkjDTL”, który odpowiada za cookies. Przeszukiwanie skryptu dostępne jest w zakładce Tools, ale należy mieć na uwadze, że powrót do początku dokumentu realizuje się przyciskiem Reset. Po przeszukaniu widać, że funkcja OnLgiyHrZEAfI() składa się z instrukcji warunkowej if, która zwraca true tylko w przypadku gdy cookie o zadanej nazwie jeszcze nie istnieje. Z drugiej strony funkcja OnLgiyHrZEAfI() jest warunkiem koniecznym do przejścia innej instrukcji if znajdującej się u dołu skryptu. Jeśli zatem przerobimy ją w ten sposób, aby zwracała wartość true za każdym razem, unikniemy problemu z tym, że emulacja kodu kończy się sukcesem tylko za pierwszym razem.

Foto 4. Przerobiona funkcja OnLgiyHrZEAfI(), która zawsze zwróci wartość true.

Foto 4. Przerobiona funkcja OnLgiyHrZEAfI(), która zawsze zwróci wartość true.

Revelo w zakładce Tools udostępnia jeszcze jedną opcję: Spoof User Agent. W założeniu autorów powinna ona zapewne służyć do symulacji odpowiedniego rodzaju i wersji przeglądarki w trakcie uruchamiania JavaScriptu. Niestety w wersji v0.6 nie działa to tak, jak powinno. Abstrahując od enigmatycznych opisów przeglądarek dostępnych na liście (np. MSIE (Old Version)), Revelo wydaje się być obojętne na jakiekolwiek zmiany. Jest to bug, który dość mocno utrudnia analizę, zwłaszcza, jeśli malware dedykowany jest dla konkretnej wersji przeglądarki internetowej.

Foto5. Pomimo wybrania z listy innego User Agenta przeglądarka widziana przez skrypty w Revelo to wciąż IE 7.0

Foto5. Pomimo wybrania z listy innego User Agenta przeglądarka widziana przez skrypty w Revelo to wciąż IE 7.0

Revelo wydaje się być nieco mniej elastyczne i przyjazne użytkownikowi niż JSDetox. Jego zaletą jest łatwość emulacji bez żadnych zmian w kodzie (ten sam kod w JSDetox trzeba było lekko zmodyfikować, aby symulacja w pełni się powiodła). Do plusów można zaliczyć także bez wątpienia zakładki Traffic Log oraz Traffic Detail, które mogą być pomocne w przypadku śledzenia wielu zapytań pochodzących z jednego skryptu. Przydatne mogą się okazać także różne funkcje modyfikowania kodu w trakcie uruchamiania. Główną wadą Revelo jest natomiast bardzo ograniczona komunikacja narzędzia z użytkownikiem. Używając Revelo nie można być pewnym czy to, że po kliknięciu element GUI nic się nie dzieje, jest efektem poprawnego wykonania się skryptu, czy też drobnym błędem twórców programu. Na dłuższą metę kłopotliwe staje się także dodawanie tagów <script> na początku i na końcu skryptów.

SpiderMonkey

SpiderMonkey to napisany w C silnik javascriptu. Jego ciekawą modyfikacje, wyposażoną w dodatkowe funkcjonalności przydatne przy analizie złośliwego kodu, opublikował Didier Stevens. SpiderMonkey dla systemu Linux działa w wieszu poleceń. Przeanalizujmy przy jego pomocy kod z pierwszego listingu. SpiderMonkey w wersji Didiera Stevensa nie wyświetla informacji na ekranie, ale tworzy pliki .log, które zawierają analizę wykonania się JavaScriptu. Ilość i nazwa plików log zależy od rodzaju funkcji, która jest emulowana.

Foto 6. Analiza JavaScript z poziomu command line

Foto 6. Analiza JavaScript z poziomu command line

W przypadku analizy kodu z pierwszego listingu SpiderMonkey stworzył dwa pliki log, które zawierają informacje o wywołaniach funkcji eval(). Jeden z tych plików zapisany jest w formacie ASCII (eval.001.log), a drugi w formacie Unicode (eval.001.uc.log). Plik logu wyświetla, jak sama nazwa wskazuje, argument przesyłany do funkcji eval(). Na tym jednak kończy się analiza. Niestety SpiderMonkey nie rozpoznał, że skrypt próbuje przekierować użytkownika na www.sekurak.pl, chociaż dalszą analizę można przeprowadzić chociażby w JSBeautifier, który przedstawi w czytelnej formie zakodowane znaki.

Foto 7. Dane wyjściowe ze SpiderMonkey w jsbeautifier

Foto 7. Dane wyjściowe ze SpiderMonkey w jsbeautifier

Zobaczmy jak SpiderMonkey sprawdzi się analizując prawdziwy malware.

UWAGA! Złośliwy kod powinien być analizowany w wirtualnym, izolowanym środowisku.

Do tej pory, w poprzednich edycjach cyklu artykułów o deobfuskacji JavaScript zajmowaliśmy się złośliwym skryptem ukrytym w przekierowaniach, bądź w osadzonych na stronach internetowych elementach. Tym razem przeanalizujemy JavaScript osadzony na stronie, na którą cyberprzestępcy zwabiali ofiarę za pomocą kampanii phisingowych (z JavaScriptem w phishingu można spotkać się także w kontekście załączników html, które po otwarciu wykonują złośliwy kod). W pliku pcap dostępnym na stronie http://www.malware-traffic-analysis.net/2015/01/13/index.html znajdują się trzy pliki JavaScript, przeanalizujmy pierwszy, dostępny w 39. pakiecie transmisji. Po otwarciu go w edytorze tekstu ukazuje się nam ogromna ilość znaków z ograniczonego zakresu symboli. Zobaczmy, co na to SpiderMonkey.

Foto 8. Uruchomienie SpiderMonkey na zakodowanym pliku JavaScript

Foto 8. Uruchomienie SpiderMonkey na zakodowanym pliku JavaScript

Mimo, że SpiderMonkey zapewne poprawnie zdekodował tajemnicze symbole, to w wyjściowym kodzie doszukał się funkcji setTimeout(), której nie potrafi zinterpretować. Można się tylko domyślać, że służy ona zapewne opóźnieniu wykonania wynikowego kodu bądź przekierowania, ale aby być tego pewnym należy zdekodować skrypt. Czytelnicy, który czytali pierwszą część artykułu mogą mieć skojarzenia z kodowaniem JSFuck, które było tam omawiane. W tym przypadku jednak autor strony malware-traffic-analysis.net podpowiada nam, że użyte zostało kodowanie jjencoding – pora więc znaleźć odpowiedni dekoder. Ten dostępny jest w jednym z projektów na githubie w postaci niemal 500-linijkowego pliku html z osadzonym JavaScriptem. Aby zdekodować skrypt należy zapisać projekt w postaci pliku html (najlepiej na wydzielonej do analizy malware maszynie wirtualnej), a następnie wkleić zawartość zobfuskowanego pliku jquery-1.14.94.js. Wynikowy kod będzie dużo bardziej czytelny i umożliwi nam dalszą analizę.

Foto 9. Kod po zdekodowaniu jjencoding i upiększeniu w jsbeautifier

Foto 9. Kod po zdekodowaniu jjencoding i upiększeniu w jsbeautifier

Na pierwszy rzut oka widać, że główna funkcja która będzie nas interesować znajduje się u góry kodu. Widać również domenę, ale warto dowiedzieć się jakie argumenty metody HTTP GET są przekazywane do kolejnego JavaScriptu. Poniżej w kodzie, zaczynając od linii 15 znajdują się dwa warunki, które w jakiś sposób (odwołując się do ruchów myszką oraz wspomnianego już wcześniej setTimeout()) uruchamiają w końcu główną funkcję szl7S7oV4MrlLKj(). Usuńmy wszystko zaczynając od linii 15, zastępując oba warunki wywołaniem wprost głównej funkcji szl7S7oV4MrlLKj() i przejdźmy do analizy przy pomocy SpiderMonkey.

Foto 10. Kod po uproszczeniu nadal jest niezrozumiały dla SpiderMonkey

Foto 10. Kod po uproszczeniu nadal jest niezrozumiały dla SpiderMonkey

SpiderMonkey będzie miał jeszcze drobne problemy z interpretacją elementów języka JavaScript, które są typowe dla przeglądarek (takie jak navigator.userAgent, screen.width, screen.height czy createElement). Aby przeskoczyć te niedogodności należałoby usunąć elementy typowo przeglądarkowe lub też, w przypadku gdy ich wartości przypisywane są do zmiennych, posłużyć się mniej lub bardziej losowym ciągiem znaków, który można następnie wyłuskać z parametrów GET url (canary word). Tak na prawdę niepotrzebny jest nam kod w liniach 8,9,10,12,13. Przypisanie wartości charakterystycznych dla przeglądarki w liniach 6 i 7 możemy zastąpić przypisaniem dowolnego łańcucha znaków, a linię 11 przerobić na funkcję document.write(). Po tych zabiegach powinniśmy być w stanie zasymulować skrypt w SpiderMonkey oraz zobaczyć jego wynik w pliki write.log

Foto11 Wynik działania SpiderMonkey

Foto11 Wynik działania SpiderMonkey

SpiderMonkey jest dość skutecznym emulatorem JavaScript, chociaż brakuje mu wsparcia dla paru podstawowych elementów (brak logowania chociażby document.location). Ma problemy z symulacją środowiska przeglądarki internetowej, chociaż każda linia kodu, która przerywała analizę i wymagała ręcznych poprawek stanowiła wyzwanie również dla JSDetox (JSDetox nie również nie zinterpretował funkcji setTimeout czy wartości screen). Brakuje funkcji upiększania kodu, ale SpiderMonkey może przydać się do stosowania równolegle z innymi narzędziami omawianymi w tej serii artykułów.

Linki

— Marcin Szymankiewicz

Spodobał Ci się wpis? Podziel się nim ze znajomymi:



Komentarze

  1. s

    No proszę, Firefox blokuje link do Revelo.
    This web page at http://www.kahusecurity.com has been reported to contain unwanted software and has been blocked based on your security preferences.

    Odpowiedz

Odpowiedz