首页
社区
课程
招聘
使用
雪    币: 2123
活跃值: (290)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
ve1kcon 1 2024-12-18 14:46
0
[原创]分享一次 C++ PWN 出题经历——深入研究异常处理机制
SleepAlone 您好,我有个问题想问下,'异常处理时从 __cxa_throw() 开始,之后进行 unwind, cleanup, handler, 程序不会再执行发生异常所在函数的剩余部分' ,既然如此程序触发异 ...
1. 您好,首先我们清楚每个函数中基本都会存在leave; ret,因为我们会需要这个语句去恢复caller函数的现场,那么走到的leave; ret不一定是在“发生异常所在函数的剩余部分”里,而是在处理异常的模块里面。

2. 说得通俗易懂一点,假设函数A执行到一半时,抛出了一个异常,那就走异常处理的流程,程序该正常退出就正常退出,该继续运行就继续运行(设置异常处理的目的不正是为了在发现程序存在异常的时候,能够在程序员可控范围内处理掉,然后让程序继续正常运行吗)。此时假设是函数B调用了函数A,且在函数B中写好了:如果函数A里面出现了异常,就怎么处理。那么处理完以后,按常理来说,是不是应该返回到函数B里面继续运行?若是要恢复函数B的现场,自然需要用到leave; ret,那么这个语句会存在于处理异常的模块里面也是合理的。

以上面的demo举例:main函数调用了input函数,且处理了异常:try { input(); ... } catch{ ... },那么处理完以后,会去执行到“printf("[+] main() return.\n"); return 0;”。

3. 然后我们回看文章的描述是“在执行 main 的 handler 时 crash”(摘自下面这一段),说明在调试时发现,所执行到的leave; ret语句,不在发生异常所在函数里。
“根据这个指令的地址,可以在 IDA 中定位到这是异常处理结束后最终的 ret 指令,所以可以确定是在执行 main 的 handler 时 crash,那么上述报错出现的原因其实就很明显了,是因为最后执行的 leave; ret 使得 ret 的地址变成了 [rbp+8],导致不合法的返回地址。”

最后衷心感谢您的阅读和反馈。
精华数
RANk
2123
雪币
290
活跃值
关注数
粉丝数
0
课程经验
0
学习收益
0
学习时长
基本信息
  能力排名: No.2893
  等    级: LV4
活跃值  活跃值:活跃值
  在线值:
  浏览人数:0
  最近活跃:2025-3-14 15:01
  注册时间:2023-04-21
勋章
能力值

账号登录
验证码登录

忘记密码?
没有账号?立即免费注册