Leaking libc address with ROP
Quick Resume
Find overflow offset
Find
POP_RDI
gadget,PUTS_PLT
andMAIN
gadgetsUżyj poprzednich gadgetów, aby wyciekować adres pamięci funkcji puts lub innej funkcji libc i znaleźć wersję libc (pobierz ją)
Z biblioteką, oblicz ROP i wykorzystaj to
Other tutorials and binaries to practice
Ten samouczek będzie wykorzystywał kod/binary 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
Code
Filename: vuln.c
ROP - Leaking LIBC template
Pobierz exploit i umieść go w tym samym katalogu co podatny binarny plik, a następnie przekaż potrzebne dane do skryptu:
Leaking libc - template1- Znalezienie offsetu
Szablon potrzebuje offsetu przed kontynuowaniem exploitacji. Jeśli jakikolwiek zostanie podany, wykona niezbędny kod, aby go znaleźć (domyślnie OFFSET = ""
):
Wykonaj python template.py
, a konsola GDB zostanie otwarta z programem, który uległ awarii. Wewnątrz tej konsoli GDB wykonaj x/wx $rsp
, aby uzyskać bajty, które miały nadpisać RIP. Na koniec uzyskaj offset używając konsoli python:
Po znalezieniu offsetu (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 Gadżetów
Teraz musimy znaleźć gadżety ROP w binarnym pliku. Te gadżety ROP będą przydatne do wywołania puts
, aby znaleźć używaną libc, a później do uruchomienia ostatecznego exploit.
PUTS_PLT
jest potrzebny do wywołania funkcji puts.
MAIN_PLT
jest potrzebny do ponownego wywołania funkcji main po jednej interakcji, aby wykorzystać przepełnienie ponownie (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ływanej funkcji.
W tym kroku nie musisz nic wykonywać, ponieważ wszystko zostanie znalezione przez pwntools podczas wykonania.
3- Znalezienie biblioteki libc
Teraz czas, aby znaleźć, która wersja biblioteki libc jest używana. Aby to zrobić, zamierzamy wyciek adresu w pamięci funkcji puts
, a następnie zamierzamy przeszukać, w której wersji biblioteki znajduje się wersja puts w tym adresie.
Aby to zrobić, najważniejsza linia wykonanego kodu to:
To wyśle kilka bajtów, aż nadpisanie RIP będzie możliwe: OFFSET
.
Następnie ustawi 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 w adresie wskazywanym przez PUTS_GOT
.
Po tym zostanie wywołany PUTS_PLT
(z PUTS_GOT
wewnątrz RDI), aby puts odczytał zawartość wewnątrz PUTS_GOT
(adres funkcji puts w pamięci) i wydrukował go.
Na koniec funkcja main jest wywoływana ponownie, abyśmy mogli ponownie wykorzystać przepełnienie.
W ten sposób oszukaliśmy funkcję puts, aby wydrukował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ż eksploatujemy lokalny binarny plik, nie ma potrzeby ustalania, która wersja libc jest używana (po prostu znajdź bibliotekę w /lib/x86_64-linux-gnu/libc.so.6
).
Jednak w przypadku zdalnego eksploatującego wyjaśnię tutaj, jak można to znaleźć:
3.1- Szukanie wersji libc (1)
Możesz sprawdzić, która biblioteka jest używana na stronie: https://libc.blukat.me/ Pozwoli to również pobrać odkrytą wersję libc
3.2- Szukanie wersji libc (2)
Możesz również 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
Wyciekniony 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:
Skopiuj libc z libs/libc6_2.23-0ubuntu10_amd64/libc-2.23.so
do naszego katalogu roboczego.
3.3- Inne funkcje do wycieku
4- Znalezienie adresu libc opartego na lokalizacji i wykorzystanie
Na tym etapie powinniśmy znać używaną bibliotekę libc. Ponieważ wykorzystujemy lokalny binarny plik, użyję tylko: /lib/x86_64-linux-gnu/libc.so.6
Na początku template.py
zmień zmienną libc na: libc = ELF("/lib/x86_64-linux-gnu/libc.so.6") #Ustaw ścieżkę do biblioteki, gdy ją znamy
Podając ścieżkę do biblioteki libc, reszta eksploitu zostanie automatycznie obliczona.
Wewnątrz funkcji get_addr
zostanie obliczony adres bazowy libc:
Zauważ, że ostateczny adres bazy libc musi kończyć się na 00. Jeśli tak nie jest, mogłeś wyciekować niepoprawną bibliotekę.
Następnie adres do funkcji system
oraz adres do ciągu "/bin/sh" będą obliczane na podstawie adresu bazy libc i podanej biblioteki libc.
Na koniec przygotowywany jest exploit do wykonania /bin/sh:
Let's explain this final ROP.
Ostatni ROP (rop1
) zakończył się ponownym wywołaniem funkcji main, więc możemy ponownie wykorzystać przepełnienie (dlatego OFFSET
jest tutaj znowu). 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 adres funkcji exit jest wywoływany, aby proces ładnie zakończył działanie i nie został wygenerowany żaden alert.
W ten sposób exploit uruchomi powłokę _/bin/sh_**.**
4(2)- Using ONE_GADGET
Możesz również użyć ONE_GADGET , aby uzyskać powłokę zamiast używać system i "/bin/sh". ONE_GADGET znajdzie w bibliotece libc sposób na uzyskanie powłoki, używając tylko jednego adresu ROP.
Jednak zazwyczaj istnieją pewne ograniczenia, najczęstsze i łatwe do ominięcia to [rsp+0x30] == NULL
. Ponieważ kontrolujesz wartości wewnątrz RSP, musisz tylko wysłać kilka dodatkowych wartości NULL, aby ograniczenie zostało ominięte.
EXPLOIT FILE
Możesz znaleźć szablon do wykorzystania tej podatności tutaj:
Leaking libc - templateCommon problems
MAIN_PLT = elf.symbols['main'] not found
Jeśli symbol "main" nie istnieje. Wtedy możesz znaleźć, gdzie znajduje się główny kod:
i ustaw adres ręcznie:
Puts nie znaleziono
Jeśli binarny plik nie używa Puts, powinieneś sprawdzić, czy używa
sh: 1: %s%s%s%s%s%s%s%s: nie znaleziono
sh: 1: %s%s%s%s%s%s%s%s: nie znaleziono
Jeśli znajdziesz ten błąd po stworzeniu wszystkich exploitów: sh: 1: %s%s%s%s%s%s%s%s: nie znaleziono
Spróbuj odjąć 64 bajty od adresu "/bin/sh":
Last updated