SEH X64(3)

接下来看__C_specific_handler函数中出现的函数。首先是RtlUnwindEx函数。在异常操作中,当找到了愿意处理当前异常的ExceptionHandler 之后就会以此为参数调用RtlUnwindEx 函数,根据X86 学到的知识,RtlUnwindEx 在执行ExceptionHandler之前应该执行展开操作,清理资源,然后再执行ExceptionHandler。

函数原型

VOID
RtlUnwindEx (
    IN PVOID TargetFrame OPTIONAL,
    IN PVOID TargetIp OPTIONAL,
    IN PEXCEPTION_RECORD ExceptionRecord OPTIONAL,
    IN PVOID ReturnValue,
    IN PCONTEXT OriginalContext,
    IN PUNWIND_HISTORY_TABLE HistoryTable OPTIONAL
    );

__C_specific_handler 传递给它的参数为

RtlUnwindEx(
	TargetFrame,
	ExceptionHandler,
	ExceptionRecord,
	(PVOID)ExceptionRecord->ExceptionCode,
	Dispatcher_Context->ContextRecord,
	Dispatcher_Context->HistoryTable);
函数通过调用RtlVirtualUnwind(第一个参数UNW_FLAG_UHANDLER) 进行虚拟展开,我们知道,虚拟展开之后context内的状态就是执行完目标地址所在的函数的状态。
RtlVirtualUnwind 函数会返回一个异常处理函数ExceptionRoutine,如果它不为空的话,代表该函数可以进行目标函数的展开操作。然后我们调用该函数,并进行展开
操作,根据调用结果采取不同的动作,如果当前函数就是ExceptionRoutine 所在的函数的话,设置 ExceptionFlags |= EXCEPTION_TARGET_UNWIND;并执行展开操作。
如果返回值是ExceptionContinueSearch,函数将继续调用RtlVirtualUnwind遍历异常链,执行展开操作,直到找到了包含ExceptionHandler的函数,我们在上面
看到过,此时函数将跳转到ExceptionHandler 执行,并不会返回。
另外,就像我们之前在X86 的SEH 中看到的一样,执行展开的函数同样包含有一个异常处理程序用于捕获在展开操作中产生的异常。但该异常处理函数并不像之前X86一样,判断当前的
操作类型之后再给出返回值,该函数直接给出返回值ExceptionCollidedUnwind。
image
从上面的截图可以发现,在执行展开操作之前,RtlpExecuteHadnlerForUnwind 会将当前的 DispacherContext 指针放入 RSP+0x20 的位置。而后当出现异常的时候,RtlpExecuteHandlerForUnwind
对应的异常处理函数RtlpUnwindHandler 会将EstablisherFrame + 0x20 即上面的RSP+0x20 取出来,然后将原来DispacherContext 的内容拷贝到当前DispatcherContext内。
然后我们回到RtlDispatchException 查看它是如何操作的。
它跳过了先前的展开过程。

case ExceptionCollidedUnwind:
    ControlPc = DispatcherContext.ControlPc;
    ImageBase = DispatcherContext.ImageBase;
    FunctionEntry = DispatcherContext.FunctionEntry;
     EstablisherFrame = DispatcherContext.EstablisherFrame;
     RtlpCopyContext(&ContextRecord1,
                    DispatcherContext.ContextRecord);

    ContextRecord1.Rip = ControlPc;
    ExceptionRoutine = DispatcherContext.LanguageHandler;
    HandlerData = DispatcherContext.HandlerData;
    HistoryTable = DispatcherContext.HistoryTable;
    ScopeIndex = DispatcherContext.ScopeIndex;
    Repeat = TRUE;

设置变量为执行展开操作之前保存的值,然后设置Repeat=TRUE并进入下一层的循环操作,即直接继续执行产生展开异常的异常处理函数,而此时改变的就只有
scopeindex,即越过了导致异常的finally层。详细的执行过程可以参考下面给的链接,展开过程中的异常讲的特别好,就不再重复了。
http://boxcounter.com/technique/2011-11-04-seh-x64/
另外,还有一个种情况是,执行异常处理函数中产生的异常。此种情况上面的描述也十分详细,不再重复了。
到此我们大概分析了SEH X64 的处理过程。
下一篇文章介绍得到X86/X64 调用堆栈的方法。其中一种用到了SEH 中的RtlVirtualUnwind 函数。
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
当您想在VS Code中使用mingw-w64作为C/C++编译器时,您需要按照以下步骤进行安装和配置: 步骤1:安装mingw-w64 1. 访问mingw-w64官方网站:https://mingw-w64.org/doku.php/download,并选择适合您操作系统的安装程序。 2. 下载适用于您的操作系统的安装程序,并运行它。 3. 在安装向导中选择合适的选项,例如选择目标架构(x86或x64)和线程模型(posix或win32)等。 4. 选择安装目录并开始安装。 5. 完成安装后,确保您知道mingw-w64的安装路径。 步骤2:配置VS Code 1. 打开VS Code,并安装C/C++扩展。可以通过扩展视图(Ctrl+Shift+X)搜索"C/C++"并进行安装。 2. 安装完成后,打开设置(File -> Preferences -> Settings)。 3. 在设置中搜索"C++"以找到相关的C/C++配置选项。 4. 找到"C++: Intelli Sense Engine"选项,并将其设置为"Tag Parser"。 5. 找到"C++: Default"配置选项,并单击"Edit in settings.json"链接。 6. 在"settings.json"文件中,找到"includePath"属性,并添加mingw-w64的安装路径。示例:"C:\\mingw-w64\\x86_64-8.1.0-posix-seh-rt_v6-rev0\\mingw64\\lib\\gcc\\x86_64-w64-mingw32\\8.1.0\\include"。 7. 保存"settings.json"文件并关闭。 步骤3:验证配置 1. 创建一个新的C/C++项目或打开一个现有的项目。 2. 在代码文件中编写一些C/C++代码。 3. 按Ctrl+Shift+B(或选择"Terminal -> Run Build Task")来构建代码。 4. 如果一切顺利,您应该能够成功编译和运行C/C++代码。 这就是在VS Code中安装和配置mingw-w64的简单教程。希望对您有帮助!如果您有任何其他问题,请随时问我。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值