又是一周加班时,趁还没开始做事,写了个栈溢出的小程序.不了解的人可能会觉得结果很难理解,但要是了解了栈结构及函数调用的具体过程后就会知其所以然.
#include <stdio.h>
void Test(int a,int b)
{
char str[40];
strcpy(str,"This is Test(). Welcome to the hell, baby!\n");
printf(str);
exit(1); //退出主进程.必要的,要不程序莫名其妙来到这里后发现没路走了,会崩掉
}
int Test2(char *sStr)
{
char str[8];
memcpy(str,sStr,16);
printf("Test2() return!\n");
return 0;
}
typedef void (*TEST)(int,int);
int main()
{
TEST t = Test;
int val = (int)t;
int str[] ={val,val,val,val,0};
Test2((char*)str);
printf("Right place!\n");
return 0;
}
输出为:
Test2() return!
This is Test(). Welcome to the hell, baby!
原因:用函数Test的地址替换掉了Test2调用的EIP的值,修改掉了函数返回的下一条指令,程序在Test2执行结束后被非法引向了Test.
所以在对栈内存进行内存操作时千万小心,别出轨了,否则会把栈上的重要信息冲掉,把程序指令流引向未知区域.栈的这种特性也被一些心思缜密的黑客高手利用,把程序引向自己预先设定好的指令段,这些指令段性质的好坏就视那位黑客的人品而论了.
附:栈结构
----------------------------
参数N ↓高地址
参数… 函数参数入栈的顺序与具体的调用方式有关
参数 3
参数 2
参数 1
----------------------------
EIP 返回本次调用后,下一条指令的地址
EBP 保存调用者的EBP,然后EBP指向此时的栈顶。
----------------------------
临时变量1
临时变量2
临时变量3
临时变量…
临时变量5 ↓低地址








