XPAJ: Inżynieria wsteczna bootkita dla 64-bitowych systemów

SE7EN

Bardzo aktywny
Fąfel
Dołączył
27 Maj 2010
Posty
1124
Reakcje/Polubienia
114
XPAJ: Inżynieria wsteczna bootkita dla 64-bitowych systemów Windows

Wprowadzenie

Liczba bootkitów systematycznie rośnie. Pojawiają się wszystkie możliwe rodzaje nowych bootkitów: wyrafinowane, proste, służące różnym celom (np. rootkity lub trojany wymuszające okup). Twórcy szkodliwego oprogramowania nie zasypują gruszek w popiele i często analizują złośliwy kod tworzony przez swoich konkurentów.

W dzisiejszych czasach nie jest łatwo zaimponować nowym bootkitem ekspertowi ds. szkodliwego oprogramowania: infekcje sektora rozruchowego zostały dokładnie przestudiowane, a w internecie można znaleźć mnóstwo informacji na ten temat. Jednak, tym razem udało nam się trafić na osobliwy przypadek: szkodnika Xpaj - infekującego pliki, uzupełnionego funkcjonalnością bootkita i posiadającego możliwość działania na systemach operacyjnych Windows x86 i Windows x64. To, co wyróżnia szkodnika spośród innych zagrożeń, to operowanie na systemach Windows x64 z włączoną funkcją PatchGuard. Szkodnik robi to przy pomocy splicingu na poziomie jądra, w celu ochrony przed odczytem lub modyfikacją zainfekowanego sektora rozruchowego.

W niniejszym artykule przeanalizujemy działanie rootkita w systemie operacyjnym Windows 7 x64. Przypadek działania szkodnika w Windows x86 nie jest wart odrębnej analizy, ponieważ szkodnik w mniejszym lub większym stopniu wykorzystuje ten sam algorytm w obu wersjach systemu operacyjnego.


Ładunek testowy?

Z analizy tej samej modyfikacji wirusa Xpaj, przeprowadzonej przez specjalistów z firmy Symantec, można wyciągnąć następujące wnioski:

funkcja zarażania plików Xpaj nie infekuje 64-bitowych modułów wykonywalnych, w tym sterowników trybu jądra. Wirus infekuje tylko 32-bitowe pliki wykonywalne (.exe i .dll);
zainfekowane pliki nie posiadają mechanizmu samodzielnej replikacji;
kod wstrzyknięty z trybu jądra do 64-bitowej aplikacji powoduje jedynie wyświetlenie wiadomości o debugowaniu, nie robi nic poza tym.
Na podstawie powyższych wniosków i statystyk infekcji (patrz poniżej), można przypuszczać, że ten wariant wirusa jest tylko wersją testową. Kolejna modyfikacja szkodnika może być już w pełni funkcjonalna i, kto wie, być może twórcy zaimplementują w niej mechanizm infekowania 64-bitowych plików wykonywalnych wraz ze sterownikami trybu jądra (co będzie oczywiście wymagało wyłączenia sprawdzania podpisu cyfrowego).


Ładowanie

Jak zwykle, wszystko rozpoczyna się od zainfekowanego sektora MBR. Jak w prawie wszystkich poprzednich przypadkach, głównym celem zainfekowanego rekordu rozruchowego jest odczytanie dodatkowych sektorów i przekazanie im kontroli.

Dodatkowe sektory na końcu dysku zawierają moduły, które są ładowane przez bootkita, gdy jest to wymagane. Wszystkie moduły, za wyjątkiem pierwszego, są skompresowane z użyciem APLib.

Pierwszy moduł działa według następującego algorytmu:

odczyt oryginalnego, niezainfekowanego kodu MBR i zapisanie go w pamięci w miejscu zarażonego MBR;
przechwycenie przerwania 13h, które jest odpowiedzialne za operacje odczytu i zapisu sektorów dysku;
przekazanie kontroli do oryginalnego rekordu rozruchowego.
Po przekazaniu kontroli do oryginalnego MBR, system operacyjny będzie kontynuował inicjację. Podczas inicjacji plik jądra i wszystkie niezbędne składniki doczytywane są z dysku. Realizując przechwycenie przerwania bootkit oczekuje na odczyt pliku jądra, obliczając sumę kontrolną od początku pliku i sprawdzając niektóre pola w nagłówku.

Aby kontynuować inicjację bootkitu, twórcy szkodliwego oprogramowania wybrali metodę podobną do użytej w TDL-4, z jedyną różnicą polegającą na tym, że tym razem to plik jądra, a nie plik KDCOM.DLL, jest wybierany jako cel. Kiedy wykryta zostanie próba odczytu pliku jądra, bootkit zapisuje pierwsze 0x120 bajtów (licząc od początku pliku) i nadpisuje nagłówek przy pomocy swojego własnego kodu.

Zaloguj lub Zarejestruj się aby zobaczyć!

Rysunek 1. Modyfikowany nagłówek pliku jądra

Następnie bootkit znajduje wyeksportowaną funkcję o nazwie MmMapIoSpace i przechwytuje ją używając splicingu. Punkt zaczepienia prowadzi do kodu w nagłówku pliku jądra.

Zaloguj lub Zarejestruj się aby zobaczyć!

Rysunek 2. Przechwyt funkcji MmMapIoSpace

Oto jak wygląda prototyp funkcji:

Zaloguj lub Zarejestruj się aby zobaczyć!

Funkcja ta odwzorowuje adres fizyczny w pamięci wirtualnej. Pamiętajmy, że pierwszy moduł bootkita cały czas rezyduje w pamięci fizycznej gdy ta funkcja jest wywoływana po raz pierwszy.

Kontynuacja inicjacji bootkita następuje po wywołaniu przechwyconej funkcji.

Zaloguj lub Zarejestruj się aby zobaczyć!

Rysunek 3. Wywołanie stosu MmMapIoSpace

Przy pierwszym wywołaniu kod w nagłówku pliku jądra przywraca skradzione bajty funkcji MmMapIoSpace i wywołuje oryginalną funkcję, która odwzorowuje adres fizyczny pierwszego modułu bootkita (zobacz Rysunek 1 i Rysunek 5) w pamięci wirtualnej. Następnie kontrola jest przekazywana do odwzorowanego kodu.

Zaloguj lub Zarejestruj się aby zobaczyć!

Rysunek 4. Nagłówek pliku jądra

Zaloguj lub Zarejestruj się aby zobaczyć!

Rysunek 5. Wywołanie oryginalnej funkcji MmMapIoSpace i zawartości pamięci fizycznej

Kontynuacja inicjacji bootkita następuje po przekazaniu kontroli do mapowanej pamięci fizycznej.

Zaloguj lub Zarejestruj się aby zobaczyć!

Rysunek 6. Odwzorowany kod

Późniejsze działanie opiera się na następującym algorytmie:

- przywrócenie skradzionych 0x120 bajtów na początek pliku jądra;
- przechwycenie przerwania INT 0x01 (KiDebugTrapOrFault) dla każdego procesora;
- wyszukanie (po hashu) wyeksportowanej funkcji ZwLoadDriver;
- przechwycenie ZwLoadDriver przy użyciu splicingu;
- wyszukanie (po hashu) wyeksportowanej funkcji NtReadFile;
- przechwycenie NtReadFile przy użyciu splicingu;
- wyszukanie (po hashu) wyeksportowanej funkcji NtWriteFile;
- przechwycenie NtWriteFile przy użyciu splicingu;
- usunięcie punktu zaczepienia z przerwania INT 0x01 (KiDebugTrapOrFault) dla każdego procesora;
- wywołanie funkcji MmMapIoSpace z jej oryginalnymi parametrami, tzn. przekazanie kontroli do jądra w celu dalszej inicjacji systemu operacyjnego.

Zaloguj lub Zarejestruj się aby zobaczyć!

Rysunek 7. Punkt zaczepienia KiDebugTrapOrFault

Zaloguj lub Zarejestruj się aby zobaczyć!

Rysunek 8. Pierwszy etap przechwycenia ZwLoadDriver, NtReadFile i NtWriteFile

Dalsza inicjacja bootkita jest obsługiwana przez przechwyt funkcji ZwLoadDriver, ponieważ w pierwszym etapie pracy bootkita punkty zaczepienia NtReadFile / NtWriteFile są szkieletami, które przekazują kontrolę oryginalnym funkcjom i nie podejmują żadnych innych działań.

Zaloguj lub Zarejestruj się aby zobaczyć!

Rysunek 9. Szkielet funkcji NtReadFile

Oczywiście jest to specjalna "furtka" przygotowana, aby wstawić przez nią później kod pracy punktów zaczepienia funkcji NtReadFile / NtWriteFile.

Bootkit kontynuuje inicjację po pierwszym wywołaniu funkcji ZwLoadDriver.

Przechwyt funkcji ZwLoadDriver zachodzi na podstawie poniższego algorytmu:

- otwarcie odsyłacza "\??\physicaldrive0";
- odczytanie sektorów dysku zawierających trzeci moduł;
- ekstrakcja APLib;
- przekazanie kontroli do punktu wejścia trzeciego modułu;
- wywołanie oryginalnej funkcji ZwLoadDriver.

Co ciekawe, kiedy wywołany zostanie punkt zaczepienia ZwLoadDriver, funkcja jest flagowana jako wywołana - jeszcze przed otwarciem symbolicznego odsyłacza "\??\physicaldrive0". Jeżeli punkt zaczepienia zostanie ponownie wywołany, kontrola jest po prostu przekazywana do oryginalnej funkcji. Zauważmy, że odsyłacz pojawia się w systemie tylko na pewnym etapie inicjacji systemu operacyjnego. A więc, jeśli funkcja ZwLoadDriver zostanie wywołana przez dowolny sterownik na odpowiednio wczesnym etapie uruchamiania systemu operacyjnego - zanim odsyłacz zostanie utworzony - dalsza inicjacja bootkita może zostać zatrzymana!

Trzeci moduł, do którego przekazywana jest kontrola, kończy inicjację bootkita w systemie.

Zaloguj lub Zarejestruj się aby zobaczyć!

Rysunek 10. Główna funkcjonalność trzeciego modułu

Trzeci moduł wykonuje następujące działania:

- ładuje różne ustawienia;
- ustawia funkcję zwrotną, która zostanie wywołana po utworzeniu procesu;
- ustawia funkcję zwrotną, która zostanie wywołana po załadowaniu modułu do pamięci;
- zastępuje szkielety punktów zaczepienia NtReadFile / NtWriteFile ich funkcjonalnymi wersjami.

Zaloguj lub Zarejestruj się aby zobaczyć!

Rysunek 11. Funkcjonalna wersja punktu zaczepienia NtReadFile

Porównajmy punkt zaczepienia funkcji NtReadFile na Rysunku 11 z Rysunkiem 9.

Jest oczywiste, że punkty zaczepienia NtReadFile / NtWriteFile są niezbędne do ochrony przed odczytem i modyfikacją krytycznych obszarów bootkita.


Funkcje zwrotne

Podczas inicjacji bootkita instalowane są dwie funkcje zwrotne.

Pierwsza funkcja "zabija" wszystkie procesy antywirusowe. Kiedy funkcja jest wywoływana podczas tworzenia dowolnego procesu w systemie, bootkit na podstawie nazwy procesu oblicza sumę kontrolną i porównuje ją z własną wewnętrzną listą sum kontrolnych.

rusakov_butkit2012_pic12.png

Rysunek 12. Sumy kontrolne nazwy procesu

Jeśli suma kontrolna nazwy procesu pasuje do sumy kontrolnej na liście bootkita, bootkit ładuje instrukcję RET w punkt wejściowy procesu i proces jest przerywany.

Zaloguj lub Zarejestruj się aby zobaczyć!

Rysunek 13. Funkcja zakończenia procesu

Druga funkcja zwrotna jest wywoływana przez bootkit, gdy moduł jest ładowany do pamięci. Wykorzystywana jest do wstrzykiwania kodu w różne procesy, łącznie z procesami popularnych przeglądarek internetowych. Podobnie, jak w przypadku funkcji przerywającej procesy, funkcja ta oblicza sumę kontrolną z nazwy procesu i porównuje ją z wewnętrzną listą sum kontrolnych.

Zaloguj lub Zarejestruj się aby zobaczyć!

Rysunek 14. Funkcja wstrzyknięcia kodu

A co z PatchGuard?

Wspomnieliśmy wcześniej o mechanizmie ochronnym, zintegrowanym z jądrem 64-bitowego systemu operacyjnego Windows. Mechanizm PatchGuard został stworzony do przeciwdziałania modyfikacjom jądra systemu operacyjnego i jego krytycznych struktur, takich jak: różne tablice usług (SSDT, IDT, GDT), obiekty jądra itd. Mechanizm ochrony uaktywnia się na wczesnym etapie inicjacji jądra i co pewien czas skanuje powyższe struktury w poszukiwaniu wprowadzonych modyfikacji. Jeśli jakiekolwiek modyfikacje zostaną zidentyfikowane, wywoływana jest celowa awaria systemu. Mechanizm ten został zaprojektowany przede wszystkim do ochrony przed rootkitami trybu jądra. Niestety posiada poważną wadę: wiele aplikacji antywirusowych i produktów bezpieczeństwa wykorzystuje przechwyty na poziomie jądra do różnych legalnych celów, w tym do działania modułów ochrony proaktywnej.

Wciąż dochodzi do ostrej wymiany zdań w tej sprawie pomiędzy producentami rozwiązań antywirusowych i firmą Microsoft. Niektórzy twierdzą, że firmy antywirusowe nie powinny stosować nieudokumentowanych punków zaczepienia w jądrze systemu i do zatrzymania wniknięcia złośliwego kodu do jądra muszą być używane inne metody. Inni uważają, że Microsoftowi nie udaje się zapewnić wymaganego poziomu bezpieczeństwa i te punkty zaczepienia są niezbędne dla zwiększenia bezpieczeństwa systemu operacyjnego. Kolejna grupa twierdzi, że nie można zaufać systemowi, do którego jądra choć raz przeniknął złośliwy kod - i na nic zdaje się leczenie takich systemów. Wszystkie z tych opinii niosą sporo racji, lecz my nie będziemy dalej roztrząsać tego tematu.

Każde narzędzie ochrony można zhakować lub obejść, w ten czy inny sposób. PatchGuard nie jest tutaj żadnym wyjątkiem. Mechanizm ten został dokładnie zbadany zarówno przez niezależnych badaczy, jak i cyberprzestępców, i wynalezionych zostało kilka metod jego obejścia. Dla przykładu, TDL-4 używa metody koncepcyjnej, w której wykrycie punktu zaczepienia rootkita jest po prostu ignorowane przez mechanizm ochrony. Istnieją również inne metody, np. działające w oparciu o modyfikację programu ładującego i pliku jądra systemu operacyjnego, mające na celu wyłączenie inicjacji PatchGuarda. Jeszcze inna metoda opiera się na modyfikacji zainicjowanego jądra i blokuje uruchomienie mechanizmu skanującego. PatchGuard nie zostanie zainicjowany również wtedy, gdy debuger jądra jest włączony podczas uruchamiania systemu operacyjnego – funkcja ta została fabrycznie wbudowana w system, aby deweloperzy oprogramowania mogli swobodnie testować i debugować swoje sterowniki.

Wirus Xpaj jest interesujący, ponieważ używa jeszcze innego koncepcyjnego sposobu na ominięcie PatchGuarda. Problemem mechanizmu PatchGuard jest to, że inicjuje się w dość późnym etapie uruchamiania systemu operacyjnego. Ponieważ Xpaj to bootkit, może on kontrolować każdy etap uruchamiania systemu operacyjnego i modyfikować jądro, zanim uruchomiony zostanie mechanizm ochronny. W momencie, gdy jądro zostanie zainicjowane, zawiera już wszystkie modyfikacje i punkty zaczepienia Xpaja, więc PatchGuard raczej CHRONI te modyfikacje ZAMIAST je WYKRYWAĆ.

Aby potwierdzić, że PatchGuard rzeczywiście chroni przed przechwyceniem ZwLoadDriver / NtReadFile / NtWriteFile, przeprowadziliśmy mały eksperyment. Uruchomiliśmy zainfekowany system w trybie debugowania, zaczekaliśmy na inicjację, włączyliśmy debuger jądra i przywróciliśmy zmodyfikowane bajty w jednej z przechwyconych funkcji. Po chwili system się zawiesił – PatchGuard wykrył modyfikację jądra w pamięci i zgłosił BSOD.

Zaloguj lub Zarejestruj się aby zobaczyć!

Rysunek 15. Awaria systemu po przywróceniu przechwyconej funkcji

Jakikolwiek dodatkowy komentarz jest zbędny.


Statystyki

Użyliśmy KSN, naszej usługi w chmurze, do zgromadzenia statystyk infekcji sektorów startowych bootkitem Xpaj i informacji o detekcji instalatora szkodnika. Najbardziej użyteczne dane, które mogą zostać wyodrębnione z tych statystyk, dotyczą rozkładu geograficznego występowania bootkita i wersji infekowanych systemów operacyjnych.

rusakov_butkit2012_pic16.png

Rysunek 16. Geograficzny rozkład dystrybucji instalatora

rusakov_butkit2012_pic17.png

Rysunek 17. Geograficzny rozkład infekcji MBR

Zaloguj lub Zarejestruj się aby zobaczyć!

Rysunek 18. Statystyki infekowanych systemów operacyjnych

Wnioski

W roku 2008 zaobserwowaliśmy powrót na scenę starej techniki cyberprzestępczej - infekcji sektora MBR. Od tamtej chwili upłynęło sporo czasu. Dzisiejsze bootkity są owocem nowoczesnej idei "budowania rootkitów". Mechanizm ten na pewno pozostanie w arsenale cyberprzestępców w najbliższej przyszłości.

Zainfekowanie sektora rozruchowego jest bardzo wygodnym sposobem inicjowania złośliwego kodu tak wcześnie, jak to możliwe. Na domiar wszystkiego, oferuje ogromne możliwości w zakresie kontroli uruchamiania systemu operacyjnego.

Rodzina systemów operacyjnych Windows x64 została bardzo rozpowszechniona i twórcy szkodliwego oprogramowania robią wszystko, aby ich złośliwe programy były bardziej uniwersalne i utrzymywały niezmiennie wysoki wskaźnik infekcji.

Firma Microsoft wprowadziła pewne ograniczenia i nowe technologie dla systemów Windows x64, zaprojektowane specjalnie do zwalczania rootkitów. Jednakże w praktyce, ani wymóg, że sterowniki trybu jądra powinny być podpisane ważnymi podpisami cyfrowymi, ani mechanizm PatchGuard nie okazały się skuteczne w poprawie sytuacji. Były i będą rootkity przeznaczone dla 64-bitowych systemów operacyjnych, a ich liczba będzie nieubłaganie rosnąć.
Źródło:

Zaloguj lub Zarejestruj się aby zobaczyć!
 

waderr73

Bardzo aktywny
Dołączył
26 Maj 2010
Posty
192
Reakcje/Polubienia
0
Re: XPAJ: Inżynieria wsteczna bootkita dla 64-bitowych syste

Ciekawe, bardzo ciekawe. Tak sobie myślę co powie XPAJ na "secure boot" w Windows 8, UEFI, GPT i Supervisory Mode Execute Protection Intela :jezyk
 
Do góry