码迷,mamicode.com
首页 > 其他好文 > 详细

栈中的"垃圾"

时间:2018-02-27 21:20:12      阅读:139      评论:0      收藏:0      [点我收藏+]

标签:include   ever   参考   32位   技术   技术分享   gdb   ==   ring   

最近看了一点点栈的知识,顺手写下来之前不清楚的点

在调用一个函数的时候,会用栈来存储信息,在这个函数调用结束之后栈上这一部分东西会被清除,通常的汇编代码为 (以32位为例)

push    ebp
mov     esp, ebp
sub     esp, xxx (xxx为这一函数所用的栈的空间大小)
... ...
mov     esp, ebp
pop     ebp
ret

这一段汇编中 EBP 位置不变,最后回到原点,意思也就是没清除栈上剩余 “ 垃圾 ” 仅是将 ESP 拉回来,再 pop EBP,这样栈上的 “ 垃圾 ” 可能会污染到接下来的函数调用,以下就是我看的文章举得一个小栗子

#include <stdio.h>

void f1()
{
        int a=1, b=2, c=3;
};
void f2()
{
        int a, b, c;
        printf ("%d, %d, %d\n", a, b, c);
};
int main()
{
        f1();
        f2();
};

这个编译之后得到的结果是

1, 2, 3

为什么产生这个结果,就跟我上面所说的有关,接下来我们进入 gdb 调试一下,不过我将它的代码增加了一点

事先声明,由于我还没搞成功 32 位 C 的编译器,所以用的 64 位的 ??

#include <stdio.h>

void g1()
{
    int a=0, b=3, c=5;
    return ;
}
void g2()
{
    int a,b,c;
    printf("%d %d %d\n", a, b, c);
    return ;
}

void f1()
{
    int x=4, y=5;
    g1();
    g2();
    return ;
}
void f2()
{
    int x, y, z;
    printf("%d %d %d\n", x, y, z);
    return ;
}


int main()
{
    f1();
    f2();

    return 0;
}

先是进行 f1, f1 中用的上述文章中的小栗子,再进行 f2 , 这个得到的结果如下

0 2 3
4 5 21912/21952/... (由于我只 int 两个值,所以 最后一个 z 是从栈上取得,因此是随机的)

我们来看一下这几个函数的 RBP 和 汇编

我先设了四个断点, f1 f2 g1 g2,接下来我们要从汇编层次来验证 F1_RBP == F2_RBP,G1_RBP == G2_RBP

接下来的图分别是, F1,G1,G2,F2,G2 的 print,F2 的 print,F1和G1 的第一箭头是将局部变量存储的位置,G2和F2 的第一个箭头都是 格式化字符串取的值的位置,这四个的第二箭头都是 RBP

技术分享图片

技术分享图片

技术分享图片

技术分享图片

技术分享图片

技术分享图片

技术分享图片

通过两个 print 也可以验证,为什么会产生这种结果

参考文章是 reverse-engineering-for-beginners 的翻译

栈中的"垃圾"

标签:include   ever   参考   32位   技术   技术分享   gdb   ==   ring   

原文地址:https://www.cnblogs.com/Vangelis/p/8480587.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!