利用栈帧改变变量的值及强行插入第三个函数
来源:互联网 发布:淘宝网怎么收藏宝贝 编辑:程序博客网 时间:2024/06/06 08:29
利用栈帧 改变另一个变量的值
在之前学习了栈帧结构后,我们可不可以不通过某一个变量名来改变该变量的值?
答案是可以的。代码如下:
#include <stdio.h>#include <windows.h>int Myadd(int x,int y){ int z=0; int *p=&x; p++; printf("Myadd:%#x\n",*p); *p=10; printf("Myadd:%#x\n",*p); z=x+y; return z;}int main(){ int a=0xAAAAAAAA; int b=0XBBBBBBBB; int c=Myadd(a,b); printf("you should run here!\n"); printf("result:%d\n",c); system("pause"); return 0;}
其实很简单,我们对x取地址,当前指针指向x的地址,令指针下移即可指向b,可以通过指针来改变b变量的值,实际上在这个过程中,我们并没有通过b变量的变量名来改变b的值。
强行插入第三个函数
通过栈帧结构,我们知道函数调用返回时,是要将call命令的下一条指令的地址压入栈中,如果我们通过改写这个地址,是否可以强行跳转至我们想要程序跳转的函数,如果可以,那么该如何返回本身应该执行的函数呢?
下面我们具体说明一下:
#include <stdio.h>#include <windows.h>int bug(){ Sleep(1000); printf("i am a bug!\n"); Sleep(3000); system("pause");}int Myadd(int x,int y){ int z=0; int *p=&x; p--; *p=bug; z=x+y; return z;}int main(){ int a=0xAAAAAAAA; int b=0XBBBBBBBB; int c=Myadd(a,b); printf("you should run here!\n"); printf("result:%d\n",c); system("pause"); return 0;}
类似于修改变量的例子,我们通过修改指针的位置可以找到之前被压入栈中的main函数的返回地址,并且通过改写改地址(修改为我们要插入函数的地址),使得函数Myadd并没有返回main函数而是跳转至了我们自己写的bug函数。
在实际运行时,我们可以发现程序确实是跳转进了我们的bug函数中,但实际上,程序在结束时是挂掉的,因为我们并没有处理如何从bug函数返回我们的main函数。
我们回想一下刚才我们是强行跳转至第三函数的,是通过修改栈中main函数的返回地址来实现的,但是我们并没有将这个地址保存下来,所以我们从bug函数想要回到main函数,程序也不知道他要回到那里继续执行,所以这个操作必须由我们完成。
#include <stdio.h>#include <windows.h>void *main_ret = NULL;int bug(){ int first=0; int *p=&first; p+=2; *p=main_ret; Sleep(1000); printf("This is bug!\n"); Sleep(3000);}int Myadd(int x,int y){ int z=0; int *p=&x; p--; printf("begin...Myadd\n"); main_ret=*p; *p=bug; z=x+y; printf("end...Myadd\n"); return z;}int main(){ int a=10; int b=20; int c=0; printf("begin...main\n"); c = Myadd(a, b); _asm{ sub esp,4 }//平衡栈帧 printf("This is main!\n"); printf("result:%d\n",c); printf("end...main\n"); system("pause"); return 0;}
通过这个截图我们可以看到函数调用的过程:
main函数–>Myadd–>bug–>main
调用Myadd函数使用了call指令,而调用bug函数是通过更改地址的方式,但返回时两个函数均使用了ret指令才能返回。
_asm是在c语言中插入汇编代码,令esp-4是为了平衡esp的位置,在我们返回main函数时,通过我们的人为操作,esp相比于正常状态是不平衡的,所以我们通过在c语言中插入一段汇编代码来平衡栈帧。
以上:就是通过栈帧结构来改变变量的值,或者强行改变函数跳转。
因此我们在写程序中,对于调用函数的过程要非常清楚,并且还要函数在调用过程中关心内存的变化、返回值、几个函数跳转的过程。
- 利用栈帧改变变量的值及强行插入第三个函数
- 不利用第三个变量交换两个数字的值
- 交换两个变量的值,不使用第三个变量的方法及实现
- 不用第三个变量及其他函数等交换两个变量的值
- 不用第三个变量交换2个变量的值
- 交换两个变量的值不使用第三个变量
- 不用第三个变量交换两个变量的值
- 交换两个变量的值,不使用第三个变量
- 不用第三个变量,直接交换两个变量的值
- 不使用第三个变量,交换两个变量的值!
- 不用第三个变量,直接交换两个变量的值
- 交换两个变量的值,不使用第三个变量
- 不通过第三个变量来交换两个变量的值
- 不用第三个变量实现交换两个变量的值
- 交换两个变量的值,不使用第三个变量
- 交换两个变量的值,不使用第三个变量
- 不用第三个变量,直接交换两个变量的值
- 不使用第三个变量 交换两个变量的值
- JSON数据格式解析(面向对象概念的体现)
- MySQL(三)复制
- MyEclipse2014 优化设置
- js防止表单重复提交
- Leetcode解题笔记 70. Climbing Stairs [Easy] 动态规划
- 利用栈帧改变变量的值及强行插入第三个函数
- 【干货】Chrome插件(扩展)开发全攻略
- 人工神经网络基础数学研究-卷积
- CentOS7.0下安装Apache2.4.20版本,安装完成之后,报 You don't have permission to access / on this server.
- 找不org.springframework.boot.context.embedded.FilterRegistrationBean
- 身份证校验 日期 长度格式 表达式
- list集合通过ajax 在页面显示 、 以及省市级联查询
- Error:Flavor 'prod' has no flavor dimension
- spring bean的获取方式