Format Strings
Podstawowe informacje
W C printf
to funkcja, która może być używana do drukowania pewnego ciągu znaków. Pierwszym parametrem, którego oczekuje ta funkcja, jest surowy tekst z formatami. Następne parametry to wartości, które mają zastąpić formaty w surowym tekście.
Inne podatne funkcje to sprintf()
i fprintf()
.
Vulnerabilność pojawia się, gdy tekst atakującego jest używany jako pierwszy argument tej funkcji. Atakujący będzie w stanie stworzyć specjalne dane wejściowe, wykorzystując możliwości formatu printf do odczytu i zapisu dowolnych danych w dowolnym adresie (czytliwym/zapisywalnym). Dzięki temu będzie mógł wykonać dowolny kod.
Formatery:
Przykłady:
Wrażliwy przykład:
Normalne użycie:
Z brakującymi argumentami:
fprintf podatny:
Dostęp do wskaźników
Format %<n>$x
, gdzie n
to liczba, pozwala wskazać printf, aby wybrał n parametr (ze stosu). Więc jeśli chcesz odczytać 4. parametr ze stosu używając printf, możesz to zrobić:
i możesz czytać od pierwszego do czwartego parametru.
Lub możesz zrobić:
i odczytać bezpośrednio czwarty.
Zauważ, że atakujący kontroluje parametr pr
intf
, co zasadniczo oznacza, że** jego dane wejściowe będą znajdować się na stosie, gdy printf
zostanie wywołane, co oznacza, że mógłby zapisać konkretne adresy pamięci na stosie.
Atakujący kontrolujący te dane wejściowe będzie w stanie dodać dowolny adres na stosie i sprawić, że printf
uzyska do nich dostęp. W następnej sekcji zostanie wyjaśnione, jak wykorzystać to zachowanie.
Arbitralne Odczyty
Możliwe jest użycie formatera %n$s
, aby sprawić, że printf
uzyska adres znajdujący się na n pozycji, a następnie wydrukuje go tak, jakby był ciągiem (drukuj, aż znajdziesz 0x00). Więc jeśli adres bazowy binarnego pliku to 0x8048000
, a wiemy, że dane wejściowe użytkownika zaczynają się na 4. pozycji na stosie, możliwe jest wydrukowanie początku binarnego pliku za pomocą:
Zauważ, że nie możesz umieścić adresu 0x8048000 na początku wejścia, ponieważ ciąg zostanie obcięty na 0x00 na końcu tego adresu.
Znajdź offset
Aby znaleźć offset do swojego wejścia, możesz wysłać 4 lub 8 bajtów (0x41414141
) następnie %1$x
i zwiększać wartość, aż uzyskasz A's
.
Last updated