Do tego laboratorium musisz pobrać i zainstalować Immunity Debugger w systemie Windows z powyższego łącza. Immunity Debugger nadal jest zależny od Pythona 2.7, który zostanie zainstalowany automatycznie, jeśli nie jest już zainstalowany w systemie. Będziesz debugować program meet.exe, który wcześniej skompilowałeś. Używając Python IDLE w systemie Windows, wpisz następujące polecenie:
W poprzednim kodzie przekazaliśmy drugi argument 408 A. Program powinien automatycznie uruchomić się pod kontrolą debugera. Być może będziesz musiał przekazać wszelkie wyjątki czasu wykonania, naciskając SHIFT-F9. 408 A przepełni bufor. Teraz jesteśmy gotowi, aby rozpocząć analizę programu. Interesuje nas wywołanie strcpy() z wnętrza funkcji Greeting(), ponieważ wiadomo, że jest podatne na ataki z powodu braku sprawdzania granic. Znajdźmy je, uruchamiając okno Executable Modules, które można otworzyć za pomocą ALT-E. Kliknij dwukrotnie moduł „meet”, a zostaniesz przeniesiony do wskaźników funkcji programu meet.exe. Zobaczysz wszystkie funkcje programu (w tym przypadku Greeting i Main). Przejdź strzałką w dół do wiersza JMP meet.greeting (możesz musieć go poszukać), a następnie naciśnij ENTER, aby przejść do tej instrukcji JMP w funkcji Greeting, jak pokazano tutaj:
UWAGA: Jeśli nie widzisz nazw symboli, takich jak Greeting, strcpy i printf, być może nie skompilowałeś pliku binarnego z symbolami debugowania. Możesz również zobaczyć mniejszą lub większą tabelę skoków, w zależności od używanej wersji systemu Windows. Nawet kompilacja w innej wersji systemu Windows może dać różne wyniki. Jeśli nadal nie widzisz symboli po prawej stronie, patrząc na ekran, po prostu postępuj zgodnie z instrukcjami w następnym akapicie, aby wyszukać ciąg ASCII „Hello %s %s” i przerwać na instrukcji CALL kilka wierszy nad nim. Jest to wywołanie strcpy, które można zweryfikować, klikając je i naciskając ENTER. Teraz, gdy patrzymy na funkcję Greeting() w oknie Deasemblera, ustawmy punkt przerwania przy wywołaniu podatnej funkcji (strcpy). Przesuwaj strzałkę w dół, aż dojdziesz do wiersza 0x011C6EF4. Ponownie, adresowanie i symbole w Twojej wersji systemu Windows mogą być inne. Jeśli tak, po prostu poszukaj instrukcji call kilka linijek nad disasemblacją pokazującą ASCII „Hello %s %s” po prawej stronie, aby zobaczyć, gdzie ustawić punkt przerwania. Możesz sprawdzić, czy jest to prawidłowe wywołanie, klikając instrukcję i naciskając ENTER. Powinno to pokazać, że wywołanie jest wykonywane do funkcji strcpy(). W tym wierszu naciśnij F2, aby ustawić punkt przerwania; adres powinien zmienić kolor na czerwony. Ten punkt przerwania pozwala na szybki powrót do tego punktu. Na przykład w tym momencie uruchom ponownie program za pomocą CTRL-F2, a następnie naciśnij F9, aby przejść do punktu przerwania. Powinieneś teraz zobaczyć, że Immunity Debugger zatrzymał się na wywołaniu funkcji, która nas interesuje (strcpy).
UWAGA: Adresy przedstawione tu prawdopodobnie będą się różnić w Twoim systemie ze względu na rebasing i ASLR. Dlatego powinieneś postępować zgodnie z technikami, a nie konkretnymi adresami. Ponadto, w zależności od wersji systemu operacyjnego, może być konieczne ręczne ustawienie punktu przerwania przy każdym uruchomieniu programu, ponieważ Immunity Debugger wydaje się mieć problemy z trwałością punktu przerwania w niektórych wersjach systemu Windows. WinDbg jest świetną alternatywą, ale nie jest tak intuicyjny. Teraz, gdy mamy ustawiony punkt przerwania w wywołaniu podatnej funkcji (strcpy), możemy kontynuować, przechodząc przez funkcję strcpy (naciskając klawisz F8). Gdy rejestry się zmienią, zobaczysz, że staną się czerwone. Ponieważ właśnie wykonaliśmy wywołanie funkcji strcpy, powinieneś zobaczyć, że wiele rejestrów zmieni kolor na czerwony. Kontynuuj przechodzenie przez program, aż dojdziesz do instrukcji RETN, która jest ostatnim wierszem kodu w funkcji powitalnej. Na przykład, ponieważ „wskaźnik powrotu” został nadpisany czterema A, debugger wskazuje, że funkcja zamierza powrócić do 0x41414141. Zwróć również uwagę, jak funkcja epilog skopiowała adres EBP (Extended Base Pointer) do ESP (Extended Stack Pointer), a następnie zdjęła wartość ze stosu (0x41414141) do EBP, jak pokazano poniżej.
UWAGA: Jeśli nie widzisz nazw symboli, takich jak Greeting, strcpy i printf, być może nie skompilowałeś pliku binarnego z symbolami debugowania. Możesz również zobaczyć mniejszą lub większą tabelę skoków, w zależności od używanej wersji systemu Windows. Nawet kompilacja w innej wersji systemu Windows może dać różne wyniki. Jeśli nadal nie widzisz symboli po prawej stronie, patrząc na ekran, po prostu postępuj zgodnie z instrukcjami w następnym akapicie, aby wyszukać ciąg ASCII „Hello %s %s” i przerwać na instrukcji CALL kilka wierszy nad nim. Jest to wywołanie strcpy, które można zweryfikować, klikając je i naciskając ENTER. Teraz, gdy patrzymy na funkcję Greeting() w oknie Deasemblera, ustawmy punkt przerwania przy wywołaniu podatnej funkcji (strcpy). Przesuwaj strzałkę w dół, aż dojdziesz do wiersza 0x011C6EF4. Ponownie, adresowanie i symbole w Twojej wersji systemu Windows mogą być inne. Jeśli tak, po prostu poszukaj instrukcji call kilka linijek nad disasemblacją pokazującą ASCII „Hello %s %s” po prawej stronie, aby zobaczyć, gdzie ustawić punkt przerwania. Możesz sprawdzić, czy jest to prawidłowe wywołanie, klikając instrukcję i naciskając ENTER. Powinno to pokazać, że wywołanie jest wykonywane do funkcji strcpy(). W tym wierszu naciśnij F2, aby ustawić punkt przerwania; adres powinien zmienić kolor na czerwony. Ten punkt przerwania pozwala na szybki powrót do tego punktu. Na przykład w tym momencie uruchom ponownie program za pomocą CTRL-F2, a następnie naciśnij F9, aby przejść do punktu przerwania. Powinieneś teraz zobaczyć, że Immunity Debugger zatrzymał się na wywołaniu funkcji, która nas interesuje (strcpy).
UWAGA: Adresy przedstawione w tym rozdziale prawdopodobnie będą się różnić w Twoim systemie ze względu na rebasing i ASLR. Dlatego powinieneś postępować zgodnie z technikami, a nie konkretnymi adresami. Ponadto, w zależności od wersji systemu operacyjnego, może być konieczne ręczne ustawienie punktu przerwania przy każdym uruchomieniu programu, ponieważ Immunity Debugger wydaje się mieć problemy z trwałością punktu przerwania w niektórych wersjach systemu Windows. WinDbg jest świetną alternatywą, ale nie jest tak intuicyjny. Teraz, gdy mamy ustawiony punkt przerwania w wywołaniu podatnej funkcji (strcpy), możemy kontynuować, przechodząc przez funkcję strcpy (naciskając klawisz F8). Gdy rejestry się zmienią, zobaczysz, że staną się czerwone. Ponieważ właśnie wykonaliśmy wywołanie funkcji strcpy, powinieneś zobaczyć, że wiele rejestrów zmieni kolor na czerwony. Kontynuuj przechodzenie przez program, aż dojdziesz do instrukcji RETN, która jest ostatnim wierszem kodu w funkcji powitalnej. Na przykład, ponieważ „wskaźnik powrotu” został nadpisany czterema A, debugger wskazuje, że funkcja zamierza powrócić do 0x41414141. Zwróć również uwagę, jak funkcja epilog skopiowała adres EBP (Extended Base Pointer) do ESP (Extended Stack Pointer), a następnie zdjęła wartość ze stosu (0x41414141) do EBP, jak pokazano poniżej.
Aby kontynuować sprawdzanie stanu uszkodzonej maszyny, w oknie stosu przewiń w dół do bieżącej ramki stosu (bieżąca ramka stosu zostanie podświetlona). Możesz również powrócić do bieżącej ramki stosu, wybierając wartość rejestru ESP, a następnie klikając prawym przyciskiem myszy tę wybraną wartość i wybierając Follow in Stack. Zauważysz, że kopię bufora można również znaleźć w lokalizacji ESP+4, jak pokazano poniżej. Informacje takie stają się cenne później, gdy wybieramy wektor ataku
Jak widać, Immunity Debugger jest łatwy w użyciu.
UWAGA : Immunity Debugger działa tylko w przestrzeni użytkownika i tylko dla aplikacji 32-bitowych w momencie pisania tego tekstu. Jeśli musisz zanurzyć się w przestrzeni jądra, będziesz musiał użyć debugera Ring0, takiego jak WinDbg firmy Microsoft.
W tym laboratorium pracowaliśmy z Immunity Debugger, aby śledzić przepływ wykonywania z naszymi złośliwymi danymi jako danymi wejściowymi. Zidentyfikowaliśmy podatne wywołanie strcpy() i ustawiliśmy punkt przerwania oprogramowania, aby przejść przez funkcję. Następnie pozwoliliśmy na kontynuowanie wykonywania i potwierdziliśmy, że możemy uzyskać kontrolę nad wskaźnikiem instrukcji. Stało się tak, ponieważ funkcja strcpy() pozwala nam nadpisać wskaźnik powrotu używany przez funkcję Greeting(), aby zwrócić kontrolę z powrotem do main().