• SEH分析笔记(X64篇


    参考:

    https://bbs.pediy.com/thread-142371.htm

    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 大括号内的代码。

            以下面的伪码为例,

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    [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 里包含几乎所有函数的栈操作、异常处理等信息。

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

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    [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:workspacecodemycode 0passthroughpassthrough.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篇)》中的部分描述,

            原型:
    1
    2
    3
    4
    5
    6
    7
    8
    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.2ase toskeamd64exceptn.c:430。

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

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

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    [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 登场~

            先来看看它的原型:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    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.2ase tos tlamd64exdsptch.c:1202。

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

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

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    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,我们来看看这个函数,

            原型:
    1
    2
    3
    4
    5
    6
    7
    EXCEPTION_DISPOSITION
    __C_specific_handler (
        IN PEXCEPTION_RECORD pExceptionRecord,
        IN PVOID pEstablisherFrame,
        IN OUT PCONTEXT pContext,
        IN OUT PVOID pDispatcherContext
        );

            反汇编码:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    [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
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    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,原型如下:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    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 恢复到原来那台机器。

            这个流程很重要,我手绘了一副图帮助理解,
           
            伪码:
    1
    2
    3
    4
    5
    6
    7
    __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 没有什么改变,原型依旧:

    1
    2
    3
    4
    5
    6
    7
    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.2ase tos tlamd64xcptmisc.asm:199。
            RtlpUnwindHandle 的实现源码位于 $WRK-v1.2ase tos tlamd64xcptmisc.asm:136。

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

            四、ExceptionNestedException 和 ExceptionCollidedUnwind

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

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

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    [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 更复杂一些,我们以如下伪码为例,
                   
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    [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 代码:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    [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 "[/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 "[/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 "[/color][color=#000080], [/color][color=#000000]__LINE__[/color][color=#000080], [/color][color=#000000]__FILE__[/color][color=#000080]);
            }
        }[/color][/font]

            反汇编码:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    [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 信息:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    [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 "[/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 "[/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 "[/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 "[/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 "[/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 "[/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 "[/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 "[/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 "[/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 的反汇编代码和注释

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

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    227
    228
    229
    230
    231
    232
    233
    234
    235
    236
    237
    238
    239
    240
    241
    242
    243
    244
    245
    246
    247
    248
    249
    250
    251
    252
    253
    254
    255
    256
    257
    258
    259
    260
    261
    262
    263
    264
    265
    266
    267
    268
    269
    270
    271
    272
    273
    274
    275
    276
    277
    278
    279
    280
    281
    282
    283
    284
    285
    286
    287
    288
    289
    290
    291
    292
    293
    294
    295
    296
    297
    298
    299
    300
    301
    302
    303
    304
    305
    306
    307
    308
    309
    310
    311
    312
    313
    314
    315
    316
    317
    318
    319
    320
    321
    322
    323
    324
    325
    326
    327
    328
    329
    330
    331
    332
    333
    334
    335
    336
    337
    338
    339
    340
    341
    342
    343
    344
    345
    346
    347
    348
    349
    350
    351
    352
    353
    354
    355
    356
    357
    358
    359
    360
    361
    362
    363
    364
    365
    366
    367
    368
    369
    370
    371
    372
    373
    374
    375
    376
    377
    378
    379
    380
    381
    382
    383
    384
    385
    386
    387
    388
    389
    390
    391
    392
    393
    394
    395
    396
    397
    398
    399
    400
    401
    [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
  • 相关阅读:
    发现一波黒帽seo神操作,通过百度打开跳广告,其他方式访问正常。下面分析原理。
    微信公众号js调起支付代码中不要使用var
    js 中 new Array() var a={} var a=[] new Object()
    Brute Force-python
    Cobaltstrike -恶意宏文件
    利用恶意office文档得shell
    nginx 安装配置php
    nginx 安装部署
    python 函数小实例
    三星s4刷机教程(卡刷)
  • 原文地址:https://www.cnblogs.com/kuangke/p/14702382.html
Copyright © 2020-2023  润新知