免费注册 查看新帖 |

Chinaunix

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

Linux堆栈溢出的经典问题,欢迎围观!大牛前进 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2009-11-25 18:33 |只看该作者 |正序浏览
原帖请见:http://blog.chinaunix.net/u/26166/showart.php?id=198375

我的环境是redhant 9 ,2.4的核。由于对Linux环境下堆栈的不熟悉,所以就这个例子,做了一些哦测试。
我的代码:
  1. #include<stdio.h>

  2. void attack()
  3. {
  4. int attack=1;
  5. printf("hi,attacked!\n");
  6. }
  7. void yaya()
  8. {
  9. int yaya=1;
  10. printf("hi,yaya is my wife\n");
  11. }
  12. void foo()
  13. {
  14. int c_foo=1;
  15.   *(& c_foo +2)=(int)attack;
  16. }

  17. void main(){
  18. int a_main=1;
  19. a_main=(int)yaya;
  20. foo();
  21. }
复制代码


然后,gdb下观察结果:
main函数的反汇编:


yaya函数的反汇编


attack函数的反汇编:


foo函数的反汇编:


在main的堆栈中,a_main的值从1变为yaya函数的入口地址0x08048347,而进入foo函数之后,本来0xbfffe2cc存放的是main返回的地址0x0804839f,但是改为attack函数的入口地址0x08048328。
这样就会导致main函数无法正常返回。


下面是我画的堆栈示意图,请指教:


从函数foo返回后,就进入了attack函数了。

打印“hi,attacked!”成功!
接着,返回段错误。

我的问题:为什么yaya函数没有执行,就出现了段错误?
照文章中所述的,yaya函数的入口地址0x08048347已经放在了0xbfffe2d4,为什么eip会访问不到么?


[ 本帖最后由 GoldenSoldier 于 2009-11-26 09:17 编辑 ]

论坛徽章:
0
35 [报告]
发表于 2010-02-10 15:51 |只看该作者
不过你能写这么清楚,牛人

论坛徽章:
0
34 [报告]
发表于 2010-02-10 15:50 |只看该作者
void foo()

{

int c_foo=1;

  *(& c_foo +2)=(int)attack;

}
修改了foo入栈前保存的环境,当然会跳到attack那里,你把它改成main,它还会跳到main那里

论坛徽章:
0
33 [报告]
发表于 2009-12-16 23:31 |只看该作者
看了MIK得方法,我也尝试了一下:
#include<stdio.h>

void attack()
{
    int attack=1;
    printf("hi,attacked!\n");
}
void yaya()
{
    int yaya=1;
    printf("hi,yaya is my wife\n");
}
void foo()
{
    int c_foo=1;
    int addr = *(&c_foo+2);
    *(& c_foo +2)=(int)attack;
    *(&c_foo + 3)=addr;
}

void main(){
    int a_main=1;
    int addr = *(&a_main+2);
    *(& a_main+2)=(int)yaya;
    *(& a_main+3)=addr;
    foo();
}

论坛徽章:
0
32 [报告]
发表于 2009-12-12 13:15 |只看该作者
yaya执行了哦

论坛徽章:
0
31 [报告]
发表于 2009-12-04 19:25 |只看该作者
mark一下

论坛徽章:
0
30 [报告]
发表于 2009-11-30 00:20 |只看该作者
四不像

论坛徽章:
0
29 [报告]
发表于 2009-11-27 18:06 |只看该作者
不过对于你这个问题,更好的办法是利用函数的第一个参数的地址来获取函数的返回地址的地址

论坛徽章:
0
28 [报告]
发表于 2009-11-27 17:41 |只看该作者
unsigned long get_ebp(void)
{
        __asm__("movl %ebp, %eax");
}


要想学会这个汇编必不可少

[ 本帖最后由 学与思 于 2009-11-27 17:42 编辑 ]

论坛徽章:
0
27 [报告]
发表于 2009-11-27 15:25 |只看该作者
原帖由 mik 于 2009-11-26 22:12 发表


在你的代码里,你要使用 main() 正常退出,

必须把 调用 foo() 时的返回地址交由 yaya() 函数来返回

void foo()
{
       int c_foo = 1;

      int yaya_ret = (int) *(& c_foo + 2);
      * ...

明白你的意思了 ,就是把存储a_main的地址里的内容换成main函数返回的地址。
我尝试了一下,见下:
  1. void foo()
  2. {
  3.   int c_foo=1;
  4.   int main_ret=(int)*(& c_foo +2);
  5.   *(& c_foo +2)=(int)attack;
  6.   *(& c_foo +4)= (int) main_ret;
  7. }
复制代码
其他的代码都没变。
这样就OK了,最后测试通过,没有出现段错误! 嘿嘿

[ 本帖最后由 GoldenSoldier 于 2009-11-27 15:27 编辑 ]
  

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

清除 Cookies - ChinaUnix - Archiver - WAP - TOP