Leaking libc address with ROP
Szybkie podsumowanie
Znajdź przesunięcie przepełnienia
Znajdź gadżet
POP_RDI
,PUTS_PLT
iMAIN
Użyj poprzednich gadżetów do wycieku adresu pamięci funkcji puts lub innej funkcji libc i znajdź wersję biblioteki libc (pobierz ją)
Z biblioteką oblicz ROP i wykorzystaj to
Inne samouczki i binaria do praktyki
Ten samouczek będzie wykorzystywał kod/binarny zaproponowany w tym samouczku: https://tasteofsecurity.com/security/ret2libc-unknown-libc/ Inne przydatne samouczki: https://made0x78.com/bseries-ret2libc/, https://guyinatuxedo.github.io/08-bof_dynamic/csaw19_babyboi/index.html
Kod
Nazwa pliku: vuln.c
Szablon ROP - Wyciek LIBC
Pobierz exploit i umieść go w tym samym katalogu co podatny plik binarny oraz podaj wymagane dane skryptowi:
pageLeaking libc - template1- Znalezienie przesunięcia
Szablon wymaga przesunięcia przed kontynuacją eksploitacji. Jeśli nie zostanie podane, zostanie wykonany niezbędny kod do jego znalezienia (domyślnie OFFSET = ""
):
Wykonaj python template.py
, otworzy się konsola GDB z programem, który uległ awarii. Wewnątrz tej konsoli GDB wykonaj x/wx $rsp
, aby uzyskać bajty, które miały nadpisać RIP. Ostatecznie uzyskaj przesunięcie za pomocą konsoli python:
Po znalezieniu przesunięcia (w tym przypadku 40) zmień zmienną OFFSET w szablonie, używając tej wartości.
OFFSET = "A" * 40
Innym sposobem byłoby użycie: pattern create 1000
-- wykonaj do ret -- pattern seach $rsp
z GEF.
2- Znajdowanie Gadgetów
Teraz musimy znaleźć Gadgety ROP wewnątrz pliku binarnego. Te Gadgety ROP będą przydatne do wywołania puts
w celu znalezienia używanej biblioteki libc, a później do uruchomienia ostatecznego ataku.
PUTS_PLT
jest potrzebny do wywołania funkcji puts.
MAIN_PLT
jest potrzebny do ponownego wywołania funkcji main po jednej interakcji, aby ponownie wykorzystać nadmiar (nieskończone rundy eksploatacji). Jest używany na końcu każdego ROP, aby ponownie wywołać program.
POP_RDI jest potrzebny do przekazania parametru do wywołanej funkcji.
W tym kroku nie musisz niczego wykonywać, ponieważ wszystko zostanie znalezione przez narzędzie pwntools podczas wykonywania.
3- Znajdowanie biblioteki libc
Nadszedł czas, aby dowiedzieć się, która wersja biblioteki libc jest używana. Aby to zrobić, zamierzamy wyciek adresu w pamięci funkcji puts
, a następnie będziemy szukać, w której wersji biblioteki znajduje się wersja puts pod tym adresem.
Aby to zrobić, najważniejsza linia wykonanego kodu to:
To wyśle kilka bajtów, aż nadpisze RIP: OFFSET
.
Następnie ustawiony zostanie adres gadżetu POP_RDI
, aby następny adres (FUNC_GOT
) został zapisany w rejestrze RDI. Dzieje się tak, ponieważ chcemy wywołać puts, przekazując mu adres PUTS_GOT
, ponieważ adres w pamięci funkcji puts jest zapisany pod adresem wskazywanym przez PUTS_GOT
.
Następnie zostanie wywołane PUTS_PLT
(z PUTS_GOT
w RDI), dzięki czemu puts odczyta zawartość wewnątrz PUTS_GOT
(adres funkcji puts w pamięci) i wypisze go.
Na koniec ponownie zostanie wywołana funkcja main, abyśmy mogli ponownie wykorzystać przepełnienie.
W ten sposób oszukaliśmy funkcję puts, aby wypisała adres w pamięci funkcji puts (która znajduje się w bibliotece libc). Teraz, gdy mamy ten adres, możemy sprawdzić, która wersja libc jest używana.
Ponieważ wykorzystujemy pewien lokalny plik binarny, nie jest konieczne ustalenie, która wersja libc jest używana (wystarczy znaleźć bibliotekę w /lib/x86_64-linux-gnu/libc.so.6
).
Jednak w przypadku zdalnego ataku wyjaśnię tutaj, jak możesz to znaleźć:
3.1- Wyszukiwanie wersji libc (1)
Możesz sprawdzić, która biblioteka jest używana na stronie internetowej: https://libc.blukat.me/ Pozwoli to również pobrać odkrytą wersję libc
3.2- Wyszukiwanie wersji libc (2)
Możesz także zrobić:
$ git clone https://github.com/niklasb/libc-database.git
$ cd libc-database
$ ./get
To zajmie trochę czasu, bądź cierpliwy. Aby to zadziałało, potrzebujemy:
Nazwa symbolu Libc:
puts
Wyciekły adres libc:
0x7ff629878690
Możemy ustalić, która libc jest najprawdopodobniej używana.
Otrzymujemy 2 dopasowania (powinieneś spróbować drugiego, jeśli pierwsze nie działa). Pobierz pierwsze:
3.3- Inne funkcje do wycieku
Skopiuj libc z libs/libc6_2.23-0ubuntu10_amd64/libc-2.23.so
do naszego katalogu roboczego.
4- Znajdowanie adresu biblioteki libc i eksploatacja
W tym momencie powinniśmy znać używaną bibliotekę libc. Ponieważ wykorzystujemy lokalny plik binarny, użyję tylko: /lib/x86_64-linux-gnu/libc.so.6
Więc na początku pliku template.py
zmień zmienną libc na: libc = ELF("/lib/x86_64-linux-gnu/libc.so.6") #Ustaw ścieżkę biblioteki gdy ją znasz
Podając ścieżkę do biblioteki libc, reszta eksploatacji będzie automatycznie obliczana.
Wewnątrz funkcji get_addr
zostanie obliczony adres bazowy libc:
Należy pamiętać, że końcowy adres podstawy libc musi kończyć się cyfrą 00. Jeśli tak nie jest w twoim przypadku, możesz ujawnić nieprawidłową bibliotekę.
Następnie adres funkcji system
oraz adres łańcucha "/bin/sh" zostaną obliczone na podstawie adresu podstawy libc i danej biblioteki libc.
Ostatecznie exploit wykonujący /bin/sh zostanie przygotowany i wysłany:
Wyjaśnijmy ten ostatni ROP.
Ostatni ROP (rop1
) kończył się ponownym wywołaniem funkcji main
, dzięki czemu możemy ponownie wykorzystać przepełnienie (dlatego tu znowu jest OFFSET
). Następnie chcemy wywołać POP_RDI
, wskazując na adres "/bin/sh" (BINSH
) i wywołać funkcję system (SYSTEM
), ponieważ adres "/bin/sh" zostanie przekazany jako parametr.
Na koniec wywoływany jest adres funkcji exit, aby proces ładnie zakończył działanie i nie generował żadnych alertów.
W ten sposób exploit uruchomi powłokę _/bin/sh.
4(2)- Używanie ONE_GADGET
Możesz również użyć ONE_GADGET, aby uzyskać powłokę zamiast korzystać z system i "/bin/sh". ONE_GADGET znajdzie w bibliotece libc sposób uzyskania powłoki, korzystając tylko z jednego adresu ROP.
Jednak zazwyczaj istnieją pewne ograniczenia, najczęstsze i łatwe do uniknięcia to takie jak [rsp+0x30] == NULL
. Ponieważ kontrolujesz wartości w RSP, wystarczy wysłać kilka dodatkowych wartości NULL, aby uniknąć ograniczenia.
PLIK EXPLOITACJI
Szablon do wykorzystania tej podatności znajdziesz tutaj:
pageLeaking libc - templatePowszechne problemy
MAIN_PLT = elf.symbols['main'] nie został znaleziony
Jeśli symbol "main" nie istnieje. W takim przypadku możesz znaleźć, gdzie znajduje się kod główny:
i ustaw adres ręcznie:
Puts not found
Jeśli plik binarny nie używa Puts, powinieneś sprawdzić, czy używa
sh: 1: %s%s%s%s%s%s%s%s: not found
sh: 1: %s%s%s%s%s%s%s%s: not found
Jeśli znajdziesz ten błąd po utworzeniu wszystkich exploitów: sh: 1: %s%s%s%s%s%s%s%s: not found
Spróbuj odjąć 64 bajty od adresu "/bin/sh":
Last updated