==== SROP ==== Program ima definiranu maksimalnu veličinu unosa od 500 preko direktive "#define INPUT_SIZE 500". Unutar main funkcije alocira se polje "buf" veličine INPUT_SIZE i ispisuje njegova adresa (stack leak). Najprije se poziva fgets kojim korisnik upisuje neku vrijednost u navedeno polje s maksimalnim unosom od INPUT_SIZE-1 (overflow nije moguć). Zatim se sscanf-om pokuša interpretirati koji broji je upisan u polje. Ako unesena vrijednost nije broj, program izlazi. Ako je intepretirana vrijednost broj, upisuje se na adresu varijable "a". Varijabla "a" je definirana kao short. To znači da varijabla može imati negativne vrijednosti. Nakon sscanf-a radi se sanity check nad vrijednosti varijable "a". Ako je vrijednost veća od INPUT_SIZE program izlazi. Pošto "a" može poprimiti negativne vrijednosti, sanity check smatra npr. "-1" ispravnim unosom. Zatim se pozivaju funkcije "myRead" i "myWrite". Varijabla "a" jest proslijeđena kao 3. argument funkciji myRead. int myRead(int fd_num, char* buf, unsigned short count){ register int fd asm("rdi") = 0; for(register int i asm("r8") = 0;i U deklaraciji funkcije 3. argument jest unsigned short. Ova vrsta primitiva (tj. ranjivosti) se naziva type confusion. Problem leži u tome što -1 i 65535 (2^16 - 1) dijele isti zapis u registru/memoriji. Ovisno o tome kako se interpretira varijabla, rezultat će biti ili negativan ili pozitivan. U ovom slučaju 3. argument je unsigned što znači da će broj biti pozitivan i time se dobije buffer overflow. Cilj jest dobiti sadržaj flag.txt datoteke. Pošto pozivanje execve syscalla nije zabranjeno, to je najlakše napraviti pozivanjem shella. Libc adresa je nepoznata i unutar datoteke (koja nije PIE) nema one-gadgeta ili korisnih ROP-gadgeta. Međutim, adresa syscalla je poznata te je poznata adresa funkcije koja namješta arbitrarnu vrijednost u rax (myRead). Na prvu bi se moglo razmišljati o namještanju registra rax na 59 (execve syscall) i pozivanje syscalla. Nažalost, rdi mora pokazivati na string "/bin/sh\x00" što nije moguće postići. Srećom, postoji vrsta napada SROP kojom je moguće namjestiti registre na proizvoljne vrijednost te je jedino potrebna adresa syscalla te funkcija koja arbitrarno postavlja rax. Kako bi se exploitao program najprije se pošalje "-1" za overflow. Zbog strukture programa, myWrite postavlja registar rdx na broj ispisanih karaktera do prve pojave null bajta. Uz to, namješta registar rsi da pointa na taj null bajt. Poslije njegovog poziva u main funkciji se pozivaju instrukcije "mov rax,0; leave; ret;". Postoje varijacije na payload koji se šalje, ključno je da poziv myRead funkcije nakon završetka main-a ima dovoljno velik rdx za upis 15 karaktera (sigreturn syscall) te da se upisom tih karaktera ne prepisuje argument "/bin/sh\x00". Izgled stack-a prije završetka main funkcije (prije ret): rsp: myRead(*,*,x>=15) rsp+1: syscall (sigreturn) rsp+2...: sigrame (rdi = "/bin/sh\x00",rsi = NULL, rdx = NULL, rax = execve, rip = syscall)