C/C++获取函数返回地址

本文讨论了在C/C++中获取函数返回地址的挑战,由于编译器优化如内联和函数打包的影响,该操作在某些场景如模块调用检查、自定义异常处理和异常信息记录等方面具有实用性。主流编译器提供了内建扩展来支持这一功能。
摘要由CSDN通过智能技术生成
一般而言, 能否覆盖函数返回地址是栈溢出攻击成功与否的前提, 而获取函数返回地址原理很简单, 栈回溯即可, 下面是x86上相应获取代码(仅为示例不可用于生产):
#define Stack_Length (4 * 4 * 4)
static void *_esp_arr[Stack_Length];
void *GetRet(void *caller)
{
	void *_esp;
	__asm mov _esp, esp
	for (int i = 0; i <= Stack_Length - 1; ++i) {
		_esp_arr[i] = &_esp[i];
	}
	DWORD Protect = 0x00, CodeProtect = Protect | PAGE_EXECUTE_READ;
	for (int k = 0; k <= Stack_Length - 1; k++) {
		if (_esp[k] > caller) {
			Protect = MemoryAllocator::Query(AppBase::GetCurrentProcess(), *_esp_arr[k])->Protect;
			if (Protect == CodeProtect) {
				_esp = _esp_arr[k]; 
				break;
			}
		}
	}
	return *_esp;
}

函数返回地址受编译器优化影响, 比如内联、函数打包等, 在实际生产过程中, 获取函数返回地址应用范围似乎有限, 但是在模块调用合法性检查、自定义异常跳转(其实setjmp和longjmp就可以了)、异常信息打印等功能上确十分有用, 主流C/C++编译器都提供了内建拓展来获取函数返回地址, 比如

// gcc
__builtin_return_address

// msvc
// https://docs.microsoft.com/zh-cn/cpp/intrinsics/returnaddress
_ReturnAddress



评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值