首页
社区
课程
招聘
[原创]SEH分析笔记(X64篇)
2011-11-4 20:02 23696

[原创]SEH分析笔记(X64篇)

2011-11-4 20:02
23696
SEH分析笔记(X64篇)
        v1.0.0
        boxcounter

        历史:
        v1.0.0, 2011-11-4:最初版本。

        [不介意转载,但请注明出处 www.boxcounter.com
        附件里有本文的原始稿,一样的内容,更好的高亮和排版。
        本文的部分代码可能会因为论坛的自动换行变得很乱,需要的朋友手动复制到自己的代码编辑器就可以正常显示了]

        在之前的《SEH分析笔记(X86篇)》中,我借助 wrk1.2 介绍了 x86 下 windows 系统内核中的 SEH 实现。这次我们来看看 x64 位 windows 系统内核中 SEH 的实现。
        本文需要大家熟悉 x64 位系统的一些特性,比如调用约定、Prolog 和 Epilog。可以通过这几篇文章熟悉一下:
        Overview of x64 Calling Conventions, MSDN
        The history of calling conventions, part 5: amd64 , The Old New Thing
        Everything You Need To Know To Start Programming 64-Bit Windows Systems, Matt Pietrek

        首先回顾一下前一篇文章。
        在 x86 windows 中,函数通过以下几个步骤来参与 SEH :
        1. 在自身的栈空间中分配并初始化一个 EXCEPTION_REGISTRATION(_RECORD) 结构体。
        2. 将该 EXCEPTION_REGISTRATION(_RECORD) 挂入当前线程的异常链表。

        当某函数触发异常时,系统首先会通过调用 KiDispatchException 来给内核调试器一个机会,如果内核调试器没有处理该异常,则该机会被转给 RtlDispatchException,这个函数就开始分发该异常。分发过程为:
        从当前线程的异常链表头开始遍历,对于每一个 SEH 注册信息(即 EXCEPTION_REGISTRATION(_RECORD)),调用其 Handler。根据 Handler 的返回值做相应的后续处理:
                1. 返回 ExceptionContinueExecution,表示 Handler 已经修复了异常触发点,从异常触发点继续执行。
                2. 返回 ExceptionContinueSearch,表示该 Handler 没有处理该异常,继续遍历异常链表。
                3. Handler 没有修复异常触发点,但是却能处理该异常(某个 __except 过滤代码返回 EXCEPTION_EXECUTE_HANDLER)。这种情况下,处理完该异常后就从异常解决代码(__except 代码块)继续执行,Handler 不会返回。
        以上是简略的 x86 SEH 流程,其中省略了很多细节,比如展开、错误处理、ExceptionNestedException 和 ExceptionCollidedUnwind 等等。

        之所以在这里重温这个流程,是因为 x64 中 SEH 的流程总体思路也是如此,只是细节上做了一些修改。但这并不表示熟悉 x86 SEH 就能很轻松的掌握 x64 SEH。

        本文分为四个部分:“异常注册”、“异常分发”、“展开、解决”和“ExceptionNestedException 和 ExceptionCollidedUnwind”。依然以 MSC 的增强版为分析对象。分析环境为:WDK 7600.16385.1,内置的 cl 的版本是15.00.30729.207,link 的版本是9.00.30729.207,测试虚拟机系统为 amd64 WinXP + wrk1.2。
       
        在讲述之前,需要先定义几个名词,以简化后续的讲述。

        RVA —— 熟悉 PE 格式的朋友都懂的,表示某个绝对地址相对于所在模块的基地址的偏移。
        EXCEPT_POINT —— 异常触发点。
        EXCEPT_FILTER —— __except 小括号内的异常过滤代码。
        EXCEPT_HANDLER —— __except 大括号内的异常解决代码。
        FINALLY_HANDLER —— __finally 大括号内的代码。

        以下面的伪码为例,

[font=Consolas][color=#000000]    [/color][color=#800080]1  [/color][color=#000000]__try
    [/color][color=#800080]2  [/color][color=#000080]{
    [/color][color=#800080]3      [/color][color=#000000]__try
    [/color][color=#800080]4      [/color][color=#000080]{
    [/color][color=#800080]5           [/color][color=#000080]*(([/color][color=#000000]ULONG[/color][color=#000080]*)[/color][color=#000000]NULL[/color][color=#000080]) = [/color][color=#800080]0[/color][color=#000080]; 
    [/color][color=#800080]6      [/color][color=#000080]}
    [/color][color=#800080]7      [/color][color=#000000]__except[/color][color=#000080](([/color][color=#000000]STATUS_INVALID_PARAMETER [/color][color=#000080]== [/color][color=#000000]GetExceptionCode[/color][color=#000080]()) ? [/color][color=#000000]EXCEPTION_CONTINUE_SEARCH [/color][color=#000080]: [/color][color=#000000]EXCEPTION_EXECUTE_HANDLER[/color][color=#000080])
    [/color][color=#800080]8      [/color][color=#000080]{
    [/color][color=#800080]9          [/color][color=#000080]...
    [/color][color=#800080]10     [/color][color=#000080]}
    [/color][color=#800080]11 [/color][color=#000080]}
    [/color][color=#800080]12 [/color][color=#000000]__finally
    [/color][color=#800080]13 [/color][color=#000080]{
    [/color][color=#800080]14     [/color][color=#000080]...
    [/color][color=#800080]15 [/color][color=#000080]{[/color][/font]

        EXCEPT_POINT 指的是行5中的代码。
        EXCEPT_FILTER 指的是行7中的“(STATUS_INVALID_PARAMETER == GetExceptionCode()) ? EXCEPTION_CONTINUE_SEARCH : EXCEPTION_EXECUTE_HANDLER”。
        EXCEPT_HANDLER 指的是行8到行10中所有的代码。
        FINALLY_HANDLER 指的是行13到行15中所有的代码。

        一、异常注册

        在 x64 windows 中,异常注册信息发生了巨大的改变。x86 中异常注册信息是在函数执行过程中在栈中分配并初始化的。x64 中变成这样:
        异常注册信息不再是动态创建,而是编译过程中生成,链接时写入 PE+ 头中的 ExceptionDirectory(参考 winnt.h 中 IMAGE_RUNTIME_FUNCTION_ENTRY 的定义)。ExceptionDirectory 里包含几乎所有函数的栈操作、异常处理等信息。

        来看看新异常注册信息的数据结构:

[font=Consolas][color=#000000]    [/color][color=#0000FF]typedef struct [/color][color=#000000]_RUNTIME_FUNCTION [/color][color=#000080]{
        [/color][color=#000000]ULONG BeginAddress[/color][color=#000080];
        [/color][color=#000000]ULONG EndAddress[/color][color=#000080];
        [/color][color=#000000]ULONG UnwindData[/color][color=#000080];
    } [/color][color=#000000]RUNTIME_FUNCTION[/color][color=#000080], *[/color][color=#000000]PRUNTIME_FUNCTION[/color][color=#000080];

    [/color][color=#0000FF]typedef enum [/color][color=#000000]_UNWIND_OP_CODES [/color][color=#000080]{
        [/color][color=#000000]UWOP_PUSH_NONVOL [/color][color=#000080]= [/color][color=#800080]0[/color][color=#000080],
        [/color][color=#000000]UWOP_ALLOC_LARGE[/color][color=#000080],       [/color][color=#008000]// 1
        [/color][color=#000000]UWOP_ALLOC_SMALL[/color][color=#000080],       [/color][color=#008000]// 2
        [/color][color=#000000]UWOP_SET_FPREG[/color][color=#000080],         [/color][color=#008000]// 3
        [/color][color=#000000]UWOP_SAVE_NONVOL[/color][color=#000080],       [/color][color=#008000]// 4
        [/color][color=#000000]UWOP_SAVE_NONVOL_FAR[/color][color=#000080],   [/color][color=#008000]// 5
        [/color][color=#000000]UWOP_SPARE_CODE1[/color][color=#000080],       [/color][color=#008000]// 6
        [/color][color=#000000]UWOP_SPARE_CODE2[/color][color=#000080],       [/color][color=#008000]// 7
        [/color][color=#000000]UWOP_SAVE_XMM128[/color][color=#000080],       [/color][color=#008000]// 8
        [/color][color=#000000]UWOP_SAVE_XMM128_FAR[/color][color=#000080],   [/color][color=#008000]// 9
        [/color][color=#000000]UWOP_PUSH_MACHFRAME     [/color][color=#008000]// 10
    [/color][color=#000080]} [/color][color=#000000]UNWIND_OP_CODES[/color][color=#000080], *[/color][color=#000000]PUNWIND_OP_CODES[/color][color=#000080];

    [/color][color=#0000FF]typedef union [/color][color=#000000]_UNWIND_CODE [/color][color=#000080]{
        [/color][color=#0000FF]struct [/color][color=#000080]{
            [/color][color=#000000]UCHAR CodeOffset[/color][color=#000080];
            [/color][color=#000000]UCHAR UnwindOp [/color][color=#000080]: [/color][color=#800080]4[/color][color=#000080];
            [/color][color=#000000]UCHAR OpInfo [/color][color=#000080]: [/color][color=#800080]4[/color][color=#000080];
        };
    
        [/color][color=#000000]USHORT FrameOffset[/color][color=#000080];
    } [/color][color=#000000]UNWIND_CODE[/color][color=#000080], *[/color][color=#000000]PUNWIND_CODE[/color][color=#000080];
    
    [/color][color=#0000FF]#define [/color][color=#000000]UNW_FLAG_NHANDLER [/color][color=#800080]0x0
    [/color][color=#0000FF]#define [/color][color=#000000]UNW_FLAG_EHANDLER [/color][color=#800080]0x1
    [/color][color=#0000FF]#define [/color][color=#000000]UNW_FLAG_UHANDLER [/color][color=#800080]0x2
    [/color][color=#0000FF]#define [/color][color=#000000]UNW_FLAG_CHAININFO [/color][color=#800080]0x4

    [/color][color=#0000FF]typedef struct [/color][color=#000000]_UNWIND_INFO [/color][color=#000080]{
        [/color][color=#000000]UCHAR Version [/color][color=#000080]: [/color][color=#800080]3[/color][color=#000080];
        [/color][color=#000000]UCHAR Flags [/color][color=#000080]: [/color][color=#800080]5[/color][color=#000080];
        [/color][color=#000000]UCHAR SizeOfProlog[/color][color=#000080];
        [/color][color=#000000]UCHAR CountOfCodes[/color][color=#000080];
        [/color][color=#000000]UCHAR FrameRegister [/color][color=#000080]: [/color][color=#800080]4[/color][color=#000080];
        [/color][color=#000000]UCHAR FrameOffset [/color][color=#000080]: [/color][color=#800080]4[/color][color=#000080];
        [/color][color=#000000]UNWIND_CODE UnwindCode[/color][color=#000080][[/color][color=#800080]1[/color][color=#000080]];
    
    [/color][color=#008000]//
    // The unwind codes are followed by an optional DWORD aligned field that
    // contains the exception handler address or a function table entry if
    // chained unwind information is specified. If an exception handler address
    // is specified, then it is followed by the language specified exception
    // handler data.
    //
    //  union {
    //      struct {
    //          ULONG ExceptionHandler;
    //          ULONG ExceptionData[];
    //      };
    //
    //      RUNTIME_FUNCTION FunctionEntry;
    //  };
    //
    
    [/color][color=#000080]} [/color][color=#000000]UNWIND_INFO[/color][color=#000080], *[/color][color=#000000]PUNWIND_INFO[/color][color=#000080];

    [/color][color=#0000FF]typedef struct [/color][color=#000000]_SCOPE_TABLE [/color][color=#000080]{
        [/color][color=#000000]ULONG Count[/color][color=#000080];
        [/color][color=#0000FF]struct
        [/color][color=#000080]{
            [/color][color=#000000]ULONG BeginAddress[/color][color=#000080];
            [/color][color=#000000]ULONG EndAddress[/color][color=#000080];
            [/color][color=#000000]ULONG HandlerAddress[/color][color=#000080];
            [/color][color=#000000]ULONG JumpTarget[/color][color=#000080];
        } [/color][color=#000000]ScopeRecord[/color][color=#000080][[/color][color=#800080]1[/color][color=#000080]];
    } [/color][color=#000000]SCOPE_TABLE[/color][color=#000080], *[/color][color=#000000]PSCOPE_TABLE[/color][color=#000080];[/color][/font]


        x64 中,MSC 为几乎所有的函数都登记了完备的信息,用来在展开过程中完整的回滚函数所做的栈、寄存器操作。登记的信息包括:
        函数是否使用了 SEH、
        函数使用的是什么组合的 SEH(__try/__except?__try/__finally?)、
        函数申请了多少栈空间、
        函数保存了哪些寄存器、
        函数是否建立了栈帧,
        等等,
        同时也记录了这些操作的顺序(以保证回滚的时候不会乱套)。

        这些信息就存储在 UNWIND_INFO 之中。
        UNWIND_INFO 相当于 x86 下的 EXCEPTION_REGISTRATION。它的成员分别是:
                Version —— 结构体的版本。
                Flags —— 标志位,可以有这么几种取值:
                        UNW_FLAG_NHANDLER (0x0): 表示既没有 EXCEPT_FILTER 也没有 EXCEPT_HANDLER。
                        UNW_FLAG_EHANDLER (0x1): 表示该函数有 EXCEPT_FILTER & EXCEPT_HANDLER。
                        UNW_FLAG_UHANDLER (0x2): 表示该函数有 FINALLY_HANDLER。
                        UNW_FLAG_CHAININFO (0x4): 表示该函数有多个 UNWIND_INFO,它们串接在一起(所谓的 chain)。
                SizeOfProlog —— 表示该函数的 Prolog 指令的大小,单位是 byte。
                CountOfCodes —— 表示当前 UNWIND_INFO 包含多少个 UNWIND_CODE 结构。
                FrameRegister —— 如果函数建立了栈帧,它表示栈帧的索引(相对于 CONTEXT::RAX 的偏移,详情参考 RtlVirtualUnwind 源码)。否则该成员的值为0。
                FrameOffset —— 表示 FrameRegister 距离函数最初栈顶(刚进入函数,还没有执行任何指令时的栈顶)的偏移,单位也是 byte。
                UnwindCode —— 是一个 UNWIND_CODE 类型的数组。元素数量由 CountOfCodes 决定。
        需要说明几点:
                1. 如果 Flags 设置了 UNW_FLAG_EHANDLER 或 UNW_FLAG_UHANDLER,那么在最后一个 UNWIND_CODE 之后存放着 ExceptionHandler(相当于 x86 EXCEPTION_REGISTRATION::handler)和 ExceptionData(相当于 x86 EXCEPTION_REGISTRATION::scopetable)。
                2. UnwindCode 数组详细记录了函数修改栈、保存非易失性寄存器的指令。
                3. MSDN 中有 UNWIND_INFO 和 UNWIND_CODE 的详细说明,推荐阅读。

        那 UNWIND_INFO 是如何与其描述的函数关联起来的呢?答案是:通过一个 RUNTIME_FUNCTION 结构体。
        RUNTIME_FUNCTION::BeginAddress 同 RUNTIME_FUNCTION::EndAddress 一起以 RVA 形式描述了函数的范围。
        RUNTIME_FUNCTION::UnwindData 就是 UNWIND_INFO 了,它也是一个 RVA 值。

        PE+ 中的 ExceptionDirectory 中存放着所有函数的 RUNTIME_FUNCTION,按 RUNTIME_FUNCTION::BeginAddress 升序排列。一旦触发异常,系统可以通过 EXCEPT_POINT 的 RVA 在 ExceptionDirectory 中二分查找到 RUNTIME_FUNCTION,进而找到 UNWIND_INFO。
       
        前面有提到,MSC 为几乎所有的函数都登记了完毕的信息,那是不是有一些特殊函数没有登记信息呢?
        是的。x64 新增了一个概念,叫做“叶函数”。熟悉数据结构的朋友可能第一时间就联想到“叶节点”。没错,“叶函数”的含义跟“叶节点”很类似,叶函数不会有子函数,也就是说它不会再调用任何函数。另外 x64 对这个概念额外加了一些要求:不修改栈指针(比如分配栈空间)、没有使用 SEH。总结下来就是:既不调用函数、又没有修改栈指针,也没有使用 SEH 的函数就叫做“叶函数”。
        叶函数可以没有登记信息,原因很简单,它根本就没信息需要登记~

        还有一个 SCOPE_TABLE 结构,熟悉 x86 SEH 的朋友应该很眼熟 :-),它等同于 x86 SEH 中的 REGISTRATIOIN_RECORD::scopetable 的类型。其成员有:
                Count —— 表示 ScopeRecord 数组的大小。
                ScopeRecord —— 等同于 x86 中的 scopetable_entry 成员。其中,
                        BeginAddress 和 EndAddress 表示某个 __try 保护域的范围。
                        HandlerAddress 和 JumpTarget 表示 EXCEPTION_FILTER、EXCEPT_HANDLER 和 FINALLY_HANDLER。具体对应情况为:
                                对于 __try/__except 组合,HandlerAddress 代表 EXCEPT_FILTER,JumpTarget 代表 EXCEPT_HANDLER。
                                对于 __try/__finally 组合,HandlerAddress 代表 FINALLY_HANDLER,JumpTarget 等于 0。
                        这四个域通常都是 RVA,但当 EXCEPT_FILTER 简单地返回或等于 EXCEPTION_EXECUTE_HANDLER 时,HandlerAddress 可能直接等于 EXCEPTION_EXECUTE_HANDLER,而不再是一个 RVA。

        我们可以通过 windbg 中的 .fnent 命令来查看某个函数的异常注册信息。比如,

        1   kd> .fnent passThrough!SehTest
        2   Debugger function entry 00000000`00778210 for:
        3   d:\workspace\code\mycode\r0\passthrough\passthrough.c(51)
        4   (fffffadf`f140f020)   PassThrough!SehTest   |  (fffffadf`f140f0c0)   PassThrough!Caller2
        5   Exact matches:
        6       PassThrough!SehTest (void)
        7   
        8   BeginAddress      = 00000000`00001020
        9   EndAddress        = 00000000`000010b2
        10  UnwindInfoAddress = 00000000`00002668
        11  
        12  Unwind info at fffffadf`f1410668, 10 bytes
        13    version 1, flags 1, prolog 4, codes 1
        14    handler routine: PassThrough!_C_specific_handler (fffffadf`f140f4ce), data 3
        15    00: offs 4, unwind op 2, op info 4        UWOP_ALLOC_SMALL.

        行8到行10描述的是 RUNTIME_FUNCTION。
        行12到行15描述的是 UNWIND_INFO。

        对于叶函数,输出是这样的,

        kd> .fnent passthrough!LeafTest
        No function entry for fffffadf`f240c080

        到这里,异常注册就讲完了,我们认识了相关的数据结构和定位方法。下面我们进入异常分发流程。

        二、异常分发

        x64 异常分发过程使用的仍然是 KiDispatchException、RtlDispatchException、RtlpExecuteHandlerForException 等函数。

        其中,KiDispatchException 中有关内核异常部分的代码完全没有变化,这里我偷懒直接拷贝《SEH分析笔记(X86篇)》中的部分描述,

        原型:
	VOID
	KiDispatchException (
	    IN PEXCEPTION_RECORD ExceptionRecord,
	    IN PKEXCEPTION_FRAME ExceptionFrame,
	    IN PKTRAP_FRAME TrapFrame,
	    IN KPROCESSOR_MODE PreviousMode,
	    IN BOOLEAN FirstChance
	    );

        对于内核异常,它的处理步骤如下:
                如果 FirstChance 为 TRUE,那么,
                        1. 首先将该异常传达给内核调试器(KD),如果 KD 处理了该异常,那么函数返回。
                        2. KD 没有处理,调用 RtlDispatchException 进行异常分发。如果分发成功,RtlDispatchExcetpion 返回 TRUE,或者根本不返回。
                        3. RtlDispatchException 分发失败,那么再给 KD 一次处理机会,如果还是没有处理,那么 BUGCHECK。
                如果 FirstChance 为 FALSE,那么将该异常传达给 KD,如果 KD 没有处理,那么 BUGCHECK。
        它的源码实现位于 $WRK-v1.2\base\ntos\ke\amd64\exceptn.c:430。

        RtlDispatchException 发生了一些改变。
        从之前描述的异常注册信息的数据结构可以发现,x64 中已经不存在异常注册链这个概念了(虽然 _NT_TIB 结构体中还保留了 ExceptionList 域)。那 x64 中 RtlDispatchException 是如何遍历异常注册信息的呢?前面虽然有提到如何通过 EXCEPT_POINT 找到 UNWIND_INFO 结构,但是假如这个 UNWIND_INFO 没有处理该异常,如何继续遍历呢?

        在解答这个问题之前,我们先来认识一个新函数和相关的数据结构,

[font=Consolas][color=#000000]    [/color][color=#0000FF]#define [/color][color=#000000]UNWIND_HISTORY_TABLE_SIZE [/color][color=#800080]12
    
    [/color][color=#0000FF]typedef struct [/color][color=#000000]_UNWIND_HISTORY_TABLE_ENTRY [/color][color=#000080]{
            [/color][color=#000000]ULONG64 ImageBase[/color][color=#000080];
            [/color][color=#000000]PRUNTIME_FUNCTION FunctionEntry[/color][color=#000080];
    } [/color][color=#000000]UNWIND_HISTORY_TABLE_ENTRY[/color][color=#000080], *[/color][color=#000000]PUNWIND_HISTORY_TABLE_ENTRY[/color][color=#000080];
    
    [/color][color=#0000FF]#define [/color][color=#000000]UNWIND_HISTORY_TABLE_NONE [/color][color=#800080]0
    [/color][color=#0000FF]#define [/color][color=#000000]UNWIND_HISTORY_TABLE_GLOBAL [/color][color=#800080]1
    [/color][color=#0000FF]#define [/color][color=#000000]UNWIND_HISTORY_TABLE_LOCAL [/color][color=#800080]2
    
    [/color][color=#0000FF]typedef struct [/color][color=#000000]_UNWIND_HISTORY_TABLE [/color][color=#000080]{
            [/color][color=#000000]ULONG Count[/color][color=#000080];
            [/color][color=#000000]UCHAR Search[/color][color=#000080];
            [/color][color=#000000]ULONG64 LowAddress[/color][color=#000080];
            [/color][color=#000000]ULONG64 HighAddress[/color][color=#000080];
            [/color][color=#000000]UNWIND_HISTORY_TABLE_ENTRY Entry[/color][color=#000080][[/color][color=#000000]UNWIND_HISTORY_TABLE_SIZE[/color][color=#000080]];
    } [/color][color=#000000]UNWIND_HISTORY_TABLE[/color][color=#000080], *[/color][color=#000000]PUNWIND_HISTORY_TABLE[/color][color=#000080];

    [/color][color=#000000]PRUNTIME_FUNCTION
    RtlLookupFunctionEntry [/color][color=#000080](
        [/color][color=#000000]IN ULONG64 ControlPc[/color][color=#000080],
        [/color][color=#000000]OUT PULONG64 ImageBase[/color][color=#000080],
        [/color][color=#000000]IN OUT PUNWIND_HISTORY_TABLE HistoryTable OPTIONAL
        [/color][color=#000080]);[/color][/font]

        RtlLookupFunctionEntry 的功能是查找指定地址所在函数的 RUNTIME_FUNCTION 和所在模块的基地址。它的参数分为为,
                ControlPc —— 需要查找的指令地址,
                ImageBase —— 返回的模块基地址,
                HistoryTable —— 用于加速查找。

        工作流程:
        RtlLookupFunctionEntry 在搜索的过程会根据是否传入 HistoryTable 而采取不同的搜索方法:
                如果传入 HistoryTable,则根据 HistoryTable->Search 表示的搜索方式在表中进行搜索:
                        如果搜索方式为 UNWIND_HISTORY_TABLE_NONE,那么不在 HistoryTable 中进行搜索。
                        如果搜索方式为 UNWIND_HISTORY_TABLE_GLOBAL,则首先在全局表 RtlpUnwindHistoryTable 开始搜索,如果搜索到,则结束搜索,函数返回。否则再在 HistoryTable 中搜索。
                        如果搜索方式为 UNWIND_HISTORY_TABLE_LOCAL,那么在 HistoryTable 中搜索。
                如果上述过程中没有搜索到需要的结果,那么找到模块基地址,从模块的 PE+ 头结构中解析出 RUNTIME_FUNCTION。如果搜索方式为 UNWIND_HISTORY_TABLE_NONE,还会将解决加入到 HistoryTable。

        之前的描述中 RtlDispatchException 定位 EXCEPT_POINT 所对应的 RUNTIME_FUNCTION 就是通过调用 RtlLookupFunctionEntry 实现的。

        回到刚才的问题,如何推动遍历呢?为了解决这个问题,x64 又引进了一个新函数。现在我们有请 x64 SEH 核心成员 RtlVirtualUnwind 登场~

        先来看看它的原型:
	PEXCEPTION_ROUTINE
	RtlVirtualUnwind (
	    IN ULONG HandlerType,
	    IN ULONG64 ImageBase,
	    IN ULONG64 ControlPc,
	    IN PRUNTIME_FUNCTION FunctionEntry,
	    IN OUT PCONTEXT ContextRecord,
	    OUT PVOID *HandlerData,
	    OUT PULONG64 EstablisherFrame,
	    IN OUT PKNONVOLATILE_CONTEXT_POINTERS ContextPointers OPTIONAL
	    );

        它的主要功能是:
                根据传入的 ControlPc 和 ContextRecord 等参数虚拟(模拟)展开该函数,并返回该函数的一些信息,比如 HandlerData(SCOPE_TABLE)、EstablisherFrame(rsp 或 栈帧)。       
        流程是:
                1. 通过 FunctionEntry 和 ImageBase 找到 UNWIND_INFO。根据 UNWIND_INFO 中记录的信息,查找 EstablisherFrame(即栈帧或者 rsp)。
                2. 根据 ControlPc 分如下两种情况展开:
                        a. ControlPc >= EpilogOffset,即 ControlPc 在 Epilog 之中。那么把剩余的 Epilog 指令模拟执行完毕即可。
                           所谓模拟是指,如果下一条 EpiLog 指令是“sub rsp, 0x32”,那么将 ContextRecord->rsp 减去0x32。并不是真正执行 sub 指令。
                        b. ControlPc < EpilogOffset,那么把 Prolog 反向模拟回滚一遍即可。
                           所谓反向回滚是指,如果 Prolog 的指令是
                           mov   [RSP + 8], RCX
                           push R15
                           push R14
                           push R13
                           那么反向回滚就是
                          pop ContextRecord->R13 (实际上是从 ContextRecord->Rsp 指向的内存中取出值存入 ContextRecord->R13,然后 ContextRecord->Rsp 加上8。并不是真正执行 pop)
                          pop ContextRecord->R14
                          pop ContextRecord->R15
                          mov ContextRecord->RCX, [ContextRecord->RSP+8]
                   然后把 ContextRecord->Rip 修改为 ControlPc 所在函数的返回地址,即父函数中的某一处 call 的下一条指令。
                   这样,ContextRecord 就被恢复成父函数在调用 ControlPc 所在函数之后的状态了。
                3. 如果 HandlerType 包含 UNW_FLAG_EHANDLER 或 UNW_FLAG_UHANDLER,那么将 UNWIND_INFO::ExceptionData 赋给传出参数 HandlerData,并返回 UNWIND_INFO::ExceptionRoutine。
                   对于 MSC 编译器生成的模块,UNWIND_INFO::ExceptionRoutine 一般指向 nt!__C_specific_handler。UNWIND_INFO::ExceptionData 指向 ControlPc 所在函数的 SCOPE_TABLE。
        RtlVirtualUnwind 的实现源码位于 $WRK-v1.2\base\ntos\rtl\amd64\exdsptch.c:1202。

        RtlVirtualUnwind 返回后,RtlDispatchException 就可以根据 ContextRecord->Rip 找到父函数对应的 RUNTIME_FUNCTION,进而找到 UNWIND_INFO。就这样推动整个遍历过程。
       
        这是一般情况,对于没有 UNWIND_INFO 的叶函数呢?
        对于叶函数,RtlLookupFunctionEntry 返回 NULL,于是 RtlDispatchException 知道这是个叶函数,就找到该叶函数的父函数,从父函数继续遍历。也就是完全无视叶函数,因为叶函数对整个异常处理过程没有任何影响。
       
        RtlDispatchException 调用 UNWIND_INFO::ExceptionHandler 依然是通过 RtlpExecuteHandlerForException,其函数原型没有变化:
       
	EXCEPTION_DISPOSITION
	RtlpExecuteHandlerForException (
	    IN PEXCEPTION_RECORD ExceptionRecord,
	    IN PVOID EstablisherFrame,
	    IN OUT PCONTEXT ContextRecord,
	    IN OUT PVOID DispatcherContext
	    );

        该函数的实现源码位于 $\WRK-v1.2\base\ntos\rtl\amd64\xcptmisc.asm:84。
        RtlpExecuteHandlerForException 的逻辑较 x86 版本没什么大变化,内部注册了一个异常处理函数 RtlpExceptionHandler。RtlpExceptionHandler 相当于 x86 中的 nt!ExecuteHandler2,其内部会返回 ExceptionNestedException 或 ExceptionContinueSearch。它的实现源码位于 $\WRK-v1.2\base\ntos\rtl\amd64\xcptmisc.asm:26。
       
        需要一提的是,最后一个参数 DispatchContext 的类型是 DISPATCHER_CONTEXT,相对于 x86 版本,它扩充了很多,

    typedef struct _DISPATCHER_CONTEXT {
        ULONG64 ControlPc;
        ULONG64 ImageBase;
        PRUNTIME_FUNCTION FunctionEntry;
        ULONG64 EstablisherFrame;
        ULONG64 TargetIp;
        PCONTEXT ContextRecord;
        PEXCEPTION_ROUTINE LanguageHandler;
        PVOID HandlerData;
        PUNWIND_HISTORY_TABLE HistoryTable;
        ULONG ScopeIndex;
        ULONG Fill0;
    } DISPATCHER_CONTEXT, *PDISPATCHER_CONTEXT;

        成员分别为:
                ControlPc —— 异常触发点。
                ImagePase —— ControlPc 所在模块的基地址。
                FunctionEntry —— ControlPc 所在函数的 RUNTIME_FUNCTION。
                EstablisherFrame —— ControlPc 所在函数的栈帧(如果建立了栈帧)或 RSP。
                TargetIp —— 解决异常的 EXCEPT_HANDLER 地址,该成员只在展开的过程中被使用。RtlpExecuteHandlerForException 没有使用它。
                ContextRecord —— 供展开过程中使用,只有当展开过程中触发新异常(返回 ExceptionCollidedUnwind)时,才会被 RtlDispatchException 真正的使用到(参考 RtlDispatchException 处理 ExceptionCollidedUnwind 的代码)。
                LanguageHandler —— ControlPc 所在函数的 UNWIND_INFO::ExceptionRoutine。
                HandlerData —— ControlPc 所在函数的 UNWIND_INFO::ExceptionData。
                ScopeIndex —— UNWIND_INFO::ExceptionData 中 SCOPE_TABLE::ScopeRecord 的索引,通常设置为0(注:请不要与 x86 中运行时不断改变的 EXCEPTION_REGISTRATION::trylevel 相混淆,ScopeIndex 不会在在函数执行过程中改变)
                Fill0 —— 未用。

        再看一下它的 .fnent 输出,

        1  kd> .fnent nt!RtlpExecuteHandlerForException
        2  Debugger function entry 00000000`01458210 for:
        3  (fffff800`008bd950)   nt!RtlpExecuteHandlerForException   |  (fffff800`008bd970)   nt!RtlpUnwindHandler
        4  Exact matches:
        5      nt!RtlpExecuteHandlerForException (void)
        6  
        7  BeginAddress      = 00000000`000bd950
        8  EndAddress        = 00000000`000bd963
        9  UnwindInfoAddress = 00000000`000dfeb8
        10
        11 Unwind info at fffff800`008dfeb8, 10 bytes
        12   version 1, flags 3, prolog 4, codes 1
        13   handler routine: nt!RtlpExceptionHandler (fffff800`008bd920), data 0
        14   00: offs 4, unwind op 2, op info 4        UWOP_ALLOC_SMALL.

        行12中显示 flags 等于3,即        UNW_FLAG_EHANDLER (0x1) | UNW_FLAG_UHANDLER (0x2),说明行13中显示的异常处理函数 nt!RtlpExceptionHandler 既负责解决异常,也负责展开。

        RtlpExecuteHandlerForException 会调用 DISPATCHER_CONTEXT::LanguageHandler。对于 MSC 编译得到的模块,它是 nt!__C_specific_handler,我们来看看这个函数,

        原型:
	EXCEPTION_DISPOSITION 
	__C_specific_handler (
	    IN PEXCEPTION_RECORD pExceptionRecord,
	    IN PVOID pEstablisherFrame,
	    IN OUT PCONTEXT pContext,
	    IN OUT PVOID pDispatcherContext
	    );

        反汇编码:
[font=Consolas][color=#000000]               kd[/color][color=#0A246A]> [/color][color=#000000]uf nt!__C_specific_handler
               nt!__C_specific_handler[/color][color=#0A246A]:
               [/color][color=#000000]fffff800`[/color][color=#800080]008a42d0 [/color][color=#0A246A]mov     qword ptr [[/color][color=#000000]rsp[/color][color=#0A246A]+[/color][color=#800080]10h[/color][color=#0A246A]],[/color][color=#000000]rdx [/color][color=#008000]; 在栈上保存 pEstablisherFrame
               [/color][color=#000000]fffff800`[/color][color=#800080]008a42d5 [/color][color=#0A246A]mov     [/color][color=#000000]rax[/color][color=#0A246A],[/color][color=#000000]rsp
               fffff800`[/color][color=#800080]008a42d8 [/color][color=#0A246A]sub     [/color][color=#000000]rsp[/color][color=#0A246A],[/color][color=#800080]88h
               [/color][color=#000000]fffff800`[/color][color=#800080]008a42df [/color][color=#0A246A]mov     qword ptr [[/color][color=#000000]rax[/color][color=#0A246A]-[/color][color=#800080]8[/color][color=#0A246A]],[/color][color=#000000]rbx
               fffff800`[/color][color=#800080]008a42e3 [/color][color=#0A246A]mov     qword ptr [[/color][color=#000000]rax[/color][color=#0A246A]-[/color][color=#800080]10h[/color][color=#0A246A]],[/color][color=#000000]rbp
               fffff800`[/color][color=#800080]008a42e7 [/color][color=#0A246A]mov     [/color][color=#000000]rbp[/color][color=#0A246A],qword ptr [[/color][color=#000000]r9[/color][color=#0A246A]]      [/color][color=#008000]; rbp = pDispatcherContext->ControlPc
               [/color][color=#000000]fffff800`[/color][color=#800080]008a42ea [/color][color=#0A246A]mov     qword ptr [[/color][color=#000000]rax[/color][color=#0A246A]-[/color][color=#800080]18h[/color][color=#0A246A]],[/color][color=#000000]rsi
               fffff800`[/color][color=#800080]008a42ee [/color][color=#0A246A]mov     qword ptr [[/color][color=#000000]rax[/color][color=#0A246A]-[/color][color=#800080]20h[/color][color=#0A246A]],[/color][color=#000000]rdi
               fffff800`[/color][color=#800080]008a42f2 [/color][color=#0A246A]mov     qword ptr [[/color][color=#000000]rax[/color][color=#0A246A]-[/color][color=#800080]28h[/color][color=#0A246A]],[/color][color=#000000]r12
               fffff800`[/color][color=#800080]008a42f6 [/color][color=#0A246A]mov     [/color][color=#000000]r12[/color][color=#0A246A],qword ptr [[/color][color=#000000]r9[/color][color=#0A246A]+[/color][color=#800080]38h[/color][color=#0A246A]]  [/color][color=#008000]; r12 = pDispatcherContext->HandlerData
               [/color][color=#000000]fffff800`[/color][color=#800080]008a42fa [/color][color=#0A246A]mov     qword ptr [[/color][color=#000000]rax[/color][color=#0A246A]-[/color][color=#800080]30h[/color][color=#0A246A]],[/color][color=#000000]r13
               fffff800`[/color][color=#800080]008a42fe [/color][color=#0A246A]mov     qword ptr [[/color][color=#000000]rax[/color][color=#0A246A]-[/color][color=#800080]38h[/color][color=#0A246A]],[/color][color=#000000]r14
               fffff800`[/color][color=#800080]008a4302 [/color][color=#0A246A]mov     [/color][color=#000000]r14[/color][color=#0A246A],qword ptr [[/color][color=#000000]r9[/color][color=#0A246A]+[/color][color=#800080]8[/color][color=#0A246A]]    [/color][color=#008000]; r14 = pDispatcherContext->ImageBase
               [/color][color=#000000]fffff800`[/color][color=#800080]008a4306 [/color][color=#0A246A]mov     qword ptr [[/color][color=#000000]rax[/color][color=#0A246A]-[/color][color=#800080]40h[/color][color=#0A246A]],[/color][color=#000000]r15
               fffff800`[/color][color=#800080]008a430a [/color][color=#0A246A]mov     [/color][color=#000000]r13[/color][color=#0A246A],[/color][color=#000000]r9                  [/color][color=#008000]; r13 = pDispatcherContext
               [/color][color=#000000]fffff800`[/color][color=#800080]008a430d [/color][color=#0A246A]sub     [/color][color=#000000]rbp[/color][color=#0A246A],[/color][color=#000000]r14                 [/color][color=#008000]; l_OffsetInFunc = pDispatcherContext->ControlPc - pDispatcherContext->ImageBase
               [/color][color=#000000]fffff800`[/color][color=#800080]008a4310 [/color][color=#0A246A]test    byte ptr [[/color][color=#000000]rcx[/color][color=#0A246A]+[/color][color=#800080]4[/color][color=#0A246A]],[/color][color=#800080]66h    [/color][color=#008000]; pExceptionRecord->ExceptionFlags, EXCEPTION_UNWIND (0x66)
               [/color][color=#000000]fffff800`[/color][color=#800080]008a4314 [/color][color=#0A246A]mov     [/color][color=#000000]rsi[/color][color=#0A246A],[/color][color=#000000]rdx                 [/color][color=#008000]; rsi = pEstablisherFrame
               [/color][color=#000000]fffff800`[/color][color=#800080]008a4317 [/color][color=#0A246A]mov     [/color][color=#000000]r15[/color][color=#0A246A],[/color][color=#000000]rcx                 [/color][color=#008000]; r15 = pExceptionRecord
[/color][color=#0A246A]<              [/color][color=#000000]fffff800`[/color][color=#800080]008a431a [/color][color=#0A246A]jne     [/color][color=#000000]nt!__C_specific_handler[/color][color=#0A246A]+[/color][color=#800080]0xf5 [/color][color=#0A246A]([/color][color=#000000]fffff800`[/color][color=#800080]008a43c5[/color][color=#0A246A])
:              
:              -------------------------------------------------------------------
:              [/color][color=#000000]nt!__C_specific_handler[/color][color=#0A246A]+[/color][color=#800080]0x50[/color][color=#0A246A]:
:              [/color][color=#000000]fffff800`[/color][color=#800080]008a4320 [/color][color=#000000]movsxd  rdi[/color][color=#0A246A],dword ptr [[/color][color=#000000]r9[/color][color=#0A246A]+[/color][color=#800080]48h[/color][color=#0A246A]]  [/color][color=#008000]; l_ScopeIndex (rdi) = pDispatcherContext->ScopeIndex
[/color][color=#0A246A]:              [/color][color=#000000]fffff800`[/color][color=#800080]008a4324 [/color][color=#0A246A]mov     qword ptr [[/color][color=#000000]rax[/color][color=#0A246A]-[/color][color=#800080]58h[/color][color=#0A246A]],[/color][color=#000000]rcx [/color][color=#008000]; [rax-58h] = pExceptionRecord,供给 GetExceptionCode(Information) 使用
[/color][color=#0A246A]:              [/color][color=#000000]fffff800`[/color][color=#800080]008a4328 [/color][color=#0A246A]mov     qword ptr [[/color][color=#000000]rax[/color][color=#0A246A]-[/color][color=#800080]50h[/color][color=#0A246A]],[/color][color=#000000]r8  [/color][color=#008000]; [rax-50h] = pContext,供给 GetExceptionCode(Information) 使用
[/color][color=#0A246A]:              [/color][color=#000000]fffff800`[/color][color=#800080]008a432c [/color][color=#0A246A]cmp     [/color][color=#FF8000]edi[/color][color=#0A246A],dword ptr [[/color][color=#000000]r12[/color][color=#0A246A]]     [/color][color=#008000]; cmp l_ScopeIndex, pDispatcherContext->HandlerData->Count
[/color][color=#0A246A]:              [/color][color=#000000]fffff800`[/color][color=#800080]008a4330 [/color][color=#0A246A]mov     [/color][color=#000000]rax[/color][color=#0A246A],[/color][color=#000000]rdi                 [/color][color=#008000]; rax = l_ScopeIndex
[/color][color=#0A246A]:<             [/color][color=#000000]fffff800`[/color][color=#800080]008a4333 [/color][color=#0A246A]jae     [/color][color=#000000]nt!__C_specific_handler[/color][color=#0A246A]+[/color][color=#800080]0x166 [/color][color=#0A246A]([/color][color=#000000]fffff800`[/color][color=#800080]008a4436[/color][color=#0A246A])
::             
::             [/color][color=#000000]nt!__C_specific_handler[/color][color=#0A246A]+[/color][color=#800080]0x69[/color][color=#0A246A]:
::             [/color][color=#000000]fffff800`[/color][color=#800080]008a4339 [/color][color=#0A246A]add     [/color][color=#000000]rax[/color][color=#0A246A],[/color][color=#000000]rax             [/color][color=#008000]; 这里 *2,下面紧接着 *8,目的是跳过指定数目的 ScopeRecord(大小为16字节)
[/color][color=#0A246A]::             [/color][color=#000000]fffff800`[/color][color=#800080]008a433c [/color][color=#0A246A]lea     [/color][color=#000000]rbx[/color][color=#0A246A],[[/color][color=#000000]r12[/color][color=#0A246A]+[/color][color=#000000]rax[/color][color=#0A246A]*[/color][color=#800080]8[/color][color=#0A246A]+[/color][color=#800080]0Ch[/color][color=#0A246A]] [/color][color=#008000]; rbx = &(pDispatcherContext->HandlerData->ScopeRecord[l_ScopeIndex].HandlerAddress)
[/color][color=#0A246A]::             
::             [/color][color=#000000]nt!__C_specific_handler[/color][color=#0A246A]+[/color][color=#800080]0x71[/color][color=#0A246A]:
::             [/color][color=#008000]; 检查 ControlPc 处于哪个 __try 保护域,之步骤一
[/color][color=#0A246A]::      >      [/color][color=#000000]fffff800`[/color][color=#800080]008a4341 [/color][color=#0A246A]mov     [/color][color=#FF8000]eax[/color][color=#0A246A],dword ptr [[/color][color=#000000]rbx[/color][color=#0A246A]-[/color][color=#800080]8[/color][color=#0A246A]] [/color][color=#008000]; eax = pDispatcherContext->HandlerData->ScopeRecord[l_ScopeIndex].BeginAddress
[/color][color=#0A246A]::      :      [/color][color=#000000]fffff800`[/color][color=#800080]008a4344 [/color][color=#0A246A]cmp     [/color][color=#000000]rbp[/color][color=#0A246A],[/color][color=#000000]rax               [/color][color=#008000]; cmp l_OffsetInFunc, pDispatcherContext->HandlerData->ScopeRecord[l_ScopeIndex].BeginAddress
[/color][color=#0A246A]::<     :      [/color][color=#000000]fffff800`[/color][color=#800080]008a4347 [/color][color=#0A246A]jb      [/color][color=#000000]nt!__C_specific_handler[/color][color=#0A246A]+[/color][color=#800080]0xdd [/color][color=#0A246A]([/color][color=#000000]fffff800`[/color][color=#800080]008a43ad[/color][color=#0A246A])
:::     :      
:::     :      [/color][color=#000000]nt!__C_specific_handler[/color][color=#0A246A]+[/color][color=#800080]0x79[/color][color=#0A246A]:
:::     :      [/color][color=#008000]; 检查 ControlPc 处于哪个 __try 保护域,之步骤二
[/color][color=#0A246A]:::     :      [/color][color=#000000]fffff800`[/color][color=#800080]008a4349 [/color][color=#0A246A]mov     [/color][color=#FF8000]eax[/color][color=#0A246A],dword ptr [[/color][color=#000000]rbx[/color][color=#0A246A]-[/color][color=#800080]4[/color][color=#0A246A]] [/color][color=#008000]; eax = pDispatcherContext->HandlerData->ScopeRecord[l_ScopeIndex].EndAddress
[/color][color=#0A246A]:::     :      [/color][color=#000000]fffff800`[/color][color=#800080]008a434c [/color][color=#0A246A]cmp     [/color][color=#000000]rbp[/color][color=#0A246A],[/color][color=#000000]rax               [/color][color=#008000]; cmp l_OffsetInFunc, pDispatcherContext->HandlerData->ScopeRecord[l_ScopeIndex].EndAddress
[/color][color=#0A246A]:::<    :      [/color][color=#000000]fffff800`[/color][color=#800080]008a434f [/color][color=#0A246A]jae     [/color][color=#000000]nt!__C_specific_handler[/color][color=#0A246A]+[/color][color=#800080]0xdd [/color][color=#0A246A]([/color][color=#000000]fffff800`[/color][color=#800080]008a43ad[/color][color=#0A246A])
::::    :      
::::    :      [/color][color=#000000]nt!__C_specific_handler[/color][color=#0A246A]+[/color][color=#800080]0x81[/color][color=#0A246A]:
::::    :      [/color][color=#008000]; 判断是否是 __try/__finally(JumpTarget 为 NULL)。如果是,那么跳转到下一个 ScopeRecord 继续遍历。
[/color][color=#0A246A]::::    :      [/color][color=#000000]fffff800`[/color][color=#800080]008a4351 [/color][color=#0A246A]cmp     dword ptr [[/color][color=#000000]rbx[/color][color=#0A246A]+[/color][color=#800080]4[/color][color=#0A246A]],[/color][color=#800080]0 [/color][color=#008000]; cmp pDispatcherContext->HandlerData->ScopeRecord[l_ScopeIndex].JumpTarget, NULL
[/color][color=#0A246A]::::<   :      [/color][color=#000000]fffff800`[/color][color=#800080]008a4355 [/color][color=#0A246A]je      [/color][color=#000000]nt!__C_specific_handler[/color][color=#0A246A]+[/color][color=#800080]0xdd [/color][color=#0A246A]([/color][color=#000000]fffff800`[/color][color=#800080]008a43ad[/color][color=#0A246A])
:::::   :      
:::::   :      [/color][color=#000000]nt!__C_specific_handler[/color][color=#0A246A]+[/color][color=#800080]0x87[/color][color=#0A246A]:
:::::   :      [/color][color=#008000]; 到这里,已经找到与异常地址最匹配的 __try/__except
[/color][color=#0A246A]:::::   :      [/color][color=#000000]fffff800`[/color][color=#800080]008a4357 [/color][color=#0A246A]mov     [/color][color=#FF8000]eax[/color][color=#0A246A],dword ptr [[/color][color=#000000]rbx[/color][color=#0A246A]] [/color][color=#008000]; eax = pDispatcherContext->HandlerData->ScopeRecord[l_ScopeIndex].HandlerAddress
[/color][color=#0A246A]:::::   :      [/color][color=#000000]fffff800`[/color][color=#800080]008a4359 [/color][color=#0A246A]cmp     [/color][color=#FF8000]eax[/color][color=#0A246A],[/color][color=#800080]1               [/color][color=#008000]; cmp pDispatcherContext->HandlerData->ScopeRecord[l_ScopeIndex].HandlerAddress, EXCEPTION_EXECUTE_HANDLER (0x1)
[/color][color=#0A246A]:::::<  :      [/color][color=#000000]fffff800`[/color][color=#800080]008a435c [/color][color=#0A246A]je      [/color][color=#000000]nt!__C_specific_handler[/color][color=#0A246A]+[/color][color=#800080]0xa3 [/color][color=#0A246A]([/color][color=#000000]fffff800`[/color][color=#800080]008a4373[/color][color=#0A246A]) [/color][color=#008000]; 如果返回 EXCEPTION_EXECUTE_HANDLER 则跳转
[/color][color=#0A246A]::::::  :      
::::::  :      [/color][color=#000000]nt!__C_specific_handler[/color][color=#0A246A]+[/color][color=#800080]0x8e[/color][color=#0A246A]:
::::::  :      [/color][color=#008000]; 是 __try/__except,且过滤域并不是 EXCEPTION_EXECUTE_HANDLER,执行 HandlerAddress 
[/color][color=#0A246A]::::::  :      [/color][color=#008000]; (注:HandlerAddress 指向的函数仍有可能会返回 EXCEPTION_EXECUTE_HANDLER) 
[/color][color=#0A246A]::::::  :      [/color][color=#000000]fffff800`[/color][color=#800080]008a435e [/color][color=#0A246A]lea     [/color][color=#000000]rcx[/color][color=#0A246A],[[/color][color=#000000]rsp[/color][color=#0A246A]+[/color][color=#800080]30h[/color][color=#0A246A]]
::::::  :      [/color][color=#000000]fffff800`[/color][color=#800080]008a4363 [/color][color=#0A246A]add     [/color][color=#000000]rax[/color][color=#0A246A],[/color][color=#000000]r14 [/color][color=#008000]; rax = pDispatcherContext->HandlerData->ScopeRecord[l_ScopeIndex].HandlerAddress + pDispatcherContext->ImageBase
[/color][color=#0A246A]::::::  :      [/color][color=#000000]fffff800`[/color][color=#800080]008a4366 [/color][color=#0A246A]mov     [/color][color=#000000]rdx[/color][color=#0A246A],[/color][color=#000000]rsi [/color][color=#008000]; rdx = pEstablisherFrame
[/color][color=#0A246A]::::::  :      [/color][color=#000000]fffff800`[/color][color=#800080]008a4369 [/color][color=#0A246A]call    [/color][color=#000000]rax     [/color][color=#008000]; 调用 EXCEPT_FILTER
[/color][color=#0A246A]::::::  :      [/color][color=#000000]fffff800`[/color][color=#800080]008a436b [/color][color=#0A246A]test    [/color][color=#FF8000]eax[/color][color=#0A246A],[/color][color=#FF8000]eax
[/color][color=#0A246A]::::::< :      [/color][color=#000000]fffff800`[/color][color=#800080]008a436d [/color][color=#0A246A]js      [/color][color=#000000]nt!__C_specific_handler[/color][color=#0A246A]+[/color][color=#800080]0xee [/color][color=#0A246A]([/color][color=#000000]fffff800`[/color][color=#800080]008a43be[/color][color=#0A246A]) [/color][color=#008000]; 返回 EXCEPTION_CONTINUE_EXECUTION (-1) 则跳转
[/color][color=#0A246A]::::::: :      
::::::: :      [/color][color=#000000]nt!__C_specific_handler[/color][color=#0A246A]+[/color][color=#800080]0x9f[/color][color=#0A246A]:
::::::: :      [/color][color=#000000]fffff800`[/color][color=#800080]008a436f [/color][color=#0A246A]test    [/color][color=#FF8000]eax[/color][color=#0A246A],[/color][color=#FF8000]eax
[/color][color=#0A246A]:::::::<:      [/color][color=#000000]fffff800`[/color][color=#800080]008a4371 [/color][color=#0A246A]jle     [/color][color=#000000]nt!__C_specific_handler[/color][color=#0A246A]+[/color][color=#800080]0xdd [/color][color=#0A246A]([/color][color=#000000]fffff800`[/color][color=#800080]008a43ad[/color][color=#0A246A]) [/color][color=#008000]; 返回 EXCEPTION_CONTINUE_SEARCH (0) 则跳转
[/color][color=#0A246A]:::::::::      
:::::::::      [/color][color=#000000]nt!__C_specific_handler[/color][color=#0A246A]+[/color][color=#800080]0xa3[/color][color=#0A246A]:
:::::::::      [/color][color=#008000]; 返回的是 EXCEPTION_EXECUTE_HANDLER
[/color][color=#0A246A]:::::>:::      [/color][color=#000000]fffff800`[/color][color=#800080]008a4373 [/color][color=#0A246A]mov     [/color][color=#FF8000]ecx[/color][color=#0A246A],dword ptr [[/color][color=#000000]rbx[/color][color=#0A246A]+[/color][color=#800080]4[/color][color=#0A246A]] [/color][color=#008000]; ecx = pDispatcherContext->HandlerData->ScopeRecord[l_ScopeIndex].JumpTarget
[/color][color=#0A246A]::::: :::      [/color][color=#000000]fffff800`[/color][color=#800080]008a4376 [/color][color=#0A246A]mov     [/color][color=#000000]r8d[/color][color=#0A246A],[/color][color=#800080]1
[/color][color=#0A246A]::::: :::      [/color][color=#000000]fffff800`[/color][color=#800080]008a437c [/color][color=#0A246A]mov     [/color][color=#000000]rdx[/color][color=#0A246A],[/color][color=#000000]rsi [/color][color=#008000]; rdx = pEstablisherFrame
[/color][color=#0A246A]::::: :::      [/color][color=#000000]fffff800`[/color][color=#800080]008a437f [/color][color=#0A246A]add     [/color][color=#000000]rcx[/color][color=#0A246A],[/color][color=#000000]r14 [/color][color=#008000]; rcx = pDispatcherContext->HandlerData->ScopeRecord[l_ScopeIndex].JumpTarget + pDispatcherContext->ImageBase
[/color][color=#0A246A]::::: :::      [/color][color=#000000]fffff800`[/color][color=#800080]008a4382 [/color][color=#0A246A]call    [/color][color=#000000]nt!_NLG_Notify [/color][color=#0A246A]([/color][color=#000000]fffff800`[/color][color=#800080]008b1460[/color][color=#0A246A])
::::: :::      [/color][color=#000000]fffff800`[/color][color=#800080]008a4387 [/color][color=#0A246A]mov     [/color][color=#000000]rax[/color][color=#0A246A],qword ptr [[/color][color=#000000]r13[/color][color=#0A246A]+[/color][color=#800080]40h[/color][color=#0A246A]] [/color][color=#008000]; rax = pDispatcherContext->HistoryTable
[/color][color=#0A246A]::::: :::      [/color][color=#000000]fffff800`[/color][color=#800080]008a438b [/color][color=#0A246A]mov     [/color][color=#FF8000]edx[/color][color=#0A246A],dword ptr [[/color][color=#000000]rbx[/color][color=#0A246A]+[/color][color=#800080]4[/color][color=#0A246A]]   [/color][color=#008000]; edx = pDispatcherContext->HandlerData->ScopeRecord[l_ScopeIndex].JumpTarget
[/color][color=#0A246A]::::: :::      [/color][color=#000000]fffff800`[/color][color=#800080]008a438e [/color][color=#000000]movsxd  r9[/color][color=#0A246A],dword ptr [[/color][color=#000000]r15[/color][color=#0A246A]]      [/color][color=#008000]; r9 = pExceptionRecord->ExceptionCode
[/color][color=#0A246A]::::: :::      [/color][color=#000000]fffff800`[/color][color=#800080]008a4391 [/color][color=#0A246A]mov     qword ptr [[/color][color=#000000]rsp[/color][color=#0A246A]+[/color][color=#800080]28h[/color][color=#0A246A]],[/color][color=#000000]rax [/color][color=#008000]; _ARG_6 = pDispatcherContext->HistoryTable
[/color][color=#0A246A]::::: :::      [/color][color=#000000]fffff800`[/color][color=#800080]008a4396 [/color][color=#0A246A]mov     [/color][color=#000000]rax[/color][color=#0A246A],qword ptr [[/color][color=#000000]r13[/color][color=#0A246A]+[/color][color=#800080]28h[/color][color=#0A246A]] [/color][color=#008000]; rax = pDispatcherContext->ContextRecord
[/color][color=#0A246A]::::: :::      [/color][color=#000000]fffff800`[/color][color=#800080]008a439a [/color][color=#0A246A]add     [/color][color=#000000]rdx[/color][color=#0A246A],[/color][color=#000000]r14 [/color][color=#008000]; rdx = pDispatcherContext->HandlerData->ScopeRecord[l_ScopeIndex].JumpTarget + pDispatcherContext->ImageBase
[/color][color=#0A246A]::::: :::      [/color][color=#000000]fffff800`[/color][color=#800080]008a439d [/color][color=#0A246A]mov     [/color][color=#000000]r8[/color][color=#0A246A],[/color][color=#000000]r15  [/color][color=#008000]; r8 = pExceptionRecord
[/color][color=#0A246A]::::: :::      [/color][color=#000000]fffff800`[/color][color=#800080]008a43a0 [/color][color=#0A246A]mov     [/color][color=#000000]rcx[/color][color=#0A246A],[/color][color=#000000]rsi [/color][color=#008000]; rcx = pEstablisherFrame
[/color][color=#0A246A]::::: :::      [/color][color=#000000]fffff800`[/color][color=#800080]008a43a3 [/color][color=#0A246A]mov     qword ptr [[/color][color=#000000]rsp[/color][color=#0A246A]+[/color][color=#800080]20h[/color][color=#0A246A]],[/color][color=#000000]rax [/color][color=#008000]; _ARG_5 = pDispatcherContext->ContextRecord
[/color][color=#0A246A]::::: :::      [/color][color=#000000]fffff800`[/color][color=#800080]008a43a8 [/color][color=#0A246A]call    [/color][color=#000000]nt!RtlUnwindEx [/color][color=#0A246A]([/color][color=#000000]fffff800`[/color][color=#800080]00891e80[/color][color=#0A246A]) [/color][color=#008000]; 这里不会返回
[/color][color=#0A246A]::::: :::      [/color][color=#008000]; RtlUnwindEx(pEstablisherFrame, 
[/color][color=#0A246A]::::: :::      [/color][color=#008000];             pDispatcherContext->HandlerData->ScopeRecord[l_ScopeIndex].JumpTarget + pDispatcherContext->ImageBase
[/color][color=#0A246A]::::: :::      [/color][color=#008000];             pExceptionRecord,
[/color][color=#0A246A]::::: :::      [/color][color=#008000];             pExceptionRecord->ExceptionCode
[/color][color=#0A246A]::::: :::      [/color][color=#008000];             pDispatcherContext->ContextRecord,
[/color][color=#0A246A]::::: :::      [/color][color=#008000];             pDispatcherContext->HistoryTable)
[/color][color=#0A246A]::::: :::      
::::: :::      [/color][color=#000000]nt!__C_specific_handler[/color][color=#0A246A]+[/color][color=#800080]0xdd[/color][color=#0A246A]:
::>>> :>:      [/color][color=#000000]fffff800`[/color][color=#800080]008a43ad [/color][color=#0A246A]inc     [/color][color=#FF8000]edi     [/color][color=#008000]; l_ScopeIndex += 1
[/color][color=#0A246A]::    : :      [/color][color=#000000]fffff800`[/color][color=#800080]008a43af [/color][color=#0A246A]add     [/color][color=#000000]rbx[/color][color=#0A246A],[/color][color=#800080]10h [/color][color=#008000]; 调整到下一个 ScopeRecord::HandlerAddress
[/color][color=#0A246A]::    : :      [/color][color=#000000]fffff800`[/color][color=#800080]008a43b3 [/color][color=#0A246A]cmp     [/color][color=#FF8000]edi[/color][color=#0A246A],dword ptr [[/color][color=#000000]r12[/color][color=#0A246A]] [/color][color=#008000]; cmp l_ScopeIndex, pDispatcherContext->HandlerData->Count
[/color][color=#0A246A]::    : <      [/color][color=#000000]fffff800`[/color][color=#800080]008a43b7 [/color][color=#0A246A]jb      [/color][color=#000000]nt!__C_specific_handler[/color][color=#0A246A]+[/color][color=#800080]0x71 [/color][color=#0A246A]([/color][color=#000000]fffff800`[/color][color=#800080]008a4341[/color][color=#0A246A])
::    :        
::    :        [/color][color=#000000]nt!__C_specific_handler[/color][color=#0A246A]+[/color][color=#800080]0xe9[/color][color=#0A246A]:
::    :        [/color][color=#008000]; pDispatcherContext->HandlerData 遍历完毕
[/color][color=#0A246A]::<   :        [/color][color=#000000]fffff800`[/color][color=#800080]008a43b9 [/color][color=#0A246A]jmp     [/color][color=#000000]nt!__C_specific_handler[/color][color=#0A246A]+[/color][color=#800080]0x166 [/color][color=#0A246A]([/color][color=#000000]fffff800`[/color][color=#800080]008a4436[/color][color=#0A246A])
:::   :        
:::   :        [/color][color=#000000]nt!__C_specific_handler[/color][color=#0A246A]+[/color][color=#800080]0xee[/color][color=#0A246A]:
:::   >        [/color][color=#000000]fffff800`[/color][color=#800080]008a43be [/color][color=#0A246A]xor     [/color][color=#FF8000]eax[/color][color=#0A246A],[/color][color=#FF8000]eax [/color][color=#008000]; eax = ExceptionContinueExecution
[/color][color=#0A246A]:::<           [/color][color=#000000]fffff800`[/color][color=#800080]008a43c0 [/color][color=#0A246A]jmp     [/color][color=#000000]nt!__C_specific_handler[/color][color=#0A246A]+[/color][color=#800080]0x16b [/color][color=#0A246A]([/color][color=#000000]fffff800`[/color][color=#800080]008a443b[/color][color=#0A246A])
::::           
::::           -------------------------------------------------------------------------------------
::::           [/color][color=#000000]nt!__C_specific_handler[/color][color=#0A246A]+[/color][color=#800080]0xf5[/color][color=#0A246A]:
::::           [/color][color=#008000]; 设置了 EXCEPTION_UNWIND,当前是展开过程
[/color][color=#0A246A]>:::           [/color][color=#000000]fffff800`[/color][color=#800080]008a43c5 [/color][color=#000000]movsxd  rdi[/color][color=#0A246A],dword ptr [[/color][color=#000000]r9[/color][color=#0A246A]+[/color][color=#800080]48h[/color][color=#0A246A]] [/color][color=#008000]; l_ScopeIndex (rdi) = pDispatcherContext->ScopeIndex
 [/color][color=#0A246A]:::           [/color][color=#000000]fffff800`[/color][color=#800080]008a43c9 [/color][color=#0A246A]mov     [/color][color=#000000]rsi[/color][color=#0A246A],qword ptr [[/color][color=#000000]r9[/color][color=#0A246A]+[/color][color=#800080]20h[/color][color=#0A246A]] [/color][color=#008000]; rsi = pDispatcherContext->TargetIp
 [/color][color=#0A246A]:::           [/color][color=#000000]fffff800`[/color][color=#800080]008a43cd [/color][color=#0A246A]sub     [/color][color=#000000]rsi[/color][color=#0A246A],[/color][color=#000000]r14                [/color][color=#008000]; rsi = pDispatcherContext->TargetIp - pDispatcherContext->ImageBase
 [/color][color=#0A246A]:::           [/color][color=#000000]fffff800`[/color][color=#800080]008a43d0 [/color][color=#0A246A]cmp     [/color][color=#FF8000]edi[/color][color=#0A246A],dword ptr [[/color][color=#000000]r12[/color][color=#0A246A]]    [/color][color=#008000]; cmp l_ScopeIndex, pDispatcherContext->HandlerData->Count
 [/color][color=#0A246A]:::           [/color][color=#000000]fffff800`[/color][color=#800080]008a43d4 [/color][color=#0A246A]mov     [/color][color=#000000]rax[/color][color=#0A246A],[/color][color=#000000]rdi                [/color][color=#008000]; rax = l_ScopeIndex
 [/color][color=#0A246A]:::<          [/color][color=#000000]fffff800`[/color][color=#800080]008a43d7 [/color][color=#0A246A]jae     [/color][color=#000000]nt!__C_specific_handler[/color][color=#0A246A]+[/color][color=#800080]0x166 [/color][color=#0A246A]([/color][color=#000000]fffff800`[/color][color=#800080]008a4436[/color][color=#0A246A])
 ::::          
 ::::          [/color][color=#000000]nt!__C_specific_handler[/color][color=#0A246A]+[/color][color=#800080]0x109[/color][color=#0A246A]:
 ::::          [/color][color=#000000]fffff800`[/color][color=#800080]008a43d9 [/color][color=#0A246A]add     [/color][color=#000000]rax[/color][color=#0A246A],[/color][color=#000000]rax [/color][color=#008000]; 
 [/color][color=#0A246A]::::          [/color][color=#000000]fffff800`[/color][color=#800080]008a43dc [/color][color=#0A246A]lea     [/color][color=#000000]rbx[/color][color=#0A246A],[[/color][color=#000000]r12[/color][color=#0A246A]+[/color][color=#000000]rax[/color][color=#0A246A]*[/color][color=#800080]8[/color][color=#0A246A]+[/color][color=#800080]8[/color][color=#0A246A]] [/color][color=#008000]; rbx = &(pDispatcherContext->HandlerData->ScopeRecord[l_ScopeIndex].EndAddress)
 [/color][color=#0A246A]::::          
 ::::          [/color][color=#000000]nt!__C_specific_handler[/color][color=#0A246A]+[/color][color=#800080]0x111[/color][color=#0A246A]:
 ::::          [/color][color=#008000]; 检查 ControlPc 处于哪个 __try 保护域,之步骤一
 [/color][color=#0A246A]::::        > [/color][color=#000000]fffff800`[/color][color=#800080]008a43e1 [/color][color=#0A246A]mov     [/color][color=#FF8000]eax[/color][color=#0A246A],dword ptr [[/color][color=#000000]rbx[/color][color=#0A246A]-[/color][color=#800080]4[/color][color=#0A246A]] [/color][color=#008000]; eax = pDispatcherContext->HandlerData->ScopeRecord[l_ScopeIndex].BeginAddress
 [/color][color=#0A246A]::::        : [/color][color=#000000]fffff800`[/color][color=#800080]008a43e4 [/color][color=#0A246A]cmp     [/color][color=#000000]rbp[/color][color=#0A246A],[/color][color=#000000]rax [/color][color=#008000]; cmp l_OffsetInFunc, pDispatcherContext->HandlerData->ScopeRecord[l_ScopeIndex].BeginAddress
 [/color][color=#0A246A]::::<       : [/color][color=#000000]fffff800`[/color][color=#800080]008a43e7 [/color][color=#0A246A]jb      [/color][color=#000000]nt!__C_specific_handler[/color][color=#0A246A]+[/color][color=#800080]0x15a [/color][color=#0A246A]([/color][color=#000000]fffff800`[/color][color=#800080]008a442a[/color][color=#0A246A])
 :::::       : 
 :::::       : [/color][color=#000000]nt!__C_specific_handler[/color][color=#0A246A]+[/color][color=#800080]0x119[/color][color=#0A246A]:
 :::::       : [/color][color=#008000]; 检查 ControlPc 处于哪个 __try 保护域,之步骤二
 [/color][color=#0A246A]:::::       : [/color][color=#000000]fffff800`[/color][color=#800080]008a43e9 [/color][color=#0A246A]mov     [/color][color=#FF8000]ecx[/color][color=#0A246A],dword ptr [[/color][color=#000000]rbx[/color][color=#0A246A]] [/color][color=#008000]; ecx = pDispatcherContext->HandlerData->ScopeRecord[l_ScopeIndex].EndAddress
 [/color][color=#0A246A]:::::       : [/color][color=#000000]fffff800`[/color][color=#800080]008a43eb [/color][color=#0A246A]cmp     [/color][color=#000000]rbp[/color][color=#0A246A],[/color][color=#000000]rcx [/color][color=#008000]; cmp l_OffsetInFunc, pDispatcherContext->HandlerData->ScopeRecord[l_ScopeIndex].EndAddress
 [/color][color=#0A246A]:::::<      : [/color][color=#000000]fffff800`[/color][color=#800080]008a43ee [/color][color=#0A246A]jae     [/color][color=#000000]nt!__C_specific_handler[/color][color=#0A246A]+[/color][color=#800080]0x15a [/color][color=#0A246A]([/color][color=#000000]fffff800`[/color][color=#800080]008a442a[/color][color=#0A246A])
 ::::::      : 
 ::::::      : [/color][color=#000000]nt!__C_specific_handler[/color][color=#0A246A]+[/color][color=#800080]0x120[/color][color=#0A246A]:
 ::::::      : [/color][color=#008000]; 到这里,已经找到与异常地址匹配的最内层(如果有多层) __try/__except
 [/color][color=#0A246A]::::::      : [/color][color=#000000]fffff800`[/color][color=#800080]008a43f0 [/color][color=#0A246A]cmp     [/color][color=#000000]rsi[/color][color=#0A246A],[/color][color=#000000]rax [/color][color=#008000]; cmp pDispatcherContext->TargetIp - pDispatcherContext->ImageBase, pDispatcherContext->HandlerData->ScopeRecord[l_ScopeIndex].BeginAddress
 [/color][color=#0A246A]::::::<     : [/color][color=#000000]fffff800`[/color][color=#800080]008a43f3 [/color][color=#0A246A]jb      [/color][color=#000000]nt!__C_specific_handler[/color][color=#0A246A]+[/color][color=#800080]0x131 [/color][color=#0A246A]([/color][color=#000000]fffff800`[/color][color=#800080]008a4401[/color][color=#0A246A])
 :::::::     : 
 :::::::     : [/color][color=#000000]nt!__C_specific_handler[/color][color=#0A246A]+[/color][color=#800080]0x125[/color][color=#0A246A]:
 :::::::     : [/color][color=#000000]fffff800`[/color][color=#800080]008a43f5 [/color][color=#0A246A]cmp     [/color][color=#000000]rsi[/color][color=#0A246A],[/color][color=#000000]rcx [/color][color=#008000]; cmp pDispatcherContext->TargetIp - pDispatcherContext->ImageBase, pDispatcherContext->HandlerData->ScopeRecord[l_ScopeIndex].EndAddress
 [/color][color=#0A246A]:::::::<    : [/color][color=#000000]fffff800`[/color][color=#800080]008a43f8 [/color][color=#0A246A]ja      [/color][color=#000000]nt!__C_specific_handler[/color][color=#0A246A]+[/color][color=#800080]0x131 [/color][color=#0A246A]([/color][color=#000000]fffff800`[/color][color=#800080]008a4401[/color][color=#0A246A])
 ::::::::    : 
 ::::::::    : [/color][color=#000000]nt!__C_specific_handler[/color][color=#0A246A]+[/color][color=#800080]0x12a[/color][color=#0A246A]:
 ::::::::    : [/color][color=#008000]; 如果标记了 EXCEPTION_TARGET_UNWIND,说明是最后一个需要局部展开的函数。但是该次局部展开只展开到 EXCEPT_HANDLER(不包含 EXCEPT_HANDLER),所以需要判断 TargetIp
 [/color][color=#0A246A]::::::::    : [/color][color=#000000]fffff800`[/color][color=#800080]008a43fa [/color][color=#0A246A]test    byte ptr [[/color][color=#000000]r15[/color][color=#0A246A]+[/color][color=#800080]4[/color][color=#0A246A]],[/color][color=#800080]20h [/color][color=#008000]; test pExceptionRecord->ExceptionFlags, EXCEPTION_TARGET_UNWIND (0x20)
 [/color][color=#0A246A]::::::::<   : [/color][color=#000000]fffff800`[/color][color=#800080]008a43ff [/color][color=#0A246A]jne     [/color][color=#000000]nt!__C_specific_handler[/color][color=#0A246A]+[/color][color=#800080]0x166 [/color][color=#0A246A]([/color][color=#000000]fffff800`[/color][color=#800080]008a4436[/color][color=#0A246A])
 :::::::::   : 
 :::::::::   : [/color][color=#000000]nt!__C_specific_handler[/color][color=#0A246A]+[/color][color=#800080]0x131[/color][color=#0A246A]:
 ::::::>>:   : [/color][color=#000000]fffff800`[/color][color=#800080]008a4401 [/color][color=#0A246A]mov     [/color][color=#FF8000]eax[/color][color=#0A246A],dword ptr [[/color][color=#000000]rbx[/color][color=#0A246A]+[/color][color=#800080]8[/color][color=#0A246A]] [/color][color=#008000]; eax = pDispatcherContext->HandlerData->ScopeRecord[l_ScopeIndex].JumpTarget
 [/color][color=#0A246A]::::::  :   : [/color][color=#000000]fffff800`[/color][color=#800080]008a4404 [/color][color=#0A246A]test    [/color][color=#FF8000]eax[/color][color=#0A246A],[/color][color=#FF8000]eax [/color][color=#008000]; 判断 pDispatcherContext->HandlerData->ScopeRecord[l_ScopeIndex].JumpTarget 是否为 NULL,即是否是 __try/__finally
 [/color][color=#0A246A]::::::  :<  : [/color][color=#000000]fffff800`[/color][color=#800080]008a4406 [/color][color=#0A246A]je      [/color][color=#000000]nt!__C_specific_handler[/color][color=#0A246A]+[/color][color=#800080]0x13f [/color][color=#0A246A]([/color][color=#000000]fffff800`[/color][color=#800080]008a440f[/color][color=#0A246A]) [/color][color=#008000]; 如果是 __try/__finally 则跳转
 [/color][color=#0A246A]::::::  ::  : 
 ::::::  ::  : [/color][color=#000000]nt!__C_specific_handler[/color][color=#0A246A]+[/color][color=#800080]0x138[/color][color=#0A246A]:
 ::::::  ::  : [/color][color=#000000]fffff800`[/color][color=#800080]008a4408 [/color][color=#0A246A]cmp     [/color][color=#000000]rsi[/color][color=#0A246A],[/color][color=#000000]rax [/color][color=#008000]; cmp pDispatcherContext->TargetIp, pDispatcherContext->HandlerData->ScopeRecord[l_ScopeIndex].JumpTarget
 [/color][color=#0A246A]::::::  ::< : [/color][color=#000000]fffff800`[/color][color=#800080]008a440b [/color][color=#0A246A]je      [/color][color=#000000]nt!__C_specific_handler[/color][color=#0A246A]+[/color][color=#800080]0x166 [/color][color=#0A246A]([/color][color=#000000]fffff800`[/color][color=#800080]008a4436[/color][color=#0A246A])
 ::::::  ::: : 
 ::::::  ::: : [/color][color=#000000]nt!__C_specific_handler[/color][color=#0A246A]+[/color][color=#800080]0x13d[/color][color=#0A246A]:
 ::::::  :::<: [/color][color=#000000]fffff800`[/color][color=#800080]008a440d [/color][color=#0A246A]jmp     [/color][color=#000000]nt!__C_specific_handler[/color][color=#0A246A]+[/color][color=#800080]0x15a [/color][color=#0A246A]([/color][color=#000000]fffff800`[/color][color=#800080]008a442a[/color][color=#0A246A])
 ::::::  ::::: 
 ::::::  ::::: [/color][color=#000000]nt!__C_specific_handler[/color][color=#0A246A]+[/color][color=#800080]0x13f[/color][color=#0A246A]:
 ::::::  ::::: [/color][color=#008000]; 注意这里是先修改 pDispatcherContext->ScopeIndex,然后调用 EXCEPT_HANDLER。这样如果 EXCEPT_HANDLER 触发异常,后续展开就会跳过这个 EXCEPT_HANDLER。
 [/color][color=#0A246A]::::::  :>::: [/color][color=#000000]fffff800`[/color][color=#800080]008a440f [/color][color=#0A246A]mov     [/color][color=#000000]rdx[/color][color=#0A246A],qword ptr [[/color][color=#000000]rsp[/color][color=#0A246A]+[/color][color=#800080]98h[/color][color=#0A246A]]
 ::::::  : ::: [/color][color=#000000]fffff800`[/color][color=#800080]008a4417 [/color][color=#0A246A]lea     [/color][color=#FF8000]eax[/color][color=#0A246A],[[/color][color=#000000]rdi[/color][color=#0A246A]+[/color][color=#800080]1[/color][color=#0A246A]]             [/color][color=#008000]; eax = l_ScopeIndex + 1
 [/color][color=#0A246A]::::::  : ::: [/color][color=#000000]fffff800`[/color][color=#800080]008a441a [/color][color=#0A246A]mov     [/color][color=#FF8000]cl[/color][color=#0A246A],[/color][color=#800080]1
 [/color][color=#0A246A]::::::  : ::: [/color][color=#000000]fffff800`[/color][color=#800080]008a441c [/color][color=#0A246A]mov     dword ptr [[/color][color=#000000]r13[/color][color=#0A246A]+[/color][color=#800080]48h[/color][color=#0A246A]],[/color][color=#FF8000]eax [/color][color=#008000]; pDispatcherContext->ScopeIndex = eax
 [/color][color=#0A246A]::::::  : ::: [/color][color=#000000]fffff800`[/color][color=#800080]008a4420 [/color][color=#0A246A]mov     [/color][color=#000000]r8d[/color][color=#0A246A],dword ptr [[/color][color=#000000]rbx[/color][color=#0A246A]+[/color][color=#800080]4[/color][color=#0A246A]]   [/color][color=#008000]; r8d = pDispatcherContext->HandlerData->ScopeRecord[i].HandlerAddress
 [/color][color=#0A246A]::::::  : ::: [/color][color=#000000]fffff800`[/color][color=#800080]008a4424 [/color][color=#0A246A]add     [/color][color=#000000]r8[/color][color=#0A246A],[/color][color=#000000]r14                  [/color][color=#008000]; r8 = pDispatcherContext->HandlerData->ScopeRecord[i].HandlerAddress + pDispatcherContext->ImageBase
 [/color][color=#0A246A]::::::  : ::: [/color][color=#000000]fffff800`[/color][color=#800080]008a4427 [/color][color=#0A246A]call    [/color][color=#000000]r8                      [/color][color=#008000]; 调用 __finally 处理块,会返回(注:对于 __try/__finally,HandlerAddress 保存的是 __finally 代码块的 RVA)
 [/color][color=#0A246A]::::::  : ::: 
 ::::::  : ::: [/color][color=#000000]nt!__C_specific_handler[/color][color=#0A246A]+[/color][color=#800080]0x15a[/color][color=#0A246A]:
 ::::>>  : :>: [/color][color=#000000]fffff800`[/color][color=#800080]008a442a [/color][color=#0A246A]inc     [/color][color=#FF8000]edi                 [/color][color=#008000]; l_ScopeIndex += 1
 [/color][color=#0A246A]::::    : : : [/color][color=#000000]fffff800`[/color][color=#800080]008a442c [/color][color=#0A246A]add     [/color][color=#000000]rbx[/color][color=#0A246A],[/color][color=#800080]10h             [/color][color=#008000]; 调整到下一个 ScopeRecord::HandlerAddress
 [/color][color=#0A246A]::::    : : : [/color][color=#000000]fffff800`[/color][color=#800080]008a4430 [/color][color=#0A246A]cmp     [/color][color=#FF8000]edi[/color][color=#0A246A],dword ptr [[/color][color=#000000]r12[/color][color=#0A246A]] [/color][color=#008000]; cmp l_ScopeIndex, pDispatcherContext->HandlerData->Count
 [/color][color=#0A246A]::::    : : < [/color][color=#000000]fffff800`[/color][color=#800080]008a4434 [/color][color=#0A246A]jb      [/color][color=#000000]nt!__C_specific_handler[/color][color=#0A246A]+[/color][color=#800080]0x111 [/color][color=#0A246A]([/color][color=#000000]fffff800`[/color][color=#800080]008a43e1[/color][color=#0A246A])
 ::::    : :   
 ::::    : :   [/color][color=#000000]nt!__C_specific_handler[/color][color=#0A246A]+[/color][color=#800080]0x166[/color][color=#0A246A]:
 >>:>    > >   [/color][color=#000000]fffff800`[/color][color=#800080]008a4436 [/color][color=#0A246A]mov     [/color][color=#FF8000]eax[/color][color=#0A246A],[/color][color=#800080]1 [/color][color=#008000]; eax = ExceptionContinueSearch (0n1)
   [/color][color=#0A246A]:           
   :           [/color][color=#000000]nt!__C_specific_handler[/color][color=#0A246A]+[/color][color=#800080]0x16b[/color][color=#0A246A]:
   >           [/color][color=#000000]fffff800`[/color][color=#800080]008a443b [/color][color=#0A246A]mov     [/color][color=#000000]r15[/color][color=#0A246A],qword ptr [[/color][color=#000000]rsp[/color][color=#0A246A]+[/color][color=#800080]48h[/color][color=#0A246A]]
               [/color][color=#000000]fffff800`[/color][color=#800080]008a4440 [/color][color=#0A246A]mov     [/color][color=#000000]r14[/color][color=#0A246A],qword ptr [[/color][color=#000000]rsp[/color][color=#0A246A]+[/color][color=#800080]50h[/color][color=#0A246A]]
               [/color][color=#000000]fffff800`[/color][color=#800080]008a4445 [/color][color=#0A246A]mov     [/color][color=#000000]r13[/color][color=#0A246A],qword ptr [[/color][color=#000000]rsp[/color][color=#0A246A]+[/color][color=#800080]58h[/color][color=#0A246A]]
               [/color][color=#000000]fffff800`[/color][color=#800080]008a444a [/color][color=#0A246A]mov     [/color][color=#000000]r12[/color][color=#0A246A],qword ptr [[/color][color=#000000]rsp[/color][color=#0A246A]+[/color][color=#800080]60h[/color][color=#0A246A]]
               [/color][color=#000000]fffff800`[/color][color=#800080]008a444f [/color][color=#0A246A]mov     [/color][color=#000000]rdi[/color][color=#0A246A],qword ptr [[/color][color=#000000]rsp[/color][color=#0A246A]+[/color][color=#800080]68h[/color][color=#0A246A]]
               [/color][color=#000000]fffff800`[/color][color=#800080]008a4454 [/color][color=#0A246A]mov     [/color][color=#000000]rsi[/color][color=#0A246A],qword ptr [[/color][color=#000000]rsp[/color][color=#0A246A]+[/color][color=#800080]70h[/color][color=#0A246A]]
               [/color][color=#000000]fffff800`[/color][color=#800080]008a4459 [/color][color=#0A246A]mov     [/color][color=#000000]rbp[/color][color=#0A246A],qword ptr [[/color][color=#000000]rsp[/color][color=#0A246A]+[/color][color=#800080]78h[/color][color=#0A246A]]
               [/color][color=#000000]fffff800`[/color][color=#800080]008a445e [/color][color=#0A246A]mov     [/color][color=#000000]rbx[/color][color=#0A246A],qword ptr [[/color][color=#000000]rsp[/color][color=#0A246A]+[/color][color=#800080]80h[/color][color=#0A246A]]
               [/color][color=#000000]fffff800`[/color][color=#800080]008a4466 [/color][color=#0A246A]add     [/color][color=#000000]rsp[/color][color=#0A246A],[/color][color=#800080]88h
               [/color][color=#000000]fffff800`[/color][color=#800080]008a446d [/color][color=#000000]ret[/color][/font]

        nt!__C_specific_handler 相当于 x86 中的 nt!_except_handler3。从上面的反汇编代码也可以看出它的逻辑跟 nt!_except_handler3 基本上一致。
        函数代码不长。主要分为两个大分支,一个分支处理异常,一个分支处理展开(我用横线分隔开了)。

        异常解决的代码负责遍历 SCOPE_TABLE,依次调用 SCOPE_TABLE::ScopeRecord.HandlerAddress 代表的 EXCEPT_FILTER,并针对返回值做出相应的处理:
                1. 返回 EXCEPTION_CONTINUE_EXECUTION,说明异常已经被 EXCEPT_FILTER 修复。返回 ExceptionContinueExecution。
                2. 返回 EXCEPTION_CONTINUE_SEARCH,继续遍历下一个 ScopeRecord。
                3. 返回 EXCEPTION_EXECUTE_HANDLER,说明当前 ScopeRecord.JumpTarget 代表的 EXCEPT_HANDLER 可以处理该异常。那么调用 RtlUnwindEx 进行展开。

        熟悉 x86 的朋友可能会疑惑:在 x86 中 nt!_except_handler3 先进行全局展开,然后对本函数自身进行不完全的局部展开,最后执行 EXCEPT_HANDLER。而在 nt!__C_specific_handler 中却找不到执行 EXCEPT_HANDLER 的指令,这是怎么回事?
        实际上,x64 对这个流程做了一些调整,EXCEPT_HANDLER 不是由 nt!__C_specific_handler 直接调用,而是作为参数传给 RtlUnwindEx,RtlUnwindEx 处理完展开之后才执行 EXCEPT_HANDLER。后续我们在讲展开的时候会看到具体的方法。

        __C_specific_handler 的展开分支,是对 SCOPE_TABLE 进行展开,逻辑很简单,不多讲了。

        更详细的信息,请参考上面反汇编代码中我附的注释。

        另外还需要说一下 SCOPE_TABLE。
        在 x86 中,遍历 scopetable 时是通过运行时动态改变的 EXCEPTION_REGISTRATION::trylevel 来确定应该首先遍历哪一个 scopetable_entry。而 x64 中没有等同于 trylevel 的数据,有的朋友可能会说“SCOPE_TABLE 中不是有每个 __try 保护域的范围 RVA 吗?通过范围不就可以确定在哪个 __try 中触发了异常吗?”。
        我们可以先试试这种方法,以下面这段伪码为例,

	1 VOID SehTest()
	2 {
	3     __try // 1
	4     {
	5     }
	6     __except()
	7     {
	8     }
	9 
	10    __try // 2
	11    {
	12        __try // 3
	13        {
	14            ...
	15        }
	16        __except()
	17        {
	18        }
	19    }
	20    __except()
	21    {
	22    }
	23
	24    __try // 4
	25    {
	26    }
	27    __finally()
	28    {
	29    }
	30}

        上述伪码中总共有4个 __try,按照 x86 中的方法,SCOPE_TABLE 的内容应该是顺序排列的,像这样:

        SCOPE_TABLE::Count 等于4,
        SCOPE_TABLE::ScopeRecord[0] 表示行3开始的 __try/__except,
        SCOPE_TABLE::ScopeRecord[1] 表示行10开始的 __try/__except,
        SCOPE_TABLE::ScopeRecord[2] 表示行12开始的 __try/__except,
        SCOPE_TABLE::ScopeRecord[3] 表示行24开始的 __try/__finally。

        假设行14处触发了异常,遍历过程应该是这样,
        首先检查 ScopeRecord[0],发现其范围不包含 EXCEPT_POINT,继续下一个,
        开始检查 ScopeRecord[1],范围匹配了。
       
        那是不是该把异常交给 ScopeRecord[1] 处理呢?
        不是!从伪码中可以很明显的看出,行14触发的异常应该首先由行12开始的 __try/__except,即 ScopeRecord[1] 处理。

        可见这种方法是行不通的。
        MSC 通过调整 SCOPE_TABLE::ScopeRecord 的排列顺序来解决这个问题:

        SCOPE_TABLE::Count 等于4,
        SCOPE_TABLE::ScopeRecord[0] 表示行3开始的 __try/__except,
        SCOPE_TABLE::ScopeRecord[1] 表示行12开始的 __try/__except,
        SCOPE_TABLE::ScopeRecord[2] 表示行10开始的 __try/__except,
        SCOPE_TABLE::ScopeRecord[3] 表示行24开始的 __try/__finally。

        即对于嵌套的 __try/__except/__finally,ScopeRecord 的排列顺序是,最内层的 __try 排在前面,其次是次内层的,依次排到最外层。
        这样就能正确的遍历 SCOPE_TABLE 了。

        再用伪码完整的展示一下 SCOPE_TABLE 的布置,

        SCOPE_TABLE::Count = 4。

        SCOPE_TABLE::ScopeRecord[0].BeginAddress = RVA_L4; (行4的 RVA) // 第一个 __try
        SCOPE_TABLE::ScopeRecord[0].EndAddress = RVA_L5;
        SCOPE_TABLE::ScopeRecord[0].HandlerAddress = RVA_L6_EXCEPT_FILTER; (行6 __except 过滤代码首地址的 RVA)
        SCOPE_TABLE::ScopeRecord[0].JumpTarget = RVA_L7;

        SCOPE_TABLE::ScopeRecord[1].BeginAddress = RVA_L13;                 // 第三个 __try
        SCOPE_TABLE::ScopeRecord[1].EndAddress = RVA_L15;
        SCOPE_TABLE::ScopeRecord[1].HandlerAddress = RVA_L16_EXCEPT_FILTER;
        SCOPE_TABLE::ScopeRecord[1].JumpTarget = RVA_L7;

        SCOPE_TABLE::ScopeRecord[2].BeginAddress = RVA_L11;                 // 第二个 __try
        SCOPE_TABLE::ScopeRecord[2].EndAddress = RVA_L19;
        SCOPE_TABLE::ScopeRecord[2].HandlerAddress = RVA_L20_EXCEPT_FILTER;
        SCOPE_TABLE::ScopeRecord[2].JumpTarget = RVA_L21;

        SCOPE_TABLE::ScopeRecord[3].BeginAddress = RVA_L25;                 // 第四个 __try
        SCOPE_TABLE::ScopeRecord[3].EndAddress = RVA_L26;
        SCOPE_TABLE::ScopeRecord[3].HandlerAddress = RVA_L28;
        SCOPE_TABLE::ScopeRecord[3].JumpTarget = 0;

        我们再模拟一下 nt!__C_specific_handler 是如何遍历 SCOPE_TABLE 的:
        1. 首先通过传入参数中的 pDispatcherContext->ControlPc 和 pDispatcherContext->ImageBase 计算出异常触发点的 RVA(简称 E_RVA)。参见 fffff800`008a430d 处的指令。
        2. 通过 pDispatcherContext->ScopeIndex 确认是否需要遍历。如果需要遍历,则从它指定的 ScopeRecord 开始遍历。pDispatcherContext->ScopeIndex 一般都为0,只有返回 ExceptionCollidedUnwind 时,RtlDispatchException 才可能将它设置为其他值。
        3. 通过比较 E_RVA 和 ScopeRecord[?].BeginAddress、ScopeRecord[?].EndAddress 来找到正确的处理函数,
                首先 ScopeRecord[0] 范围不匹配,遍历下一个,
                然后 ScopeRecord[1],发现范围匹配,并且是 __try/__except 组合。于是调用 ScopeRecord[1].HandlerAddress,假设它返回的是 EXCEPTION_CONTINUE_SEARCH,那么继续遍历下一个,
                这次是 ScopeRecord[2],发现范围匹配,并且是 __try/__except 组合。于是调用 ScopeRecord[2].HandlerAddress,假设它返回的是 EXCEPTION_EXECUTE_HANDLER,那么说明找到了解决方案。
        4. 调用 RtlUnwindEx,把 ScopeRecord[2].JumpTarget 对应的绝对地址作为 TargetIp 参数传给它。RtlUnwindEx 全局展开完毕后执行 TargetIp。

        到这里,异常分发就大致讲述完毕。接下来是关于展开和解决的内容。

        三、展开、解决

        x64 中展开使用的函数有 RtlVirtualUnwind、RtlUnwindEx 和 RtlpExecuteHandlerForUnwind。其中 RtlVirtualUnwind 已经讲了,我们来看看余下的两个。

        首先是 RtlUnwindEx,原型如下:

	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
	    );

        参数分别是:
                TargetFrame —— 目标帧,即最后一个需要展开的帧。
                TargetIp —— 前面有讲过,它就是 ScopeRecord[?].JumpTarget 代表的地址,即 EXCEPT_HANDLER。
                ExceptionRecord —— 异常信息。
                ReturnValue —— 传递给 TargetIp 的返回值,分析过程中没发现它有什么用处。
                OriginalContext —— 虽然被声明为 IN,但是实际上 RtlUnwindEx 并没有使用它内部的数据,
                HistoryTable —— 用于加速查找 RUNTIME_FUNCTION。

        主要功能是:
                从自身开始展开,到 TargetFrame 停止。然后跳转到 TargetIp 继续执行。
        流程:
                1. 申请一个类型为 CONTEXT 的局部变量 l_Context,调用 RtlCaptureContext 将当前自身的环境复制到 l_Context。
                2. 通过 RtlVirtualUnwind 对 l_Context 进行模拟展开,推动遍历。对每个遍历到的 UNWIND_INFO,检查 UNWIND_INFO::Flags 是否包含 UNW_FLAG_UHANDLER。如果包含,则调用 UNWIND_INFO::ExceptionHandler 进行局部展开。否则继续遍历下一个。
                   循环本步骤,直到展开到 TargetFrame,即到达解决异常的 EXCEPT_HANDLER 所在的函数(简称为 ExceptionHandlerFunc)了。
                3. 这时 l_Context 内已经是从 RtlUnwindEx 完整展开到 EXCEPT_HANDLER 的环境了。即此时 l_Context 已经是 ExceptionHandlerFunc 的执行环境了。
                   调用 RtlRestoreContext,用 l_Context 替换当前线程的执行环境,于是就跳转到 EXCEPT_HANDLER 继续执行。
        这样就完美的从触发异常的环境跳到了新的环境中。

        这个过程有点类似这种手法:
                1. 将某台机器的系统 ghost 到一个 bak.gho 文件。
                2. 把 bak.gho 恢复到一台临时机器,然后对这台临时机器做一些调整。调整完毕后制作一个临时机器的 bak_mod.gho。
                3. 将 bak_mod.gho 恢复到原来那台机器。

        这个流程很重要,我手绘了一副图帮助理解,
       
        伪码:
	__try
	{
	    ExRaiseStatus(STATUS_INVALID_PARAMETER);
	}
	__except(EXCEPTION_EXECUTE_HANDLER)
	{
	}

        图:
        1. 异常解决流程,从 EXCEPT_POINT 到 RtlUnwindEx,途中已经找到能够解决该异常的 EXCEPT_HANDLER 了(以参数 TargetIp 表示),当前线程状态为 ThreadContext
           +---------------------------------------+
           | ......                                |
           | RtlRaiseStatus                    |调 |
           | RtlDispatchException              |用 |-> ThreadContext &
           | RtlpExecuteHandlerForException    |方 |   TargetIp = ExceptionHandler
           | __C_specific_handler              |向 |
           | RtlUnwindEx                       v   |
           |                                       |
           +---------------------------------------+
       
        2. RtlUnwindEx 将当前自身状态复制到 ThreadContext_Copy 中
           +---------------------------------------+                                     +---------------------------------------+
           | ......                                |                                     | ......                                |
           | RtlRaiseStatus                    |调 |                                     | RtlRaiseStatus                    |调 |
           | RtlDispatchException              |用 |-> ThreadContext &                   | RtlDispatchException              |用 |-> ThreadContext_Copy &
           | RtlpExecuteHandlerForException    |方 |   TargetIp = ExceptionHandler       | RtlpExecuteHandlerForException    |方 |   TargetIp = ExceptionHandler
           | __C_specific_handler              |向 |                                     | __C_specific_handler              |向 |
           | RtlUnwindEx                       v   |                                     | RtlUnwindEx                       v   |
           |                                       |                                     |                                       |
           +---------------------------------------+                                     +---------------------------------------+
       
        3. 用 ThreadContext_Copy 进行展开,一直展开到异常触发点停止。
           +---------------------------------------+                                     +---------------------------------------+
           | .....                                 |                                     | ......                                |
           | RtlRaiseStatus                    |调 |                                     | RtlRaiseStatus                    ^展 |
           | RtlDispatchException              |用 |-> ThreadContext                     | RtlDispatchException              |开 |-> ThreadContext_Copy &
           | RtlpExecuteHandlerForException    |方 |   TargetIp = ExceptionHandler       | RtlpExecuteHandlerForException    |方 |   TargetIp = ExceptionHandler
           | __C_specific_handler              |向 |                                     | __C_specific_handler              |向 |
           | RtlUnwindEx                       v   |                                     | RtlUnwindEx                       |   |
           |                                       |                                     |                                       |
           +---------------------------------------+                                     +---------------------------------------+
       
        4. 将 ThreadContext_Copy.Rip 设置为 TargetIp,以 ThreadContext_Copy 为参数调用 RtlpRestoreContext。跳转到 TargetIp 继续执行。
           +---------------------------------------+
           | ......                                |
           | EXCEPT_HANDLER                        |-> ThreadContext (ThreadContext.Rip = TargetIp)
           |                                       |
           +---------------------------------------+

        这样就完成了展开和执行 EXCEPT_HANDLER 的工作。

        RtlpExecuteHandlerForUnwind 没有什么改变,原型依旧:

	EXCEPTION_DISPOSITION
	RtlpExecuteHandlerForUnwind (
	    IN PEXCEPTION_RECORD ExceptionRecord,
	    IN PVOID EstablisherFrame,
	    IN OUT PCONTEXT ContextRecord,
	    IN OUT PVOID DispatcherContext
	    );

        它会注册一个异常处理函数 RtlpUnwindHandle,当触发新异常时 RtlpUnwindHandler 会返回 ExceptionCollidedUnwind。关于 ExceptionCollidedUnwind,我们后面还会详细讲述。
        RtlpExecuteHandlerForUnwind 的实现源码位于 $\WRK-v1.2\base\ntos\rtl\amd64\xcptmisc.asm:199。
        RtlpUnwindHandle 的实现源码位于 $\WRK-v1.2\base\ntos\rtl\amd64\xcptmisc.asm:136。

        到这里,我们讲完了展开的逻辑。接下来我们要讲述两个比较特殊的返回值: ExceptionNestedException 和 ExceptionCollidedUnwind。

        四、ExceptionNestedException 和 ExceptionCollidedUnwind

        之所以专门讲述这两个返回值,是因为在分析过程中,我感觉常规情况的 SEH 流程理解起来并不困难,难理解的是这两种不一般的情况。它们不一般之处在于:在处理异常的过程中又触发了新的异常。
        先来讲一下这两个返回值的含义:
        ExceptionNestedException —— 在异常分发过程中触发新的异常,比如执行 EXCEPT_FILTER 时触发异常。
        ExceptionCollidedUnwind —— 在展开过程中触发新的异常,比如执行 FINALLY_HANDLER 时触发异常。

        首先来讲讲 ExceptionNestedException,以如下伪码为例:

[font=Consolas][color=#000000]    [/color][color=#800080]1  [/color][color=#000000]VOID SehTest[/color][color=#000080]()
    [/color][color=#800080]2  [/color][color=#000080]{
    [/color][color=#800080]3      [/color][color=#000000]__try
    [/color][color=#800080]4      [/color][color=#000080]{
    [/color][color=#800080]5          [/color][color=#000000]ExRaiseStatus[/color][color=#000080]();
    [/color][color=#800080]6      [/color][color=#000080]}
    [/color][color=#800080]7      [/color][color=#000000]__except[/color][color=#000080]([/color][color=#000000]ExRaiseStatus[/color][color=#000080](), [/color][color=#000000]EXCEPTION_CONTINUE_SEARCH[/color][color=#000080]) [/color][color=#008000]// EXCEPT_FILTER_1
    [/color][color=#800080]8      [/color][color=#000080]{ [/color][color=#008000]// EXCEPT_HANDLER_1
    [/color][color=#800080]9      [/color][color=#000080]}
    [/color][color=#800080]10 [/color][color=#000080]}
    [/color][color=#800080]11 
    12 [/color][color=#000000]VOID Caller[/color][color=#000080]()
    [/color][color=#800080]13 [/color][color=#000080]{
    [/color][color=#800080]14     [/color][color=#000000]__try
    [/color][color=#800080]15     [/color][color=#000080]{
    [/color][color=#800080]16         [/color][color=#000000]SehTest[/color][color=#000080]();
    [/color][color=#800080]17     [/color][color=#000080]}
    [/color][color=#800080]18     [/color][color=#000000]__except[/color][color=#000080]([/color][color=#000000]EXCEPTION_EXECUTE_HANDLER[/color][color=#000080]) [/color][color=#008000]// EXCEPT_FILTER_2
    [/color][color=#800080]19     [/color][color=#000080]{ [/color][color=#008000]// EXCEPT_HANDLER_2
    [/color][color=#800080]20     [/color][color=#000080]}
    [/color][color=#800080]21 [/color][color=#000080]}[/color][/font]

        上述代码会两次触发异常,第一次是行5的 ExRaiseStatus,第二次是行7的 ExRaiseStatus。为了方便区分,我将它们分别标记为 EXCEPT_POINT#1、EXCEPT_POINT#2。
        我们来看一下这两个异常的处理流程:

        1. ExRaiseStatus#1 会创建保存 EXCEPT_POINT#1 触发时的状态 Context#1,并构建一个 EXCEPTION_RECORD,然后将他们作为参数来调用 RtlDispatchException#1。(注:这种方式的的触发点是 ExRaiseStatus 内部,而非 SehTest 的第5行。即Context#1 记录的异常触发点是 ExRaiseStatus#1 内部)

        2. RtlDispatchException#1 根据 Context#1 首先找到 EXCEPT_POINT#1 所在函数 ExRaiseStatus#1 的 UNWIND_INFO,发现其 UNWIND_INFO::Flags 为 UNW_FLAG_NHANDLER,于是继续遍历。

        3. RtlDispatchException#1 遍历到 SehTest,发现其 UNWIND_INFO::Flags 为 UNW_FLAG_EHANDLER,于是调用其 UNWIND_INFO::ExceptionHandler,即 __C_specific_handler$2。__C_specific_handler$2 遍历 SehTest 的 SCOPE_TABLE,发现唯一的一个 ScopeRecord。于是执行 ScopeRecord[0].HandlerAddress,即行7的 SehTest::EXCEPT_FILTER_1#1。此时的调用栈如下(竖线后的内容为函数的 UNWIND_INFO::Flags 和 UNWIND_INFO::ExceptionHandler,其中 Flags 缩写为 E、U、N):
                (1)  Caller                                 | E  & __C_specific_handler$1
                (2)  SehTest                                | E  & __C_specific_handler$2
                (3)  ExRaiseStatus#1                        | N
                (4)  RtlDispatchException#1                 | N
                (5)  RtlpExecuteHandlerForException#1       | EU & RtlpExceptionHandler$5
                (6)  __C_specific_handler$2                 | N
                (7)  EXCEPT_FILTER_1#1                      | N

        4. EXCEPT_FILTER#1 触发 EXCEPT_POINT#2。同步骤1类似,ExRaiseStatus 会调用 RtlDispatchException#2,这个过程中同样会创建保存 EXCEPT_POINT#2 的状态,我们称之为 Context#2。

        5. RtlDispatchException#2 根据 Context#2 找到了 EXCEPT_POINT#2 所在函数 ExRaiseStatus#2,发现其 UNWIND_INFO::Flags 为 UNW_FLAG_NHANDLER,于是继续遍历。

        6. RtlDispatchException#2 遍历到 EXCEPT_FILTER_1#1,发现其 UNWIND_INFO::Flags 为 UNW_FLAG_NHANDLER,于是继续遍历。(注:EXCEPT_FILTER 虽然代码形式上从属于 SehTest 函数,但实际上它是一个单独的函数,有自己的 UNWIND_INFO,跟 SEH 的 UNWIND_INFO 并不是同一个)

        7. RtlDispatchException#2 遍历到 __C_specific_handler$2、RltpExecuteHandlerForException#1、RtlDispatchException#1、ExRaiseStatus#1,这些函数要么被标记为 UNW_FLAG_NHANDLER,要么 UNWIND_INFO::ExceptionHandler 返回 ExcetpionNestedException,结果都是继续遍历,所以不再一一讲述。继续遍历下一个。

        8. RtlDispatchException#2 遍历到 SehTest,发现其 UNWIND_INFO::Flags 为 UNW_FLAG_EHANDLER,于是调用其 UNWIND_INFO::ExceptionRoutine,即 __C_specific_handler$2,发现范围匹配,于是调用 EXCEPT_FILTER_1#1,于是又触发异常,这次是 #3 异常。此时的调用栈如下:
                (1)  Caller                                 | E  & __C_specific_handler$1
                (2)  SehTest                                | E  & __C_specific_handler$2
                (3)  ExRaiseStatus#1                        | N
                (4)  RtlDispatchException#1                 | N
                (5)  RtlpExecuteHandlerForException#1       | EU & RtlpExceptionHandler$5
                (6)  __C_specific_handler$2                 | N
                (7)  EXCEPT_FILTER_1#1                      | N
                (8)  ExRaiseStatus#2                        | N
                (9)  RtlDispatchException#2                 | N
                (10) RtlpExecuteHandlerForException#2       | EU & RtlpExceptionHandler$10
                (11) __C_specific_handler$2                 | N
                (12) EXCEPT_FILTER_1#2                      | N
                (13) ExRaiseStatus#3                        | N

        9. #3 异常的处理流程同 #2 的处理流程类似,也会再遍历到 __C_specific_handler$2,也会再调用 EXCEPT_FILTER_1,于是会触发 #4 异常、#5 异常等等。最终内核栈溢出,BSOD。

        以上就是 ExceptionNestedException 的产生以及处理的流程。过程中还有一些细节操作,为了描述简洁,我没有在上述过程中一一讲述。

        再来看看 ExceptionCollidedUnwind。它比 ExceptionNestedException 更复杂一些,我们以如下伪码为例,
               
[font=Consolas][color=#000000]    [/color][color=#800080]1  [/color][color=#000000]VOID SehTest[/color][color=#000080]()
    [/color][color=#800080]2  [/color][color=#000080]{
    [/color][color=#800080]3      [/color][color=#000000]__try
    [/color][color=#800080]4      [/color][color=#000080]{
    [/color][color=#800080]5          [/color][color=#000000]ExRaiseStatus[/color][color=#000080]();
    [/color][color=#800080]6      [/color][color=#000080]}
    [/color][color=#800080]7      [/color][color=#000000]__finally
    [/color][color=#800080]8      [/color][color=#000080]{ [/color][color=#008000]// FINALLY_HANDLER_1
    [/color][color=#800080]9          [/color][color=#000000]ExRaiseStatus[/color][color=#000080]();
    [/color][color=#800080]10     [/color][color=#000080]}
    [/color][color=#800080]11 [/color][color=#000080]}
    [/color][color=#800080]12 
    13 [/color][color=#000000]VOID Caller[/color][color=#000080]()
    [/color][color=#800080]14 [/color][color=#000080]{
    [/color][color=#800080]15     [/color][color=#000000]__try
    [/color][color=#800080]16     [/color][color=#000080]{
    [/color][color=#800080]17         [/color][color=#000000]SehTest[/color][color=#000080]();
    [/color][color=#800080]18     [/color][color=#000080]}
    [/color][color=#800080]19     [/color][color=#000000]__except[/color][color=#000080]([/color][color=#000000]EXCEPTION_EXECUTE_HANDLER[/color][color=#000080]) [/color][color=#008000]// EXCEPT_FILTER_2
    [/color][color=#800080]20     [/color][color=#000080]{ [/color][color=#008000]// EXCEPT_HANDLER_2
    [/color][color=#800080]21     [/color][color=#000080]}
    [/color][color=#800080]22 [/color][color=#000080]}[/color][/font]

        伪码中也有两处触发异常的地方,第一次在行5,第二次在行9。也分别标记为 EXCEPT_POINT#1 和 EXCEPT_POINT#2。处理流程:
       
        1. ExRaiseStatus#1 创建保存 EXCEPT_POINT#1 的状态 Context#1,并构建一个 EXCEPTION_RECORD,然后将他们作为参数来调用 RtlDispatchException#1。

        2. RtlDispatchException#1 根据 Context#1 开始遍历:
                首先遍历到 EXCEPT_POINT#1 所在函数 ExRaiseStatus,发现其 UNWIND_INFO::Flags 为 UNW_FLAG_NHANDLER,于是遍历下一个。
                然后遍历到 SehTest,发现其 UNWIND_INFO::Flags 为 UNW_FLAG_UHANDLER,于是继续遍历下一个。
                然后遍历到 Caller,发现其 UNWIND_INFO::Flags 为 UNW_FLAG_EHANDLER,于是调用其 UNWIND_INFO::ExceptionRoutine 即 __C_specific_handler。__C_specific_handler 发现可以处理该异常,于是以 EXCEPT_HANDLER_2 为 TargetIp 参数调用 RtlUnwindEx。

        3. RtlUnwindEx 从自身开始展开,展开到 SehTest,执行 FINALLY_HANDLER_1 时触发新异常。此时调用栈为:
           (1)  Caller                              | E  & __C_specific_handler$1
           (2)  SehTest                             | U  & __C_specific_handler$2
           (3)  ExRaiseStatus#1                     | N
           (4)  RtlDispatchException#1              | N
           (5)  RtlpExecuteHandlerForException#1    | EU & RtlpExceptionHandler$5
           (6)  __C_specific_handler$1              | N
           (7)  RtlUnwindEx#1                       | N
           (8)  RtlpExecuteHandlerForUnwind#1       | EU & RtlpUnwindHandler$8
           (9)  __C_specific_handler$2              | N
           (10) FINALLY_HANDLER_1                   | N
           (11) ExRaiseStatus#2                     | N
           需要说明的是,调用栈(7) RtlUnwindEx 创建并初始化了一个 DISPATCHER_CONTEXT 变量(后续称之为 pDispatcherContextForUnwind),并作为参数传递给调用栈(8) RltpExecuteHandlerForUnwind,后者在调用(9) __C_specific_handler$2 之前将 pDispatcherContextForUnwind 保存在自己的栈中。此时 pDispatcherContextForUnwind 的内容表示的是调用栈(2) SehTest 的情况。后续步骤会用到这个 pDispatcherContextForUnwind。
       
        4. (11) ExRaiseStatus#2 将 EXCEPT_POINT#2 触发时的状态保存到 Context#2,然后调用 RtlDispatchException#2 进行 EXCEPT_POINT#2 的分发。
       
        5. RtlDispatchException#2 根据 Context#2 开始遍历,
                首先遍历到 EXCEPT_POINT#2 所在函数 ExRaiseStatus#2,发现其 UNWIND_INFO::Flags 为 UNW_FLAG_NHANDLER,于是遍历下一个。
                然后遍历到 FINALLY_HANDLER_1(同前面提到的 EXCEPT_FILTER 一样,FINALLY_HANDLER 实际上也是一个单独的函数,有自己的 RUNTIME_FUNCTION 和 UNWIND_INFO),发现其 UNWIND_INFO::Flags 为        UNW_FLAG_NHANDLER,于是遍历下一个。
                   然后遍历到(9) __C_specific_handler$2,发现其 UNWIND_INFO::Flags 为 UNW_FLAG_NHANDLER,于是继续遍历。
                然后遍历到(8) RtlpExecuteHandlerForUnwind#1,发现其 UNWIND_INFO::Flags 包含 UNW_FLAG_EHANDLER。于是调用其 UNWIND_INFO::ExceptionRoutine 即 RtlpUnwindHandler$8。RtlpUnwindHandler$8 会取出步骤3中所提到的 pDispatcherContextForUnwind,将其内容拷贝到自己的传出参数(参考 RtlpUnwindHandler 的函数原型)pDispatcherContext 中,然后返回 ExceptionCollidedUnwind。

        6. RtlDispatchException#2 收到 ExceptionCollidedUnwind 后,从传回来的 pDispatchContext 中取出诸如 ControlPc、EstablisherFrame 等值(如步骤3所说,此时这些值反应的是(2) SehTest 的状态),用这些值来继续遍历。
                首先遍历到(2) SehTest,调用 RtlpExecuteHandlerForException#2,进而调用 __C_specific_handler$2,但是发现 pDispatcherContext->ScopeIndex(步骤(9)中在调用(10) FINALLY_HANDLER_1 之前+1了,参考 __C_specific_handler 反汇编码)等于 pDispatcherContext->HandlerData->Count。于是继续遍历。
                然后遍历到(1) Caller,调用 RtlpExecuteHandlerForException#2,进而调用 __C_specific_handler$1,发现它可以处理 #2 异常,于是以 EXCEPT_HANDLER#2 为 TargetIp 参数调用 RtlUnwindEx。此时调用栈如下:
           (1)  Caller                              | E  & __C_specific_handler$1
           (2)  SehTest                             | U  & __C_specific_handler$2
           (3)  ExRaiseStatus#1                     | N
           (4)  RtlDispatchException#1              | N
           (5)  RtlpExecuteHandlerForException#1    | EU & RtlpExceptionHandler$6
           (6)  __C_specific_handler$1              | N
           (7)  RtlUnwindEx#1                       | N
           (8)  RtlpExecuteHandlerForUnwind#1       | EU & RtlpUnwindHandler$8
           (9)  __C_specific_handler$2              | N
           (10) FINALLY_HANDLER#1                   | N
           (11) ExRaiseStatus#2                     | N
           (12) RtlDispatchException#2              | N
           (13) RtlpExecuteHandlerForException#2    | EU & RtlpExceptionHandler
           (14) __C_specific_handler$1              | N
           (15) RtlUnwindEx                         | N

        7. (17) RtlUnwindEx 展开完毕后,通过 RtlRestoreContext 跳转到 EXCEPT_HANDLER#2 继续执行。

        在上述过程中,我们可以发现,遍历过程中 RtlDispatchException 等系统函数被频繁遍历到。于是就有了前面提到的全局展开历史表 RtlpUnwindHistoryTable,这个表中存放着 RtlDispatchException、RtlUnwindEx 等函数的 RUNTIME_FUNCTION 和 ImageBase 信息,这样就不用每次都去解析 PE+ 中的 ExceptionDirectory,实现了加速。

        到这里,我们就讲完了 x64 SEH 的实现。可以发现,x64 和 x86 的 SEH 思想或者说框架是一样的:
        1. RtlDispatchException 和 RtlUnwindEx 都对异常注册信息进行遍历。前者是为了分发异常而遍历,后者是为了展开而遍历。
        2. MSC 提供的异常处理函数按照“异常解决”和“展开”两个分支,对 SCOPE_TABLE/scopetable 进行遍历。前者是为了找到 EXCEPT_FILTER & EXCEPT_HANDLER,后者是为了找到 FINALLY_HANDLER。
        3. RtlDispatchException 和 RtlUnwindEx 借助 MSC 提供的异常处理函数这个桥梁,配合处理异常。
        主要的改变有两点:
        1. RtlDispatchException 和 RtlUnwindEx 通过调用 RtlVirtualUnwind 推动遍历。
        2. 所有的非叶函数都参与到 SEH,尽管大部分的函数都没有使用到 SEH。

        以上我们主要讲述的是 x64 SEH 的内部实现。对于使用者,也有一个好消息,我们来看看,
       
        C 代码:

[font=Consolas][color=#000000]    VOID SehTest[/color][color=#000080]()
    {
        [/color][color=#000000]__try
        [/color][color=#000080]{
            [/color][color=#000000]__try
            [/color][color=#000080]{
                [/color][color=#000000]ExRaiseStatus[/color][color=#000080]([/color][color=#000000]STATUS_INVALID_PARAMETER[/color][color=#000080]);
                [/color][color=#000000]DbgPrint[/color][color=#000080]([/color][color=#808080]"%u [%s] __try \n"[/color][color=#000080], [/color][color=#000000]__LINE__[/color][color=#000080], [/color][color=#000000]__FILE__[/color][color=#000080]);
            }
            [/color][color=#000000]__except[/color][color=#000080](([/color][color=#000000]STATUS_INVALID_PARAMETER [/color][color=#000080]== [/color][color=#000000]GetExceptionCode[/color][color=#000080]()) ? [/color][color=#000000]EXCEPTION_CONTINUE_SEARCH [/color][color=#000080]: [/color][color=#000000]EXCEPTION_EXECUTE_HANDLER[/color][color=#000080])
            {
                [/color][color=#000000]DbgPrint[/color][color=#000080]([/color][color=#808080]"%u [%s] __except \n"[/color][color=#000080], [/color][color=#000000]__LINE__[/color][color=#000080], [/color][color=#000000]__FILE__[/color][color=#000080]);
            }
        }
        [/color][color=#000000]__finally
        
            DbgPrint[/color][color=#000080]([/color][color=#808080]"%u [%s] __finally \n"[/color][color=#000080], [/color][color=#000000]__LINE__[/color][color=#000080], [/color][color=#000000]__FILE__[/color][color=#000080]);
        }
    }[/color][/font]

        反汇编码:

[font=Consolas][color=#000000]    kd[/color][color=#0A246A]> [/color][color=#000000]uf passthrough!SehTest
    PassThrough!SehTest[/color][color=#0A246A]:
    [/color][color=#000000]fffffadf`f1100020 [/color][color=#0A246A]sub     [/color][color=#000000]rsp[/color][color=#0A246A],[/color][color=#800080]38h
    [/color][color=#000000]fffffadf`f1100024 [/color][color=#0A246A]mov     [/color][color=#FF8000]ecx[/color][color=#0A246A],[/color][color=#800080]0C000000Dh
    [/color][color=#000000]fffffadf`f1100029 [/color][color=#0A246A]call    qword ptr [[/color][color=#000000]PassThrough!_imp_ExRaiseStatus [/color][color=#0A246A]([/color][color=#000000]fffffadf`f1101050[/color][color=#0A246A])]
    [/color][color=#000000]fffffadf`f110002f [/color][color=#0A246A]lea     [/color][color=#000000]r8[/color][color=#0A246A],[[/color][color=#000000]PassThrough! ?? [/color][color=#0A246A]::[/color][color=#000000]FNODOBFM[/color][color=#0A246A]::[/color][color=#000000]`string` [/color][color=#0A246A]([/color][color=#000000]fffffadf`f1100500[/color][color=#0A246A])]
    [/color][color=#000000]fffffadf`f1100036 [/color][color=#0A246A]mov     [/color][color=#FF8000]edx[/color][color=#0A246A],[/color][color=#800080]39h
    [/color][color=#000000]fffffadf`f110003b [/color][color=#0A246A]lea     [/color][color=#000000]rcx[/color][color=#0A246A],[[/color][color=#000000]PassThrough! ?? [/color][color=#0A246A]::[/color][color=#000000]FNODOBFM[/color][color=#0A246A]::[/color][color=#000000]`string` [/color][color=#0A246A]([/color][color=#000000]fffffadf`f1100540[/color][color=#0A246A])]
    [/color][color=#000000]fffffadf`f1100042 [/color][color=#0A246A]call    [/color][color=#000000]PassThrough!DbgPrint [/color][color=#0A246A]([/color][color=#000000]fffffadf`f11004a6[/color][color=#0A246A])
    [/color][color=#000000]fffffadf`f1100047 [/color][color=#0A246A]jmp     [/color][color=#000000]PassThrough!SehTest[/color][color=#0A246A]+[/color][color=#800080]0x42 [/color][color=#0A246A]([/color][color=#000000]fffffadf`f1100062[/color][color=#0A246A])
    
    [/color][color=#000000]PassThrough!SehTest[/color][color=#0A246A]+[/color][color=#800080]0x42[/color][color=#0A246A]:
    [/color][color=#000000]fffffadf`f1100062 [/color][color=#0A246A]lea     [/color][color=#000000]r8[/color][color=#0A246A],[[/color][color=#000000]PassThrough! ?? [/color][color=#0A246A]::[/color][color=#000000]FNODOBFM[/color][color=#0A246A]::[/color][color=#000000]`string` [/color][color=#0A246A]([/color][color=#000000]fffffadf`f1100500[/color][color=#0A246A])]
    [/color][color=#000000]fffffadf`f1100069 [/color][color=#0A246A]mov     [/color][color=#FF8000]edx[/color][color=#0A246A],[/color][color=#800080]42h
    [/color][color=#000000]fffffadf`f110006e [/color][color=#0A246A]lea     [/color][color=#000000]rcx[/color][color=#0A246A],[[/color][color=#000000]PassThrough! ?? [/color][color=#0A246A]::[/color][color=#000000]FNODOBFM[/color][color=#0A246A]::[/color][color=#000000]`string` [/color][color=#0A246A]([/color][color=#000000]fffffadf`f1100570[/color][color=#0A246A])]
    [/color][color=#000000]fffffadf`f1100075 [/color][color=#0A246A]call    [/color][color=#000000]PassThrough!DbgPrint [/color][color=#0A246A]([/color][color=#000000]fffffadf`f11004a6[/color][color=#0A246A])
    [/color][color=#000000]fffffadf`f110007a [/color][color=#0A246A]add     [/color][color=#000000]rsp[/color][color=#0A246A],[/color][color=#800080]38h
    [/color][color=#000000]fffffadf`f110007e ret[/color][/font]

        我们发现 SehTest 内部完全没有任何 SEH 的踪迹,不像 x86 那样会有创建、销毁 EXCEPTION_REGISTRATION_RECORD 和调整 EXCEPTION_REGISTRATION_RECORD::trylevel 等操作。
        这样的好处就是使用者无需再担心性能损耗,可以放心大胆的使用 SEH 机制了。

        附录一 boxr 扩展

        为了方便自己分析,我写了一个简单的 windbg 扩展,提供了几个 x64 seh 常用功能:

        !boxr.unwindinfo    module-name    unwindinfo_addr
        功能:
                用于查询指定 UNWIND_INFO 结构的详细信息。
        参数说明:
                module-name —— 待查询的 UNWIND_INFO 结构对应函数的模块名
                unwindinfo_addr —— UNWIND_INFO 结构的绝对地址

        !boxr.rtfn    option    module    runtimefunction_addr
        功能:
                用于查询指定 RUNTIME_FUNCTION 结构的详细信息。(rtfn 表示 RunTime_FunctioN)
        参数说明:
                option —— 参数选项,目前支持两种:
                        /a 表示 module 参数为模块基地址
                        /n 表示 module 参数为模块名称
                module —— RUNTIME_FUNCTION 结构对应函数所在的模块,具体形式根据 option 而定。
                runtimefunction_addr —— 需要查询的 RUNTIME_FUNCTION 结构体的绝对地址。支持 @rax 操作方式,但不支持复杂的组合,比如 @rax+8。

        使用的方法是:用 .extpath+ 命令将 boxr.dll 所在的目录添加到 windbg 的搜索路径中,然后就可以使用了。需要卸载时就 .unload。

        简单说明一下这两个命令。

        比如我们要查看下面这个函数的 UNWIND_INFO 信息:
[font=Consolas][color=#000000]    VOID SehTest[/color][color=#000080]()
    {
        [/color][color=#000000]__try
        [/color][color=#000080]{
            [/color][color=#000000]DbgPrint[/color][color=#000080]([/color][color=#808080]"%u [%s] __try \n"[/color][color=#000080], [/color][color=#000000]__LINE__[/color][color=#000080], [/color][color=#000000]__FILE__[/color][color=#000080]);
        }
        [/color][color=#000000]__except[/color][color=#000080]([/color][color=#000000]EXCEPTION_EXECUTE_HANDLER[/color][color=#000080])
        {
            [/color][color=#000000]DbgPrint[/color][color=#000080]([/color][color=#808080]"%u [%s] __except \n"[/color][color=#000080], [/color][color=#000000]__LINE__[/color][color=#000080], [/color][color=#000000]__FILE__[/color][color=#000080]);
        }
    
        [/color][color=#000000]__try
        [/color][color=#000080]{
            [/color][color=#000000]__try
            [/color][color=#000080]{
                [/color][color=#000000]__try
                [/color][color=#000080]{
                    [/color][color=#000000]CollidedUnwind[/color][color=#000080]();
                }
                [/color][color=#000000]__except[/color][color=#000080]([/color][color=#000000]EXCEPTION_EXECUTE_HANDLER[/color][color=#000080])
                {
                    [/color][color=#000000]DbgPrint[/color][color=#000080]([/color][color=#808080]"%u [%s] __except \n"[/color][color=#000080], [/color][color=#000000]__LINE__[/color][color=#000080], [/color][color=#000000]__FILE__[/color][color=#000080]);
                }
            }
            [/color][color=#000000]__except[/color][color=#000080]([/color][color=#000000]EXCEPTION_EXECUTE_HANDLER[/color][color=#000080])
            {
                [/color][color=#000000]DbgPrint[/color][color=#000080]([/color][color=#808080]"%u [%s] __except \n"[/color][color=#000080], [/color][color=#000000]__LINE__[/color][color=#000080], [/color][color=#000000]__FILE__[/color][color=#000080]);
            }
        }
        [/color][color=#000000]__finally
        [/color][color=#000080]{
            [/color][color=#000000]DbgPrint[/color][color=#000080]([/color][color=#808080]"%u [%s] __finally \n"[/color][color=#000080], [/color][color=#000000]__LINE__[/color][color=#000080], [/color][color=#000000]__FILE__[/color][color=#000080]);
        }
    
        [/color][color=#000000]__try
        [/color][color=#000080]{
            [/color][color=#000000]DbgPrint[/color][color=#000080]([/color][color=#808080]"%u [%s] __try \n"[/color][color=#000080], [/color][color=#000000]__LINE__[/color][color=#000080], [/color][color=#000000]__FILE__[/color][color=#000080]);
    
            [/color][color=#000000]__try
            [/color][color=#000080]{
                [/color][color=#000000]DbgPrint[/color][color=#000080]([/color][color=#808080]"%u [%s] __try \n"[/color][color=#000080], [/color][color=#000000]__LINE__[/color][color=#000080], [/color][color=#000000]__FILE__[/color][color=#000080]);
            }
            [/color][color=#000000]__finally
            [/color][color=#000080]{
                [/color][color=#000000]DbgPrint[/color][color=#000080]([/color][color=#808080]"%u [%s] __finally \n"[/color][color=#000080], [/color][color=#000000]__LINE__[/color][color=#000080], [/color][color=#000000]__FILE__[/color][color=#000080]);
            }
        }
        [/color][color=#000000]__except[/color][color=#000080]([/color][color=#000000]EXCEPTION_EXECUTE_HANDLER[/color][color=#000080])
        {
            [/color][color=#000000]DbgPrint[/color][color=#000080]([/color][color=#808080]"%u [%s] __except \n"[/color][color=#000080], [/color][color=#000000]__LINE__[/color][color=#000080], [/color][color=#000000]__FILE__[/color][color=#000080]);
        }
    
        [/color][color=#0000FF]return[/color][color=#000080];
    }[/color][/font]
       
        操作步骤:
        1. 使用 .fnent 命令获得 SehTest 的基本信息,
                kd> .fnent passthrough!SehTest
                Debugger function entry 00000000`00758210 for:
                (fffffadf`f135d080)   PassThrough!SehTest   |  (fffffadf`f135d180)   PassThrough!LeafTest
                Exact matches:
                    PassThrough!SehTest (void)
               
                BeginAddress      = 00000000`00001080
                EndAddress        = 00000000`00001175
                UnwindInfoAddress = 00000000`000026b8
               
                Unwind info at fffffadf`f135e6b8, 10 bytes
                  version 1, flags 3, prolog 4, codes 1
                  handler routine: PassThrough!_C_specific_handler (fffffadf`f135d5de), data 6
                  00: offs 4, unwind op 2, op info 4        UWOP_ALLOC_SMALL.
        2. 使用 !boxr.unwindinfo 查询详细信息,
                kd> !boxr.unwindinfo passthrough fffffadf`f135e6b8
                _UNWIND_INFO for fffffadff135e6b8
                Flags:
                    EU
                ExceptionRoutine:
                    PassThrough!_C_specific_handler (fffffadf`f135d5de)
                ScopeTable:
                    Count: 6
                    ScopeRecord[0]      (fffffadff135e6c8)
                        BeginAddress:
                            PassThrough!SehTest+0x4 (fffffadf`f135d084)
                        EndAddress:
                            PassThrough!SehTest+0x1e (fffffadf`f135d09e)
                        HandlerAddress:
                            PassThrough!SehTest$filt$0 (fffffadf`f135d8a0)
                        JumpTarget:
                            PassThrough!SehTest+0x1e (fffffadf`f135d09e)
                    [省略中间3个 ScopeRecord 成员]
                    ScopeRecord[5]      (fffffadff135e718)
                        BeginAddress:
                            PassThrough!SehTest+0x8b (fffffadf`f135d10b)
                        EndAddress:
                            PassThrough!SehTest+0xd7 (fffffadf`f135d157)
                        HandlerAddress:
                            PassThrough!SehTest$filt$5 (fffffadf`f135d960)
                        JumpTarget:
                            PassThrough!SehTest+0xd7 (fffffadf`f135d157)
               
        !boxr.rtfn 的用法也类似,比如:
                kd> !box.rtfn /n passThrough @rax
                _RUNTIME_FUNCTION for fffffadff1113000
                BeginAddress:
                    PassThrough!CollidedUnwind (fffffadf`f1110020)
                EndAddress:
                    PassThrough!CollidedUnwind+0x38 (fffffadf`f1110058)
                UnwindData:
                    fffffadff1111688
                _UNWIND_INFO for fffffadff1111688
                Flags:
                    U
                ExceptionRoutine:
                    PassThrough!_C_specific_handler (fffffadf`f11104ee)
                ScopeTable:
                    Count: 1
                    ScopeRecord[0]      (fffffadff1111698)
                        BeginAddress:
                            PassThrough!CollidedUnwind+0x4 (fffffadf`f1110024)
                        EndAddress:
                            PassThrough!CollidedUnwind+0x10 (fffffadf`f1110030)
                        HandlerAddress:
                            PassThrough!CollidedUnwind$fin$0 (fffffadf`f1110750)
                        JumpTarget:
                            0       

        需要说明的是,我写这个扩展的目的仅仅是为了分析 x64 SEH 过程中能轻松的查看相关数据结构的详细信息,所以并没有在这个扩展上花很多时间。其代码是从 MS 例子代码的基础上增加了我需要的功能。应该有一些 BUG,但是对我来说不重要,已经满足我的需要了。源码也放在附件里,方便分析的朋友根据自己的需要进行修改。
        另外有一个疑问:我编译的 x64 wrk1.2 内核无法对 .c代码进行源码调试,对 .asm 代码倒是可以,这是为什么?我看了一下编译选项,没看出什么猫腻。有经验的朋友分享一下吧,感谢 :-)

        附录二 RtlUnwindEx 的反汇编代码和注释

        由于无法源码调试,只好把它反汇编出来加上注释……

[font=Consolas][color=#000000]             VOID
             RtlUnwindEx [/color][color=#000080](
[/color][color=#008000]/* rcx    */     [/color][color=#000000]IN PVOID pEstablisherFrame OPTIONAL[/color][color=#000080],
[/color][color=#008000]/* rdx    */     [/color][color=#000000]IN PVOID pJumpTargetIp OPTIONAL[/color][color=#000080],
[/color][color=#008000]/* r8     */     [/color][color=#000000]IN PEXCEPTION_RECORD pExceptionRecord OPTIONAL[/color][color=#000080],
[/color][color=#008000]/* r9     */     [/color][color=#000000]IN PVOID ReturnValue[/color][color=#000080],
[/color][color=#008000]/* rsp+28 */     [/color][color=#000000]IN PCONTEXT pOriginalContext[/color][color=#000080],
[/color][color=#008000]/* rsp+30 */     [/color][color=#000000]IN PUNWIND_HISTORY_TABLE pHistoryTable OPTIONAL
                 [/color][color=#000080]);[/color][/font]

[font=Consolas][color=#000000]             kd[/color][color=#0A246A]> [/color][color=#000000]uf nt!RtlUnwindEx
             nt!RtlUnwindEx[/color][color=#0A246A]:
             [/color][color=#000000]fffff800`[/color][color=#800080]00891e70 [/color][color=#0A246A]mov     qword ptr [[/color][color=#000000]rsp[/color][color=#0A246A]+[/color][color=#800080]20h[/color][color=#0A246A]],[/color][color=#000000]r9
             fffff800`[/color][color=#800080]00891e75 [/color][color=#0A246A]mov     qword ptr [[/color][color=#000000]rsp[/color][color=#0A246A]+[/color][color=#800080]18h[/color][color=#0A246A]],[/color][color=#000000]r8
             fffff800`[/color][color=#800080]00891e7a [/color][color=#0A246A]mov     qword ptr [[/color][color=#000000]rsp[/color][color=#0A246A]+[/color][color=#800080]10h[/color][color=#0A246A]],[/color][color=#000000]rdx
             fffff800`[/color][color=#800080]00891e7f [/color][color=#0A246A]mov     [/color][color=#000000]rax[/color][color=#0A246A],[/color][color=#000000]rsp
             fffff800`[/color][color=#800080]00891e82 [/color][color=#0A246A]sub     [/color][color=#000000]rsp[/color][color=#0A246A],[/color][color=#800080]678h
             [/color][color=#000000]fffff800`[/color][color=#800080]00891e89 [/color][color=#0A246A]mov     qword ptr [[/color][color=#000000]rax[/color][color=#0A246A]-[/color][color=#800080]8[/color][color=#0A246A]],[/color][color=#000000]rbx
             fffff800`[/color][color=#800080]00891e8d [/color][color=#0A246A]mov     qword ptr [[/color][color=#000000]rax[/color][color=#0A246A]-[/color][color=#800080]10h[/color][color=#0A246A]],[/color][color=#000000]rbp
             fffff800`[/color][color=#800080]00891e91 [/color][color=#0A246A]mov     qword ptr [[/color][color=#000000]rax[/color][color=#0A246A]-[/color][color=#800080]18h[/color][color=#0A246A]],[/color][color=#000000]rsi
             fffff800`[/color][color=#800080]00891e95 [/color][color=#0A246A]mov     [/color][color=#000000]rsi[/color][color=#0A246A],qword ptr [[/color][color=#000000]rsp[/color][color=#0A246A]+[/color][color=#800080]6A0h[/color][color=#0A246A]] [/color][color=#008000]; rsi = pOriginalContext
             [/color][color=#000000]fffff800`[/color][color=#800080]00891e9d [/color][color=#0A246A]mov     qword ptr [[/color][color=#000000]rax[/color][color=#0A246A]-[/color][color=#800080]20h[/color][color=#0A246A]],[/color][color=#000000]rdi
             fffff800`[/color][color=#800080]00891ea1 [/color][color=#0A246A]mov     qword ptr [[/color][color=#000000]rax[/color][color=#0A246A]-[/color][color=#800080]28h[/color][color=#0A246A]],[/color][color=#000000]r12
             fffff800`[/color][color=#800080]00891ea5 [/color][color=#0A246A]mov     qword ptr [[/color][color=#000000]rax[/color][color=#0A246A]-[/color][color=#800080]40h[/color][color=#0A246A]],[/color][color=#000000]r15
             fffff800`[/color][color=#800080]00891ea9 [/color][color=#0A246A]mov     [/color][color=#000000]rbp[/color][color=#0A246A],[/color][color=#000000]rcx
             fffff800`[/color][color=#800080]00891eac [/color][color=#0A246A]mov     [/color][color=#000000]r15[/color][color=#0A246A],[/color][color=#000000]rdx
             fffff800`[/color][color=#800080]00891eaf [/color][color=#0A246A]lea     [/color][color=#000000]rdx[/color][color=#0A246A],[[/color][color=#000000]rsp[/color][color=#0A246A]+[/color][color=#800080]40h[/color][color=#0A246A]] [/color][color=#008000]; rsp+40 为 l_HighLimit
             [/color][color=#000000]fffff800`[/color][color=#800080]00891eb4 [/color][color=#0A246A]lea     [/color][color=#000000]rcx[/color][color=#0A246A],[[/color][color=#000000]rsp[/color][color=#0A246A]+[/color][color=#800080]50h[/color][color=#0A246A]] [/color][color=#008000]; rsp+50 为 l_LowLimit
             [/color][color=#000000]fffff800`[/color][color=#800080]00891eb9 [/color][color=#0A246A]mov     [/color][color=#000000]rbx[/color][color=#0A246A],[/color][color=#000000]r8
             fffff800`[/color][color=#800080]00891ebc [/color][color=#0A246A]mov     [/color][color=#000000]rdi[/color][color=#0A246A],[/color][color=#000000]rsi
             fffff800`[/color][color=#800080]00891ebf [/color][color=#0A246A]lea     [/color][color=#000000]r12[/color][color=#0A246A],[[/color][color=#000000]rax[/color][color=#0A246A]-[/color][color=#800080]518h[/color][color=#0A246A]] [/color][color=#008000]; r12 = &l_Context
             [/color][color=#000000]fffff800`[/color][color=#800080]00891ec6 [/color][color=#0A246A]call    [/color][color=#000000]nt!RtlpGetStackLimits [/color][color=#0A246A]([/color][color=#000000]fffff800`[/color][color=#800080]00890da0[/color][color=#0A246A])
             [/color][color=#000000]fffff800`[/color][color=#800080]00891ecb [/color][color=#0A246A]mov     [/color][color=#000000]rcx[/color][color=#0A246A],[/color][color=#000000]rsi
             fffff800`[/color][color=#800080]00891ece [/color][color=#0A246A]call    [/color][color=#000000]nt!RtlCaptureContext [/color][color=#0A246A]([/color][color=#000000]fffff800`[/color][color=#800080]008bd150[/color][color=#0A246A])
             [/color][color=#000000]fffff800`[/color][color=#800080]00891ed3 [/color][color=#0A246A]mov     [/color][color=#000000]rax[/color][color=#0A246A],qword ptr [[/color][color=#000000]rsp[/color][color=#0A246A]+[/color][color=#800080]6A8h[/color][color=#0A246A]] [/color][color=#008000]; rax = pHistoryTable
             [/color][color=#000000]fffff800`[/color][color=#800080]00891edb [/color][color=#0A246A]test    [/color][color=#000000]rax[/color][color=#0A246A],[/color][color=#000000]rax
[/color][color=#0A246A]<            [/color][color=#000000]fffff800`[/color][color=#800080]00891ede [/color][color=#0A246A]je      [/color][color=#000000]nt!RtlUnwindEx[/color][color=#0A246A]+[/color][color=#800080]0x74 [/color][color=#0A246A]([/color][color=#000000]fffff800`[/color][color=#800080]00891ee4[/color][color=#0A246A])
[/color][color=#000000].            
.            nt!RtlUnwindEx[/color][color=#0A246A]+[/color][color=#800080]0x70[/color][color=#0A246A]:
[/color][color=#000000].            fffff800`[/color][color=#800080]00891ee0 [/color][color=#0A246A]mov     byte ptr [[/color][color=#000000]rax[/color][color=#0A246A]+[/color][color=#800080]4[/color][color=#0A246A]],[/color][color=#800080]1 [/color][color=#008000]; pHistoryTable->Search = UNWIND_HISTORY_TABLE_GLOBAL
[/color][color=#000000].            
.            nt!RtlUnwindEx[/color][color=#0A246A]+[/color][color=#800080]0x74[/color][color=#0A246A]:
>            [/color][color=#000000]fffff800`[/color][color=#800080]00891ee4 [/color][color=#0A246A]xor     [/color][color=#FF8000]ecx[/color][color=#0A246A],[/color][color=#FF8000]ecx
             [/color][color=#000000]fffff800`[/color][color=#800080]00891ee6 [/color][color=#0A246A]test    [/color][color=#000000]rbx[/color][color=#0A246A],[/color][color=#000000]rbx [/color][color=#008000]; 判断 pExceptionRecord 是否为 NULL
[/color][color=#0A246A]<            [/color][color=#000000]fffff800`[/color][color=#800080]00891ee9 [/color][color=#0A246A]jne     [/color][color=#000000]nt!RtlUnwindEx[/color][color=#0A246A]+[/color][color=#800080]0xbc [/color][color=#0A246A]([/color][color=#000000]fffff800`[/color][color=#800080]00891f2c[/color][color=#0A246A])
[/color][color=#000000].            
.            nt!RtlUnwindEx[/color][color=#0A246A]+[/color][color=#800080]0x7b[/color][color=#0A246A]:
[/color][color=#000000].            [/color][color=#008000]; pExceptionRecord 等于 NULL
[/color][color=#000000].            fffff800`[/color][color=#800080]00891eeb [/color][color=#0A246A]mov     [/color][color=#000000]rax[/color][color=#0A246A],qword ptr [[/color][color=#000000]rsi[/color][color=#0A246A]+[/color][color=#800080]0F8h[/color][color=#0A246A]]  [/color][color=#008000]; rax = pOriginalContext->Rip
[/color][color=#000000].            fffff800`[/color][color=#800080]00891ef2 [/color][color=#0A246A]lea     [/color][color=#000000]rbx[/color][color=#0A246A],[[/color][color=#000000]rsp[/color][color=#0A246A]+[/color][color=#800080]0C0h[/color][color=#0A246A]]            [/color][color=#008000]; rbx = &l_ExceptionRecord
[/color][color=#000000].            fffff800`[/color][color=#800080]00891efa [/color][color=#0A246A]mov     dword ptr [[/color][color=#000000]rsp[/color][color=#0A246A]+[/color][color=#800080]0C0h[/color][color=#0A246A]],[/color][color=#800080]0C0000027h [/color][color=#008000]; l_ExceptionRecord.ExceptionCode = STATUS_UNWIND (0xC0000027)
[/color][color=#000000].            fffff800`[/color][color=#800080]00891f05 [/color][color=#0A246A]mov     qword ptr [[/color][color=#000000]rsp[/color][color=#0A246A]+[/color][color=#800080]0D0h[/color][color=#0A246A]],[/color][color=#000000]rax  [/color][color=#008000]; l_ExceptionRecord.ExceptionAddress = pOriginalContext->Rip
[/color][color=#000000].            fffff800`[/color][color=#800080]00891f0d [/color][color=#0A246A]mov     [/color][color=#000000]rax[/color][color=#0A246A],qword ptr [[/color][color=#000000]rsp[/color][color=#0A246A]+[/color][color=#800080]6A8h[/color][color=#0A246A]]  [/color][color=#008000]; rax = pHistoryTable
[/color][color=#000000].            fffff800`[/color][color=#800080]00891f15 [/color][color=#0A246A]mov     qword ptr [[/color][color=#000000]rsp[/color][color=#0A246A]+[/color][color=#800080]690h[/color][color=#0A246A]],[/color][color=#000000]rbx  [/color][color=#008000]; [r8-home] = &l_ExceptionRecord ????
[/color][color=#000000].            fffff800`[/color][color=#800080]00891f1d [/color][color=#0A246A]mov     qword ptr [[/color][color=#000000]rsp[/color][color=#0A246A]+[/color][color=#800080]0C8h[/color][color=#0A246A]],[/color][color=#000000]rcx  [/color][color=#008000]; l_ExceptionRecord.ExceptionRecord = NULL
[/color][color=#000000].            fffff800`[/color][color=#800080]00891f25 [/color][color=#0A246A]mov     dword ptr [[/color][color=#000000]rsp[/color][color=#0A246A]+[/color][color=#800080]0D8h[/color][color=#0A246A]],[/color][color=#FF8000]ecx  [/color][color=#008000]; l_ExceptionRecord.NumberParameters = 0
[/color][color=#000000].            
.            nt!RtlUnwindEx[/color][color=#0A246A]+[/color][color=#800080]0xbc[/color][color=#0A246A]:
>            [/color][color=#000000]fffff800`[/color][color=#800080]00891f2c [/color][color=#0A246A]mov     [/color][color=#000000]rbx[/color][color=#0A246A],qword ptr [[/color][color=#000000]rsp[/color][color=#0A246A]+[/color][color=#800080]680h[/color][color=#0A246A]]  [/color][color=#008000]; rbx = &[rcx-home]
             [/color][color=#000000]fffff800`[/color][color=#800080]00891f34 [/color][color=#0A246A]mov     [/color][color=#FF8000]esi[/color][color=#0A246A],[/color][color=#800080]2 [/color][color=#008000]; l_ExceptionFlags(esi) = EXCEPTION_UNWINDING (2)
             [/color][color=#000000]fffff800`[/color][color=#800080]00891f39 [/color][color=#0A246A]mov     [/color][color=#FF8000]ecx[/color][color=#0A246A],[/color][color=#800080]6 [/color][color=#008000]; ecx = EXCEPTION_EXIT_UNWIND (6)
             [/color][color=#000000]fffff800`[/color][color=#800080]00891f3e [/color][color=#0A246A]test    [/color][color=#000000]rbp[/color][color=#0A246A],[/color][color=#000000]rbp [/color][color=#008000]; 判断 pEstablisherFrame 是否为 NULL
             [/color][color=#000000]fffff800`[/color][color=#800080]00891f41 [/color][color=#0A246A]mov     qword ptr [[/color][color=#000000]rsp[/color][color=#0A246A]+[/color][color=#800080]648h[/color][color=#0A246A]],[/color][color=#000000]r13 [/color][color=#008000]; 保存 r13 
             [/color][color=#000000]fffff800`[/color][color=#800080]00891f49 [/color][color=#0A246A]mov     qword ptr [[/color][color=#000000]rsp[/color][color=#0A246A]+[/color][color=#800080]640h[/color][color=#0A246A]],[/color][color=#000000]r14 [/color][color=#008000]; 保存 r14
             [/color][color=#000000]fffff800`[/color][color=#800080]00891f51 [/color][color=#0A246A]cmove   [/color][color=#FF8000]esi[/color][color=#0A246A],[/color][color=#FF8000]ecx [/color][color=#008000]; if (NULL == pEstablisherFrame) { l_ExceptionFlags = EXCEPTION_EXIT_UNWIND (6) }
             [/color][color=#000000]fffff800`[/color][color=#800080]00891f54 [/color][color=#0A246A]xchg    [/color][color=#FF8000]ax[/color][color=#0A246A],[/color][color=#FF8000]ax
             [/color][color=#000000]fffff800`[/color][color=#800080]00891f58 [/color][color=#0A246A]xchg    [/color][color=#FF8000]ax[/color][color=#0A246A],[/color][color=#FF8000]ax
             [/color][color=#000000]fffff800`[/color][color=#800080]00891f5c [/color][color=#0A246A]xchg    [/color][color=#FF8000]ax[/color][color=#0A246A],[/color][color=#FF8000]ax
             
             [/color][color=#000000]nt!RtlUnwindEx[/color][color=#0A246A]+[/color][color=#800080]0xf0[/color][color=#0A246A]:
           > [/color][color=#000000]fffff800`[/color][color=#800080]00891f60 [/color][color=#0A246A]mov     [/color][color=#000000]r13[/color][color=#0A246A],qword ptr [[/color][color=#000000]rdi[/color][color=#0A246A]+[/color][color=#800080]0F8h[/color][color=#0A246A]] [/color][color=#008000]; r13 = pOriginalContext->Rip
           [/color][color=#000000]. fffff800`[/color][color=#800080]00891f67 [/color][color=#0A246A]lea     [/color][color=#000000]rdx[/color][color=#0A246A],[[/color][color=#000000]rsp[/color][color=#0A246A]+[/color][color=#800080]60h[/color][color=#0A246A]] [/color][color=#008000]; rdx = &l_pImageBase
           [/color][color=#000000]. fffff800`[/color][color=#800080]00891f6c [/color][color=#0A246A]mov     [/color][color=#000000]r8[/color][color=#0A246A],[/color][color=#000000]rax        [/color][color=#008000]; r8 = pHistoryTable
           [/color][color=#000000]. fffff800`[/color][color=#800080]00891f6f [/color][color=#0A246A]mov     [/color][color=#000000]rcx[/color][color=#0A246A],[/color][color=#000000]r13
           . fffff800`[/color][color=#800080]00891f72 [/color][color=#0A246A]mov     qword ptr [[/color][color=#000000]rsp[/color][color=#0A246A]+[/color][color=#800080]68h[/color][color=#0A246A]],[/color][color=#000000]r13
           . fffff800`[/color][color=#800080]00891f77 [/color][color=#0A246A]call    [/color][color=#000000]nt!RtlLookupFunctionEntry [/color][color=#0A246A]([/color][color=#000000]fffff800`[/color][color=#800080]00890e60[/color][color=#0A246A])
           [/color][color=#000000].                   [/color][color=#008000]; l_pFunctionEntry = RtlLookupFunctionEntry(pOriginalContext->Rip, 
           [/color][color=#000000].                   [/color][color=#008000];                                           &l_pImageBase,
           [/color][color=#000000].                   [/color][color=#008000];                                           pHistoryTable)
           [/color][color=#000000]. fffff800`[/color][color=#800080]00891f7c [/color][color=#0A246A]test    [/color][color=#000000]rax[/color][color=#0A246A],[/color][color=#000000]rax [/color][color=#008000]; 判断 l_pFunctionEntry (eax) 是否为 NULL
           [/color][color=#000000]. fffff800`[/color][color=#800080]00891f7f [/color][color=#0A246A]mov     [/color][color=#000000]r14[/color][color=#0A246A],[/color][color=#000000]rax [/color][color=#008000]; r14 = l_pFunctionEntry
[/color][color=#0A246A]<          [/color][color=#000000]. fffff800`[/color][color=#800080]00891f82 [/color][color=#0A246A]je      [/color][color=#000000]nt!RtlUnwindEx[/color][color=#0A246A]+[/color][color=#800080]0x3ab [/color][color=#0A246A]([/color][color=#000000]fffff800`[/color][color=#800080]0089221b[/color][color=#0A246A])
[/color][color=#000000].          . 
.          . nt!RtlUnwindEx[/color][color=#0A246A]+[/color][color=#800080]0x118[/color][color=#0A246A]:
[/color][color=#000000].          . fffff800`[/color][color=#800080]00891f88 [/color][color=#0A246A]mov     [/color][color=#000000]rdx[/color][color=#0A246A],[/color][color=#000000]rdi [/color][color=#008000]; rdx = pOriginalContext
[/color][color=#000000].          . fffff800`[/color][color=#800080]00891f8b [/color][color=#0A246A]mov     [/color][color=#000000]rcx[/color][color=#0A246A],[/color][color=#000000]r12 [/color][color=#008000]; rcx = &l_Context
[/color][color=#000000].          . fffff800`[/color][color=#800080]00891f8e [/color][color=#0A246A]call    [/color][color=#000000]nt!RtlpCopyContext [/color][color=#0A246A]([/color][color=#000000]fffff800`[/color][color=#800080]00891080[/color][color=#0A246A])
[/color][color=#000000].          .                   [/color][color=#008000]; RtlpCopyContext(&l_Context, pOriginalContext)
[/color][color=#000000].          . fffff800`[/color][color=#800080]00891f93 [/color][color=#0A246A]mov     [/color][color=#000000]rdx[/color][color=#0A246A],qword ptr [[/color][color=#000000]rsp[/color][color=#0A246A]+[/color][color=#800080]60h[/color][color=#0A246A]] [/color][color=#008000]; rdx = l_pImageBase
[/color][color=#000000].          . fffff800`[/color][color=#800080]00891f98 [/color][color=#0A246A]mov     qword ptr [[/color][color=#000000]rsp[/color][color=#0A246A]+[/color][color=#800080]38h[/color][color=#0A246A]],[/color][color=#800080]0   [/color][color=#008000]; _ARG_8 = 0
[/color][color=#000000].          . fffff800`[/color][color=#800080]00891fa1 [/color][color=#0A246A]lea     [/color][color=#000000]rax[/color][color=#0A246A],[[/color][color=#000000]rsp[/color][color=#0A246A]+[/color][color=#800080]680h[/color][color=#0A246A]]          [/color][color=#008000]; rax = &[rcx-home],这里被用作局部变量 l_pEstablisherFrame 空间
[/color][color=#000000].          . fffff800`[/color][color=#800080]00891fa9 [/color][color=#0A246A]mov     [/color][color=#000000]r9[/color][color=#0A246A],[/color][color=#000000]r14                  [/color][color=#008000]; r9 = l_pFunctionEntry
[/color][color=#000000].          . fffff800`[/color][color=#800080]00891fac [/color][color=#0A246A]mov     [/color][color=#000000]r8[/color][color=#0A246A],[/color][color=#000000]r13                  [/color][color=#008000]; r8 = pOriginalContext->Rip
[/color][color=#000000].          . fffff800`[/color][color=#800080]00891faf [/color][color=#0A246A]mov     qword ptr [[/color][color=#000000]rsp[/color][color=#0A246A]+[/color][color=#800080]30h[/color][color=#0A246A]],[/color][color=#000000]rax [/color][color=#008000]; _ARG7 = &l_pEstablisherFrame
[/color][color=#000000].          . fffff800`[/color][color=#800080]00891fb4 [/color][color=#0A246A]lea     [/color][color=#000000]rax[/color][color=#0A246A],[[/color][color=#000000]rsp[/color][color=#0A246A]+[/color][color=#800080]58h[/color][color=#0A246A]]           [/color][color=#008000]; rax = &l_pHandlerData
[/color][color=#000000].          . fffff800`[/color][color=#800080]00891fb9 [/color][color=#0A246A]mov     [/color][color=#FF8000]ecx[/color][color=#0A246A],[/color][color=#800080]2                   [/color][color=#008000]; ecx = UNW_FLAG_UHANDLER (2)
[/color][color=#000000].          . fffff800`[/color][color=#800080]00891fbe [/color][color=#0A246A]mov     qword ptr [[/color][color=#000000]rsp[/color][color=#0A246A]+[/color][color=#800080]28h[/color][color=#0A246A]],[/color][color=#000000]rax [/color][color=#008000]; _ARG_6 = &l_pHandlerData
[/color][color=#000000].          . fffff800`[/color][color=#800080]00891fc3 [/color][color=#0A246A]mov     qword ptr [[/color][color=#000000]rsp[/color][color=#0A246A]+[/color][color=#800080]20h[/color][color=#0A246A]],[/color][color=#000000]r12 [/color][color=#008000]; _ARG_5 = &l_Context
[/color][color=#000000].          . fffff800`[/color][color=#800080]00891fc8 [/color][color=#0A246A]call    [/color][color=#000000]nt!RtlVirtualUnwind [/color][color=#0A246A]([/color][color=#000000]fffff800`[/color][color=#800080]00891380[/color][color=#0A246A])
[/color][color=#000000].          .                   [/color][color=#008000]; l_pExceptionRoutine = RtlVirtualUnwind(UNW_FLAG_UHANDLER,
[/color][color=#000000].          .                   [/color][color=#008000];                                        l_pImageBase,
[/color][color=#000000].          .                   [/color][color=#008000];                                        pOriginalContext->Rip,
[/color][color=#000000].          .                   [/color][color=#008000];                                        l_pFunctionEntry,
[/color][color=#000000].          .                   [/color][color=#008000];                                        &l_Context,
[/color][color=#000000].          .                   [/color][color=#008000];                                        &l_pHandlerData,
[/color][color=#000000].          .                   [/color][color=#008000];                                        &l_pEstablisherFrame,
[/color][color=#000000].          .                   [/color][color=#008000];                                        NULL);
[/color][color=#000000].          . fffff800`[/color][color=#800080]00891fcd [/color][color=#0A246A]mov     [/color][color=#000000]rbx[/color][color=#0A246A],qword ptr [[/color][color=#000000]rsp[/color][color=#0A246A]+[/color][color=#800080]680h[/color][color=#0A246A]] [/color][color=#008000]; rbx = l_pEstablisherFrame
[/color][color=#000000].          . fffff800`[/color][color=#800080]00891fd5 [/color][color=#0A246A]mov     [/color][color=#000000]rcx[/color][color=#0A246A],[/color][color=#000000]rax                  [/color][color=#008000]; rcx = l_pExceptionRoutine
[/color][color=#000000].          . fffff800`[/color][color=#800080]00891fd8 [/color][color=#0A246A]mov     qword ptr [[/color][color=#000000]rsp[/color][color=#0A246A]+[/color][color=#800080]48h[/color][color=#0A246A]],[/color][color=#000000]rax
.          . fffff800`[/color][color=#800080]00891fdd [/color][color=#0A246A]test    [/color][color=#FF8000]bl[/color][color=#0A246A],[/color][color=#800080]7                     [/color][color=#008000]; 检查 l_pEstablisherFrame 是否对齐
[/color][color=#000000].[/color][color=#0A246A]<         [/color][color=#000000]. fffff800`[/color][color=#800080]00891fe0 [/color][color=#0A246A]jne     [/color][color=#000000]nt!RtlUnwindEx[/color][color=#0A246A]+[/color][color=#800080]0x431 [/color][color=#0A246A]([/color][color=#000000]fffff800`[/color][color=#800080]008922a1[/color][color=#0A246A])
[/color][color=#000000]..         . 
..         . nt!RtlUnwindEx[/color][color=#0A246A]+[/color][color=#800080]0x176[/color][color=#0A246A]:
[/color][color=#000000]..         . fffff800`[/color][color=#800080]00891fe6 [/color][color=#0A246A]cmp     [/color][color=#000000]rbx[/color][color=#0A246A],qword ptr [[/color][color=#000000]rsp[/color][color=#0A246A]+[/color][color=#800080]50h[/color][color=#0A246A]]  [/color][color=#008000]; cmp l_pEstablisherFrame, l_LowLimit
[/color][color=#000000]..[/color][color=#0A246A]<        [/color][color=#000000]. fffff800`[/color][color=#800080]00891feb [/color][color=#0A246A]jb      [/color][color=#000000]nt!RtlUnwindEx[/color][color=#0A246A]+[/color][color=#800080]0x184 [/color][color=#0A246A]([/color][color=#000000]fffff800`[/color][color=#800080]00891ff4[/color][color=#0A246A])
[/color][color=#000000]...        . 
...        . nt!RtlUnwindEx[/color][color=#0A246A]+[/color][color=#800080]0x17d[/color][color=#0A246A]:
[/color][color=#000000]...        . fffff800`[/color][color=#800080]00891fed [/color][color=#0A246A]cmp     [/color][color=#000000]rbx[/color][color=#0A246A],qword ptr [[/color][color=#000000]rsp[/color][color=#0A246A]+[/color][color=#800080]40h[/color][color=#0A246A]]  [/color][color=#008000]; cmp l_pEstablisherFrame, l_HighLimit
[/color][color=#000000]...[/color][color=#0A246A]<       [/color][color=#000000]. fffff800`[/color][color=#800080]00891ff2 [/color][color=#0A246A]jb      [/color][color=#000000]nt!RtlUnwindEx[/color][color=#0A246A]+[/color][color=#800080]0x1d3 [/color][color=#0A246A]([/color][color=#000000]fffff800`[/color][color=#800080]00892043[/color][color=#0A246A])
[/color][color=#000000]....       . 
....       . nt!RtlUnwindEx[/color][color=#0A246A]+[/color][color=#800080]0x184[/color][color=#0A246A]:
[/color][color=#000000]....       . [/color][color=#008000]; 检查 l_pEstablisherFrame 是否合法
[/color][color=#000000]..[/color][color=#0A246A]>[/color][color=#000000].       . fffff800`[/color][color=#800080]00891ff4 [/color][color=#0A246A]mov     [/color][color=#FF8000]cl[/color][color=#0A246A],byte ptr [/color][color=#FF8000]gs[/color][color=#0A246A]:[[/color][color=#800080]20DEh[/color][color=#0A246A]]   [/color][color=#008000]; cl = _KPCR->DpcRoutineActive
[/color][color=#000000].. .       . fffff800`[/color][color=#800080]00891ffc [/color][color=#0A246A]test    [/color][color=#FF8000]cl[/color][color=#0A246A],[/color][color=#FF8000]cl                    [/color][color=#008000]; 判断当前是否在执行 DPC
[/color][color=#000000].[/color][color=#0A246A]< [/color][color=#000000].       . fffff800`[/color][color=#800080]00891ffe [/color][color=#0A246A]jne     [/color][color=#000000]nt!RtlUnwindEx[/color][color=#0A246A]+[/color][color=#800080]0x431 [/color][color=#0A246A]([/color][color=#000000]fffff800`[/color][color=#800080]008922a1[/color][color=#0A246A]) [/color][color=#008000]; 如果是在执行 DPC 则失败???
[/color][color=#000000].. .       . 
.. .       . nt!RtlUnwindEx[/color][color=#0A246A]+[/color][color=#800080]0x194[/color][color=#0A246A]:
[/color][color=#000000].. .       . fffff800`[/color][color=#800080]00892004 [/color][color=#0A246A]mov     [/color][color=#000000]rcx[/color][color=#0A246A],qword ptr [[/color][color=#000000]rsp[/color][color=#0A246A]+[/color][color=#800080]40h[/color][color=#0A246A]] [/color][color=#008000]; rcx = l_HighLimit
[/color][color=#000000].. .       . fffff800`[/color][color=#800080]00892009 [/color][color=#0A246A]mov     [/color][color=#000000]rax[/color][color=#0A246A],qword ptr [[/color][color=#000000]rcx[/color][color=#0A246A]-[/color][color=#800080]28h[/color][color=#0A246A]] [/color][color=#008000]; rax = l_KernelStackCtrl->Previous.StackBase
[/color][color=#000000].. .       . fffff800`[/color][color=#800080]0089200d [/color][color=#0A246A]test    [/color][color=#000000]rax[/color][color=#0A246A],[/color][color=#000000]rax                 [/color][color=#008000]; 判断 l_KernelStackCtrl->Previous.StackBase 是否为 NULL
[/color][color=#000000].[/color][color=#0A246A]< [/color][color=#000000].       . fffff800`[/color][color=#800080]00892010 [/color][color=#0A246A]je      [/color][color=#000000]nt!RtlUnwindEx[/color][color=#0A246A]+[/color][color=#800080]0x431 [/color][color=#0A246A]([/color][color=#000000]fffff800`[/color][color=#800080]008922a1[/color][color=#0A246A])
[/color][color=#000000].. .       . 
.. .       . nt!RtlUnwindEx[/color][color=#0A246A]+[/color][color=#800080]0x1a6[/color][color=#0A246A]:
[/color][color=#000000].. .       . fffff800`[/color][color=#800080]00892016 [/color][color=#0A246A]mov     [/color][color=#000000]rdx[/color][color=#0A246A],qword ptr [[/color][color=#000000]rcx[/color][color=#0A246A]-[/color][color=#800080]20h[/color][color=#0A246A]]  [/color][color=#008000]; rdx = l_KernelStackCtrl->Previous.StackLimit
[/color][color=#000000].. .       . fffff800`[/color][color=#800080]0089201a [/color][color=#0A246A]mov     [/color][color=#000000]rbx[/color][color=#0A246A],qword ptr [[/color][color=#000000]rsp[/color][color=#0A246A]+[/color][color=#800080]680h[/color][color=#0A246A]] [/color][color=#008000]; rbx = l_pEstablisherFrame
[/color][color=#000000].. .       . fffff800`[/color][color=#800080]00892022 [/color][color=#0A246A]cmp     [/color][color=#000000]rbx[/color][color=#0A246A],[/color][color=#000000]rdx                  [/color][color=#008000]; cmp l_pEstablisherFrame, l_KernelStackCtrl->Previous.StackLimit
[/color][color=#000000].[/color][color=#0A246A]< [/color][color=#000000].       . fffff800`[/color][color=#800080]00892025 [/color][color=#0A246A]jb      [/color][color=#000000]nt!RtlUnwindEx[/color][color=#0A246A]+[/color][color=#800080]0x431 [/color][color=#0A246A]([/color][color=#000000]fffff800`[/color][color=#800080]008922a1[/color][color=#0A246A])
[/color][color=#000000].. .       . 
.. .       . nt!RtlUnwindEx[/color][color=#0A246A]+[/color][color=#800080]0x1bb[/color][color=#0A246A]:
[/color][color=#000000].. .       . fffff800`[/color][color=#800080]0089202b [/color][color=#0A246A]cmp     [/color][color=#000000]rbx[/color][color=#0A246A],[/color][color=#000000]rax [/color][color=#008000]; cmp l_pEstablisherFrame, l_KernelStackCtrl->Previous.StackBase
[/color][color=#000000].[/color][color=#0A246A]< [/color][color=#000000].       . fffff800`[/color][color=#800080]0089202e [/color][color=#0A246A]jae     [/color][color=#000000]nt!RtlUnwindEx[/color][color=#0A246A]+[/color][color=#800080]0x431 [/color][color=#0A246A]([/color][color=#000000]fffff800`[/color][color=#800080]008922a1[/color][color=#0A246A])
[/color][color=#000000].. .       . 
.. .       . nt!RtlUnwindEx[/color][color=#0A246A]+[/color][color=#800080]0x1c4[/color][color=#0A246A]:
[/color][color=#000000].. .       . fffff800`[/color][color=#800080]00892034 [/color][color=#0A246A]mov     [/color][color=#000000]rcx[/color][color=#0A246A],qword ptr [[/color][color=#000000]rsp[/color][color=#0A246A]+[/color][color=#800080]48h[/color][color=#0A246A]] [/color][color=#008000]; rcx = l_pExceptionRoutine
[/color][color=#000000].. .       . fffff800`[/color][color=#800080]00892039 [/color][color=#0A246A]mov     qword ptr [[/color][color=#000000]rsp[/color][color=#0A246A]+[/color][color=#800080]50h[/color][color=#0A246A]],[/color][color=#000000]rdx [/color][color=#008000]; l_LowLimit = l_KernelStackCtrl->Previous.StackLimit
[/color][color=#000000].. .       . fffff800`[/color][color=#800080]0089203e [/color][color=#0A246A]mov     qword ptr [[/color][color=#000000]rsp[/color][color=#0A246A]+[/color][color=#800080]40h[/color][color=#0A246A]],[/color][color=#000000]rax [/color][color=#008000]; l_HighLimit = l_KernelStackCtrl->Previous.StackBase
[/color][color=#000000].. .       . 
.. .       . nt!RtlUnwindEx[/color][color=#0A246A]+[/color][color=#800080]0x1d3[/color][color=#0A246A]:
[/color][color=#000000].. [/color][color=#0A246A]>       [/color][color=#000000]. fffff800`[/color][color=#800080]00892043 [/color][color=#0A246A]test    [/color][color=#000000]rbp[/color][color=#0A246A],[/color][color=#000000]rbp [/color][color=#008000]; 判断 pEstablisherFrame 是否为 NULL
[/color][color=#000000].. [/color][color=#0A246A]<       [/color][color=#000000]. fffff800`[/color][color=#800080]00892046 [/color][color=#0A246A]je      [/color][color=#000000]nt!RtlUnwindEx[/color][color=#0A246A]+[/color][color=#800080]0x1e1 [/color][color=#0A246A]([/color][color=#000000]fffff800`[/color][color=#800080]00892051[/color][color=#0A246A])
[/color][color=#000000].. .       . 
.. .       . nt!RtlUnwindEx[/color][color=#0A246A]+[/color][color=#800080]0x1d8[/color][color=#0A246A]:
[/color][color=#000000].. .       . fffff800`[/color][color=#800080]00892048 [/color][color=#0A246A]cmp     [/color][color=#000000]rbp[/color][color=#0A246A],[/color][color=#000000]rbx [/color][color=#008000]; cmp pEstablisherFrame, l_pEstablisherFrame
[/color][color=#000000].[/color][color=#0A246A]< [/color][color=#000000].       . fffff800`[/color][color=#800080]0089204b [/color][color=#0A246A]jb      [/color][color=#000000]nt!RtlUnwindEx[/color][color=#0A246A]+[/color][color=#800080]0x431 [/color][color=#0A246A]([/color][color=#000000]fffff800`[/color][color=#800080]008922a1[/color][color=#0A246A])
[/color][color=#000000].. .       . 
.. .       . nt!RtlUnwindEx[/color][color=#0A246A]+[/color][color=#800080]0x1e1[/color][color=#0A246A]:
[/color][color=#000000].. [/color][color=#0A246A]>       [/color][color=#000000]. fffff800`[/color][color=#800080]00892051 [/color][color=#0A246A]test    [/color][color=#000000]rcx[/color][color=#0A246A],[/color][color=#000000]rcx [/color][color=#008000]; 判断 l_pExceptionRoutine 是否为 NULL
[/color][color=#000000]..  [/color][color=#0A246A]<      [/color][color=#000000]. fffff800`[/color][color=#800080]00892054 [/color][color=#0A246A]je      [/color][color=#000000]nt!RtlUnwindEx[/color][color=#0A246A]+[/color][color=#800080]0x39b [/color][color=#0A246A]([/color][color=#000000]fffff800`[/color][color=#800080]0089220b[/color][color=#0A246A])
[/color][color=#000000]..  .      . 
..  .      . nt!RtlUnwindEx[/color][color=#0A246A]+[/color][color=#800080]0x1ea[/color][color=#0A246A]:
[/color][color=#000000]..  .      . fffff800`[/color][color=#800080]0089205a [/color][color=#0A246A]mov     [/color][color=#000000]r13[/color][color=#0A246A],qword ptr [[/color][color=#000000]rsp[/color][color=#0A246A]+[/color][color=#800080]58h[/color][color=#0A246A]] [/color][color=#008000]; r13 = l_pHandlerData
[/color][color=#000000]..  .      . fffff800`[/color][color=#800080]0089205f [/color][color=#0A246A]mov     qword ptr [[/color][color=#000000]rsp[/color][color=#0A246A]+[/color][color=#800080]90h[/color][color=#0A246A]],[/color][color=#000000]r15 [/color][color=#008000]; [rsp+90] = pJumpTargetIp
[/color][color=#000000]..  .      . fffff800`[/color][color=#800080]00892067 [/color][color=#0A246A]xor     [/color][color=#000000]r15d[/color][color=#0A246A],[/color][color=#000000]r15d
..  .      . fffff800`[/color][color=#800080]0089206a [/color][color=#0A246A]xchg    [/color][color=#FF8000]ax[/color][color=#0A246A],[/color][color=#FF8000]ax
[/color][color=#000000]..  .      . fffff800`[/color][color=#800080]0089206d [/color][color=#0A246A]xchg    [/color][color=#FF8000]ax[/color][color=#0A246A],[/color][color=#FF8000]ax
[/color][color=#000000]..  .      . 
..  .      . nt!RtlUnwindEx[/color][color=#0A246A]+[/color][color=#800080]0x200[/color][color=#0A246A]:
[/color][color=#000000]..  .    [/color][color=#0A246A]> [/color][color=#000000]. fffff800`[/color][color=#800080]00892070 [/color][color=#0A246A]cmp     [/color][color=#000000]rbp[/color][color=#0A246A],[/color][color=#000000]rbx [/color][color=#008000]; cmp pEstablisherFrame, l_pEstablisherFrame
[/color][color=#000000]..  .[/color][color=#0A246A]<   [/color][color=#000000]. . fffff800`[/color][color=#800080]00892073 [/color][color=#0A246A]jne     [/color][color=#000000]nt!RtlUnwindEx[/color][color=#0A246A]+[/color][color=#800080]0x208 [/color][color=#0A246A]([/color][color=#000000]fffff800`[/color][color=#800080]00892078[/color][color=#0A246A])
[/color][color=#000000]..  ..   . . 
..  ..   . . nt!RtlUnwindEx[/color][color=#0A246A]+[/color][color=#800080]0x205[/color][color=#0A246A]:
[/color][color=#000000]..  ..   . . fffff800`[/color][color=#800080]00892075 [/color][color=#0A246A]or      [/color][color=#FF8000]esi[/color][color=#0A246A],[/color][color=#800080]20h [/color][color=#008000]; l_ExceptionFlags |= EXCEPTION_TARGET_UNWIND (0x20)
[/color][color=#000000]..  ..   . . 
..  ..   . . nt!RtlUnwindEx[/color][color=#0A246A]+[/color][color=#800080]0x208[/color][color=#0A246A]:
[/color][color=#000000]..  .[/color][color=#0A246A]>   [/color][color=#000000]. . fffff800`[/color][color=#800080]00892078 [/color][color=#0A246A]mov     [/color][color=#000000]r10[/color][color=#0A246A],qword ptr [[/color][color=#000000]rsp[/color][color=#0A246A]+[/color][color=#800080]690h[/color][color=#0A246A]] [/color][color=#008000]; r10 = &l_ExceptionRecord
[/color][color=#000000]..  .    . . fffff800`[/color][color=#800080]00892080 [/color][color=#0A246A]mov     [/color][color=#000000]rax[/color][color=#0A246A],qword ptr [[/color][color=#000000]rsp[/color][color=#0A246A]+[/color][color=#800080]698h[/color][color=#0A246A]] [/color][color=#008000]; rax = ReturnValue
[/color][color=#000000]..  .    . . fffff800`[/color][color=#800080]00892088 [/color][color=#0A246A]mov     qword ptr [[/color][color=#000000]rsp[/color][color=#0A246A]+[/color][color=#800080]0A0h[/color][color=#0A246A]],[/color][color=#000000]rcx [/color][color=#008000]; l_DispatcherContext.LanguageHandler = l_pExceptionRoutine
[/color][color=#000000]..  .    . . fffff800`[/color][color=#800080]00892090 [/color][color=#0A246A]mov     dword ptr [[/color][color=#000000]r10[/color][color=#0A246A]+[/color][color=#800080]4[/color][color=#0A246A]],[/color][color=#FF8000]esi    [/color][color=#008000]; l_ExceptionRecord.ExceptionFlags = l_ExceptionFlags
[/color][color=#000000]..  .    . . fffff800`[/color][color=#800080]00892094 [/color][color=#0A246A]mov     qword ptr [[/color][color=#000000]rdi[/color][color=#0A246A]+[/color][color=#800080]78h[/color][color=#0A246A]],[/color][color=#000000]rax  [/color][color=#008000]; pOriginalContext->Rax = ReturnValue
[/color][color=#000000]..  .    . . fffff800`[/color][color=#800080]00892098 [/color][color=#0A246A]mov     [/color][color=#000000]rax[/color][color=#0A246A],qword ptr [[/color][color=#000000]rsp[/color][color=#0A246A]+[/color][color=#800080]68h[/color][color=#0A246A]]  [/color][color=#008000]; rax = pOriginalContext->Rip
[/color][color=#000000]..  .    . . fffff800`[/color][color=#800080]0089209d [/color][color=#0A246A]mov     qword ptr [[/color][color=#000000]rsp[/color][color=#0A246A]+[/color][color=#800080]70h[/color][color=#0A246A]],[/color][color=#000000]rax  [/color][color=#008000]; l_DispatcherContext.ControlPc = pOriginalContext->Rip
[/color][color=#000000]..  .    . . fffff800`[/color][color=#800080]008920a2 [/color][color=#0A246A]mov     [/color][color=#000000]rax[/color][color=#0A246A],qword ptr [[/color][color=#000000]rsp[/color][color=#0A246A]+[/color][color=#800080]60h[/color][color=#0A246A]]  [/color][color=#008000]; rax = l_pImageBase
[/color][color=#000000]..  .    . . fffff800`[/color][color=#800080]008920a7 [/color][color=#0A246A]lea     [/color][color=#000000]r9[/color][color=#0A246A],[[/color][color=#000000]rsp[/color][color=#0A246A]+[/color][color=#800080]70h[/color][color=#0A246A]]             [/color][color=#008000]; r9 = &l_DispatcherContext
[/color][color=#000000]..  .    . . fffff800`[/color][color=#800080]008920ac [/color][color=#0A246A]mov     qword ptr [[/color][color=#000000]rsp[/color][color=#0A246A]+[/color][color=#800080]78h[/color][color=#0A246A]],[/color][color=#000000]rax  [/color][color=#008000]; l_DispatcherContext.ImageBase = l_pImageBase
[/color][color=#000000]..  .    . . fffff800`[/color][color=#800080]008920b1 [/color][color=#0A246A]mov     [/color][color=#000000]rax[/color][color=#0A246A],qword ptr [[/color][color=#000000]rsp[/color][color=#0A246A]+[/color][color=#800080]6A8h[/color][color=#0A246A]] [/color][color=#008000]; rax = pHistoryTable
[/color][color=#000000]..  .    . . fffff800`[/color][color=#800080]008920b9 [/color][color=#0A246A]mov     [/color][color=#000000]r8[/color][color=#0A246A],[/color][color=#000000]rdi                   [/color][color=#008000]; r8 = pOriginalContext
[/color][color=#000000]..  .    . . fffff800`[/color][color=#800080]008920bc [/color][color=#0A246A]mov     [/color][color=#000000]rdx[/color][color=#0A246A],[/color][color=#000000]rbx                  [/color][color=#008000]; rdx = l_pEstablisherFrame
[/color][color=#000000]..  .    . . fffff800`[/color][color=#800080]008920bf [/color][color=#0A246A]mov     [/color][color=#000000]rcx[/color][color=#0A246A],[/color][color=#000000]r10                  [/color][color=#008000]; rcx = &l_ExceptionRecord
[/color][color=#000000]..  .    . . fffff800`[/color][color=#800080]008920c2 [/color][color=#0A246A]mov     qword ptr [[/color][color=#000000]rsp[/color][color=#0A246A]+[/color][color=#800080]80h[/color][color=#0A246A]],[/color][color=#000000]r14   [/color][color=#008000]; l_DispatcherContext.FunctionEntry = l_pFunctionEntry
[/color][color=#000000]..  .    . . fffff800`[/color][color=#800080]008920ca [/color][color=#0A246A]mov     qword ptr [[/color][color=#000000]rsp[/color][color=#0A246A]+[/color][color=#800080]0B0h[/color][color=#0A246A]],[/color][color=#000000]rax  [/color][color=#008000]; l_DispatcherContext.HistoryTable = pHistoryTable
[/color][color=#000000]..  .    . . fffff800`[/color][color=#800080]008920d2 [/color][color=#0A246A]mov     qword ptr [[/color][color=#000000]rsp[/color][color=#0A246A]+[/color][color=#800080]88h[/color][color=#0A246A]],[/color][color=#000000]rbx   [/color][color=#008000]; l_DispatcherContext.EstablisherFrame = l_pEstablisherFrame
[/color][color=#000000]..  .    . . fffff800`[/color][color=#800080]008920da [/color][color=#0A246A]mov     qword ptr [[/color][color=#000000]rsp[/color][color=#0A246A]+[/color][color=#800080]98h[/color][color=#0A246A]],[/color][color=#000000]rdi   [/color][color=#008000]; l_DispatcherContext.ContextRecord = pOriginalContext
[/color][color=#000000]..  .    . . fffff800`[/color][color=#800080]008920e2 [/color][color=#0A246A]mov     qword ptr [[/color][color=#000000]rsp[/color][color=#0A246A]+[/color][color=#800080]0A8h[/color][color=#0A246A]],[/color][color=#000000]r13  [/color][color=#008000]; l_DispatcherContext.HandlerData = l_pHandlerData
[/color][color=#000000]..  .    . . fffff800`[/color][color=#800080]008920ea [/color][color=#0A246A]mov     dword ptr [[/color][color=#000000]rsp[/color][color=#0A246A]+[/color][color=#800080]0B8h[/color][color=#0A246A]],[/color][color=#000000]r15d [/color][color=#008000]; l_DispatcherContext.ScopeIndex = 0
[/color][color=#000000]..  .    . . fffff800`[/color][color=#800080]008920f2 [/color][color=#0A246A]and     [/color][color=#FF8000]esi[/color][color=#0A246A],[/color][color=#800080]0FFFFFF9Fh            [/color][color=#008000]; l_ExceptionFlags &= ~(EXCEPTION_TARGET_UNWIND|EXCEPTION_COLLIDED_UNWIND)
[/color][color=#000000]..  .    . . fffff800`[/color][color=#800080]008920f5 [/color][color=#0A246A]call    [/color][color=#000000]nt!RtlpExecuteHandlerForUnwind [/color][color=#0A246A]([/color][color=#000000]fffff800`[/color][color=#800080]008bd9d0[/color][color=#0A246A])
[/color][color=#000000]..  .    . .                   [/color][color=#008000]; RtlpExecuteHandlerForUnwind(&l_ExceptionRecord,
[/color][color=#000000]..  .    . .                   [/color][color=#008000];                             l_pEstablisherFrame,
[/color][color=#000000]..  .    . .                   [/color][color=#008000];                             pOriginalContext,
[/color][color=#000000]..  .    . .                   [/color][color=#008000];                             &l_DispatcherContext);
[/color][color=#000000]..  .    . . fffff800`[/color][color=#800080]008920fa [/color][color=#0A246A]dec     [/color][color=#FF8000]eax
[/color][color=#000000]..  .[/color][color=#0A246A]<   [/color][color=#000000]. . fffff800`[/color][color=#800080]008920fc [/color][color=#0A246A]je      [/color][color=#000000]nt!RtlUnwindEx[/color][color=#0A246A]+[/color][color=#800080]0x368 [/color][color=#0A246A]([/color][color=#000000]fffff800`[/color][color=#800080]008921d8[/color][color=#0A246A]) [/color][color=#008000]; 如果返回 ExceptionContinueSearch 则跳转
[/color][color=#000000]..  ..   . . 
..  ..   . . nt!RtlUnwindEx[/color][color=#0A246A]+[/color][color=#800080]0x292[/color][color=#0A246A]:
[/color][color=#000000]..  ..   . . fffff800`[/color][color=#800080]00892102 [/color][color=#0A246A]cmp     [/color][color=#FF8000]eax[/color][color=#0A246A],[/color][color=#800080]2 [/color][color=#008000]; cmp eax, ExceptionCollidedUnwind (3 - 1)
[/color][color=#000000]..  ..[/color][color=#0A246A]<  [/color][color=#000000]. . fffff800`[/color][color=#800080]00892105 [/color][color=#0A246A]jne     [/color][color=#000000]nt!RtlUnwindEx[/color][color=#0A246A]+[/color][color=#800080]0x426 [/color][color=#0A246A]([/color][color=#000000]fffff800`[/color][color=#800080]00892296[/color][color=#0A246A])
[/color][color=#000000]..  ...  . . 
..  ...  . . nt!RtlUnwindEx[/color][color=#0A246A]+[/color][color=#800080]0x29b[/color][color=#0A246A]:
[/color][color=#000000]..  ...  . . [/color][color=#008000]; ExceptionCollidedUnwind 的情况
[/color][color=#000000]..  ...  . . fffff800`[/color][color=#800080]0089210b [/color][color=#0A246A]mov     [/color][color=#000000]r8[/color][color=#0A246A],qword ptr [[/color][color=#000000]rsp[/color][color=#0A246A]+[/color][color=#800080]70h[/color][color=#0A246A]]   [/color][color=#008000]; r8 = l_DispatcherContext.ControlPc
[/color][color=#000000]..  ...  . . fffff800`[/color][color=#800080]00892110 [/color][color=#0A246A]mov     [/color][color=#000000]r10[/color][color=#0A246A],qword ptr [[/color][color=#000000]rsp[/color][color=#0A246A]+[/color][color=#800080]78h[/color][color=#0A246A]]  [/color][color=#008000]; r10 = l_DispatcherContext.ImageBase
[/color][color=#000000]..  ...  . . fffff800`[/color][color=#800080]00892115 [/color][color=#0A246A]mov     [/color][color=#000000]rdx[/color][color=#0A246A],qword ptr [[/color][color=#000000]rsp[/color][color=#0A246A]+[/color][color=#800080]98h[/color][color=#0A246A]]  [/color][color=#008000]; rdx = l_DispatcherContext.ContextRecord
[/color][color=#000000]..  ...  . . fffff800`[/color][color=#800080]0089211d [/color][color=#0A246A]mov     [/color][color=#000000]rcx[/color][color=#0A246A],qword ptr [[/color][color=#000000]rsp[/color][color=#0A246A]+[/color][color=#800080]6A0h[/color][color=#0A246A]] [/color][color=#008000]; rcx = pOriginalContext
[/color][color=#000000]..  ...  . . fffff800`[/color][color=#800080]00892125 [/color][color=#0A246A]mov     [/color][color=#000000]r14[/color][color=#0A246A],qword ptr [[/color][color=#000000]rsp[/color][color=#0A246A]+[/color][color=#800080]80h[/color][color=#0A246A]]  [/color][color=#008000]; r14 = l_DispatcherContext.FunctionEntry
[/color][color=#000000]..  ...  . . fffff800`[/color][color=#800080]0089212d [/color][color=#0A246A]mov     qword ptr [[/color][color=#000000]rsp[/color][color=#0A246A]+[/color][color=#800080]68h[/color][color=#0A246A]],[/color][color=#000000]r8
..  ...  . . fffff800`[/color][color=#800080]00892132 [/color][color=#0A246A]mov     qword ptr [[/color][color=#000000]rsp[/color][color=#0A246A]+[/color][color=#800080]60h[/color][color=#0A246A]],[/color][color=#000000]r10
..  ...  . . fffff800`[/color][color=#800080]00892137 [/color][color=#0A246A]call    [/color][color=#000000]nt!RtlpCopyContext [/color][color=#0A246A]([/color][color=#000000]fffff800`[/color][color=#800080]00891080[/color][color=#0A246A])
[/color][color=#000000]..  ...  . . [/color][color=#008000];                 RtlpCopyContext(pOriginalContext, l_DispatcherContext.ContextRecord);
[/color][color=#000000]..  ...  . . fffff800`[/color][color=#800080]0089213c [/color][color=#0A246A]mov     [/color][color=#000000]rdx[/color][color=#0A246A],[/color][color=#000000]rcx        [/color][color=#008000]; rdx = pOriginalContext
[/color][color=#000000]..  ...  . . fffff800`[/color][color=#800080]0089213f [/color][color=#0A246A]mov     [/color][color=#000000]rdi[/color][color=#0A246A],[/color][color=#000000]rcx        [/color][color=#008000]; rdi = pOriginalContext
[/color][color=#000000]..  ...  . . fffff800`[/color][color=#800080]00892142 [/color][color=#0A246A]lea     [/color][color=#000000]rcx[/color][color=#0A246A],[[/color][color=#000000]rsp[/color][color=#0A246A]+[/color][color=#800080]160h[/color][color=#0A246A]] [/color][color=#008000]; rcx = &l_Context
[/color][color=#000000]..  ...  . . fffff800`[/color][color=#800080]0089214a [/color][color=#0A246A]lea     [/color][color=#000000]r12[/color][color=#0A246A],[[/color][color=#000000]rsp[/color][color=#0A246A]+[/color][color=#800080]160h[/color][color=#0A246A]] [/color][color=#008000]; r12 = &l_Context
[/color][color=#000000]..  ...  . . fffff800`[/color][color=#800080]00892152 [/color][color=#0A246A]call    [/color][color=#000000]nt!RtlpCopyContext [/color][color=#0A246A]([/color][color=#000000]fffff800`[/color][color=#800080]00891080[/color][color=#0A246A])
[/color][color=#000000]..  ...  . . [/color][color=#008000];                 RtlpCopyContext(&l_Context, pOriginalContext);
[/color][color=#000000]..  ...  . . fffff800`[/color][color=#800080]00892157 [/color][color=#0A246A]mov     qword ptr [[/color][color=#000000]rsp[/color][color=#0A246A]+[/color][color=#800080]38h[/color][color=#0A246A]],[/color][color=#800080]0   [/color][color=#008000]; _ARG_8 = NULL
[/color][color=#000000]..  ...  . . fffff800`[/color][color=#800080]00892160 [/color][color=#0A246A]lea     [/color][color=#000000]rax[/color][color=#0A246A],[[/color][color=#000000]rsp[/color][color=#0A246A]+[/color][color=#800080]680h[/color][color=#0A246A]]          [/color][color=#008000]; rax = &l_pEstablisherFrame
[/color][color=#000000]..  ...  . . fffff800`[/color][color=#800080]00892168 [/color][color=#0A246A]mov     qword ptr [[/color][color=#000000]rsp[/color][color=#0A246A]+[/color][color=#800080]30h[/color][color=#0A246A]],[/color][color=#000000]rax [/color][color=#008000]; _ARG_7 = &l_pEstablisherFrame
[/color][color=#000000]..  ...  . . fffff800`[/color][color=#800080]0089216d [/color][color=#0A246A]lea     [/color][color=#000000]rax[/color][color=#0A246A],[[/color][color=#000000]rsp[/color][color=#0A246A]+[/color][color=#800080]58h[/color][color=#0A246A]]           [/color][color=#008000]; rax = &l_pHandlerData
[/color][color=#000000]..  ...  . . fffff800`[/color][color=#800080]00892172 [/color][color=#0A246A]mov     [/color][color=#000000]r9[/color][color=#0A246A],[/color][color=#000000]r14                  [/color][color=#008000]; r9 = l_DispatcherContext.FunctionEntry
[/color][color=#000000]..  ...  . . fffff800`[/color][color=#800080]00892175 [/color][color=#0A246A]mov     qword ptr [[/color][color=#000000]rsp[/color][color=#0A246A]+[/color][color=#800080]28h[/color][color=#0A246A]],[/color][color=#000000]rax [/color][color=#008000]; _ARG_6 = &l_pHandlerData
[/color][color=#000000]..  ...  . . fffff800`[/color][color=#800080]0089217a [/color][color=#0A246A]lea     [/color][color=#000000]rax[/color][color=#0A246A],[[/color][color=#000000]rsp[/color][color=#0A246A]+[/color][color=#800080]160h[/color][color=#0A246A]]          [/color][color=#008000]; rax = &l_Context
[/color][color=#000000]..  ...  . . fffff800`[/color][color=#800080]00892182 [/color][color=#0A246A]mov     [/color][color=#000000]rdx[/color][color=#0A246A],[/color][color=#000000]r10                 [/color][color=#008000]; rdx = l_DispatcherContext.ImageBase
[/color][color=#000000]..  ...  . . fffff800`[/color][color=#800080]00892185 [/color][color=#0A246A]xor     [/color][color=#FF8000]ecx[/color][color=#0A246A],[/color][color=#FF8000]ecx                 [/color][color=#008000]; ecx = UNW_FLAG_NHANDLER (0)
[/color][color=#000000]..  ...  . . fffff800`[/color][color=#800080]00892187 [/color][color=#0A246A]mov     qword ptr [[/color][color=#000000]rsp[/color][color=#0A246A]+[/color][color=#800080]20h[/color][color=#0A246A]],[/color][color=#000000]rax [/color][color=#008000]; _ARG_5 = &l_Context
[/color][color=#000000]..  ...  . . fffff800`[/color][color=#800080]0089218c [/color][color=#0A246A]call    [/color][color=#000000]nt!RtlVirtualUnwind [/color][color=#0A246A]([/color][color=#000000]fffff800`[/color][color=#800080]00891380[/color][color=#0A246A])
[/color][color=#000000]..  ...  . .                   [/color][color=#008000]; RtlVirtualUnwind(UNW_FLAG_NHANDLER,
[/color][color=#000000]..  ...  . .                   [/color][color=#008000];                  l_DispatcherContext.ImageBase,
[/color][color=#000000]..  ...  . .                   [/color][color=#008000];                  l_DispatcherContext.ControlPc,
[/color][color=#000000]..  ...  . .                   [/color][color=#008000];                  l_DispatcherContext.FunctionEntry,
[/color][color=#000000]..  ...  . .                   [/color][color=#008000];                  &l_Context,
[/color][color=#000000]..  ...  . .                   [/color][color=#008000];                  &l_pHandlerData,
[/color][color=#000000]..  ...  . .                   [/color][color=#008000];                  &l_pEstablisherFrame,
[/color][color=#000000]..  ...  . .                   [/color][color=#008000];                  NULL);
[/color][color=#000000]..  ...  . . fffff800`[/color][color=#800080]00892191 [/color][color=#0A246A]mov     [/color][color=#000000]rbx[/color][color=#0A246A],qword ptr [[/color][color=#000000]rsp[/color][color=#0A246A]+[/color][color=#800080]88h[/color][color=#0A246A]]   [/color][color=#008000]; rbx = l_DispatcherContext.EstablisherFrame
[/color][color=#000000]..  ...  . . fffff800`[/color][color=#800080]00892199 [/color][color=#0A246A]mov     [/color][color=#000000]rcx[/color][color=#0A246A],qword ptr [[/color][color=#000000]rsp[/color][color=#0A246A]+[/color][color=#800080]0A0h[/color][color=#0A246A]]  [/color][color=#008000]; rcx = l_DispatcherContext.LanguageHandler
[/color][color=#000000]..  ...  . . fffff800`[/color][color=#800080]008921a1 [/color][color=#0A246A]mov     [/color][color=#000000]r13[/color][color=#0A246A],qword ptr [[/color][color=#000000]rsp[/color][color=#0A246A]+[/color][color=#800080]0A8h[/color][color=#0A246A]]  [/color][color=#008000]; r13 = l_DispatcherContext.HandlerData
[/color][color=#000000]..  ...  . . fffff800`[/color][color=#800080]008921a9 [/color][color=#0A246A]mov     [/color][color=#000000]rax[/color][color=#0A246A],qword ptr [[/color][color=#000000]rsp[/color][color=#0A246A]+[/color][color=#800080]0B0h[/color][color=#0A246A]]  [/color][color=#008000]; rax = l_DispatcherContext.HistoryTable
[/color][color=#000000]..  ...  . . fffff800`[/color][color=#800080]008921b1 [/color][color=#0A246A]mov     [/color][color=#000000]r15d[/color][color=#0A246A],dword ptr [[/color][color=#000000]rsp[/color][color=#0A246A]+[/color][color=#800080]0B8h[/color][color=#0A246A]] [/color][color=#008000]; r15d = l_DispatcherContext.ScopeIndex
[/color][color=#000000]..  ...  . . fffff800`[/color][color=#800080]008921b9 [/color][color=#0A246A]mov     qword ptr [[/color][color=#000000]rsp[/color][color=#0A246A]+[/color][color=#800080]680h[/color][color=#0A246A]],[/color][color=#000000]rbx  [/color][color=#008000]; l_pEstablisherFrame = l_DispatcherContext.EstablisherFrame
[/color][color=#000000]..  ...  . . fffff800`[/color][color=#800080]008921c1 [/color][color=#0A246A]mov     qword ptr [[/color][color=#000000]rsp[/color][color=#0A246A]+[/color][color=#800080]48h[/color][color=#0A246A]],[/color][color=#000000]rcx   [/color][color=#008000]; l_pExceptionRoutine = l_DispatcherContext.LanguageHandler
[/color][color=#000000]..  ...  . . fffff800`[/color][color=#800080]008921c6 [/color][color=#0A246A]mov     qword ptr [[/color][color=#000000]rsp[/color][color=#0A246A]+[/color][color=#800080]58h[/color][color=#0A246A]],[/color][color=#000000]r13   [/color][color=#008000]; l_pHandlerData = l_DispatcherContext.HandlerData
[/color][color=#000000]..  ...  . . fffff800`[/color][color=#800080]008921cb [/color][color=#0A246A]mov     qword ptr [[/color][color=#000000]rsp[/color][color=#0A246A]+[/color][color=#800080]6A8h[/color][color=#0A246A]],[/color][color=#000000]rax  [/color][color=#008000]; pHistoryTable = l_DispatcherContext.HistoryTable
[/color][color=#000000]..  ...  . . fffff800`[/color][color=#800080]008921d3 [/color][color=#0A246A]or      [/color][color=#FF8000]esi[/color][color=#0A246A],[/color][color=#800080]40h                   [/color][color=#008000]; l_ExceptionFlags |= EXCEPTION_COLLIDED_UNWIND (40)
[/color][color=#000000]..  ...[/color][color=#0A246A]< [/color][color=#000000]. . fffff800`[/color][color=#800080]008921d6 [/color][color=#0A246A]jmp     [/color][color=#000000]nt!RtlUnwindEx[/color][color=#0A246A]+[/color][color=#800080]0x382 [/color][color=#0A246A]([/color][color=#000000]fffff800`[/color][color=#800080]008921f2[/color][color=#0A246A])
[/color][color=#000000]..  .... . . 
..  .... . . nt!RtlUnwindEx[/color][color=#0A246A]+[/color][color=#800080]0x368[/color][color=#0A246A]:
[/color][color=#000000]..  .[/color][color=#0A246A]>[/color][color=#000000].. . . fffff800`[/color][color=#800080]008921d8 [/color][color=#0A246A]cmp     [/color][color=#000000]rbx[/color][color=#0A246A],[/color][color=#000000]rbp [/color][color=#008000]; cmp l_DispatcherContext.EstablisherFrame, pEstablisherFrame
[/color][color=#000000]..  . ..[/color][color=#0A246A]<[/color][color=#000000]. . fffff800`[/color][color=#800080]008921db [/color][color=#0A246A]je      [/color][color=#000000]nt!RtlUnwindEx[/color][color=#0A246A]+[/color][color=#800080]0x37d [/color][color=#0A246A]([/color][color=#000000]fffff800`[/color][color=#800080]008921ed[/color][color=#0A246A])
[/color][color=#000000]..  . .... . 
..  . .... . nt!RtlUnwindEx[/color][color=#0A246A]+[/color][color=#800080]0x36d[/color][color=#0A246A]:
[/color][color=#000000]..  . .... . fffff800`[/color][color=#800080]008921dd [/color][color=#0A246A]mov     [/color][color=#000000]rcx[/color][color=#0A246A],qword ptr [[/color][color=#000000]rsp[/color][color=#0A246A]+[/color][color=#800080]48h[/color][color=#0A246A]] [/color][color=#008000]; rcx = l_pExceptionRoutine
[/color][color=#000000]..  . .... . fffff800`[/color][color=#800080]008921e2 [/color][color=#0A246A]mov     [/color][color=#000000]rax[/color][color=#0A246A],[/color][color=#000000]rdi                 [/color][color=#008000]; rax = pOriginalContext
[/color][color=#000000]..  . .... . fffff800`[/color][color=#800080]008921e5 [/color][color=#0A246A]mov     [/color][color=#000000]rdi[/color][color=#0A246A],[/color][color=#000000]r12                 [/color][color=#008000]; rdi = &l_Context
[/color][color=#000000]..  . .... . fffff800`[/color][color=#800080]008921e8 [/color][color=#0A246A]mov     [/color][color=#000000]r12[/color][color=#0A246A],[/color][color=#000000]rax                 [/color][color=#008000]; r12 = pOriginalContext
[/color][color=#000000]..  . .v.. . fffff800`[/color][color=#800080]008921eb [/color][color=#0A246A]jmp     [/color][color=#000000]nt!RtlUnwindEx[/color][color=#0A246A]+[/color][color=#800080]0x382 [/color][color=#0A246A]([/color][color=#000000]fffff800`[/color][color=#800080]008921f2[/color][color=#0A246A])
[/color][color=#000000]..  . .... . 
..  . .... . nt!RtlUnwindEx[/color][color=#0A246A]+[/color][color=#800080]0x37d[/color][color=#0A246A]:
[/color][color=#000000]..  . ..[/color][color=#0A246A]>[/color][color=#000000]. . fffff800`[/color][color=#800080]008921ed [/color][color=#0A246A]mov     [/color][color=#000000]rcx[/color][color=#0A246A],qword ptr [[/color][color=#000000]rsp[/color][color=#0A246A]+[/color][color=#800080]48h[/color][color=#0A246A]] [/color][color=#008000]; rcx = l_pExceptionRoutine
[/color][color=#000000]..  . .. . . 
..  . .. . . nt!RtlUnwindEx[/color][color=#0A246A]+[/color][color=#800080]0x382[/color][color=#0A246A]:
[/color][color=#000000]..  . .[/color][color=#0A246A]> [/color][color=#000000]. . fffff800`[/color][color=#800080]008921f2 [/color][color=#0A246A]test    [/color][color=#000000]sil[/color][color=#0A246A],[/color][color=#800080]40h  [/color][color=#008000]; test sil, EXCEPTION_COLLIDED_UNWIND (40)
[/color][color=#000000]..  . .  [/color][color=#0A246A]< [/color][color=#000000]. fffff800`[/color][color=#800080]008921f6 [/color][color=#0A246A]jne     [/color][color=#000000]nt!RtlUnwindEx[/color][color=#0A246A]+[/color][color=#800080]0x200 [/color][color=#0A246A]([/color][color=#000000]fffff800`[/color][color=#800080]00892070[/color][color=#0A246A])
[/color][color=#000000]..  . .    . 
..  . .    . nt!RtlUnwindEx[/color][color=#0A246A]+[/color][color=#800080]0x38c[/color][color=#0A246A]:
[/color][color=#000000]..  . .    . fffff800`[/color][color=#800080]008921fc [/color][color=#0A246A]mov     [/color][color=#000000]r13[/color][color=#0A246A],qword ptr [[/color][color=#000000]rsp[/color][color=#0A246A]+[/color][color=#800080]68h[/color][color=#0A246A]]  [/color][color=#008000]; r13 = pOriginalContext->Rip
[/color][color=#000000]..  . .    . fffff800`[/color][color=#800080]00892201 [/color][color=#0A246A]mov     [/color][color=#000000]r15[/color][color=#0A246A],qword ptr [[/color][color=#000000]rsp[/color][color=#0A246A]+[/color][color=#800080]688h[/color][color=#0A246A]] [/color][color=#008000]; r15 = pJumpTargetIp
[/color][color=#000000]..  . .[/color][color=#0A246A]<   [/color][color=#000000]. fffff800`[/color][color=#800080]00892209 [/color][color=#0A246A]jmp     [/color][color=#000000]nt!RtlUnwindEx[/color][color=#0A246A]+[/color][color=#800080]0x3c7 [/color][color=#0A246A]([/color][color=#000000]fffff800`[/color][color=#800080]00892237[/color][color=#0A246A])
[/color][color=#000000]..  . ..   . 
..  . ..   . nt!RtlUnwindEx[/color][color=#0A246A]+[/color][color=#800080]0x39b[/color][color=#0A246A]:
[/color][color=#000000]..  [/color][color=#0A246A]> [/color][color=#000000]..   . fffff800`[/color][color=#800080]0089220b [/color][color=#0A246A]cmp     [/color][color=#000000]rbx[/color][color=#0A246A],[/color][color=#000000]rbp  [/color][color=#008000]; cmp l_DispatcherContext.EstablisherFrame, pEstablisherFrame
[/color][color=#000000]..    .[/color][color=#0A246A]<   [/color][color=#000000]. fffff800`[/color][color=#800080]0089220e [/color][color=#0A246A]je      [/color][color=#000000]nt!RtlUnwindEx[/color][color=#0A246A]+[/color][color=#800080]0x3c7 [/color][color=#0A246A]([/color][color=#000000]fffff800`[/color][color=#800080]00892237[/color][color=#0A246A])
[/color][color=#000000]..    ..   . 
..    ..   . nt!RtlUnwindEx[/color][color=#0A246A]+[/color][color=#800080]0x3a0[/color][color=#0A246A]:
[/color][color=#000000]..    ..   . fffff800`[/color][color=#800080]00892210 [/color][color=#0A246A]mov     [/color][color=#000000]rax[/color][color=#0A246A],[/color][color=#000000]rdi [/color][color=#008000]; rax = &l_Context
[/color][color=#000000]..    ..   . fffff800`[/color][color=#800080]00892213 [/color][color=#0A246A]mov     [/color][color=#000000]rdi[/color][color=#0A246A],[/color][color=#000000]r12 [/color][color=#008000]; rdi = pOriginalContext
[/color][color=#000000]..    ..   . fffff800`[/color][color=#800080]00892216 [/color][color=#0A246A]mov     [/color][color=#000000]r12[/color][color=#0A246A],[/color][color=#000000]rax [/color][color=#008000]; r12 = &l_Context
[/color][color=#000000]..    .[/color][color=#0A246A]<   [/color][color=#000000]. fffff800`[/color][color=#800080]00892219 [/color][color=#0A246A]jmp     [/color][color=#000000]nt!RtlUnwindEx[/color][color=#0A246A]+[/color][color=#800080]0x3c7 [/color][color=#0A246A]([/color][color=#000000]fffff800`[/color][color=#800080]00892237[/color][color=#0A246A])
[/color][color=#000000]..    ..   . 
..    ..   . nt!RtlUnwindEx[/color][color=#0A246A]+[/color][color=#800080]0x3ab[/color][color=#0A246A]:
>[/color][color=#000000].    ..   . fffff800`[/color][color=#800080]0089221b [/color][color=#0A246A]mov     [/color][color=#000000]rcx[/color][color=#0A246A],qword ptr [[/color][color=#000000]rdi[/color][color=#0A246A]+[/color][color=#800080]98h[/color][color=#0A246A]]  [/color][color=#008000]; rcx = pOriginalContext->Rsp
 [/color][color=#000000].    ..   . fffff800`[/color][color=#800080]00892222 [/color][color=#0A246A]mov     [/color][color=#000000]rax[/color][color=#0A246A],qword ptr [[/color][color=#000000]rcx[/color][color=#0A246A]]      [/color][color=#008000]; rax = pOriginalContext->Rsp[0]
 [/color][color=#000000].    ..   . fffff800`[/color][color=#800080]00892225 [/color][color=#0A246A]mov     qword ptr [[/color][color=#000000]rdi[/color][color=#0A246A]+[/color][color=#800080]0F8h[/color][color=#0A246A]],[/color][color=#000000]rax [/color][color=#008000]; pOriginalContext->Rip = pOriginalContext->Rsp[0]
 [/color][color=#000000].    ..   . fffff800`[/color][color=#800080]0089222c [/color][color=#0A246A]lea     [/color][color=#000000]rax[/color][color=#0A246A],[[/color][color=#000000]rcx[/color][color=#0A246A]+[/color][color=#800080]8[/color][color=#0A246A]]              [/color][color=#008000]; rax = pOriginalContext->Rsp + 8
 [/color][color=#000000].    ..   . fffff800`[/color][color=#800080]00892230 [/color][color=#0A246A]mov     qword ptr [[/color][color=#000000]rdi[/color][color=#0A246A]+[/color][color=#800080]98h[/color][color=#0A246A]],[/color][color=#000000]rax  [/color][color=#008000]; pOriginalContext->Rsp = pOriginalContext->Rsp + 8 (跳过返回值)
 [/color][color=#000000].    ..   .
 .    ..   . nt!RtlUnwindEx[/color][color=#0A246A]+[/color][color=#800080]0x3c7[/color][color=#0A246A]:
 [/color][color=#000000].    .[/color][color=#0A246A]>   [/color][color=#000000]. fffff800`[/color][color=#800080]00892237 [/color][color=#0A246A]test    [/color][color=#FF8000]bl[/color][color=#0A246A],[/color][color=#800080]7 [/color][color=#008000]; 检查 l_DispatcherContext.EstablisherFrame 是否对齐
 [/color][color=#000000].    .[/color][color=#0A246A]<   [/color][color=#000000]. fffff800`[/color][color=#800080]0089223a [/color][color=#0A246A]jne     [/color][color=#000000]nt!RtlUnwindEx[/color][color=#0A246A]+[/color][color=#800080]0x444 [/color][color=#0A246A]([/color][color=#000000]fffff800`[/color][color=#800080]008922b4[/color][color=#0A246A])
 [/color][color=#000000].    ..   . 
 .    ..   . nt!RtlUnwindEx[/color][color=#0A246A]+[/color][color=#800080]0x3cc[/color][color=#0A246A]:
 [/color][color=#000000].    ..   . fffff800`[/color][color=#800080]0089223c [/color][color=#0A246A]cmp     [/color][color=#000000]rbx[/color][color=#0A246A],qword ptr [[/color][color=#000000]rsp[/color][color=#0A246A]+[/color][color=#800080]50h[/color][color=#0A246A]] [/color][color=#008000]; cmp l_DispatcherContext.EstablisherFrame, l_LowLimit
 [/color][color=#000000].    ..[/color][color=#0A246A]<  [/color][color=#000000]. fffff800`[/color][color=#800080]00892241 [/color][color=#0A246A]jb      [/color][color=#000000]nt!RtlUnwindEx[/color][color=#0A246A]+[/color][color=#800080]0x3da [/color][color=#0A246A]([/color][color=#000000]fffff800`[/color][color=#800080]0089224a[/color][color=#0A246A])
 [/color][color=#000000].    ...  . 
 .    ...  . nt!RtlUnwindEx[/color][color=#0A246A]+[/color][color=#800080]0x3d3[/color][color=#0A246A]:
 [/color][color=#000000].    ...  . fffff800`[/color][color=#800080]00892243 [/color][color=#0A246A]cmp     [/color][color=#000000]rbx[/color][color=#0A246A],qword ptr [[/color][color=#000000]rsp[/color][color=#0A246A]+[/color][color=#800080]40h[/color][color=#0A246A]] [/color][color=#008000]; cmp l_DispatcherContext.EstablisherFrame, l_HighLimit
 [/color][color=#000000].    ...[/color][color=#0A246A]< [/color][color=#000000]. fffff800`[/color][color=#800080]00892248 [/color][color=#0A246A]jb      [/color][color=#000000]nt!RtlUnwindEx[/color][color=#0A246A]+[/color][color=#800080]0x414 [/color][color=#0A246A]([/color][color=#000000]fffff800`[/color][color=#800080]00892284[/color][color=#0A246A])
 [/color][color=#000000].    .... . 
 .    .... . nt!RtlUnwindEx[/color][color=#0A246A]+[/color][color=#800080]0x3da[/color][color=#0A246A]:
 [/color][color=#000000].    ..[/color][color=#0A246A]>[/color][color=#000000]. . fffff800`[/color][color=#800080]0089224a [/color][color=#0A246A]mov     [/color][color=#FF8000]al[/color][color=#0A246A],byte ptr [/color][color=#FF8000]gs[/color][color=#0A246A]:[[/color][color=#800080]20DEh[/color][color=#0A246A]] [/color][color=#008000]; al = _KPCR->DpcRoutineActive
 [/color][color=#000000].    .. . . fffff800`[/color][color=#800080]00892252 [/color][color=#0A246A]test    [/color][color=#FF8000]al[/color][color=#0A246A],[/color][color=#FF8000]al
 [/color][color=#000000].    .. .[/color][color=#0A246A]<[/color][color=#000000]. fffff800`[/color][color=#800080]00892254 [/color][color=#0A246A]jne     [/color][color=#000000]nt!RtlUnwindEx[/color][color=#0A246A]+[/color][color=#800080]0x43c [/color][color=#0A246A]([/color][color=#000000]fffff800`[/color][color=#800080]008922ac[/color][color=#0A246A])
 [/color][color=#000000].    .. ... 
 .    .. ... nt!RtlUnwindEx[/color][color=#0A246A]+[/color][color=#800080]0x3e6[/color][color=#0A246A]:
 [/color][color=#000000].    .. ... fffff800`[/color][color=#800080]00892256 [/color][color=#0A246A]mov     [/color][color=#000000]rcx[/color][color=#0A246A],qword ptr [[/color][color=#000000]rsp[/color][color=#0A246A]+[/color][color=#800080]40h[/color][color=#0A246A]] [/color][color=#008000]; rcx = l_HighLimit
 [/color][color=#000000].    .. ... fffff800`[/color][color=#800080]0089225b [/color][color=#0A246A]mov     [/color][color=#000000]rax[/color][color=#0A246A],qword ptr [[/color][color=#000000]rcx[/color][color=#0A246A]-[/color][color=#800080]28h[/color][color=#0A246A]] [/color][color=#008000]; rax = l_KernelStackCtrl->Previous.StackBase
 [/color][color=#000000].    .. ... fffff800`[/color][color=#800080]0089225f [/color][color=#0A246A]test    [/color][color=#000000]rax[/color][color=#0A246A],[/color][color=#000000]rax
 .    .. .[/color][color=#0A246A]<[/color][color=#000000]. fffff800`[/color][color=#800080]00892262 [/color][color=#0A246A]je      [/color][color=#000000]nt!RtlUnwindEx[/color][color=#0A246A]+[/color][color=#800080]0x43c [/color][color=#0A246A]([/color][color=#000000]fffff800`[/color][color=#800080]008922ac[/color][color=#0A246A])
 [/color][color=#000000].    .. ... 
 .    .. ... nt!RtlUnwindEx[/color][color=#0A246A]+[/color][color=#800080]0x3f4[/color][color=#0A246A]:
 [/color][color=#000000].    .. ... fffff800`[/color][color=#800080]00892264 [/color][color=#0A246A]mov     [/color][color=#000000]rdx[/color][color=#0A246A],qword ptr [[/color][color=#000000]rcx[/color][color=#0A246A]-[/color][color=#800080]20h[/color][color=#0A246A]]  [/color][color=#008000]; rdx = l_KernelStackCtrl->Previous.StackLimit
 [/color][color=#000000].    .. ... fffff800`[/color][color=#800080]00892268 [/color][color=#0A246A]mov     [/color][color=#000000]rbx[/color][color=#0A246A],qword ptr [[/color][color=#000000]rsp[/color][color=#0A246A]+[/color][color=#800080]680h[/color][color=#0A246A]] [/color][color=#008000]; rbx = l_pEstablisherFrame
 [/color][color=#000000].    .. ... fffff800`[/color][color=#800080]00892270 [/color][color=#0A246A]cmp     [/color][color=#000000]rbx[/color][color=#0A246A],[/color][color=#000000]rdx                  [/color][color=#008000]; cmp l_pEstablisherFrame, l_KernelStackCtrl->Previous.StackLimit
 [/color][color=#000000].    .[/color][color=#0A246A]< [/color][color=#000000]... fffff800`[/color][color=#800080]00892273 [/color][color=#0A246A]jb      [/color][color=#000000]nt!RtlUnwindEx[/color][color=#0A246A]+[/color][color=#800080]0x444 [/color][color=#0A246A]([/color][color=#000000]fffff800`[/color][color=#800080]008922b4[/color][color=#0A246A])
 [/color][color=#000000].    .. ... 
 .    .. ... nt!RtlUnwindEx[/color][color=#0A246A]+[/color][color=#800080]0x405[/color][color=#0A246A]:
 [/color][color=#000000].    .. ... fffff800`[/color][color=#800080]00892275 [/color][color=#0A246A]cmp     [/color][color=#000000]rbx[/color][color=#0A246A],[/color][color=#000000]rax [/color][color=#008000]; cmp l_pEstablisherFrame, l_KernelStackCtrl->Previous.StackBase
 [/color][color=#000000].    .[/color][color=#0A246A]< [/color][color=#000000]... fffff800`[/color][color=#800080]00892278 [/color][color=#0A246A]jae     [/color][color=#000000]nt!RtlUnwindEx[/color][color=#0A246A]+[/color][color=#800080]0x444 [/color][color=#0A246A]([/color][color=#000000]fffff800`[/color][color=#800080]008922b4[/color][color=#0A246A])
 [/color][color=#000000].    .. ... 
 .    .. ... nt!RtlUnwindEx[/color][color=#0A246A]+[/color][color=#800080]0x40a[/color][color=#0A246A]:
 [/color][color=#000000].    .. ... fffff800`[/color][color=#800080]0089227a [/color][color=#0A246A]mov     qword ptr [[/color][color=#000000]rsp[/color][color=#0A246A]+[/color][color=#800080]50h[/color][color=#0A246A]],[/color][color=#000000]rdx [/color][color=#008000]; l_LowLimit = l_KernelStackCtrl->Previous.StackLimit
 [/color][color=#000000].    .. ... fffff800`[/color][color=#800080]0089227f [/color][color=#0A246A]mov     qword ptr [[/color][color=#000000]rsp[/color][color=#0A246A]+[/color][color=#800080]40h[/color][color=#0A246A]],[/color][color=#000000]rax [/color][color=#008000]; l_HighLimit = l_KernelStackCtrl->Previous.StackBase
 [/color][color=#000000].    .. ... 
 .    .. ... nt!RtlUnwindEx[/color][color=#0A246A]+[/color][color=#800080]0x414[/color][color=#0A246A]:
 [/color][color=#000000].    .. [/color][color=#0A246A]>[/color][color=#000000].. fffff800`[/color][color=#800080]00892284 [/color][color=#0A246A]cmp     [/color][color=#000000]rbx[/color][color=#0A246A],[/color][color=#000000]rbp [/color][color=#008000]; cmp l_pEstablisherFrame, pEstablisherFrame
 [/color][color=#000000].    .. [/color][color=#0A246A]<[/color][color=#000000].. fffff800`[/color][color=#800080]00892287 [/color][color=#0A246A]je      [/color][color=#000000]nt!RtlUnwindEx[/color][color=#0A246A]+[/color][color=#800080]0x449 [/color][color=#0A246A]([/color][color=#000000]fffff800`[/color][color=#800080]008922b9[/color][color=#0A246A])
 [/color][color=#000000].    .. ... 
 .    .. ... nt!RtlUnwindEx[/color][color=#0A246A]+[/color][color=#800080]0x419[/color][color=#0A246A]:
 [/color][color=#000000].    .. ... fffff800`[/color][color=#800080]00892289 [/color][color=#0A246A]mov     [/color][color=#000000]rax[/color][color=#0A246A],qword ptr [[/color][color=#000000]rsp[/color][color=#0A246A]+[/color][color=#800080]6A8h[/color][color=#0A246A]] [/color][color=#008000]; rax = pHistoryTable
 [/color][color=#000000].    .. ..[/color][color=#0A246A]^ [/color][color=#000000]fffff800`[/color][color=#800080]00892291 [/color][color=#0A246A]jmp     [/color][color=#000000]nt!RtlUnwindEx[/color][color=#0A246A]+[/color][color=#800080]0xf0 [/color][color=#0A246A]([/color][color=#000000]fffff800`[/color][color=#800080]00891f60[/color][color=#0A246A])
 [/color][color=#000000].    .. ..  
 .    .. ..  nt!RtlUnwindEx[/color][color=#0A246A]+[/color][color=#800080]0x426[/color][color=#0A246A]:
 [/color][color=#000000].    [/color][color=#0A246A]>[/color][color=#000000]. ..  fffff800`[/color][color=#800080]00892296 [/color][color=#0A246A]mov     [/color][color=#FF8000]ecx[/color][color=#0A246A],[/color][color=#800080]0C0000026h [/color][color=#008000]; ecx = STATUS_INVALID_DISPOSITION
 [/color][color=#000000].     . ..  fffff800`[/color][color=#800080]0089229b [/color][color=#0A246A]call    [/color][color=#000000]nt!RtlRaiseStatus [/color][color=#0A246A]([/color][color=#000000]fffff800`[/color][color=#800080]00889df0[/color][color=#0A246A])
 [/color][color=#000000].     . ..  fffff800`[/color][color=#800080]008922a0 [/color][color=#0A246A]int     [/color][color=#800080]3
 [/color][color=#000000].     . ..  
 .     . ..  nt!RtlUnwindEx[/color][color=#0A246A]+[/color][color=#800080]0x431[/color][color=#0A246A]:
 >     [/color][color=#000000]. ..  fffff800`[/color][color=#800080]008922a1 [/color][color=#0A246A]mov     [/color][color=#FF8000]ecx[/color][color=#0A246A],[/color][color=#800080]0C0000028h [/color][color=#008000]; ecx = STATUS_BAD_STACK
       [/color][color=#000000]. ..  fffff800`[/color][color=#800080]008922a6 [/color][color=#0A246A]call    [/color][color=#000000]nt!RtlRaiseStatus [/color][color=#0A246A]([/color][color=#000000]fffff800`[/color][color=#800080]00889df0[/color][color=#0A246A])
       [/color][color=#000000]. ..  fffff800`[/color][color=#800080]008922ab [/color][color=#0A246A]int     [/color][color=#800080]3
       [/color][color=#000000]. ..  
       . ..  nt!RtlUnwindEx[/color][color=#0A246A]+[/color][color=#800080]0x43c[/color][color=#0A246A]:
       [/color][color=#000000]. .[/color][color=#0A246A]>  [/color][color=#000000]fffff800`[/color][color=#800080]008922ac [/color][color=#0A246A]mov     [/color][color=#000000]rbx[/color][color=#0A246A],qword ptr [[/color][color=#000000]rsp[/color][color=#0A246A]+[/color][color=#800080]680h[/color][color=#0A246A]] [/color][color=#008000]; rbx = l_pEstablisherFrame
       [/color][color=#000000]. .   
       . .   nt!RtlUnwindEx[/color][color=#0A246A]+[/color][color=#800080]0x444[/color][color=#0A246A]:
       > [/color][color=#000000].   fffff800`[/color][color=#800080]008922b4 [/color][color=#0A246A]cmp     [/color][color=#000000]rbx[/color][color=#0A246A],[/color][color=#000000]rbp [/color][color=#008000]; cmp l_pEstablisherFrame, pEstablisherFrame
[/color][color=#0A246A]<        [/color][color=#000000].   fffff800`[/color][color=#800080]008922b7 [/color][color=#0A246A]jne     [/color][color=#000000]nt!RtlUnwindEx[/color][color=#0A246A]+[/color][color=#800080]0x479 [/color][color=#0A246A]([/color][color=#000000]fffff800`[/color][color=#800080]008922e9[/color][color=#0A246A])
[/color][color=#000000].        .   
.        .   nt!RtlUnwindEx[/color][color=#0A246A]+[/color][color=#800080]0x449[/color][color=#0A246A]:
[/color][color=#000000].        [/color][color=#0A246A]>   [/color][color=#000000]fffff800`[/color][color=#800080]008922b9 [/color][color=#0A246A]mov     [/color][color=#000000]rax[/color][color=#0A246A],qword ptr [[/color][color=#000000]rsp[/color][color=#0A246A]+[/color][color=#800080]698h[/color][color=#0A246A]]  [/color][color=#008000]; rax = ReturnValue
[/color][color=#000000].            fffff800`[/color][color=#800080]008922c1 [/color][color=#0A246A]mov     [/color][color=#000000]rbx[/color][color=#0A246A],qword ptr [[/color][color=#000000]rsp[/color][color=#0A246A]+[/color][color=#800080]690h[/color][color=#0A246A]]  [/color][color=#008000]; rbx = pExceptionRecord
[/color][color=#000000].            fffff800`[/color][color=#800080]008922c9 [/color][color=#0A246A]mov     qword ptr [[/color][color=#000000]rdi[/color][color=#0A246A]+[/color][color=#800080]78h[/color][color=#0A246A]],[/color][color=#000000]rax   [/color][color=#008000]; pOriginalContext->Rax, ReturnValue
[/color][color=#000000].            fffff800`[/color][color=#800080]008922cd [/color][color=#0A246A]cmp     dword ptr [[/color][color=#000000]rbx[/color][color=#0A246A]],[/color][color=#800080]80000029h [/color][color=#008000]; cmp pExceptionRecord->ExceptionCode, STATUS_UNWIND_CONSOLIDATE
[/color][color=#000000].[/color][color=#0A246A]<           [/color][color=#000000]fffff800`[/color][color=#800080]008922d3 [/color][color=#0A246A]je      [/color][color=#000000]nt!RtlUnwindEx[/color][color=#0A246A]+[/color][color=#800080]0x46c [/color][color=#0A246A]([/color][color=#000000]fffff800`[/color][color=#800080]008922dc[/color][color=#0A246A])
[/color][color=#000000]..           
..           nt!RtlUnwindEx[/color][color=#0A246A]+[/color][color=#800080]0x465[/color][color=#0A246A]:
[/color][color=#000000]..           fffff800`[/color][color=#800080]008922d5 [/color][color=#0A246A]mov     qword ptr [[/color][color=#000000]rdi[/color][color=#0A246A]+[/color][color=#800080]0F8h[/color][color=#0A246A]],[/color][color=#000000]r15 [/color][color=#008000]; pOriginalContext->Rip, pJumpTargetIp
[/color][color=#000000]..           
..           nt!RtlUnwindEx[/color][color=#0A246A]+[/color][color=#800080]0x46c[/color][color=#0A246A]:
[/color][color=#000000].[/color][color=#0A246A]>           [/color][color=#000000]fffff800`[/color][color=#800080]008922dc [/color][color=#0A246A]mov     [/color][color=#000000]rdx[/color][color=#0A246A],[/color][color=#000000]rbx [/color][color=#008000]; rdx = pExceptionRecord
[/color][color=#000000].            fffff800`[/color][color=#800080]008922df [/color][color=#0A246A]mov     [/color][color=#000000]rcx[/color][color=#0A246A],[/color][color=#000000]rdi [/color][color=#008000]; rcx = pOriginalContext
[/color][color=#000000].            fffff800`[/color][color=#800080]008922e2 [/color][color=#0A246A]call    [/color][color=#000000]nt!RtlRestoreContext [/color][color=#0A246A]([/color][color=#000000]fffff800`[/color][color=#800080]008bd290[/color][color=#0A246A])
[/color][color=#000000].[/color][color=#0A246A]<           [/color][color=#000000]fffff800`[/color][color=#800080]008922e7 [/color][color=#0A246A]jmp     [/color][color=#000000]nt!RtlUnwindEx[/color][color=#0A246A]+[/color][color=#800080]0x4a0 [/color][color=#0A246A]([/color][color=#000000]fffff800`[/color][color=#800080]00892310[/color][color=#0A246A])
[/color][color=#000000]..           
..           nt!RtlUnwindEx[/color][color=#0A246A]+[/color][color=#800080]0x479[/color][color=#0A246A]:
>[/color][color=#000000].           fffff800`[/color][color=#800080]008922e9 [/color][color=#0A246A]cmp     [/color][color=#000000]r13[/color][color=#0A246A],qword ptr [[/color][color=#000000]rdi[/color][color=#0A246A]+[/color][color=#800080]0F8h[/color][color=#0A246A]] [/color][color=#008000]; pOriginalContext->Rip
 [/color][color=#000000].[/color][color=#0A246A]<          [/color][color=#000000]fffff800`[/color][color=#800080]008922f0 [/color][color=#0A246A]jne     [/color][color=#000000]nt!RtlUnwindEx[/color][color=#0A246A]+[/color][color=#800080]0x48d [/color][color=#0A246A]([/color][color=#000000]fffff800`[/color][color=#800080]008922fd[/color][color=#0A246A])
 [/color][color=#000000]..          
 ..          nt!RtlUnwindEx[/color][color=#0A246A]+[/color][color=#800080]0x482[/color][color=#0A246A]:
 [/color][color=#000000]..          fffff800`[/color][color=#800080]008922f2 [/color][color=#0A246A]mov     [/color][color=#FF8000]ecx[/color][color=#0A246A],[/color][color=#800080]0C00000FFh [/color][color=#008000]; ecx = STATUS_BAD_FUNCTION_TABLE
 [/color][color=#000000]..          fffff800`[/color][color=#800080]008922f7 [/color][color=#0A246A]call    [/color][color=#000000]nt!RtlRaiseStatus [/color][color=#0A246A]([/color][color=#000000]fffff800`[/color][color=#800080]00889df0[/color][color=#0A246A])
 [/color][color=#000000]..          fffff800`[/color][color=#800080]008922fc [/color][color=#0A246A]int     [/color][color=#800080]3
 [/color][color=#000000]..          
 ..          nt!RtlUnwindEx[/color][color=#0A246A]+[/color][color=#800080]0x48d[/color][color=#0A246A]:
 [/color][color=#000000].[/color][color=#0A246A]>          [/color][color=#000000]fffff800`[/color][color=#800080]008922fd [/color][color=#0A246A]mov     [/color][color=#000000]rcx[/color][color=#0A246A],qword ptr [[/color][color=#000000]rsp[/color][color=#0A246A]+[/color][color=#800080]690h[/color][color=#0A246A]] [/color][color=#008000]; rcx = pExceptionRecord
 [/color][color=#000000].           fffff800`[/color][color=#800080]00892305 [/color][color=#0A246A]xor     [/color][color=#000000]r8d[/color][color=#0A246A],[/color][color=#000000]r8d                  [/color][color=#008000]; r8d = 0
 [/color][color=#000000].           fffff800`[/color][color=#800080]00892308 [/color][color=#0A246A]mov     [/color][color=#000000]rdx[/color][color=#0A246A],[/color][color=#000000]rdi                  [/color][color=#008000]; rdx = pOriginalContext
 [/color][color=#000000].           fffff800`[/color][color=#800080]0089230b [/color][color=#0A246A]call    [/color][color=#000000]nt!ZwRaiseException [/color][color=#0A246A]([/color][color=#000000]fffff800`[/color][color=#800080]008b9b80[/color][color=#0A246A])
 [/color][color=#000000].                             [/color][color=#008000]; ZwRaiseException(pExceptionRecord, pOriginalContext, FALSE);
 [/color][color=#000000].           
 .           nt!RtlUnwindEx[/color][color=#0A246A]+[/color][color=#800080]0x4a0[/color][color=#0A246A]:
 >           [/color][color=#000000]fffff800`[/color][color=#800080]00892310 [/color][color=#0A246A]mov     [/color][color=#000000]r15[/color][color=#0A246A],qword ptr [[/color][color=#000000]rsp[/color][color=#0A246A]+[/color][color=#800080]638h[/color][color=#0A246A]]
             [/color][color=#000000]fffff800`[/color][color=#800080]00892318 [/color][color=#0A246A]mov     [/color][color=#000000]r14[/color][color=#0A246A],qword ptr [[/color][color=#000000]rsp[/color][color=#0A246A]+[/color][color=#800080]640h[/color][color=#0A246A]]
             [/color][color=#000000]fffff800`[/color][color=#800080]00892320 [/color][color=#0A246A]mov     [/color][color=#000000]r13[/color][color=#0A246A],qword ptr [[/color][color=#000000]rsp[/color][color=#0A246A]+[/color][color=#800080]648h[/color][color=#0A246A]]
             [/color][color=#000000]fffff800`[/color][color=#800080]00892328 [/color][color=#0A246A]mov     [/color][color=#000000]r12[/color][color=#0A246A],qword ptr [[/color][color=#000000]rsp[/color][color=#0A246A]+[/color][color=#800080]650h[/color][color=#0A246A]]
             [/color][color=#000000]fffff800`[/color][color=#800080]00892330 [/color][color=#0A246A]mov     [/color][color=#000000]rdi[/color][color=#0A246A],qword ptr [[/color][color=#000000]rsp[/color][color=#0A246A]+[/color][color=#800080]658h[/color][color=#0A246A]]
             [/color][color=#000000]fffff800`[/color][color=#800080]00892338 [/color][color=#0A246A]mov     [/color][color=#000000]rsi[/color][color=#0A246A],qword ptr [[/color][color=#000000]rsp[/color][color=#0A246A]+[/color][color=#800080]660h[/color][color=#0A246A]]
             [/color][color=#000000]fffff800`[/color][color=#800080]00892340 [/color][color=#0A246A]mov     [/color][color=#000000]rbp[/color][color=#0A246A],qword ptr [[/color][color=#000000]rsp[/color][color=#0A246A]+[/color][color=#800080]668h[/color][color=#0A246A]]
             [/color][color=#000000]fffff800`[/color][color=#800080]00892348 [/color][color=#0A246A]mov     [/color][color=#000000]rbx[/color][color=#0A246A],qword ptr [[/color][color=#000000]rsp[/color][color=#0A246A]+[/color][color=#800080]670h[/color][color=#0A246A]]
             [/color][color=#000000]fffff800`[/color][color=#800080]00892350 [/color][color=#0A246A]add     [/color][color=#000000]rsp[/color][color=#0A246A],[/color][color=#800080]678h
             [/color][color=#000000]fffff800`[/color][color=#800080]00892357 [/color][color=#000000]ret[/color][/font]


参考资料

  [1] wrk 源码
  [2] Improving Automated Analysis of Windows x64 Binaries, skape
  [3] Programming against the x64 exception handling support, Skywing
  [4] Exceptional Behavior - x64 Structured Exception Handling, The NT Insider

SEH分析笔记(x64篇)_v1.0.0.7z

[培训]《安卓高级研修班(网课)》月薪三万计划,掌握调试、分析还原ollvm、vmp的方法,定制art虚拟机自动化脱壳的方法

上传的附件:
收藏
点赞8
打赏
分享
最新回复 (20)
雪    币: 108
活跃值: (873)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
yangya 2011-11-4 20:13
2
0
不错,好帖子,看不懂哈
雪    币: 342
活跃值: (199)
能力值: ( LV7,RANK:100 )
在线值:
发帖
回帖
粉丝
boxcounter 2 2011-11-4 20:51
3
0
参考资料

        [1] wrk 源码
        [2] Improving Automated Analysis of Windows x64 Binaries, skape
        [3] Programming against the x64 exception handling support, Skywing
        [4] Exceptional Behavior - x64 Structured Exception Handling, The NT Insider
雪    币: 4410
活跃值: (2799)
能力值: ( LV13,RANK:283 )
在线值:
发帖
回帖
粉丝
littlewisp 2 2011-11-4 20:57
4
0
标记一下,明天再学习。支持X64的文章
雪    币: 32408
活跃值: (18760)
能力值: (RANK:350 )
在线值:
发帖
回帖
粉丝
kanxue 8 2011-11-4 21:38
5
0
精华鼓励一下
雪    币: 242
活跃值: (418)
能力值: ( LV11,RANK:188 )
在线值:
发帖
回帖
粉丝
XPoy 3 2011-11-5 02:04
6
0
LZ你太帅了!我要用千斤顶
雪    币: 1675
活跃值: (594)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
djxh 2011-11-5 02:12
7
0
严重支持,学习。。。
雪    币: 367
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
zeracker 2011-11-5 18:29
8
0
谢了。转载.............
雪    币: 5660
活跃值: (12)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
rjchen 2011-11-8 12:26
9
0
这个太好了啊,收藏学习了
雪    币: 203
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
lookkscan 2011-11-8 17:22
10
0
表示lz很有才啊!
雪    币: 201
活跃值: (16)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
善良屠夫 2011-11-8 21:43
11
0
精华 绝对的精华
雪    币: 349
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
rocross 2011-11-9 10:35
12
0
厉害,学习学习。
雪    币: 349
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
Osleti 2011-11-10 22:08
13
0
学习了。。。膜拜楼主
雪    币: 746
活跃值: (4030)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
kagayaki 2011-11-10 23:42
14
0
膜拜楼主 。。。
雪    币: 237
活跃值: (15)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
zuoyefeng 2011-11-11 03:50
15
0
markkkkkkkk
雪    币: 500
活跃值: (785)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
lizhenzhe 2011-11-15 14:46
16
0
mark一下
雪    币: 688
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
maomaolk 2019-3-5 15:58
17
0
mark一下
雪    币: 2659
活跃值: (3272)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
Mr.hack 2021-2-16 10:11
18
0
相较于32位的seh异常处理,64位的还是变复杂了很多
雪    币: 4448
活跃值: (3481)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
木志本柯 2021-3-11 13:38
19
0
wc这什么玩意。。。
雪    币: 4856
活跃值: (4383)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
~时光荏苒 2021-7-26 20:58
20
0
感谢分享!正好需要看看
雪    币: 333
活跃值: (970)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
fatcateatrat 2024-1-23 10:36
21
0
看看前人的学习成果
游客
登录 | 注册 方可回帖
返回