//环境 centos 5.x
//程序实例1: #include<stdio.h> #include<stdlib.h> void bug() { system("reboot");//re boot system exit(0);//end process } int stack_test(int a,int b)//函数压栈中 依次压入 主函数a,b拷贝值,b在高地址 {//压栈顺序是参数从右到左,然后栈帧,而求值顺序则是undefined的,由编译器实现决定。 printf("before write: 0x%x\n",b);//输出写入前b值 int *p=&a; //p指向a p++; //p偏移向b *p=0xdddd;//*p值改变 b被改变 printf("after write: 0x%x\n",b); int c=0xcccc; return c; } int main() { int a=0xaaaa; int b=0xbbbb; int ret=stack_test(a,b); printf("you shoule run here\n"); return ; } //程序实例2: #include<stdio.h> #include<stdlib.h> void bug() { system("reboot");//reboot system exit(0);//end process } int stack_test(int a,int b) { int *p=&a; p--; *p=bug; int c=0xcccc; return c; } int main() { int a=0xaaaa; int b=0xbbbb; int ret=stack_test(a,b); printf("you shoule run here\n"); return ; } //输出结果:before write: 0xbbbb // after write: 0xdddd // you shoule run here //(gdb) p &a centos 下gdb调试信息 /* (gdb) p&a $1 = (int *) 0xbffff630 (gdb) p&b $2 = (int *) 0xbffff634 (gdb) p&p $3 = (int **) 0xbffff620 (gdb) p&c $4 = (int *) 0xbffff624 (gdb) n 14 p--; (gdb) p p $5 = (int *) 0xbffff630 (gdb) n 15 *p=bug; (gdb) p p $6 = (int *) 0xbffff62c (gdb) p *p $7 = 134513797 (gdb) n 21 int c=0xcccc; (gdb) p* p $8 = 134513684 (gdb) p bug $9 = {void ()} 0x8048414 <bug> (gdb) p& bug $10 = (void (*)()) 0x8048414 <bug> gdb) n 22 return c; (gdb) n 23 } (gdb) n bug () at process.c:5 5 { (gdb) n Breakpoint 2, bug () at process.c:6 6 system("reboot");//re boot system 由调试 信息和下图可得: 当函数调用时首先esp动 依次压入 形参b,a 返回函数指针 return(a add-4) 然后压入ebp 让ebp等于esp 此时ebp记录了返回信息之后 esp动依次压入局部变量 p c ,p开始指向a,p--后,p指向ebp指向空间,当p=bug后 p记录bug函数栈帧,return c 调用了bug 函数 系统重启*/
原文地址:http://shaungqiran.blog.51cto.com/10532904/1758969