函数调用栈学习笔记(做两个利用函数调用栈实现的例子)

本文详细介绍了利用函数调用栈平衡原理实现的栈回溯与溢出修复技术,包括如何在不同函数中记录和修改栈帧,确保程序在遇到异常情况时能够正确返回并执行后续代码。通过实际代码示例,展示了如何在不完全调用特定函数的情况下,通过修改栈帧属性来实现栈修复,确保程序的稳定性和安全性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

利用函数调用栈平衡原理实现溢出调用(有点类似于栈溢出,只不过这里是直接修改,也可以命使用溢出方式实现)
============================================================================================
#include <stdio.h>
#include <string.h>


unsigned int oldEbpAddress = 0;
unsigned int oldRetAddress = 0;


typedef void (*pf)();

//这里只能修复到继续返回main执行,但是在main函数结束时栈被破坏,报异常
void fun2()
{
	//记录老EBP地址
	__asm mov [oldEbpAddress],ebp


	//通过老EBP找出函数返回地址,并给它设置原函数返回地址
	*((unsigned int*)(oldEbpAddress + 4)) = oldRetAddress;


	printf("fun2\n");
}

//这里采用naked模式编写fun2完美实现栈修复,可以与上面的进行比较看效果
char *str = "fun2\n";
void __declspec(naked) fun2()
{
	__asm 
	{
		//压入函数返回地址
		push  oldRetAddress

		//调用printf函数
		push offset str
		call dword ptr printf	//注意这里的dword ptr
		add esp, 4	//自己维护栈平衡

		ret	//函数返回
	}
}

void fun()
{
	//记录老EBP地址
	__asm mov [oldEbpAddress],ebp

	//通过老EBP记录下函数返回地址,在fun2中再使用
	oldRetAddress = *((unsigned int*)(oldEbpAddress + 4));

	//通过老EBP修改函数返回地址为fun2函数首地址
	*((unsigned int*)(oldEbpAddress + 4)) = (unsigned int)(pf)fun2;printf("fun\n");

}

//说明:这里我们没能调用函数fun2,但是由于我们在fun函数中对返回地址做了一系列修改让fun2也得到了执行机会,
//同时在fun2中对栈也做了一个简单处理能返回main函数继续执行
int main()
{
	printf("main\n");
	fun();
	printf("main next\n");
	getchar();
}

=====================================================利用函数调用栈平衡原理实现栈回溯=====================================================
#include <stdio.h>
#include <Windows.h>

int fun3()
{
	unsigned int ebpAddress;
	unsigned int ebpPreviousAddress;

	printf("----------------fun3------------------\n");

	__asm mov [ebpAddress],ebp //得到当前函数EBP

	ebpPreviousAddress = *((unsigned int*)ebpAddress); //EBP地址中保存的值为来自调用函数的EBP值

	printf("0x%08X\n", ebpPreviousAddress);

	//循环执行上面的步骤
	while(1){
		__try{

			ebpAddress = ebpPreviousAddress;
			ebpPreviousAddress = *((unsigned int*)ebpAddress);
			printf("0x%08X\n", ebpPreviousAddress);
		}
		__except(EXCEPTION_EXECUTE_HANDLER){

			//这里一直回溯到无法回溯时产生异常退出回溯
			break;
		}
	}
	return 0;
}

int fun2()
{
	printf("----------------fun2------------------\n");
	fun3();
	return 0;
}

int fun1()
{
	printf("----------------fun1------------------\n");
	fun2();
	return 0;
}

int _tmain(int argc, _TCHAR* argv[])
{
	fun1();
	getchar();
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值