Heurystyka w programach antywirusowych Obrona Jakub Dębski stopień trudności Istnieją dwie główne metody wykrywania złośliwego oprogramowania oparte na wzorcach zagrożeń i na analizie heurystycznej. Pierwszy typ zapewnia stuprocentową wykrywalność zagrożeń, które są znane, jednak wymaga ciągłej aktualizacji baz sygnatur. Jest to obecnie najpopularniejsza metoda detekcji, choć ma istotną wadę, mianowicie jest metodą reakcyjną. Ponieważ Internet umożliwia błyskawiczne rozprzestrzenianie się niebezpieczeństwa, jest ona często niewystarczająca. Metoda oparta na wzorcach zagrożeń charakteryzuje się niebezpieczną luką w czasie pomiędzy pojawieniem się zagrożenia a udostępnieniem wzorca je wykrywającego. Wzorzec jest przygotowywany przez specjalistów z firm antywirusowych, którzy muszą otrzymać nową próbkę, następnie przeanalizować ją i przygotować sygnaturę, która będzie zagrożenie w sposób jednoznaczny identyfikować, nie powodując przy tym fałszywych alarmów (Rysunek 1.). Alternatywą dla ręcznego wybierania wzorców jest wykorzystanie automatycznie generowanych sum kontrolnych, ale są one wrażliwe nawet na drobne modyfikacje i stosowanie ich szybko prowadzi do nadmiernego rozrostu baz. Rozwiązaniem tego problemu są zdobywające coraz większą popularność mechanizmy prewencyjne oparte na klasyfikacji heurystycznej. Heurystyka (gr. heurisko znaleźć) to umiejętność odkrywania nowych faktów i związków pomiędzy faktami poprzez umiejętne postawienie hipotez. Algorytmy heurystyczne na podstawie wiedzy o cechach istniejących niebezpieczeństw są w stanie przeanalizować skanowany obiekt i stwierdzić, czy można go zaklasyfikować jako niebezpieczny. Uogólnione wzorce Metody wykrywania nieznanych wirusów były implementowane w programach antywirusowych od początku ich istnienia. Najprost- Z artykułu dowiesz się czym jest heurystyka w programach antywirusowych, jakie są rodzaje wykorzystywanych heurystyk, przed jakimi problemami stoją twórcy heurystyk. Co powinieneś wiedzieć powinieneś znać podstawy asemblera, powinieneś mieć ogólne pojęcie o budowie systemów operacyjnych, powinieneś znać terminologię związaną z niebezpiecznym oprogramowaniem. 2
Heurystyka w programach antywirusowych szą metodą rozpoznawania nowych wersji wirusów są uogólnione wzorce. Wzorzec (scan-string, pattern) jest ciągiem bajtów wyekstrahowanym z wirusa, który w sposób jednoznaczny go identyfikuje. Mając wzorzec wirusa możemy zastosować jeden z licznych algorytmów dopasowujących, w celu znalezienia go w badanym pliku. Wzorzec musi spełniać kilka wymagań, aby można go było zastosować do identyfikacji zagrożenia: powinien być fragmentem charakterystycznym dla wirusa (nie może występować w czystych plikach), nie może być zbyt krótki (mógłby powodować fałszywe alarmy), nie może być zbyt długi (dopasowanie go byłoby długotrwałe, a zajętość pamięci znaczna przy licznej bazie zagrożeń). Listing 1. Fragment wirusa asemblerowego nadający się na wzorzec 8BBDAA174000 mov edi,[ebp][004017aa] 8B7778 mov esi,[edi][78] 03B59E174000 add esi,[ebp][0040179e] 8B7E0C mov edi,[esi][0c]03bd9e174000 add edi,[ebp][0040179e] 813F4B45524E cmp d,[edi],04e52454b ;"NREK" 0F857C000000 jne.001013f35 Przyjrzyjmy się fragmentowi wirusa asemblerowego, który spełnia wymagania wzorca (Listing 1). Powyższy fragment jest charakterystyczny, ponieważ poszukuje pod wyliczanym adresem słowa KERN, co nie powinno wystąpić w pliku czystym. Po lewej stronie znajdują się bajty reprezentujące instrukcje, których ciąg może stanowić wzorzec służący do wykrycia wirusa. Ponieważ wirus ten uzyskuje dostęp do własnych danych techniką delta offset (tu względem rejestru ebp), w innych wersjach wirusa, po wprowadzeniu do niego niewielkiej zmiany, adresy mogą się zmienić. Aby uogólnić ten wzorzec na inne wersje, możemy zastąpić część bajtów znakiem zastępczym odpowiadającym podczas dopasowywania za dowolny bajt (Listing 2). W ostatniej linii mamy skok warunkowy, którego adres docelowy jest offsetem względem aktualnej instrukcji. Po dodaniu do wirusa dodatkowych rozkazów offset ten może się zmienić, więc w miejsce tych bajtów możemy wstawić znaki zastępcze lub całkiem je wyciąć, ponieważ znajdują się na końcu scan-stringa. Dzięki powyższym zabiegom scanstring będzie potrafił wykryć zarówno nowe wersje tego wirusa, jak też wszystkie wirusy, które zawierają opisany wzorzec. Ponieważ autorzy niebezpiecznych programów często wykorzystują fragmenty istniejącego złośliwego kodu, możliwe jest wybranie wzorca wychwytującego zupełnie nowe zagrożenia. Zbytnie skracanie i uogólnianie scan-stringów może powodować fałszywe alarmy. Rozwiązaniem Rysunek 1. Wykrywanie reakcyjne (Reactive) kontra heurystyczne (Proactive) tego problemu jest stosowanie kilku krótkich wzorców, które muszą znajdować się w badanym pliku, aby stwierdzić obecność wirusa. Od tego podejścia już tylko krok do heurystyki statycznej, czyli najpopularniejszej metody heurystycznego wykrywania wirusów. Heurystyka Heurystykę w programach antywirusowych można podzielić na kilka kategorii w zależności od sposobu działania. Najczęstszym spotykanym podziałem jest wyszczególnienie heurystyki statycznej i dynamicznej. Do metod heurystycznych zalicza się również analizę behawioralną oraz sprawdzanie integralności. Przypatrzmy się poszczególnym typom i przeanalizujmy ich wady i zalety. Heurystyka statyczna Heurystyka statyczna opiera się na analizie obiektu w postaci, w jakiej zostanie on przekazany do analizy; na traktowaniu obiektu jako ciągu bajtów. Analiza taka bazuje na dyskryminatorach zebranych z istniejących niebezpiecznych programów, czyli na cechach odróżniających niebezpieczne programy od czystych plików. Aby analizowany obiekt został uznany za podejrzany, musi zawierać określoną liczbę dyskryminatorów. Dyskryminatory najczęściej są ciągami bajtów, ale mogą być związane np. z nietypowym wyglądem pliku wykonywalnego. Rozpatrzmy przykład wykrywania typowego, napisanego w asemblerze wirusa za pomocą heurystyki statycznej. Typowy wirus infekuje plik wykonywalny poprzez dołączenie do niego swojego kodu, następnie przeszukuje dysk w celu znale- hakin9 Nr 01/2007 3
Obrona zienia innych plików podatnych na infekcję. Aby wykryć wirusa przy użyciu heurystyki statycznej, musimy zgromadzić kolekcję mikrowzorców, których występowanie będzie świadczyło o podejrzanym działaniu. Stworzenie użytecznej bazy mikrowzorców wymaga wiedzy na temat zasady działania wirusów i technik w nich stosowanych. Mikrowzorcem może być przykładowo pobranie offsetu delta, które można znaleźć w większości wirusów plikowych. Offset delta pobierany jest przez wirusa w celu ustalenia adresu początku samego siebie. Jest on wirusowi potrzebny, jeżeli chce w prosty sposób korzystać z danych, które są zawarte w obszarze wirusa. Popularną metodą ustalenia offsetu delta jest sekwencja rozkazów: E800000000 call $+5 5D pop ebp ED sub ebp,???????? co przekłada się na mikrowzorzec E8000000005DED. Występowanie tego mikrowzorca może sugerować, że ciąg bajtów jest kodem, który został dopisany do pliku wykonywalnego. Innym przykładem mikrowzorca może być sprawdzanie formatu pliku PE32 przed infekcją lub podczas poszukiwania w pamięci adresów funkcji API, za pomocą porównań z charakterystycznymi oznaczeniami MZ i PE. Jego Listing 2. Istotne informacje z fragmentu wirusa asemblerowego 8BBD???????? mov edi,[ebp][????????] 8B7778 mov esi,[edi][78] 03B5???????? add esi,[ebp][????????] 8B7E0C mov edi,[esi][0c] 03BD???????? add edi,[ebp][????????] 813F4B45524E cmp d,[edi],04e52454b ;"NREK" 0F85 jne???????? Rysunek 2. Epidemia robaka Bagle.AS. (Źródło: www.virus-radar.com) adres znajduje się pod offsetem 3C względem MZ (Listing 3). W tym przykładzie za uogólniony scan-string może służyć ciąg bajtów 4D5A75*8B*3C*504575, gdzie * to 1-10 dowolnych znaków. Innymi mikrowzorcami infektorów plików mogą być nazwy funkcji API pojawiające się nie w sekcji importów, teksty *.exe, *.*, będące specyfikacją dla wyszukiwania plików do zarażenia lub wartości CRC32 policzone z nazw API (wiele wirusów, szczególnie wzorowanych na napisanych przez grupę 29A, korzystało z procedury wyszukiwania adresów API bazującej na sumie kontrolnej nazwy). W przypadku złośliwych programów pisanych w językach wysokiego poziomu podejrzane może być występowanie tekstów określających klucze rejestru odpowiedzialne za autostart aplikacji w systemie (np. SOFTWARE\ Microsoft\Windows\ CurrentVersion\Run), fragmenty, z których składane są maile (np. MA- IL FROM:) czy adresy blokowanych stron WWW (np. windowsupdate.microsoft.com). Wykrywanie heurystyczne niebezpiecznego oprogramowania tworzonego w językach wysokiego poziomu jest jednak znacznie bardziej skomplikowane niż wykrycie kodu asemblerowego. W celu zwiększenia jakości klasyfikacji przy użyciu heurystyki statycznej można połączyć mikrowzorce z nietypowym wyglądem pliku spowodowanym modyfikacjami przeprowadzonymi podczas infekcji. Przykładowo za nietypowe można uznać sytuacje, gdy: punkt wejścia do programu (Entry- Point) wskazuje na ostatnią sekcję, która nie jest sekcją kodu (wirus dopisał się do ostatniej sekcji), entrypoint wskazuje na wnętrze nagłówka pliku PE (małe wirusy platform Win9x umieszczały się w nagłówku pliku), sekcja kodu posiada oprócz atrybutu wykonywalne, także odczyt i zapis (częste w przypadku wirusów polimorficznych), sekcja relokacji lub sekcja zasobów jest większa, niż być powinna. Utrudnieniem techniki wykrywania wirusów według nietypowego wyglądu stały się popularne ostatnio kompresory (np. UPX) i protektory (np. Asprotect) plików wykonywalnych, które wprowadzają typowe dla wirusów modyfikacje. Możliwe jest zidentyfikowanie protektora i zignorowanie go przy tego typu detekcji, ale szczególnie w przypadku protektorów o otwartych źródłach protektory są często modyfikowane i zidentyfikowanie wszystkich ich wersji jest kłopotliwe. Z drugiej strony samo występowanie zabezpieczenia w pliku stanowi pierwszą oznakę, że autor programu ma coś do ukrycia i jest to podejrzane. 4
Heurystyka w programach antywirusowych Zaletą heurystyki statycznej jest duża szybkość działania tym większa, że analizowane obszary zwykle nie są duże i można w całości wczytać je do pamięci. Jej wadą jest ograniczone pole analizy umożliwiające wykrycie jedynie tych zagrożeń, które posiadają często występujące cechy. Heurystyka taka potrafi przeanalizować jedynie kod, który nie jest zaszyfrowany, ale po uzyskaniu postaci zdeszyfrowanej (np. za pomocą emulacji) można ją przekazać ponownie do skanowania przy użyciu heurystyki statycznej. Po znalezieniu w analizowanym obiekcie wystarczającej liczby charakterystycznych cech możemy stwierdzić, że obiekt jest niebezpieczny. Heurystyka statyczna dla innych rodzajów wirusów, na przykład skryptowych lub makrowirusów, tworzona jest w sposób analogiczny. Rysunek 3. Fragmenty dwóch wersji robaka Agobot Listing 3. Fragment wirusa infekującego pliki. Sprawdzenie nagłówka pliku 66813A4D5A cmp w,[edx],05a4d ;"ZM" 75F8 jne.00040106e 8BCA mov ecx,edx 8B493C mov ecx,[ecx][3c] 03CA add ecx,edx 3BC8 cmp ecx,eax 7FED jg.00040106e 6681395045 cmp w,[ecx],04550 ;"EP" 75E6 jne.00040106e Heurystyka dynamiczna Heurystyką dynamiczną nazywa się analizę przeprowadzaną podczas działania podejrzanego programu, dzięki czemu możliwe jest poznanie zachowania obiektu lub uzyskanie postaci obiektu dającej więcej informacji. Zwykle taką analizę przeprowadza się podczas uruchomienia podejrzanego programu w środowisku bezpiecznym, za pomocą emulatora procesora i systemu operacyjnego. Środowisko takie nazywane jest piaskownicą (ang. sandbox). Program w niej uruchomiony niczym dziecko znajdujące się w piaskownicy nie może popsuć niczego, co znajduje się poza nią, a jego działania można obserwować i analizować. Do heurystyki dynamicznej można zaliczyć również analizę behawioralną przeprowadzaną na działającym systemie, o której więcej będzie w dalszej części tekstu. Emulatory w programach antywirusowych początkowo tworzone były w celu odszyfrowania części zaszyfrowanej wirusów polimorficznych. Wykonywały polimorficzny kod wirusa do czasu, aż zakończył on deszyfrację, co najczęściej wiązało się z wywołaniem funkcji systemowej. Następnie rozszerzono ich funkcjonalność o możliwość analizy behawioralnej, więc wywołanie funkcji systemowej nie kończy działania, ale jest również emulowane zgodnie z zachowaniem rzeczywistego systemu operacyjnego. Wykonując program w bezpiecznym środowisku można sprawdzić, jakie akcje próbuje on podjąć i stwierdzić w ten sposób, czy stanowi potencjalne zagrożenie. Innymi podejrzanymi zachowaniami, które może wykryć heurystyka dynamiczna, są na przykład: liniowa modyfikacja obszaru pamięci, a potem skok w zmodyfikowany obszar (deszyfracja, często stosowana w wirusach polimorficznych), wykonywanie pustych pętli, które nie modyfikują stanu rejestrów procesora ani pamięci (sztuczka utrudniająca analizę programu i spowalniająca emulację), czy wykonywanie kodu w obszarze stosu. Wszystkie te cechy świadczą o tym, że wykonywany program nie jest programem normalnym. Wśród twórców wirusów istnieje przekonanie, że skomplikowanie kodu polimorficznego utrudnia znalezienie wirusa w pliku. Nic bardziej mylnego. Sam kod polimorficzny i metamorficzny jest relatywnie prosty do wykrycia, gdyż jest całkowicie różny od kodu wygenerowanego przez kompilator, a nawet od kodu asemblerowego stworzonego przez człowieka. Generatory polimorficzne tworzą znaczną liczbę instrukcji lub zestawów instrukcji nic nierobiących, tzw. śmieci. Kod ten, całkowicie niezoptymalizowany, daje się za pomocą mniej lub bardziej skomplikowanych metod zidentyfikować i potraktować jako podejrzane zachowanie. Ponieważ protektory plików wykonywalnych również zawierają polimor- hakin9 Nr 01/2007 5
Obrona ficzne deszyfratory, ich nowe wersje mogą być fałszywie identyfikowane powyższymi metodami. Stosowanie emulacji w procesie analizy ma kilka istotnych minusów. Główną wadą jest relatywnie niewielka szybkość działania samego emulatora, a dodatkowe sprawdzenia wykonywane podczas analizy heurystycznej jeszcze emulację spowalniają. Duże znaczenie dla szybkości działania ma też problem stopu, czyli stwierdzenie, kiedy emulacja powinna się zakończyć. Choć powstało wiele metod przyspieszających działanie emulatorów i wciąż powstają nowe (np. wykorzystanie wirtualizacji procesorów), istnieje kilka barier nie do pokonania. Najtrudniejszą z nich jest niedeterministyczność wykonywania kodu. Dla niebezpiecznego programu nie jest problemem, jeżeli zadziała raz na kilka uruchomień. Może być to spowodowane wywołaniem funkcji zwracającej losową wartość lub warunkami logicznymi, które środowisko musi spełnić. Emulator działający w sposób deterministyczny nie jest w stanie obsłużyć tych sytuacji, ponieważ emulacja podąża jedną ścieżką, nie badając wszystkich możliwych rozgałęzień kodu. Zatem emulator może pójść ścieżką, która kończy działanie niebezpiecznego programu, przez co nie będzie można stwierdzić podejrzanego zachowania. Autorzy niebezpiecznego oprogramowania starają się również wykrywać uruchomienie w sztucznym środowisku i reagować na nie, ukrywając swoją obecność. Innym przykładem niedeterministyczności może być odmienne działanie programu w różnych wersjach systemu operacyjnego. Przed twórcą emulatora pozostaje problem wyboru, którą wersję emulować. Analiza behawioralna Każdy proces działający w trybie użytkownika musi komunikować się z systemem operacyjnym za pomocą udostępnionego interfejsu API. W trybie tym pracują wszystkie standardowe aplikacje, w tym większość niebezpiecznych programów, ponieważ nie muszą do działania uzyskiwać nadzwyczajnych uprawnień w systemie. Monitorując wywołania funkcji systemowych jesteśmy w stanie uzyskać dokładne informacje na temat zachowania analizowanego programu. Monitorowanie może odbywać się albo podczas emulacji w środowisku bezpiecznym, albo w działającym systemie. Monitorowanie działającego systemu, mimo jego spowolnienia, zyskuje coraz większą popularność, ponieważ jest w stanie wykryć zagrożenia, którym emulacja nie jest w stanie sprostać. Zaletą analizy behawioralnej jest przeniesienie klasyfikacji na znacznie wyższy poziom abstrakcji. Nie operujemy w tym przypadku na pojedynczych instrukcjach kodu maszynowego, ale w domenie opisanej Listing 4. Początek logu programu TraceApi na wirusie Win32.Miam GetProcAddress(77e60000,GetModuleHandleA) GetProcAddress(77e60000,GetCurrentDirectoryA) GetProcAddress(77e60000,FindFirstFileA) GetProcAddress(77e60000,FindNextFileA) GetProcAddress(77e60000,CreateFileA) GetProcAddress(77e60000,GetFileSize) GetProcAddress(77e60000,LocalAlloc) GetProcAddress(77e60000,ReadFile) GetProcAddress(77e60000,SetFilePointer) GetProcAddress(77e60000,WriteFile) GetProcAddress(77e60000,CloseHandle) GetProcAddress(77e60000,LocalFree) GetProcAddress(77e60000,GetLocalTime) GetProcAddress(77e60000,SetCurrentDirectoryA) GetProcAddress(77e60000,GetWindowsDirectoryA) GetProcAddress(77e60000,GetSystemDirectoryA) GetModuleHandleA(User32.dll) przez zachowania. Unikamy w ten sposób problemów wynikających z różnic w kodzie, które szczególnie widoczne są w przypadku programów wygenerowanych przez kompilatory języków wysokiego poziomu (Rysunek 3). Co więcej, zmiany wprowadzane w kolejnych wersjach niebezpiecznego oprogramowania zwykle w niewielki sposób zmieniają jego zachowanie, gdyż autorzy zwiększają, co najwyżej, funkcjonalność programu. Przykładowo, wykorzystując emulator możemy stwierdzić, że program wykonuje podejrzaną sekwencję wywołań systemowych i określić obiekt jako nowego wirusa lub jako odmianę istniejącego. Większość wirusów działających pod Windows na początku działania pobiera z systemu adresy funkcji, które będą wykorzystywane. Zakładając, że adres 0x77e60000 jest adresem biblioteki KERNEL32.DLL w pamięci procesu, pobieranie listy wygląda następująco (wynik programu TraceApi na wirusie Win32.Miam). Patrz Listing 4. Pobranie adresów wykorzystywanych funkcji API jest dla wirusa niezbędne w sytuacji, gdy chce on skorzystać z funkcji systemowych, które nie znajdują się w Import Address Table infekowanego pliku. Sekwencje takie można znaleźć w wirusach asemblerowych i takie zachowanie świadczy o działaniu dołączonego do programu wirusa. Oczywiście heurystyczna klasyfikacja behawioralna może dotyczyć wszystkich czynności, które wykonuje analizowany program, a które mogą być niebezpieczne. Najczęściej monitorowanie behawioralne dotyczy typowych działań niebezpiecznych programów, jakimi są: modyfikacja plików wykonywalnych, pobieranie i uruchamianie plików z Internetu, wysyłanie listów za pomocą własnego silnika SMTP, modyfikacja rejestru, modyfikacja plików systemowych, zabijanie procesów (np. programów antywirusowych), 6
Heurystyka w programach antywirusowych modyfikacja innych procesów, szpiegowanie klawiatury, nasłuchiwanie na otwartych portach, praca programu bez widocznego okna. Problemem dla monitorów behawioralnych mogą być aplikacje wielowątkowe, ponieważ monitor musi skupić się albo na czynnościach wykonywanych globalnie przez całą aplikację, albo na czynnościach wykonywanych przez poszczególne wątki. Większość współcześnie tworzonego niebezpiecznego oprogramowania działa jednak w jednym wątku. Monitory behawioralne posiadają zwykle rozbudowywaną bazę fałszywych alarmów, gdyż niebezpieczne programy pisane w językach wysokiego poziomu charakteryzują się pod względem zachowania wysokim podobieństwem do plików czystych. Przykładowo moduły autoaktualizacji programów są pod względem zachowania bardzo podobne do popularnych downloaderów. Oprócz przeprowadzania skomplikowanej analizy zachowań, blokowane mogą być wszystkie potencjalnie niebezpieczne akcje, takie jak wstrzykiwanie kodu do innych procesów i tworzenie w nich zdalnych wątków czy automatyczne uruchamianie makr MS Office. Co więcej, niektóre programy antywirusowe blokują wykonanie przez użytkownika wszystkich skryptów (.vbs,.bat,.cmd), traktując je jako potencjalnie niebezpieczne. Również monitorowanie dostępu do rejestru staje się elementem programów antywirusowych. Wymaga jednak interaktywnego stwierdzenia, czy dana modyfikacja była zamierzona, czy nie, co jest kłopotliwe dla niedoświadczonego użytkownika. nie ulegają zmianie. Jeszcze kilka lat temu nie było problemem monitorowanie zmian w plikach poprzez sprawdzenie zapamiętanej poprawnej sumy kontrolnej. Wraz z upowszechnieniem Internetu wzrosła liczba aplikacji, które automatycznie aktualizują się do najnowszych wersji, modyfikując nie tylko pliki danych, ale też pliki wykonywalne. Także sam system operacyjny nie jest stały, ale modyfikowany za pomocą ukazujących się mniej lub bardziej regularnie łat. Uwzględniając fakt, że baza sum kontrolnych może również stać się celem ataku, monitorowanie zmian na podstawie sum kontrolnych jest coraz rzadziej stosowane. Sprawdzanie integralności działa jednak w przypadku heurystycznego wykrywania rootkitów, jak czyni to System Virginity Verifier. Analizuje on zmiany wprowadzone w pamięci modułów systemowych i porównuje je z poprawnymi wartościami odczytanymi z plików (najlepiej podpisanych cyfrowo). Jeżeli integralność modułów zostanie naruszona, prawdopodobne jest działanie rootkita, który zmodyfikował system w celu ukrycia w nim obiektów. Integralność plików możemy sprawdzić dzięki istnieniu coraz częściej stosowanych podpisów cyfrowych. Niektóre programy antywirusowe nie potrafią przebić się przez warstwy zabezpieczające plików wykonywalnych i wszystkie takie pliki zgłaszają jako podejrzane. Jeżeli jesteśmy twórcami oprogramowania i chcemy zabezpieczyć program, jednocześnie nie przyprawiając użytkowników o palpitacje serca na skutek fałszywego alarmu, program taki powinniśmy podpisać. Firmy antywirusowe będą dzięki temu mogły zidentyfikować twórcę programu i nie zgłaszać użytkownikowi zabezpieczenia jako podejrzanego. Sprawdzanie integralności stało się jednym z podstawowych mechanizmów bezpieczeństwa w systemie Windows Vista. Wspomniany mechanizm Kernel Patch Protection sprawdza, czy nie zostały wprowadzone w systemie nielegalne zmiany: modyfikowanie tablicy usług systemowych (systfem service tables), modyfikowanie tablicy przerwań (IDT), modyfikowanie tablicy globalnych deskryptorów (GDT), Sprawdzanie integralności Najprostszym podejściem do heurystycznego wykrywania obecności niebezpiecznego oprogramowania jest zbadanie, czy określone obszary systemu (pliki, rejestr) Rysunek 4. Wizualizacja robaków InTheWild według podobieństwa behawioralnego. Widzimy duże skupienia określające rodziny hakin9 Nr 01/2007 7
Obrona używanie w jądrze stosu, który nie został przydzielony przez jądro, łatanie dowolnej części jądra. Sprawą dyskusyjną jest, czy mechanizm ten rzeczywiście zwiększa bezpieczeństwo systemu. Modyfikowanie systemu operacyjnego było od dawna stosowane przez programy zabezpieczające, dzięki czemu mogły one wykonać dodatkowe sprawdzenia, które uniemożliwiał sam system. Przykładowo działający w czasie rzeczywistym system analizy zachowań musi zintegrować się z systemem, być bliżej systemu niż niebezpieczne oprogramowanie, aby mógł je kontrolować. Istnienie Kernel Patch Protection uniemożliwia taką integrację. Chociaż mechanizm ten zabezpieczy system przed niektórymi rootkitami, ich twórcy i tak są w stanie go ominąć, wykorzystując nielegalne sztuczki. Sztuczek tych nie mogą jednak stosować producenci programów antywirusowych, dzięki czemu złośliwe oprogramowanie uzyskuje nad zabezpieczającym przewagę. Redukując możliwości analizy behawioralnej Microsoft zmniejszył siłę heurystycznej detekcji najpopularniejszych zagrożeń, czyli działających w trybie użytkownika. Wykrywanie anomalii Kiedy mówimy o heurystycznej detekcji niebezpiecznego oprogramowania, możemy wyróżnić dwa typy klasyfikacji, które faktycznie są wykrywaniem anomalii: wszystko, co nie jest podobne do normalnego programu, jest niebezpieczne, wszystko, co jest podobne do niebezpiecznego programu, jest niebezpieczne. Pierwszy rodzaj wykrywania anomalii był skuteczny w przypadku infektorów plików. Wykrywanie polimorfizmu i metamorfizmu, nietypowej budowy plików czy kodu asemblerowego w punkcie wejścia programu pozwalało na odróżnienie O autorze Jakub Dębski, starszy analityk w firmie ESET (producent programu NOD32), specjalizującej się w ochronie proaktywnej z wykorzystaniem najbardziej zaawansowanych mechanizmów analizy heurystycznej. Wcześniej wieloletni pracownik polskich firm antywirusowych. Był kierownikiem projektu silnika mks_vir, następnie ArcaVir. Studia na Wojskowej Akademii Technicznej ukończył obroną pracy dyplomowej na temat wykorzystania sieci neuronowych w detekcji zagrożeń internetowych. Kontakt z autorem:debski.jakub@wp.pl plików bezpiecznych od zainfekowanych. W momencie, gdy autorzy złośliwych programów przerzucili się na języki wysokiego poziomu, programy bezpieczne i niebezpieczne stały się zbyt podobne, by można je było łatwo rozróżnić. Twórcom heurystyk pozostało poszukiwanie podobieństw złośliwych programów do innych złośliwych programów. Co to oznacza? Współcześnie nie jest możliwe wykrycie całkowicie nowego typu zagrożenia, gdy nie ma ono cech wspólnych z już istniejącymi. Na szczęście dla użytkowników (i twórców programów antywirusowych), autorzy złośliwych programów wprowadzają w kolejnych wersjach niewielkie zmiany, bazują na istniejących rozwiązaniach i używają do zabezpieczenia plików popularnych narzędzi. Dzięki temu nowe zagrożenia posiadają wiele cech wspólnych na wszystkich poziomach, od podobieństwa binarnego, aż do podobieństwa opisanego w domenie zachowań (Rysunek 4). Już po otrzymaniu jednej próbki program antywirusowy, wykorzystujący zaawansowaną heurystykę, jest w stanie wykryć wszystkie warianty tego zagrożenia. Oszukiwanie heurystyki Teoretycznie detekcja niebezpiecznego programu, którego autor postarał się, żeby program nie był wykryty, jest bardzo trudna. W sytuacji, gdy autor złośliwego programu napisze go od podstaw, nie wzorując się na istniejących rozwiązaniach, istnieje dość nikła szansa, że algorytm heurystyczny go wykryje. Jeszcze mniejsze jest prawdopodobieństwo wykrycia takiego zagrożenia przy użyciu uogólnionego wzorca. Co więcej, na skutek dostępności darmowych lub testowych wersji programów antywirusowych, autor nowego programu może sprawdzić, czy jest on wykrywany metodami heurystycznymi. W takim przypadku może modyfikować go do czasu, aż przestanie być uznawany za podejrzany. Istnieją również serwisy online skanujące plik dużą liczbą silników antywirusowych, takie jak Jotti's malware scan czy VirusTotal, z których twórca robaka czy trojana może skorzystać. Z tego powodu firmy antywirusowe trzymają w rękawie kilka asów, jakimi są niedostępne ogólnie mechanizmy detekcji, które umożliwiają wczesne wykrycie nowego zagrożenia i dostarczenie próbki do firmy w celu błyskawicznego przygotowania remedium. Podsumowanie Heurystyka w programach antywirusowych ewoluuje wraz z zagrożeniami. Programy antywirusowe od kilku lat nie służą jedynie do wykrywania i usuwania wirusów komputerowych, ale skupiają się na ochronie użytkownika przed szerokim wachlarzem ataków. Stały się pakietami zabezpieczającymi przed złośliwym oprogramowaniem, włamaniami, phishingiem, rootkitami, a nawet spamem. Do ich wykrycia mogą wykorzystać albo wzorce, albo mechanizmy prewencyjne, jakimi są współcześnie heurystyki. Co jest skuteczniejsze? Wiadomo lepiej zapobiegać, niż leczyć. 8