WWW2Exec - .dtors & .fini_array
.dtors
Danas je veoma čudno naći binarni fajl sa .dtors sekcijom!
Destruktori su funkcije koje se izvršavaju pre završetka programa (nakon što se funkcija main
završi).
Adrese ovih funkcija se čuvaju unutar .dtors
sekcije binarnog fajla i stoga, ako uspete da upišete adresu shell koda u __DTOR_END__
, taj će se izvršiti pre nego što program završi.
Dobijte adresu ove sekcije sa:
Obično ćete pronaći DTOR markere između vrednosti ffffffff
i 00000000
. Dakle, ako vidite samo te vrednosti, to znači da nema registrovane funkcije. Zato prepišite 00000000
sa adresom shell koda kako biste ga izvršili.
Naravno, prvo morate pronaći mesto za čuvanje shell koda kako biste ga kasnije mogli pozvati.
.fini_array
Essentially this is a structure with functions that will be called before the program finishes, like .dtors
. This is interesting if you can call your shellcode just jumping to an address, or in cases where you need to go back to main
again to exploit the vulnerability a second time.
Napomena da kada se izvrši funkcija iz .fini_array
prelazi se na sledeću, tako da neće biti izvršena više puta (sprječavajući večne petlje), ali će vam dati samo 1 izvršenje funkcije postavljene ovde.
Napomena da se unosi u .fini_array
nazivaju u obrnutom redosledu, pa verovatno želite da počnete sa pisanjem od poslednjeg.
Večna petlja
Da biste zloupotrebili .fini_array
kako biste dobili večnu petlju, možete proveriti šta je urađeno ovde: Ako imate najmanje 2 unosa u .fini_array
, možete:
Koristite svoj prvi zapis da ponovo pozovete ranjivu funkciju za proizvoljno pisanje
Zatim, izračunajte povratnu adresu na steku koju čuva
__libc_csu_fini
(funkcija koja poziva sve funkcije.fini_array
) i stavite tamo adresu__libc_csu_fini
To će naterati
__libc_csu_fini
da pozove sam sebe ponovo izvršavajući ponovo funkcije.fini_array
koje će pozvati ranjivu WWW funkciju 2 puta: jednom za proizvoljno pisanje i još jednom da ponovo prepiše povratnu adresu__libc_csu_fini
na steku da bi se ponovo pozvao.
Napomena da sa Full RELRO, odeljak .fini_array
je postavljen kao samo za čitanje.
link_map
Kao što je objašnjeno u ovom postu, ako program završi korišćenjem return
ili exit()
, pokrenuće se __run_exit_handlers()
koji će pozvati registrovane destruktore.
Ako program izađe putem funkcije _exit()
, pozvaće se exit
syscall i hendleri za izlaz neće biti izvršeni. Dakle, da biste potvrdili da se __run_exit_handlers()
izvršava, možete postaviti prekidnu tačku na nju.
Važan kod je (izvor):
Primetite kako se map -> l_addr + fini_array -> d_un.d_ptr
koristi za izračunavanje pozicije niza funkcija za pozivanje.
Postoje nekoliko opcija:
Prepisati vrednost
map->l_addr
kako bi pokazivala na lažnifini_array
sa instrukcijama za izvršavanje proizvoljnog kodaPrepisati unose
l_info[DT_FINI_ARRAY]
il_info[DT_FINI_ARRAYSZ]
(koji su više-manje uzastopni u memoriji), kako bi pokazivali na lažnu strukturuElf64_Dyn
koja će ponovo nateratiarray
da pokazuje na memoriju kojom upravlja napadač.Ovaj opis prepisuje
l_info[DT_FINI_ARRAY]
sa adresom kontrolisane memorije u.bss
koja sadrži lažnifini_array
. Ovaj lažni niz sadrži prvo adresu jednog alata koja će biti izvršena, a zatim razliku između adrese ovog lažnog niza i vrednostimap->l_addr
tako da će*array
pokazivati na lažni niz.Prema glavnoj objavi ove tehnike i ovom opisu ld.so ostavlja pokazivač na steku koji pokazuje na binarni
link_map
u ld.so. Pomoću proizvoljnog pisanja moguće je prepisati ga i naterati da pokazuje na lažnifini_array
koji kontroliše napadač sa adresom jednog alata na primer.
Nakon prethodnog koda možete pronaći još jedan interesantan odeljak sa kodom:
U ovom slučaju bilo bi moguće prebrisati vrednost map->l_info[DT_FINI]
koja pokazuje na lažiranu strukturu ElfW(Dyn)
. Pronađite više informacija ovde.
Prepisivanje TLS-Storage dtor_list-a u __run_exit_handlers
__run_exit_handlers
Kao što je objašnjeno ovde, ako program završi putem return
ili exit()
, izvršiće se __run_exit_handlers()
koji će pozvati sve registrovane funkcije destruktora.
Kod iz _run_exit_handlers()
:
Kod iz __call_tls_dtors()
funkcije:
Za svaku registrovanu funkciju u tls_dtor_list
, demantovace pokazivac iz cur->func
i pozvace je sa argumentom cur->obj
.
Koriscenjem tls
funkcije iz ovog forka GEF-a, moguce je videti da je dtor_list
veoma blizu stack canary-ja i PTR_MANGLE cookie-ja. Dakle, prelivanjem preko njega bilo bi moguce prepisati cookie i stack canary.
Prelivanjem PTR_MANGLE cookie-ja, bilo bi moguce zaobici funkciju PTR_DEMANLE
postavljanjem je na 0x00, sto znaci da je xor
koji se koristi za dobijanje prave adrese samo adresa koja je konfigurisana. Zatim, pisanjem na dtor_list
moguce je povezati nekoliko funkcija sa funkcijom adrese i njenim argumentom.
Na kraju primetite da sacuvani pokazivac nece biti samo ekskluzivno xorovan sa cookie-jem vec i rotiran za 17 bitova:
Dakle, morate uzeti ovo u obzir pre dodavanja nove adrese.
Pronađite primer u originalnom postu.
Ostali izmenjeni pokazivači u __run_exit_handlers
__run_exit_handlers
Ova tehnika je objašnjena ovde i ponovo zavisi od programa koji izlazi pozivajući return
ili exit()
tako da se poziva __run_exit_handlers()
.
Pogledajmo više koda ove funkcije:
Promenljiva f
pokazuje na strukturu initial
i u zavisnosti od vrednosti f->flavor
biće pozvane različite funkcije.
Adresa funkcije koja će biti pozvana biće na različitom mestu u zavisnosti od vrednosti, ali će uvek biti demangleovana.
Osim toga, u opcijama ef_on
i ef_cxa
takođe je moguće kontrolisati argument.
Moguće je proveriti strukturu initial
u sesiji za debagovanje sa GEF pokretanjem gef> p initial
.
Da biste iskoristili ovo, potrebno je ili procureti ili izbrisati PTR_MANGLE
kolačić a zatim prepisati cxa
unos u initial sa system('/bin/sh')
.
Primer ovoga možete pronaći u originalnom blog postu o tehnici.
Last updated