Format Strings
Podstawowe informacje
W języku C printf
to funkcja, która może być używana do wyświetlania ciągu znaków. Pierwszym parametrem, którego oczekuje ta funkcja, jest surowy tekst z formatami. Następne parametry, które są oczekiwane, to wartości, które mają zastąpić formatery z surowego tekstu.
Inne podatne funkcje to sprintf()
i fprintf()
.
Podatność pojawia się, gdy tekst atakującego jest używany jako pierwszy argument tej funkcji. Atakujący będzie w stanie stworzyć specjalne dane wykorzystując możliwości ciągu formatującego printf, aby odczytać i zapisać dowolne dane pod dowolnym adresem (do odczytu/zapisu). Dzięki temu będzie mógł wykonać dowolny kod.
Formatery:
Przykłady:
Wrażliwy przykład:
Normalne użycie:
Z Brakującymi Argumentami:
podatny fprintf:
Dostęp do wskaźników
Format %<n>$x
, gdzie n
to liczba, pozwala wskazać printfowi, aby wybrał n-ty parametr (ze stosu). Jeśli chcesz odczytać 4. parametr ze stosu za pomocą printf, możesz to zrobić:
i odczytałbyś od pierwszego do czwartego parametru.
Albo możesz:
i przeczytaj bezpośrednio czwarty.
Zauważ, że atakujący kontroluje parametr pr
intf
, co oznacza, że jego wejście będzie na stosie, gdy zostanie wywołane printf
, co oznacza, że może wpisać konkretne adresy pamięci na stosie.
Atakujący kontrolujący to wejście, będzie mógł dodać dowolny adres na stosie i sprawić, że printf
będzie mógł się do nich odwołać. W następnej sekcji zostanie wyjaśnione, jak wykorzystać to zachowanie.
Odczyt arbitralny
Możliwe jest użycie formatownika %n$s
aby sprawić, że printf
pobierze adres znajdujący się na pozycji n, a następnie wydrukuje go jakby to był łańcuchem znaków (wydrukuj do momentu znalezienia 0x00). Dlatego jeśli bazowy adres binarny to 0x8048000
, i wiemy, że wejście użytkownika zaczyna się na 4. pozycji na stosie, możliwe jest wydrukowanie początku binarnego z:
Należy pamiętać, że nie można umieścić adresu 0x8048000 na początku wejścia, ponieważ ciąg zostanie zakończony zerem na końcu tego adresu.
Znajdź przesunięcie
Aby znaleźć przesunięcie dla swojego wejścia, możesz wysłać 4 lub 8 bajtów (0x41414141
), a następnie %1$x
i zwiększyć wartość, aż odzyskasz A's
.
Last updated