jakubk64@home:~$

OverFlow1 (picoCTF2019)

Opis

useful image

Rozwiązanie

Na początek otrzymujemy plik flag.txt do odczytania którego oczywiście nie mamy uprawnień oraz program wraz z jego kodem źródłowym w języku C:

useful image

Działanie programu polega na tym, że pobiera on od nas dowolny napis i bez analizy kodu źródłowego nie jesteśmy w stanie powiedzieć wiele więcej niż to, że przyjmuje on napis i wyrzuca na ekran jakiś adres z pamięci:

useful image

Gdy zajrzymy do kodu źródłowego widzimy kilka istotnych elementów. Po pierwsze bufor ma wielkość 64 bitów. Następnie widzimy proste sprawdzenie poprawności działania zadania a pod nim funkcję odpowiadającą za pobranie flagi z pliku i wydrukowanie jej na ekran (nr. 1). Następnie widzimy definicję funkcji vuln(), która pobiera wpisany przez nas tekst i zwraca adress wyjścia (nr. 2). Niżej widzimy wywołanie wymienionej funkcji (nr. 3).

useful image

W tym momencie wiemy, że program zwraca na końcu adres w pamięci. Wiemy również, że do pobrania tekstu używa funkcji gets, która będzie przyjmowała wpisywane przez nas dane aż do napotkania znaku końca linii (‘\n’) przez co jest podatna na tzw. “buffer overflow”. Wykorzystujac wiedzę, że bufor ma wielkość 64 bitów sprawdzamy możliwości przeładowania bufora, aby uzyskać flagę. Aby uzyskać flagę musimy znać jej adres w pamięci. W tym celu możemy użyć polecenia:

objdump -d ./vuln | grep flag

“objdump” pozwoli na prostą, niskopoziomową analizę działania programu pokazując jednocześnie adres w pamięci poszczególnych elementów w programie a “grep” pozwoli wyłowić naiistotniejszą dla nas informację - adres naszej flagi.

useful image

Teraz trzeba przetestować, w którym miejscu należy umieścić flagę, tak aby po przepełnieniu bufora program przeskoczył do niej i pozwolił ją odczytać. Ze względu na działanie kompilatora przeładowanie bufora i pisanie po pamięci nie zawsze musi nastąpić bezpośrednio po rozmiarze bufora, dlatego sprawdzamy w którym miejscu wprowadzanego przez nas napisu należy umieścić adres flagi, tak aby kontrolować działanie programu. W tym celu po odpaleniu wpisujemy 64 dowolne znaki (64 ze względu na wielkosć bufora = 64), a następnie dopisujemy po 4 znaki i obserwujemy zachowanie programu tj. w tym przypadku kiedy zwróci nam inny adres z pamięci niż adres wyjścia:

useful image

Jak widzimy należy wpisać 80 znaków napisu z czego 4 ostatnie zastąpimy odpowiednio “przetworzonym” adresem flagi. Adres flagi to 080485e6. Ze względu na architekturę systemu (Intel, 32-bitowy) używamy “little endian”, dzielimy adres na bloki 8-bitowe i piszemy je w odwrotnej kolejności dodając “\x” przed każdym 8-bitowym blokiem, aby został on prawidłowo przetworzony. Przygotowany napis do wpisania w programie wygląda więc następująco:

1111111111111111111111111111111111111111111111111111111111111111222233334444\xe6\x85\x04\x08

Zapisujemy go do pomocniczego pliku tekstowego poleceniem:

echo -e '1111111111111111111111111111111111111111111111111111111111111111222233334444\xe6\x85\x04\x08' > ~/tmp

Następnie odcyztujemy wartosć pliku pomocniczego i przekierowujemy to przez strumień na wejście programu “vuln”

cat ~/tmp - | ./vuln

Dzięki temu bufor zostaje przepełniony, zwracany przez program adres to nie adres wyjścia a adres szukanej przez nas flagi. Program więc odczytuje flagę i “zawiesza się”:

useful image useful image

Flag: picoCTF{n0w_w3r3_ChaNg1ng_r3tURn5b80c9cbf}