标题: 理解子程序程序调用的堆栈和寄存器的变化 [打印本页]

作者: 51黑tt    时间: 2016-3-6 00:16
标题: 理解子程序程序调用的堆栈和寄存器的变化
Hobo(756085934) 20:32:00
#incldue<stdio.h>
void print(void)
{
    printf("why here??");
}
void main(int argc,char** argv)
{
   int buf[1];
   buf[2]=print;
   return;
}
结果输出:
why here??
Hobo(756085934) 20:33:03
这种事情真的是太有意思了
扬(375357907) 20:34:35
hobo那个编译通不过啊
Hobo(756085934) 20:34:56
传说中缓冲区溢出,经常被黑客利用
扬(375357907) 20:35:15
怎么我编译有错误呢
Hobo(756085934) 20:35:14
编译能通过的,
扬(375357907) 20:35:23
are you sure?
Hobo(756085934) 20:35:28
sure
扬(375357907) 20:35:29
我用vc编译的通不过
Hobo(756085934) 20:35:43
你等我看下,我是不是哪里写错了
小屁孩(595605150) 20:35:53
这个咋能通过...
扬(375357907) 20:35:55
F:\程序\test\test.cpp(10) : error C2440: '=' : cannot convert from 'void (__cdecl *)(void)' to 'int'
        This conversion requires a reinterpret_cast, a C-style cast or function-style cast
F:\程序\test\test.cpp(11) : error C2562: 'main' : 'void' function returning a value
        F:\程序\test\test.cpp(7) : see declaration of 'main'
小车(15157102) 20:36:17
编译问题都不自行解决。说明还是初学者
Hobo(756085934) 20:36:48
#include<iostream>
using namespace std;
void print(void)
{
cout<<"why here??"<<endl;
_exit(0);
}
int main()
{
int buf[1] ;
buf[2] = (int)print;
cout<<"watch out what happenning.."<<endl;
return 1;
}
Hobo(756085934) 20:36:58
你再试试这个
Hobo(756085934) 20:37:50
通过没啊??
Hobo(756085934) 20:37:54
编译??
扬(375357907) 20:38:18
呵呵
扬(375357907) 20:38:33
void 的 main
金水火(57024564) 20:38:44
呵呵。
扬(375357907) 20:38:46
不过为什么啊,能解释下吗
Hobo(756085934) 20:39:15
需要汇编才能解释,我还有点蒙
扬(375357907) 20:39:48
why here?
Hobo(756085934) 20:39:48
具体细节在压栈退栈的时候
扬(375357907) 20:40:33
继续
Hobo(756085934) 20:40:46
我不懂汇编了,看不懂
Hobo(756085934) 20:41:18
进入main 函数后的栈内容下:
[ eip ][ ebp ][ buff[0] ]
高地址<---- 低地址
以上3 个存储单元中eip 为main 函数的返回地址,buff[0]单元就是buff 申明的一个int
空间。程序中我们定义int buff[1],那么只有对buff[0]的操作才是合理的(我们只申请
了一个int 空间),而我们的buff[2]=why_here 操作超出了buff 的空间,这个操作越界了,
也就是溢出了。溢出的后果是: 对buff[2]赋值其实就是覆盖了栈中的eip 存放单元的数
据,将main 函数的返回地址改为了why_here 函数的入口地址。这样main 函数结束后返回
的时候将这个地址作为了返回地址而加以运行。
Hobo(756085934) 20:41:27
原文的描述
小屁孩(595605150) 20:44:11

扬(375357907) 20:44:20
呵呵,明白了,学习学习
金水火(57024564) 20:44:21
相当于return print()?
小屁孩(595605150) 20:44:22
不对吧,怎么会执行
cyt(53238) 20:44:39
啥事?
小屁孩(595605150) 20:45:12
只是把函数指针强制转成int存放在未分配的空间了
Hobo(756085934) 20:45:14
返回地址应该是下一条指令执行的地址吧
金水火(57024564) 20:45:32
#incldue<stdio.h>
void print(void)
{
    printf("why here??");
}
void main(int argc,char** argv)
{
   int buf[1];
   buf[2]=print;
   return 1;
}
结果输出:
why here??
金水火(57024564) 20:45:36
cyt 看下
小屁孩(595605150) 20:45:52
我这没输出哎why here哎
扬(375357907) 20:46:00
我靠,真的?
扬(375357907) 20:46:08
可能是编译器的 问题?
Hobo(756085934) 20:46:15
  buf[2]=(int)print;
小屁孩(595605150) 20:46:55

小屁孩(595605150) 20:47:12
警告里面说了嘛,函数指针强制转换为int
Hobo(756085934) 20:47:12
return ;
不带1
小屁孩(595605150) 20:48:10
void print(void)
{
    printf("why here??\n");
_exit(0);
}
#if 1
int main(int argc, char* argv[])
{
  int buf[1];
   buf[2]=  (int)print;
   return 0;
}
小屁孩(595605150) 20:48:28

啥都没输出
小屁孩(595605150) 20:48:51
根本没进函数体哎
Hobo(756085934) 20:49:11
不会吧
cyt(53238) 20:49:33
hobo上面的解释基本正确呀,不过有个地方
进入main 函数后的栈内容下:
[ eip ][ ebp ][ buff[0] ]
那buff[1]覆盖的是ebp,不是eip呀
小屁孩(595605150) 20:49:55
为啥我执行没显示呢?
cyt(53238) 20:50:19
你的编译是不是设定了int缺省是64位呀?
Hobo(756085934) 20:50:36
我抄资料的,汇编不熟
cyt(53238) 20:51:18
哦,你写的是buff[2],是我看错
小屁孩(595605150) 20:51:54
cyt,为啥我执行没执行函数呢?
cyt(53238) 20:52:38
所以我你的编译器是不是指定了int是64位?
cyt(53238) 20:52:55
你用什么编译器?
金水火(57024564) 20:53:13
一般是vc吧
小屁孩(595605150) 20:53:16
32位,cl,vc2005
cyt(53238) 20:53:47
vc可以看汇编的呀,看看编译出来的汇编是什么?
扬(375357907) 20:54:45
我用gcc提示段错误
Hobo(756085934) 20:54:52
cyt,进入main后,ebp里放的是什么
cyt(53238) 20:56:33
堆栈里面放ebp,然后ebp记着当前的esp,然后esp往前增长,esp和ebp之间的就是传输参数
cyt(53238) 20:57:19
好像大概是这样子吧,太久不搞
cyt(53238) 20:57:49
哦,错了
Hobo(756085934) 20:59:00
那假如是一个int buffer[10]的话,是不是eip存放返回地址,ebp存放当前堆栈段的指针,紧接着是大小为10的数组?
cyt(53238) 20:59:32
应该是 eip返回地址,记录ebp,然后参数压栈,然后ebp = esp,然后esp往前增长。esp和ebp之间的就是函数内用的变量,ebp之前的就是参数。






欢迎光临 (http://www.51hei.com/bbs/) Powered by Discuz! X3.1