利用栈帧改变变量的值及强行插入第三个函数

来源:互联网 发布:淘宝网怎么收藏宝贝 编辑:程序博客网 时间: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语言中插入一段汇编代码来平衡栈帧。

以上:就是通过栈帧结构来改变变量的值,或者强行改变函数跳转。
因此我们在写程序中,对于调用函数的过程要非常清楚,并且还要函数在调用过程中关心内存的变化、返回值、几个函数跳转的过程。

阅读全文
0 0
原创粉丝点击