string_format_read
Differences
This shows you the differences between two versions of the page.
| Both sides previous revisionPrevious revisionNext revision | Previous revision | ||
| string_format_read [2025/02/08 14:33] – kresimir | string_format_read [2025/12/01 11:40] (current) – external edit 127.0.0.1 | ||
|---|---|---|---|
| Line 1: | Line 1: | ||
| ====String format read/ | ====String format read/ | ||
| - | Format string read napad iskorištava dinamiku funkcija s formatiranim stringovima i načina na koji se argumenti dodjeljuju tim funkcijama. | + | Format string read napad iskorištava dinamiku funkcija s formatiranim stringovima i načina na koji se argumenti dodjeljuju tim funkcijama. Moguć je onda, kad ranjiva aplikacija dozvoljava korisniku-napadaču da definira format string naredbe " |
| - | Uzmimo | + | Uzmimo |
| printf(" | printf(" | ||
| - | %s označava „placeholder” za string varijablu koji će printf ispuniti zadanim argumentom username i zatim ispisati rezultat. | + | %s označava „placeholder” za string varijablu koji će printf ispuniti zadanim argumentom username i zatim ispisati rezultat. Interno, printf prati svaki placeholder (npr. %s, %d, %x, %p …) i očekuje da je svaki potkrijepljen dodatnim argumentom kako bi ga popunio. Npr. |
| - | Interno, printf prati svaki placeholder (npr. %s, %d, %x, %p ...) i očekuje da je svaki potkrijepljen dodatnim argumentom kako bi ga popunio. | + | |
| - | Npr. | + | |
| printf(" | printf(" | ||
| mora sadržavati 2 dodatna argumenta uz početni string (dakle first_name i last_name) kako bi ispravno radio. | mora sadržavati 2 dodatna argumenta uz početni string (dakle first_name i last_name) kako bi ispravno radio. | ||
| Line 12: | Line 10: | ||
| Ranjivost: | Ranjivost: | ||
| Ako programer definira ispis varijable uz pomoć formatirane funkcije bez da zada ispravan broj argumenta, formatirana | Ako programer definira ispis varijable uz pomoć formatirane funkcije bez da zada ispravan broj argumenta, formatirana | ||
| - | funkcija ne može razaznati radi li se o grešci ili ne zbog čega uzima argumente | + | funkcija ne može razaznati radi li se o grešci ili ne zbog čega će uzeti onoliko argumenata koliko je definirano u format stringu. Prvih pet uzima iz registara sačuvanih |
| - | (argumenti 7 itd...) kako bi popunila zadane formate. | + | |
| Primjer: | Primjer: | ||
| printf(„%p %p”); | printf(„%p %p”); | ||
| - | Ispisat će se sadržaji argumenata 2 i 3 (koji zapravo ne postoje, već će se uzeti s tih pozicija u memoriji: x64 konvencija, | + | Ispisat će se sadržaji argumenata 2 i 3 (koji zapravo ne postoje, već će se uzeti s tih pozicija u memoriji: x64 konvencija, |
| - | u formatu pointera: | + | |
| printf(format); | printf(format); | ||
| Ekvivalent gornjem primjeru, ispisat će se sadržaj u memoriji koji bi sadržavao argumente na 2 i 3 u formatu pointera. | Ekvivalent gornjem primjeru, ispisat će se sadržaj u memoriji koji bi sadržavao argumente na 2 i 3 u formatu pointera. | ||
| X64 konvencija na linuxu definira da se argumenti za funkcije nalaze redom: | X64 konvencija na linuxu definira da se argumenti za funkcije nalaze redom: | ||
| - | Unutar funkcije registri koji sadrže argumente pushaju se na stog nakon lokalnih varijabli. | + | Unutar funkcije, registri koji sadrže argumente pushaju se na stog nakon lokalnih varijabli. |
| Zbog toga format string read napad omogućava napadaču da čita proizvoljan broj podataka sa stoga ako je korisniku dopušteno definiranje format stringa. | Zbog toga format string read napad omogućava napadaču da čita proizvoljan broj podataka sa stoga ako je korisniku dopušteno definiranje format stringa. | ||
| Maksimalan broj argumenata koje registri mogu sadržavati jest 6. | Maksimalan broj argumenata koje registri mogu sadržavati jest 6. | ||
| - | RDI (prvi registar) sadrži | + | RDI (prvi registar) sadrži |
| - | To znači da ako se unese veći broj formata | + | To znači da ako se format string definira |
| - | argumente sa stoga koji prethode base pointeru. | + | |
| ====Kupon==== | ====Kupon==== | ||
| Line 49: | Line 45: | ||
| printf(input) | printf(input) | ||
| - | nalazi se ranjivost string format reada. Unutar polja kupon veličine 48 bajtova nalazi se flag. Dakle potrebno je ispisati vrijednost flag-a sa stoga uz pomoć | + | nalazi se ranjivost string format reada. Unutar polja kupon veličine 48 bajtova nalazi se flag. Dakle potrebno je ispisati vrijednost flag-a sa stoga uz pomoć |
| - | string format | + | |
| - | zbog optimizacije stoga, no u ovom slučaju poredak je sačuvan, za provjeru uvijek je moguće ručno pregledati stog uz pomoć gdb-a). | + | To znači da će se nakon poziva nove funkcije polje kupon nalaziti na adresama iznad postavljene |
| - | To znači da će se nakon poziva nove funkcije polje kupon nalaziti na adresama iznad postavljenje | + | |
| - | namijenjena argumentima 7 pa nadalje. Dakle, ako u polje input upišemo // | + | |
| za argumente 2-6, a preostalih 6 //%p// će ispisati sadržaj cijelog polja kupon (jer mu je veličina 48 bajtova, a jedan pointer je veličine 8 bajtova). | za argumente 2-6, a preostalih 6 //%p// će ispisati sadržaj cijelog polja kupon (jer mu je veličina 48 bajtova, a jedan pointer je veličine 8 bajtova). | ||
| Nakon ispisa danih adresa od 6. pointera pa nadalje jest sadržaj polja kupon. Taj sadržaj je potrebno provući kroz hex converter u tekst i time će se dobiti sadržaj polja kupon. | Nakon ispisa danih adresa od 6. pointera pa nadalje jest sadržaj polja kupon. Taj sadržaj je potrebno provući kroz hex converter u tekst i time će se dobiti sadržaj polja kupon. | ||
| Line 59: | Line 53: | ||
| ----- | ----- | ||
| Napomena 1: | Napomena 1: | ||
| - | Zbog little endian zapisa, %p format očekuje da su na nižim adresama bajtovi manjih potencija, a sami zapis stringa je poredan od niže adrese prema višoj zbog čega | + | Zbog little endian zapisa, %p format očekuje da su na nižim adresama bajtovi manjih potencija, a sami zapis stringa je poredan od niže adrese prema višoj zbog čega je svaki bajt stringa unutar pointera ispisan obrnutim redoslijedom. Posljedično tome završetak stringa (opisan s newline \n tj. \x0a u hex formatu) " |
| - | je svaki bajt stringa unutar pointera ispisan obrnutim redoslijedom. Posljedično tome završetak stringa (opisan s newline \n tj. \x0a u hex formatu) " | + | Recimo da je ispis nekog pointera |
| - | Recimo da je ispis nekog pointer | + | |
| pointera kako bi se ispisale ispravne vrijednosti: | pointera kako bi se ispisale ispravne vrijednosti: | ||
| Line 132: | Line 125: | ||
| Prva adresa koja tome odgovara je na offsetu 20 od vrha stacka (tj. rsp-a) prikazano crvenom strelicom. | Prva adresa koja tome odgovara je na offsetu 20 od vrha stacka (tj. rsp-a) prikazano crvenom strelicom. | ||
| - | Jedan offset odgovara 8 bajtova pošto je to zadana veličina argumenta //%p//. Međutim za dohvatiti tu adresu format string read napadom potrebno je upisati //%25$p//, a ne //%20$p// zato što se po Linux call konvenciji prvih 5 argumenata uvijek nalaze u registrima. Stoga, tek nakon 5. argumenta se vrijednost krenu uzimati s vrha stoga. | + | Jedan offset odgovara 8 bajtova pošto je to zadana veličina argumenta //%p//. Međutim za dohvatiti tu adresu format string read napadom potrebno je upisati //%25$p//, a ne //%20$p// zato što se po Linux call konvenciji prvih 5 argumenata uvijek nalaze u registrima. Stoga, tek nakon 5. argumenta se vrijednosti počnu |
| Nakon toga je potrebno kroz debugger vidjeti koliki je offset od adrese koje smo dobili do pohranjene //return// adrese (pohranjenu //return// adresu možemo vidjeti npr. naredbom telescope $rbp). | Nakon toga je potrebno kroz debugger vidjeti koliki je offset od adrese koje smo dobili do pohranjene //return// adrese (pohranjenu //return// adresu možemo vidjeti npr. naredbom telescope $rbp). | ||
| Line 207: | Line 200: | ||
| {{pwntools_fmt_str.png}} | {{pwntools_fmt_str.png}} | ||
| - | Automatiziranje exploita se može postići uz pomoć pwntoolsa. Iako postoje 2 načina automatiziranja (jedan s FmtStr objektom, a drugi s fmtstr_payload funkcijom), ovdje će se proći | + | Automatiziranje exploita se može postići uz pomoć pwntoolsa. Iako postoje 2 načina automatiziranja (jedan s FmtStr objektom, a drugi s fmtstr_payload funkcijom), ovdje će se prikazati |
| Funkcija fmtstr_payload kao argumente prima offset do prvog kontroliranog argumenta printf funkcije i dictonary u obliku {adresa: | Funkcija fmtstr_payload kao argumente prima offset do prvog kontroliranog argumenta printf funkcije i dictonary u obliku {adresa: | ||
string_format_read.1739025212.txt.gz · Last modified: 2025/12/01 11:40 (external edit)