-------- ELF32 UNIX DOSYA SISTEMLERINDE GLOBAL_CONSTRUCTOR ve GLOBAL_DESTRUCTOR PATLAMALARI-------- Author : murderkey Contact: murderkey[_*at*_]hellcode.net Visit : http://www.hellcode.net/mkey Date : 12/20/2005 $$$$$$$$$$$$$$$$$$$$ $$$$$$$$$$$$$$$$$$$$$$$ $$$$$$$$$$$$$$$$$$$$$$$$ $$$$$$$$$$$$$$$$$$$$$$$$$$ Bu ufak dokumanda elf32 dosya sistem yapisinda bulunan global_constructor ve global_destructor lar nasil patlatilir onu gostermeye calisacagim. Aslinda bu yaziyi ozel olarak hazirlamadim, __inline__ assembly kodlarken constructorlara fonksiyon atamasi yapmam gerekti ve burda kullandigim datalarin birinde overflow (hafiza tasmasi) meydana geldigi icin, ilgilenen assembly programcilarina bir fikir olsun diye yaziyorum. NOT: Bu tur bi hafiza tasmasiyla daha once karsilasmadim, zaten real time programlarda bu tur aciklarin bulunma olasiligi bir hayli dusuktur, cunku hic bir programci constructor atamasi veya destructor atamasi yapmaya ihtiyac duymaz, bunlara ihtiyac duyan kisiler bizim gibi C programlama dilinin yetmedigi yerlerde __inline__ assembly kullanan kisilerdir. Evet asagidaki vulnerable program uzerinde calisiyoruz. #include #include #include static void murderkey_morfin() __attribute__ ((constructor)); static void murderkey_extasy() __attribute__ ((destructor)); int main(void) { fprintf(stderr," program main fonksiyonu calistirabilecekmi ?\n"); return(EXIT_SUCCESS); } static void murderkey_morfin() { char overdoze[0x16]; printf("Program matrixe girmeden cakilacak -> SIGSEGV\n"); strcpy(&overdoze[0],"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"); return; } static void murderkey_extasy() { fprintf(stderr,"Program patlamazsa bu yaziyi gormeniz lazim\n"); return; } Evet gordugunuz gibi, program elf32 constructor kisminda murderkey_morfin() fonksiyonunu barindiriyor ve bu fonksiyon strcpy ile 20 bytelik bir hafizayi overflow ediyor. Burda onemli olan constructor ve destructorlarin main() fonksiyonundan once hafizaya yuklenmesi ve calistirilmasidir. Programimizi derleyip calistiralim bakalim ne olacak. h4x0r elf32 # gcc murderkey-overdoze.c -o murderkey-overdoze -W -Wall -ggdb3 h4x0r elf32 # ./murderkey-overdoze Program matrixe girmeden cakilacak -> SIGSEGV Segmentation fault h4x0r elf32 # Evet bizimde bekledigimiz gibi main() e girmeden once constructor larda programimiz patladi. SIGSEGV. Simdi bizim burda dikkat edecegimiz yer programin hafizayi nasil kullandigi ve bu aciktan istifade ederek exploit etmek. Programi Gdb ile attach edip hemen inceleyelim. h4x0r elf32 # gdb -q ./murderkey-overdoze Using host libthread_db library "/lib/libthread_db.so.1". (gdb) (gdb) maintenance info sections Exec file: `/root/elf32/murderkey-overdoze', file type elf32-i386. 0x08048134->0x08048147 at 0x00000134: .interp ALLOC LOAD READONLY DATA HAS_CONTENTS 0x08048148->0x08048168 at 0x00000148: .note.ABI-tag ALLOC LOAD READONLY DATA HAS_CONTENTS 0x08048168->0x0804819c at 0x00000168: .hash ALLOC LOAD READONLY DATA HAS_CONTENTS 0x0804819c->0x0804821c at 0x0000019c: .dynsym ALLOC LOAD READONLY DATA HAS_CONTENTS 0x0804821c->0x08048277 at 0x0000021c: .dynstr ALLOC LOAD READONLY DATA HAS_CONTENTS 0x08048278->0x08048288 at 0x00000278: .gnu.version ALLOC LOAD READONLY DATA HAS_CONTENTS 0x08048288->0x080482a8 at 0x00000288: .gnu.version_r ALLOC LOAD READONLY DATA HAS_CONTENTS 0x080482a8->0x080482b8 at 0x000002a8: .rel.dyn ALLOC LOAD READONLY DATA HAS_CONTENTS 0x080482b8->0x080482d8 at 0x000002b8: .rel.plt ALLOC LOAD READONLY DATA HAS_CONTENTS 0x080482d8->0x080482ef at 0x000002d8: .init ALLOC LOAD READONLY CODE HAS_CONTENTS 0x080482f0->0x08048340 at 0x000002f0: .plt ALLOC LOAD READONLY CODE HAS_CONTENTS 0x08048340->0x08048548 at 0x00000340: .text ALLOC LOAD READONLY CODE HAS_CONTENTS 0x08048548->0x08048563 at 0x00000548: .fini ALLOC LOAD READONLY CODE HAS_CONTENTS 0x08048580->0x0804868d at 0x00000580: .rodata ALLOC LOAD READONLY DATA HAS_CONTENTS 0x08048690->0x08048694 at 0x00000690: .eh_frame ALLOC LOAD READONLY DATA HAS_CONTENTS 0x08049694->0x080496a0 at 0x00000694: .ctors ALLOC LOAD DATA HAS_CONTENTS <----------- BURASI ILK GIRIS YERI 0x080496a0->0x080496ac at 0x000006a0: .dtors ALLOC LOAD DATA HAS_CONTENTS <----------- BURASI CIKIS YERI 0x080496ac->0x080496b0 at 0x000006ac: .jcr ALLOC LOAD DATA HAS_CONTENTS 0x080496b0->0x08049778 at 0x000006b0: .dynamic ALLOC LOAD DATA HAS_CONTENTS 0x08049778->0x0804977c at 0x00000778: .got ALLOC LOAD DATA HAS_CONTENTS 0x0804977c->0x08049798 at 0x0000077c: .got.plt ALLOC LOAD DATA HAS_CONTENTS 0x08049798->0x080497a4 at 0x00000798: .data ALLOC LOAD DATA HAS_CONTENTS 0x080497a4->0x080497ac at 0x000007a4: .bss ALLOC 0x00000000->0x000001e3 at 0x000007a4: .comment READONLY HAS_CONTENTS 0x00000000->0x00000078 at 0x00000988: .debug_aranges READONLY HAS_CONTENTS 0x00000000->0x0000001b at 0x00000a00: .debug_pubnames READONLY HAS_CONTENTS 0x00000000->0x00001bec at 0x00000a1b: .debug_info READONLY HAS_CONTENTS 0x00000000->0x000001d8 at 0x00002607: .debug_abbrev READONLY HAS_CONTENTS 0x00000000->0x0000034e at 0x000027df: .debug_line READONLY HAS_CONTENTS 0x00000000->0x00000068 at 0x00002b30: .debug_frame READONLY HAS_CONTENTS 0x00000000->0x00000025 at 0x00002b98: .debug_str READONLY HAS_CONTENTS 0x00000000->0x000037b3 at 0x00002bbd: .debug_macinfo READONLY HAS_CONTENTS Evet elf32 binarysinde .ctors yani global_constructor larimiz 0x08049694->0x080496a0 adresleri arasinda yer almakta. bizim fonksiyonumuz da burda yer almasi lazim. yani fonksiyondan kasitim murderkey_morfin() fonksiyonu. (gdb) info address murderkey_morfin Symbol "murderkey_morfin" is a function at address 0x804841d. (gdb) Evet murderkey_morfin() fonksiyon adresimiz hafizamizda .text segmentinde 0x804841d adresinde yer almakta. bakalim .ctors sectionunda bu adresimiz varmi (gdb) x/10x 0x08049694 0x8049694 <__CTOR_LIST__>: 0xffffffff 0x0804841d 0x00000000 0xffffffff 0x80496a4 <__DTOR_LIST__+4>: 0x08048449 0x00000000 0x00000000 0x00000001 0x80496b4 <_DYNAMIC+4>: 0x00000001 0x0000000c (gdb) Evet 0x0804841d __CTOR_LIST icinde cok guzel. bu demek oluyorki program main() e girmeden bu fonksiyonumuz calisacak. Programi gdb den calistiriyoruz. (gdb) run Starting program: /root/elf32/murderkey-overdoze warning: Unable to find dynamic linker breakpoint function. GDB will be unable to debug shared library initializers and track explicitly loaded dynamic code. Program matrixe girmeden cakilacak -> SIGSEGV Program received signal SIGSEGV, Segmentation fault. 0x08048546 in __do_global_ctors_aux () (gdb) 0x08048546 in __do_global_ctors_aux () <0-------- Evet tahmin ettiginiz gibi global_constructor de program patladi. Simdi hafizaya bakalim bizim kopyaladigimiz AAAAAA lar ne durumda, program exploit edilebilirmi ? (gdb) info registers eax 0xb7fdd538 -1208101576 ecx 0xb7fb71af -1208258129 edx 0x804864c 134514252 ebx 0x804977c 134518652 esp 0xbffff808 0xbffff808 ebp 0x414141 0x414141 esi 0x0 0 edi 0xbffff894 -1073743724 eip 0x8048546 0x8048546 eflags 0x10246 66118 cs 0x73 115 ss 0x7b 123 ds 0x7b 123 es 0x7b 123 fs 0x0 0 gs 0x0 0 (gdb) Evet tahmin ettigim gibi ebp overwrite olmus durumda . 0x414141 yani bizim AAA larimiz ile. burda aklimiza hemen off-by-one methodu ile exploit etmek geliyor ama bu taktik burda yemez, neden diye sorarsaniz program daha main() fonksiyonuna girmedi,yani hic bir frame icinde deiliz, isterseniz bunu gorebiliriz. (gdb) frame #0 0x08048546 in __do_global_ctors_aux () (gdb) evet gordugunuz gibi. (gdb) info frame Cannot access memory at address 0x414145 (gdb) burda yapilacak hic birsey yok. fakat strcpy() deki AAA lari biraz arttirirsaniz EIP overwrite olacaginiz gorursunuz. ben bilerek onu yapmadim eger oyle olsaydi return into libc teknigini kullanabilirdik. Simdi burda onemli olan sey global constructor ve destructor fonksiyonlarinin arguman alamamasi. zaten orda static void olarak tanimlanmis durumda. Burda yapmamiz gereken sey yine destructor ve constructor icine baska bi fonksiyon inject edip bunu calistirabilmek. 4 byte ile yapilabilecek birsey bu. cheers