透析栈帧——栈帧的应用

一、不调用变量本身,而修改该变量的数据

【示例代码】

#include <stdio.h>

int myadd(int x, int y)
{
	int *p = &x;
	p++;
	printf("before: %d\n",*p);
	*p = 30;
	printf("after: %d\n", y);
}

int main()
{
	int a = 10;
	int b = 20;

	myadd(a, b);

	printf("main:you should running here!\n ");

	return 0;
}

【图解】

【说明】

首先,让指针p指向x的地址,p++后指针向上移动,此时p指向y的地址,故而*P==y==20; 当给*p赋值30后,此时p仍指向y的地址,相当于给y赋值,所以y==30。

【执行结果】

 

二、非法调用第三方函数

【示例代码】

#include <stdio.h>

void *ret = NULL;

void bug()
{
	int x;
	int *q = &x;
	q += 2;
	*q = ret;
	printf("bug: I am bug!\n");
	Sleep(2000);
}

int myadd(int x, int y)
{
	int *p = &x;
	p--;
	ret = *p;
	*p = bug;
	printf("myadd: myadd is called,begin return...\n");
}

int main()
{
	int a = 10;
	int b = 20;
	int c = myadd(a, b);
	__asm{                  
		sub esp,4
	}
	printf("main:you should running here!\n ");

	return 0;
}

【说明】

在栈帧结构中,函数调用返回时,是利用函数被调用之前所保存call指令的下一条指令的地址而回到main函数,当我们改写这个地址时,此时函数便可强行跳转至另一个函数中去。

对于上述代码而言,函数的调用过程为:main函数—>myadd函数—>bug函数—>main函数

  • 在main函数中 

执行到c=myadd(a,b)语句时,程序跳转至myadd函数

  • 在myadd函数中

(1)指针p先指向x的地址

(2)执行p--找到main函数的返回地址

(3)将该地址保存(ret=*p)

(4)将p指向的地址改为bug函数的返回地址

(5)执行输出语句

(6)myadd函数结束,程序跳转至bug函数

  • 在bug函数中

(1)定义变量x,定位bug函数

(2)指针q先指向x的地址

(3)执行q+=2语句找到执行完bug函数后所要返回的地址

(4)执行*q=ret语句将该地址改为main函数的返回地址

(5)执行输出语句

(6)休眠2s

(7)bug函数结束,程序跳转至main函数

  • 在main函数中

执行__asm{ sub esp,4} 语句,在c语言中插入汇编代码,sub esp,4 就是 esp-4 ,目的是平衡栈帧。每一个函数在被调用时都是通过call指令调用的,此时执行push指令将地址入栈,在调用完返回时是通过ret指令返回的,此时执行pop指令将地址出栈,一入一出,栈帧刚好平衡。在调用bug函数时,我们是通过修改地址的方式调用的,没有执行push指令,但在返回时,我们通过ret指令返回,执行了pop指令,无入有出,此时栈帧结构不平衡,所以我们要执行esp-4这步语句来使栈帧结构达到平衡。

【执行结果】

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值