利用栈帧改变变量的值及强行插入第三个函数
2017-12-06 17:19
253 查看
利用栈帧 改变另一个变量的值
在之前学习了栈帧结构后,我们可不可以不通过某一个变量名来改变该变量的值?答案是可以的。代码如下:
#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语言中插入一段汇编代码来平衡栈帧。
以上:就是通过栈帧结构来改变变量的值,或者强行改变函数跳转。
因此我们在写程序中,对于调用函数的过程要非常清楚,并且还要函数在调用过程中关心内存的变化、返回值、几个函数跳转的过程。
相关文章推荐
- x264中open_file_yuv函数欣赏(顺便谈谈如何利用指针在被调函数中改变主调函数中变量的值)
- 利用函数将一个浮点型变量转化为二进制
- C++ 利用template给函数中的变量赋初值
- 栈帧——函数调用,变量在内存中如何存取
- C#利用类型引用改变private类型变量的值
- 当函数的参数中包括变量,而又想在函数执行时,改变该变量的值,使其返回,应该用指针
- const类型的成员函数内部如何改变成员变量
- 利用批处理或命令行永久改变环境变量
- 利用SYS_CONTEXT函数跟踪oracle字段内容无故改变
- delphi7与XE的变量与函数的改变
- c/c++笔试题——const类型的成员函数内部如何改变成员变量
- 不用第三个变量及其他函数等交换两个变量的值
- C语言中,如何通过函数来改变一个变量的值
- const 成员函数不能改变成员变量的值,但是可以改变成员函数localstack变量的值
- c/c++笔试题——const类型的成员函数内部如何改变成员变量
- 如何用eval()函数在局部函数内改变全局变量
- JS利用prototype改变元素实例的方法的变量作用域
- c/c++笔试题——const类型的成员函数内部如何改变成员变量
- qt信号和槽问题(变量只在槽函数中改变问题)