首页
社区
课程
招聘
[原创]SEH分析笔记(X86篇)
发表于: 2011-10-5 12:46 36824

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

2011-10-5 12:46
36824
历史:
        v1.0.0, 2011-10-05:最初版本。
        v1.0.1, 2011-10-06:补充总结之前的资源泄漏示例。
        v1.0.2, 2011-10-31:调整若干描述语句;增加 ExceptionNestedException 返回值的补充说明。
        注:本帖内容没有同步更新,请下载附件。

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

        这两天琢磨了下SEH,这里记录一下自己琢磨的一些心得。
        SEH 这个概念我就不啰嗦了,任何一个介绍 SEH 的资料都有讲。我主要记录一些自己的理解。可能有一些概念理解的不够清晰,有一些说法比较狭隘,欢迎看到本文的朋友一起讨论、修正,非常感谢。
        首先,SEH 是针对于异常的一种处理机制,这个异常分为硬件异常和软件异常,这里所说的硬件异常是狭义的异常,也就是 CPU 产生的异常。比如除零操作,CPU 执行除零操作时候,会自主启动异常处理机制。软件异常,就是程序模拟的异常,比如调用 RaiseException 函数。软件异常是可以随意触发的,windows 系统内部遇到问题会触发,开发人员高兴了也可以触发。
        抛出了问题,就要有解决方案。那这么多问题和解决方案,如何管理呢?windows 系统当仁不让的提供了它管理方案 —— SEH。我看一些资料有详细的讨论 SEH 的确切含义,这里我不参与讨论,而只是简单的理解为“系统提供的异常处理机制,以及编译器对其进行增强的部分”。

        来说说系统提供的异常处理机制。
        windows 提供的异常处理机制实际上只是一个简单的框架,一般情况下开发人员都不会直接用到。咱通常所用的异常处理(比如 C++ 的 throw、try、catch)都是编译器在系统提供的异常处理机制上进行加工了的增强版本。这里先抛开增强版的不提,继续说原始版本。
        原始版本的机制很简单:谁都可以触发异常,谁都可以处理异常(只要它能看得见)。但是不管是触发还是处理都得先登记。系统把这些登记信息保存在一个链表里,并且这个链表保存在线程的数据结构里。也就是说,异常所涉及的一些行为都是线程相关的。比如,线程 T1 触发的异常就只能由线程 T1 来处理,其他线程根本就不知道 T1 发生了什么事,更不会狗拿耗子。
        等登记完毕后,线程就可以抛出或处理异常了,系统也可以做相应的管理工作了。(这里啰嗦一句,系统提供的 SEH 其实是一个针对于“触发异常-解决异常”的管理机制,系统自身是不提供任何具体异常的解决方案的。解决方案还是要由用户自身来提供(增强版里编译器也会来提供解决方案,来帮“不负责”的程序猿擦屁股,这是后话))
        系统提供的管理工作简单来说包括(但不限于):找到触发异常的线程的异常处理链表(前头登记的那个),然后按照规则(具体的规则后续再说)对该异常进行分发,根据分发后的处理结果再进行下一步的分发或者结束处理。
        系统管理所使用的数据结构和宏:
[font=Consolas][color=#000000]    [/color][color=#0000FF]#define [/color][color=#000000]EXCEPTION_CHAIN_END [/color][color=#000080](([/color][color=#0000FF]struct [/color][color=#000000]_EXCEPTION_REGISTRATION_RECORD [/color][color=#000080]* [/color][color=#000000]POINTER_32[/color][color=#000080])-[/color][color=#800080]1[/color][color=#000080])

    [/color][color=#0000FF]typedef enum [/color][color=#000000]_EXCEPTION_DISPOSITION [/color][color=#000080]{
        [/color][color=#000000]ExceptionContinueExecution[/color][color=#000080],
        [/color][color=#000000]ExceptionContinueSearch[/color][color=#000080],
        [/color][color=#000000]ExceptionNestedException[/color][color=#000080],
        [/color][color=#000000]ExceptionCollidedUnwind
    [/color][color=#000080]} [/color][color=#000000]EXCEPTION_DISPOSITION[/color][color=#000080];

    [/color][color=#0000FF]typedef struct [/color][color=#000000]_EXCEPTION_RECORD [/color][color=#000080]{
        [/color][color=#000000]DWORD ExceptionCode[/color][color=#000080];
        [/color][color=#000000]DWORD ExceptionFlags[/color][color=#000080];
        [/color][color=#0000FF]struct [/color][color=#000000]_EXCEPTION_RECORD [/color][color=#000080]*[/color][color=#000000]ExceptionRecord[/color][color=#000080];
        [/color][color=#000000]PVOID ExceptionAddress[/color][color=#000080];
        [/color][color=#000000]DWORD NumberParameters[/color][color=#000080];
        [/color][color=#000000]ULONG_PTR ExceptionInformation[/color][color=#000080][[/color][color=#000000]EXCEPTION_MAXIMUM_PARAMETERS[/color][color=#000080]];
    } [/color][color=#000000]EXCEPTION_RECORD[/color][color=#000080];

    [/color][color=#0000FF]typedef [/color][color=#000000]EXCEPTION_RECORD [/color][color=#000080]*[/color][color=#000000]PEXCEPTION_RECORD[/color][color=#000080];

    [/color][color=#0000FF]typedef
    [/color][color=#000000]EXCEPTION_DISPOSITION
    [/color][color=#000080](*[/color][color=#000000]PEXCEPTION_ROUTINE[/color][color=#000080]) (
        [/color][color=#000000]IN [/color][color=#0000FF]struct [/color][color=#000000]_EXCEPTION_RECORD [/color][color=#000080]*[/color][color=#000000]ExceptionRecord[/color][color=#000080],
        [/color][color=#000000]IN PVOID EstablisherFrame[/color][color=#000080],
        [/color][color=#000000]IN OUT [/color][color=#0000FF]struct [/color][color=#000000]_CONTEXT [/color][color=#000080]*[/color][color=#000000]ContextRecord[/color][color=#000080],
        [/color][color=#000000]IN OUT PVOID DispatcherContext
        [/color][color=#000080]);

    [/color][color=#0000FF]typedef struct [/color][color=#000000]_EXCEPTION_REGISTRATION_RECORD [/color][color=#000080]{
        [/color][color=#0000FF]struct [/color][color=#000000]_EXCEPTION_REGISTRATION_RECORD [/color][color=#000080]*[/color][color=#000000]Next[/color][color=#000080];
        [/color][color=#000000]PEXCEPTION_ROUTINE Handler[/color][color=#000080];
    } [/color][color=#000000]EXCEPTION_REGISTRATION_RECORD[/color][color=#000080];

    [/color][color=#0000FF]typedef [/color][color=#000000]EXCEPTION_REGISTRATION_RECORD [/color][color=#000080]*[/color][color=#000000]PEXCEPTION_REGISTRATION_RECORD[/color][color=#000080];
[/color][/font]


        其中 EXCEPTION_REGISTRATION_RECORD 结构就是登记信息。来介绍下它的成员:
        1. EXCEPTION_REGISTRATION_RECORD::Next 域指向下一个 EXCEPTION_REGISTRATION_RECORD,由此构成一个异常登记信息(从字面上说,应该叫做“异常注册记录”更恰当)链表。链表中的最后一个结点会将 Next 置为 EXCEPTION_CHAIN_END,表示链表到此结束。
        2. EXCEPTION_REGISTRATION_RECORD::Handler 指向异常处理函数。

        前面有简单的说过原始版本 SEH 的管理工作,这里再根据以上列出的相关数据结构稍微详细一点说说。
        当接收到异常后,系统找到当前线程(还记不记得,前面有说过,异常是线程相关的。系统接收到的异常就是当前正在运行的线程触发的。其实这个说法还不准确,DPC 也会触发异常,而它是线程无关的,这里为了方便理解,先只考虑线程)的异常链表,从链表中的第一个结点开始遍历,找到一个 EXCEPTION_REGISTRATION_RECORD 就调用它的 Handler,并把该异常(由第一个类型为 EXCEPTION_RECORD 的参数表示)传递给该 Handler,Handler 处理并返回一个类型为 EXCEPTION_DISPOSITION 的枚举值。该返回值指示系统下一步该做什么:
        ExceptionContinueExecution 表示:“我已修正了此异常的故障,请你从事发点重新执行,谢谢”。
        ExceptionContinueSearch 表示:“我没有处理此异常,请你继续搜索其他的解决方案,抱歉”。
        ExceptionNestedException 和 ExceptionCollidedUnwind 这里先不做解释,后面会细说。
        这样系统根据不同的返回值来继续遍历异常链表或者回到触发点继续执行。

        需要说明一下,本文主要以内核模式下的异常来说,因为相比用户模式下的异常处理流程,内核模式少了模式切换、栈切换以及反向回调等步骤。
       
        我们现在来看看详细的内核异常流程。

        首先,CPU 执行的指令触发了异常,CPU 改执行 IDT 中 KiTrap??,KiTrap?? 会调用 KiDispatchException。该函数原型如下:
        VOID
        KiDispatchException (
            IN PEXCEPTION_RECORD ExceptionRecord,
            IN PKEXCEPTION_FRAME ExceptionFrame,
            IN PKTRAP_FRAME TrapFrame,
            IN KPROCESSOR_MODE PreviousMode,
            IN BOOLEAN FirstChance
            );
        其名称明白的说明了函数的主要功能:分派异常。其实现可以参考 $wrk-v1.2\base\ntos\ke\i386\exceptn.c:1033。我的笔记:
        在当前栈中分配一个 CONTEXT,调用 KeContextFromKframes 初始化它。
        检查 ExceptionRecord->ExceptionCode,如果:
                是 STATUS_BREAKPOINT,那么将 CONTEXT::Eip 减一;
                是 KI_EXCEPTION_ACCESS_VIOLATION,那么将检查是否是由 AtlThunk 触发(这个小环节没有深究),如果是触发 NX(不可执行),那么将 ExceptionRecord->ExceptionInformation [0] 置为 0(貌似表示触发操作的类型,0表示读、1表示写);
        如果 PreviousMode 是 KernelMode,那么,
                如果 FirstChance 为 TRUE,那么将该异常传达给内核调试器,如果内核调试器没有处理,那么调用 RtlDispatchException 进行处理。
                如果 FirstChance 为 FALSE,那么再次将该异常传达给内核调试器,如果内核调试器没有处理,那么 BUGCHECK。
        如果 PreviousMode 是 UserMode,那么,
                如果 FirstChance 为 TRUE,那么将该异常传达给内核调试器,如果内核调试器没有处理,那么将异常传达给应用层调试器。如果仍然没有处理,那么将 KTRAP_FRAME 和 EXCEPTION_RECORD 拷贝到 UserMode 的栈中,并设置 KTRAP_FRAME::Eip 设置为 ntdll!KiUserExceptionDispatcher,返回(将该异常交由应用层异常处理程序进行处理)。
                如果 FirstChance 为 FALSE,那么再次将异常传达给应用层调试器,如果仍然没有处理,那么调用 ZwTerminateProcess 结束进程,并 BUGCHECK。

        抛开应用层异常不说,我们来看 PreviousMode 是 KernelMode 的情况,其重点是调用 RtlDispatchException 的操作。我们来看一下这个函数:
        BOOLEAN
        RtlDispatchException (
                IN PEXCEPTION_RECORD ExceptionRecord,
            IN PCONTEXT ContextRecord
            );
        它的实现可以参考 $wrk-v1.2\base\ntos\rtl\i386\exdsptch.c:126。我的笔记:
        遍历当前线程的异常链表,挨个调用 RtlpExecuteHandlerForException,RtlpExecuteHandlerForException 会调用异常处理函数。再根据返回值做出不同的处理:
        对于 ExceptionContinueExecution,结束遍历,返回。(对于标记为‘EXCEPTION_NONCONTINUABLE’的异常,会调用 RtlRaiseException。)
        对于 ExceptionContinueSearch,继续遍历下一个结点。
        对于 ExceptionNestedException,则从指定的新异常继续遍历。
        只有正确处理 ExceptionContinueExecution 才会返回 TRUE,其他情况都返回 FALSE。

        在继续讲述异常处理机制之前,咱们需要先来认识一下异常链表。
        之前有提到过:系统将异常链表头保存在线程结构里。来看看具体的数据结构:
        线程的内核数据结构体现是 _ETHREAD,从它开始进入,直到咱们关注的异常链表。

        kd> dt _ETHREAD
        ntdll!_ETHREAD
           +0x000 Tcb              : _KTHREAD
           ... 省略之后的成员

        kd> dt _KTHREAD
        ntdll!_KTHREAD
           ... 省略的域成员
           +0x074 Teb              : Ptr32 Void
           ... 省略的域成员

        Teb 成员的类型实际是 _TEB,来看看
        kd> dt _TEB
        ntdll!_TEB
           +0x000 NtTib            : _NT_TIB
           ... 省略的域成员       

        kd> dt _NT_TIB
        ntdll!_NT_TIB
           +0x000 ExceptionList    : Ptr32 _EXCEPTION_REGISTRATION_RECORD
           +0x004 StackBase        : Ptr32 Void
           +0x008 StackLimit       : Ptr32 Void
           +0x00c SubSystemTib     : Ptr32 Void
           +0x010 FiberData        : Ptr32 Void
           +0x010 Version          : Uint4B
           +0x014 ArbitraryUserPointer : Ptr32 Void
           +0x018 Self             : Ptr32 _NT_TIB
        _NT_TIB 的第一个域成员 ExceptionList 就是异常链表头。

        但是系统不是这么一步一步找的,而是借助 FS 寄存器来加速寻找。先来说说系统对 FS 的使用。
        在应用层,FS 寄存器“指向”当前执行线程的 _TEB 结构体。在内核层,FS 寄存器“指向”另一个跟 CPU 相关的结构体:_KPCR,来看看它的结构,
        nt!_KPCR
           +0x000 NtTib            : _NT_TIB
           +0x000 Used_ExceptionList : Ptr32 _EXCEPTION_REGISTRATION_RECORD
           ... 省略的域成员       
        与 _TEB 一样,它的第一个域成员也是 _NT_TIB,只不过此时是 nt!_NT_TIB,而在应用层是 ntdll!_NT_TIB,但它们的结构是一样的。

        这样,不论在应用层还是在内核层,系统都可以使用 FS:[0] 找到异常链表。

        到这里,咱们已经聊完了 CPU 触发的异常的处理流程,总结一下它的调用流程:
        CPU 检测到异常 -> KiTrap?? -> KiDispatchException -> RtlDispatchException -> RtlpExecuteHandlerForException

        这是硬件异常,咱们再来看看软件异常。
        软件异常跟硬件异常的处理流程非常接近,只有触发点的不同,调用流程是:
        RtlRaiseException -> RtlDispatchException -> RtlpExecuteHandlerForException

        后面两个被调用的函数咱已经聊过了,主要来看看 RtlRaiseException。这个函数从其名字上就能看出是用来触发异常的。原型如下:
        VOID
        RtlRaiseException (
            IN PEXCEPTION_RECORD ExceptionRecord
        );
        其实现可以参考 $wrk-v1.2\base\ntos\rtl\i386\raise.asm:71。我的笔记:
        RtlRaiseException 首先调用 RtlDispatchException 分发异常,如果 RtlDispatchException 成功分发(有处理函数处理了这个异常),那么结束本函数。
        如果没有成功分发,那么调用 ZwRaiseException 再次触发该异常,这次传入的异常的 FirstChance 被置为 FALSE。

        到这里,系统提供的 SEH 机制(本文又称之为原始版本)大致讲解完毕。咱可以回味一下:
        1. 原始版本的实现较简单,代码量不大,而且 wrk 基本上有所有关键函数的实现代码。
        2. 原始版本的功能过于简单,实际过程中很难直接使用。整个异常处理过程无非就是遍历异常链表,挨个调用异常注册信息的处理函数,如果其中有某个处理函数处理了该异常(返回值为 ExceptionContinueExecution),那么就从异常触发点(如果是断点异常,则要回退一个字节的指令(int 3 指令本身))重新执行。否则不管是整个链表中没有找到合适的处理函数(返回值为 ExceptionContinueSearch),或者遍历过程中出现问题(返回值为 ExceptionNestedException),系统都会简单粗暴的 BUGCHECK。而这也带来一个问题:
           线程运行过程中会调用很多个函数,每个函数都有可能注册异常处理,它们提供的异常处理函数既可能处理该函数自身触发的异常,又可能需要处理其子孙函数触发的异常。前者还好说,自己出了问题,多少还有可能自己修复。而后者就很头疼了,它无法了解所有其调用的子孙函数内部的实现,要想修复子孙函数触发的异常,太困难了。而一旦没有正确处理,或者没人处理,系统就崩掉。这个后果太严重。于是实际上现实程序设计中,基本上没有直接使用原始版本的 SEH,而是使用编译器提供的增强版本。

        下面咱们就来聊聊编译器提供的增强版本。

        首先要说明,增强版本有很多个,不同的编译器提供的的 SEH 增强版本或多或少都有不同处。但是,他们一般都是基于 windows 系统提供的原始版本进行完善的。一个典型的增强版就是微软的编译器(后面简称为 MSC)里提供的 __try、__finally,__except。咱们接下来就用这个增强版作为目标进行分析。我使用的 MSC 是 WDK 7600.16385.1,内置的 cl 的版本是15.00.30729.207,link 的版本是9.00.30729.207,测试虚拟机系统为 32位 Win2k3sp1 + wrk。

        咱们先看看增强版的数据结构,跟之前的原始版本有很多相似之处:
[font=Consolas][color=#000000]    [/color][color=#0000FF]typedef struct [/color][color=#000000]_EXCEPTION_REGISTRATION PEXCEPTION_REGISTRATION[/color][color=#000080];
    [/color][color=#0000FF]struct [/color][color=#000000]_EXCEPTION_REGISTRATION[/color][color=#000080]{
        [/color][color=#0000FF]struct [/color][color=#000000]_EXCEPTION_REGISTRATION [/color][color=#000080]*[/color][color=#000000]prev[/color][color=#000080];
        [/color][color=#0000FF]void [/color][color=#000080](*[/color][color=#000000]handler[/color][color=#000080])([/color][color=#000000]PEXCEPTION_RECORD[/color][color=#000080], [/color][color=#000000]PEXCEPTION_REGISTRATION[/color][color=#000080], [/color][color=#000000]PCONTEXT[/color][color=#000080], [/color][color=#000000]PEXCEPTION_RECORD[/color][color=#000080]);
        [/color][color=#0000FF]struct [/color][color=#000000]scopetable_entry [/color][color=#000080]*[/color][color=#000000]scopetable[/color][color=#000080];
        [/color][color=#0000FF]int [/color][color=#000000]trylevel[/color][color=#000080];
        [/color][color=#0000FF]int [/color][color=#000000]_ebp[/color][color=#000080];
        [/color][color=#000000]PEXCEPTION_POINTERS xpointers[/color][color=#000080];
    };[/color][/font]

        这个 EXCEPTION_REGISTRATION 在增强版中就相当于原始版本中的 EXCEPTION_REGISTRATION_RECORD。可以这么理解它:
[font=Consolas][color=#000000]    [/color][color=#0000FF]struct [/color][color=#000000]_EXCEPTION_REGISTRATION[/color][color=#000080]{
        [/color][color=#0000FF]struct [/color][color=#000000]_EXCEPTION_REGISTRATION_RECORD ExceptionRegistrationRecord[/color][color=#000080];
        [/color][color=#0000FF]struct [/color][color=#000000]scopetable_entry [/color][color=#000080]*[/color][color=#000000]scopetable[/color][color=#000080];
        [/color][color=#0000FF]int [/color][color=#000000]trylevel[/color][color=#000080];
        [/color][color=#0000FF]int [/color][color=#000000]_ebp[/color][color=#000080];
        [/color][color=#000000]PEXCEPTION_POINTERS xpointers[/color][color=#000080];
    }; [/color][color=#008000]// 注:本结构体只用于理解原始版和增强版的区别,实际代码中并没有这种形式的定义    [/color][/font]


        也就是说它沿用了老版本的注册信息结构,只是在域成员名称上做了些改动,把 Next 改名为 prev,把 Handler 改为 handler。除此之外,在原始版本基础上增加了4个域成员(scopetable、trylevel、_ebp、xpointers),用来支持它的增强功能。
        需要说明的是,这结构体来源于 MSC 的 crt 源码里的 exsup.inc,这个文件使用的是汇编语法,该结构体定义是从该文件的注释中提取出来。在实际的分析过程中,发现它的定义有一些问题:最后一个域成员 xpointers 实际上存放在 prev 之前,也就是说,实际中 __try 增强版用的结构体是这样的:
[font=Consolas][color=#000000]    
    [/color][color=#0000FF]typedef struct [/color][color=#000000]_EXCEPTION_REGISTRATION PEXCEPTION_REGISTRATION[/color][color=#000080];
    [/color][color=#0000FF]struct [/color][color=#000000]_EXCEPTION_REGISTRATION[/color][color=#000080]{
        [/color][color=#000000]PEXCEPTION_POINTERS xpointers[/color][color=#000080];
        [/color][color=#0000FF]struct [/color][color=#000000]_EXCEPTION_REGISTRATION [/color][color=#000080]*[/color][color=#000000]prev[/color][color=#000080];
        [/color][color=#0000FF]void [/color][color=#000080](*[/color][color=#000000]handler[/color][color=#000080])([/color][color=#000000]PEXCEPTION_RECORD[/color][color=#000080], [/color][color=#000000]PEXCEPTION_REGISTRATION[/color][color=#000080], [/color][color=#000000]PCONTEXT[/color][color=#000080], [/color][color=#000000]PEXCEPTION_RECORD[/color][color=#000080]);
        [/color][color=#0000FF]struct [/color][color=#000000]scopetable_entry [/color][color=#000080]*[/color][color=#000000]scopetable[/color][color=#000080];
        [/color][color=#0000FF]int [/color][color=#000000]trylevel[/color][color=#000080];
        [/color][color=#0000FF]int [/color][color=#000000]_ebp[/color][color=#000080];
    };[/color][/font]

        相关的宏和结构
[font=Consolas][color=#000000]    TRYLEVEL_NONE           [/color][color=#0A246A]equ     -[/color][color=#800080]1
    [/color][color=#000000]TRYLEVEL_INVALID        [/color][color=#0A246A]equ     -[/color][color=#800080]2[/color][/font]

        scopetable_entry
           +0x000 previousTryLevel : Uint4B
           +0x004 lpfnFilter       : Ptr32     int
           +0x008 lpfnHandler      : Ptr32     int

        咱们先来简单的看一下增强版中出现的几个新域成员。
        EXCEPTION_REGISTRATION::scopetable 是类型为 scopetable_entry 的数组。
        EXCEPTION_REGISTRATION::trylevel 是数组下标,用来索引 scopetable 中的数组成员。
        _ebp 是包含该 _EXCEPTION_REGISTRATION 结构体的函数的栈帧指针。对于没有 FPO 优化过的函数,一开头通常有个 push ebp 的操作,_ebp 的值就是被压入的 ebp 的值,后续咱们通过代码就再看实际的应用。
       
        按照原始版本的设计,每一对“触发异常-处理异常”都会有一个注册信息即 EXCEPTION_REGISTRATION_RECORD。也就是说,如果按照原始的设计,每一个 __try/__except(__finally) 都应该对应一个 EXCEPTION_REGISTRATION。但是实际的 MSC 实现不是这样的。
        真正的实现是:
        每个使用 __try/__except(__finally) 的函数,不管其内部嵌套或反复使用多少 __try/__except(__finally),都只注册一遍,即只将一个 EXCEPTION_REGISTRATION 挂入当前线程的异常链表中(对于递归函数,每一次调用都会创建一个 EXCEPTION_REGISTRATION,并挂入线程的异常链表中,这是另外一回事)。
        那如何处理函数内部出现的多个 __try/__except(__finally) 呢?这多个 __except 代码块的功能可能大不相同,而注册信息 EXCEPTION_REGISTRATION 中只能提供一个处理函数 handler,怎么办?
        MSC 的做法是,MSC 提供一个处理函数,即 EXCEPTION_REGISTRATION::handler 被设置为 MSC 的某个函数,而不是程序猿提供的 __except 代码块。程序猿提供的多个 __except 块被存储在 EXCEPTION_REGISTRATION::scopetable 数组中。我们看看上面的 scopetable_entry 定义,由于我没有找到它的定义代码,所以就贴了 windbg 中 dt 输出结果。
        其中 scopetable_entry::lpfnHandler 就是程序猿提供的 __except 异常处理块代码。而 lpfnFilter 就是 __except 的过滤块代码。对于 __finally 代码块,其 lpfnFilter 被置为 NULL,lpfnHandler 就是其包含的代码块。

        下面,我们用一小段简单的伪代码来详细说明。
[font=Consolas][color=#000000]    [/color][color=#800080]1     [/color][color=#000000]VOID SimpleSeh[/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=#000080]}   
    [/color][color=#800080]6         [/color][color=#000000]__except[/color][color=#000080]([/color][color=#000000]ExceptionFilter_0[/color][color=#000080](...))
    [/color][color=#800080]7         [/color][color=#000080]{   
    [/color][color=#800080]8             [/color][color=#000000]ExceptCodeBlock_0[/color][color=#000080];
    [/color][color=#800080]9         [/color][color=#000080]}   
    [/color][color=#800080]10    
    11        [/color][color=#000000]__try
    [/color][color=#800080]12        [/color][color=#000080]{
    [/color][color=#800080]13            [/color][color=#000000]__try
    [/color][color=#800080]14            [/color][color=#000080]{
    [/color][color=#800080]15            [/color][color=#000080]}
    [/color][color=#800080]16            [/color][color=#000000]__except[/color][color=#000080]([/color][color=#000000]ExceptionFilter_1[/color][color=#000080](...))
    [/color][color=#800080]17            [/color][color=#000080]{
    [/color][color=#800080]18                [/color][color=#000000]ExceptCodeBlock_1[/color][color=#000080];
    [/color][color=#800080]19            [/color][color=#000080]}
    [/color][color=#800080]20        [/color][color=#000080]}   
    [/color][color=#800080]21        [/color][color=#000000]__except[/color][color=#000080]([/color][color=#000000]ExceptionFilter_2[/color][color=#000080](...))
    [/color][color=#800080]22        [/color][color=#000080]{   
    [/color][color=#800080]23            [/color][color=#000000]ExceptCodeBlock_2[/color][color=#000080];
    [/color][color=#800080]24        [/color][color=#000080]}   
    [/color][color=#800080]25    [/color][color=#000080]}[/color][/font]

        编译时,编译器会为 SimpleSeh 分配一个 EXCEPTION_REGISTRATION 和一个拥有3个成员的 scopetable 数组,并将 EXCEPTION_REGISTRATION::scopetable 指向该数组(请留意:EXCEPTION_REGISTRATION::scopetable 只是一个指针,不是数组)。然后按照 __try 关键字出现的顺序,将对应的__except/__finally 都存入该数组,步骤如下:

        scopetable[0].lpfnFilter = ExceptionFilter_0;
        scopetable[0].lpfnHandler = ExceptCodeBlock_0;

        scopetable[1].lpfnFilter = ExceptionFilter_1;
        scopetable[1].lpfnHandler = ExceptCodeBlock_1;

        scopetable[2].lpfnFilter = ExceptionFilter_2;
        scopetable[2].lpfnHandler = ExceptCodeBlock_2;

        我们假象当前开始执行 SimpleSeh 函数,在行14和行15之间触发了异常。
        根据之前我们的讨论的流程:RtlRaiseException -> RtlDispatchException -> RtlpExecuteHandlerForException。
        RtlpExecuteHandlerForException 会调用注册信息中的处理函数,即 EXCEPTION_REGISTRATION::handler。该函数是由 MSC 提供的,内部会依次调用 scopetable 中的 lpfnHandler。
        那咱们来模拟执行一下,在14和15行之前触发异常,那应该先从 scopetable[2] 的 ExceptionFilter_2 开始执行,假设该函数返回 EXCEPTION_CONTINUE_SEARCH。那接下来应该是 scopetable[1],假设 ExceptionFilter_1 也返回 EXCEPTION_CONTINUE_SEARCH。那么接下来是不是就应该轮到 scopetable[0] 了?不是。咱们再看看上面的伪代码,行14和行15之间的代码并没处于第一个 __try/__except 的范围中,该异常轮不到 scopetable[0] 来处理。那怎么办?SimpleSeh 执行的过程中怎么知道到 scopetable[1] 就应该停止?
       
        MSC 是通过 scopetable_entry::previousTryLevel 来解决这个问题的。上面数组的设置,完整的形式其实是这样:

        scopetable[0].previousTryLevel = TRYLEVEL_NONE;
        scopetable[0].lpfnFilter = ExceptionFilter_0;
        scopetable[0].lpfnHandler = ExceptCodeBlock_0;

        scopetable[1].previousTryLevel = TRYLEVEL_NONE;
        scopetable[1].lpfnFilter = ExceptionFilter_1;
        scopetable[1].lpfnHandler = ExceptCodeBlock_1;

        scopetable[2].previousTryLevel = 1;
        scopetable[2].lpfnFilter = ExceptionFilter_2;
        scopetable[2].lpfnHandler = ExceptCodeBlock_2;

        scopetable_entry::previousTryLevel 包含的意思是“下一个该轮到数组下标为 previousTryLevel 的单元了”。当 scopetable_entry::previousTryLevel 等于 TRYLEVEL_NONE(-1) 时,就会停止遍历 scopetable。

        咱再来模拟执行一遍,当14和15行之间触发异常时,首先遍历到 scopetable[2],处理完后,找到 scopetable[2].previousTryLevel,发现其值为1,那么遍历到 scopetable[1],处理完后,找到 scopetable[1].previousTryLevel,发现其值为 TRYLEVEL_NONE,于是停止遍历。
        好像挺圆满的,是吧。

        咱们再假设下,如果行4和行5之间触发了同样的异常,执行流程应该如何。首先,执行 scopetable[2],然后在 scopetable[1],然后……(省略若干同上字)。停!这次的异常是在第一个 __try/__except 中触发的,轮不到 scopetable[2] 来处理,怎么办?
        这个时候就轮到 EXCEPTION_REGISTRATION::trylevel 出场了~。EXCEPTION_REGISTRATION::trylevel 的作用就是标识从那个数组单元开始遍历。
        与 scopetable_entry::previousTryLevel 不同,EXCEPTION_REGISTRATION::trylevel 是动态变化的,也就是说,这个值在 SimpleSeh 执行过程中是会经常改变的。比如,
        执行到行4和行5之间,该值就会被修改为0;
        执行到第12行,该值被修改为1;
        执行到14行,该值为2。
        这样,当异常触发时候,MSC 就能正确的遍历 scopetable 了。
       
        这里我画了一幅草图来帮助理解:
        图中下方是低地址端,上方是高地址端。
        (boxcounter: 这幅图是我借助 vim 的列操作手绘的,哪位朋友知道有专门画这类文本图的工具吗(除了 emacs 的图操作模式,这玩意太臃肿了,我不太喜欢)?欢迎告知我 ns.boxcounter[a]gmail.com。非常感谢。)


       4G   |--------------------------|        ...
            |  ...                     |         |
        --> |--------------------------|         |
       /    | ret_addr                 |         |
     func1  | _EXCEPTION_REGISTRATION  |    _EXCEPTION_REGISTRATION                    /  previousTryLevel = TRYLEVEL_NONE        \
       \    | ...                      |         |                    -> scopetable[0] |  lpfnFilter       = ExceptionFilter_0    |
        --> |--------------------------|         |                   /                 \  lpfnHandler      = ExceptionCodeBlock_0 /
       /    | ret_addr                 |         |                  /                  /  previousTryLevel = TRYLEVEL_NONE        \   <-
     func2  | _EXCEPTION_REGISTRATION  |    _EXCEPTION_REGISTRATION      scopetable[1] |  lpfnFilter       = ExceptionFilter_1    |    |
       \    | ...                      |         |                  \                  \  lpfnHandler      = ExceptionCodeBlock_1 /    |
        --> |--------------------------|         |                   \                 /  previousTryLevel = 1                    \   -^
       /    | ret_addr                 |         |                    -> scopetable[2] |  lpfnFilter       = ExceptionFilter_2    |
     func3  | _EXCEPTION_REGISTRATION  |    _EXCEPTION_REGISTRATION                    \  lpfnHandler      = ExceptionCodeBlock_2 /
       \    | ...                      |         |
        --> |--------------------------|         |
       /    | ret_addr                 |         |
     func4  | _EXCEPTION_REGISTRATION  |    _EXCEPTION_REGISTRATION
       \    | ...                      |           ^
        --> |                          |           |
            |                          |         FS:[0]
       0 -> |--------------------------|

        这幅图中的函数关系是: func1 -> func2 -> func3 -> func4

        到目前位置,咱们已经熟悉了增强版的概要流程。下面结合真实代码来分析。代码分为三块:SEH 创建代码、MSC 提供的 handler 函数,以及展开函数。
        在开始看分析代码之前,先把后面分析过程中需要用的宏和结构体列出来:
       
[font=Consolas][color=#000000]    [/color][color=#0000FF]#define [/color][color=#000000]EXCEPTION_NONCONTINUABLE [/color][color=#800080]0x1    [/color][color=#008000]// Noncontinuable exception
    [/color][color=#0000FF]#define [/color][color=#000000]EXCEPTION_UNWINDING [/color][color=#800080]0x2         [/color][color=#008000]// Unwind is in progress
    [/color][color=#0000FF]#define [/color][color=#000000]EXCEPTION_EXIT_UNWIND [/color][color=#800080]0x4       [/color][color=#008000]// Exit unwind is in progress
    [/color][color=#0000FF]#define [/color][color=#000000]EXCEPTION_STACK_INVALID [/color][color=#800080]0x8     [/color][color=#008000]// Stack out of limits or unaligned
    [/color][color=#0000FF]#define [/color][color=#000000]EXCEPTION_NESTED_CALL [/color][color=#800080]0x10      [/color][color=#008000]// Nested exception handler call
    [/color][color=#0000FF]#define [/color][color=#000000]EXCEPTION_TARGET_UNWIND [/color][color=#800080]0x20    [/color][color=#008000]// Target unwind in progress
    [/color][color=#0000FF]#define [/color][color=#000000]EXCEPTION_COLLIDED_UNWIND [/color][color=#800080]0x40  [/color][color=#008000]// Collided exception handler call

    [/color][color=#0000FF]#define [/color][color=#000000]EXCEPTION_UNWIND [/color][color=#000080]([/color][color=#000000]EXCEPTION_UNWINDING [/color][color=#000080]| [/color][color=#000000]EXCEPTION_EXIT_UNWIND [/color][color=#000080]| [/color][color=#000000]\
                              EXCEPTION_TARGET_UNWIND [/color][color=#000080]| [/color][color=#000000]EXCEPTION_COLLIDED_UNWIND[/color][color=#000080])

    [/color][color=#000000]nt[/color][color=#000080]![/color][color=#000000]_EXCEPTION_RECORD
       [/color][color=#000080]+[/color][color=#800080]0x000 [/color][color=#000000]ExceptionCode    [/color][color=#000080]: [/color][color=#000000]Int4B
       [/color][color=#000080]+[/color][color=#800080]0x004 [/color][color=#000000]ExceptionFlags   [/color][color=#000080]: [/color][color=#000000]Uint4B
       [/color][color=#000080]+[/color][color=#800080]0x008 [/color][color=#000000]ExceptionRecord  [/color][color=#000080]: [/color][color=#000000]Ptr32 _EXCEPTION_RECORD
       [/color][color=#000080]+[/color][color=#800080]0x00c [/color][color=#000000]ExceptionAddress [/color][color=#000080]: [/color][color=#000000]Ptr32 Void
       [/color][color=#000080]+[/color][color=#800080]0x010 [/color][color=#000000]NumberParameters [/color][color=#000080]: [/color][color=#000000]Uint4B
       [/color][color=#000080]+[/color][color=#800080]0x014 [/color][color=#000000]ExceptionInformation [/color][color=#000080]: [[/color][color=#800080]15[/color][color=#000080]] [/color][color=#000000]Uint4B

    [/color][color=#0000FF]typedef enum [/color][color=#000000]_EXCEPTION_DISPOSITION [/color][color=#000080]{
        [/color][color=#000000]ExceptionContinueExecution[/color][color=#000080],
        [/color][color=#000000]ExceptionContinueSearch[/color][color=#000080],
        [/color][color=#000000]ExceptionNestedException[/color][color=#000080],
        [/color][color=#000000]ExceptionCollidedUnwind
    [/color][color=#000080]} [/color][color=#000000]EXCEPTION_DISPOSITION[/color][color=#000080];

    [/color][color=#008000]// scopetable_entry::lpfnFilter 的返回值,也就是 __except 过滤块的返回值
    [/color][color=#0000FF]#define [/color][color=#000000]EXCEPTION_EXECUTE_HANDLER       [/color][color=#800080]1
    [/color][color=#0000FF]#define [/color][color=#000000]EXCEPTION_CONTINUE_SEARCH       [/color][color=#800080]0
    [/color][color=#0000FF]#define [/color][color=#000000]EXCEPTION_CONTINUE_EXECUTION    [/color][color=#000080]-[/color][color=#800080]1
[/color][/font]

[课程]FART 脱壳王!加量不加价!FART作者讲授!

收藏
免费 9
支持
分享
最新回复 (49)
雪    币: 342
活跃值: (199)
能力值: ( LV7,RANK:100 )
在线值:
发帖
回帖
粉丝
2
一、SEH 创建代码
        这里我没有继续使用上面的 SimpleSeh 进行分析,而是新写了一个简单的 SehTest 函数。
[font=Consolas][color=#000000]        VOID SehTest[color=#000080]()
        {
            [color=#000000]ULONG ulVal [color=#000080]= [color=#800080]0[color=#000080];

            [color=#000000]__try [color=#008000]// 第一个 __try 域
            [color=#000080]{
                [color=#000000]ulVal [color=#000080]= [color=#800080]0x11111111[color=#000080]; [color=#008000]// 最后一位为1表示“在 __try 代码块中”
            [color=#000080]}
            [color=#000000]__except[color=#000080]([color=#000000]Filter_0[color=#000080]())
            {
                [color=#000000]ulVal [color=#000080]= [color=#800080]0x11111110[color=#000080]; [color=#008000]// 最后一位为0表示“在 __except/__finally 代码块中”
            [color=#000080]}

            [color=#000000]__try [color=#008000]// 第二个 __try 域
            [color=#000080]{
                [color=#000000]ulVal [color=#000080]= [color=#800080]0x22222222[color=#000080];

                [color=#000000]__try [color=#008000]// 第三个 __try 域
                [color=#000080]{
                    [color=#000000]ulVal [color=#000080]= [color=#800080]0x33333333[color=#000080];

                    *(([color=#000000]ULONG[color=#000080]*)[color=#000000]NULL[color=#000080]) = [color=#000000]ulVal[color=#000080]; [color=#008000]// 触发异常
                [color=#000080]}
                [color=#000000]__finally
                [color=#000080]{
                    [color=#000000]ulVal [color=#000080]= [color=#800080]0x33333330[color=#000080];
                }
            }
            [color=#000000]__except[color=#000080]([color=#000000]Filter_2[color=#000080]())
            {
                [color=#000000]ulVal [color=#000080]= [color=#800080]0x22222220[color=#000080];
            }

            [color=#0000FF]return[color=#000080];
        }
[/font]


        反汇编代码如下:
        (需要说明一下我的命名习惯是,"l_"前缀的变量是函数的局部变量,没有任何前缀的变量是传入的参数)

kd> uf passthrough!SehTest
;PassThrough!SehTest [d:\workspace\code\mycode\r0\passthrough\passthrough.c @ 604]:
f8720040 mov edi,edi
f8720042 push ebp ; l_ExceptionRegistration->_ebp
f8720043 mov ebp,esp
f8720045 push 0FFFFFFFEh ; l_ExceptionRegistration->trylevel = TRYLEVEL_INVALID (-2)
f8720047 push offset PassThrough!__safe_se_handler_table+0x8 (f8721468) ; l_ExceptionRegistration->scopetable
f872004c push offset PassThrough!_except_handler4 (f8720390) ; l_ExceptionRegistration->handler
f8720051 mov eax,dword ptr fs:[00000000h]
f8720057 push eax ; _EXCEPTION_REGISTRATION::prev
f8720058 add esp,0FFFFFFF4h ; 这里分配了 0xc 字节的栈空间,其中紧贴着 l_ExceptionRegistration->prev
; 的4个字节存放着 l_ExceptionRegistration->xpointers
f872005b push ebx
f872005c push esi
f872005d push edi
f872005e mov eax,dword ptr [PassThrough!__security_cookie (f87220b0)]
f8720063 xor dword ptr [ebp-8],eax ; 对 scopetable 进行异或加密
f8720066 xor eax,ebp ; 对 __security_cookie 进行加密
f8720068 push eax ; 把加密了的 __security_cookie 也压入栈中,后面用来对 scopetable 进行解密
f8720069 lea eax,[ebp-10h]
f872006c mov dword ptr fs:[00000000h],eax ; 将 l_ExceptionRegistration 挂入线程异常链表中
f8720072 mov dword ptr [ebp-18h],esp
f8720075 mov dword ptr [ebp-1Ch],0
f872007c mov dword ptr [ebp-4],0 ; 进入第一个 __try 域,l_ExceptionRegistration->trylevel = 0
f8720083 mov dword ptr [ebp-1Ch],11111111h
f872008a mov dword ptr [ebp-4],0FFFFFFFEh ; 离开第一个 __try 域,l_ExceptionRegistration->trylevel = TRYLEVEL_NONE (-2)
f8720091 jmp PassThrough!SehTest+0x6a (f87200aa)
; ---------------------------------------------------------------------------------
; 这里有个空洞,用 uf 命令是不会显示的。范围是 f8720093 到 f87200a9,汇编码如下
;
; PassThrough!SehTest+0x53 [d:\workspace\code\mycode\r0\passthrough\passthrough.c @ 611]:
; f8720093 call PassThrough!Filter_0 (f8720010)
; f8720098 ret
;
; f8720099 mov esp,dword ptr [ebp-18h] ; 第一个 __except 处理域
; f872009c mov dword ptr [ebp-1Ch],11111110h
; f87200a3 mov dword ptr [ebp-4],0FFFFFFFEh ; 离开第一个 __try 域,l_ExceptionRegistration->trylevel = TRYLEVEL_NONE (-2)
; ---------------------------------------------------------------------------------
;PassThrough!SehTest+0x6a [d:\workspace\code\mycode\r0\passthrough\passthrough.c @ 616]:
f87200aa mov dword ptr [ebp-4],1 ; 进入第二个 __try 域,l_ExceptionRegistration->trylevel = 1
f87200b1 mov dword ptr [ebp-1Ch],22222222h
f87200b8 mov dword ptr [ebp-4],2 ; 进入第三个 __try 域,l_ExceptionRegistration->trylevel = 2
f87200bf mov dword ptr [ebp-1Ch],33333333h
f87200c6 mov eax,dword ptr [ebp-1Ch]
f87200c9 mov dword ptr ds:[00000000h],eax ; 触发异常
f87200ce mov dword ptr [ebp-4],1 ; 离开第三个 __try 域,l_ExceptionRegistration->trylevel = 1
f87200d5 call PassThrough!SehTest+0x9c (f87200dc)
f87200da jmp PassThrough!SehTest+0xa4 (f87200e4)
; ---------------------------------------------------------------------------------
; 空洞,范围是 f87200dc 到 f87200e3,汇编码如下
;
; PassThrough!SehTest+0x9c [d:\workspace\code\mycode\r0\passthrough\passthrough.c @ 628]:
; f87200dc c745e430333333 mov dword ptr [ebp-1Ch],33333330h ; __finally 域
; ---------------------------------------------------------------------------------
;PassThrough!SehTest+0xa4 [d:\workspace\code\mycode\r0\passthrough\passthrough.c @ 630]:
f87200e4 mov dword ptr [ebp-4],0FFFFFFFEh ; 离开第二个 __try 域,l_ExceptionRegistration->trylevel = TRYLEVEL_NONE (-2)
f87200eb jmp PassThrough!SehTest+0xc4 (f8720104)
; ---------------------------------------------------------------------------------
; 空洞,范围是 f87200ed 到 f8720103,汇编码如下
;
; PassThrough!SehTest+0xad [d:\workspace\code\mycode\r0\passthrough\passthrough.c @ 631]:
; f87200ed e83effffff call PassThrough!Filter_2 (f8720030)
; f87200f2 c3 ret
;
; f87200f3 8b65e8 mov esp,dword ptr [ebp-18h] ; 第二个 __except 处理域
; f87200f6 c745e420222222 mov dword ptr [ebp-1Ch],22222220h
; f87200fd c745fcfeffffff mov dword ptr [ebp-4],0FFFFFFFEh ; 离开第三个 __try 域,l_ExceptionRegistration->trylevel = TRYLEVEL_NONE (-2)
; ---------------------------------------------------------------------------------
;PassThrough!SehTest+0xc4 [d:\workspace\code\mycode\r0\passthrough\passthrough.c @ 637]:
f8720104 mov ecx,dword ptr [ebp-10h]
f8720107 mov dword ptr fs:[0],ecx ; 恢复旧的 EXCEPTION_REGISTRATION。即从线程异常链表中摘除 l_ExceptionRegistration
f872010e pop ecx
f872010f pop edi
f8720110 pop esi
f8720111 pop ebx
f8720112 mov esp,ebp
f8720114 pop ebp
f8720115 ret


        来看看 scopetable 的内容:

        kd> dd f8721468
        f8721468  fffffffe 00000000 ffffffd4 00000000  < 16个字节的坑
        f8721478  [fffffffe f8720093 f8720099] [fffffffe
        f8721488  f87200ed f87200f3] [00000001 00000000
        f8721498  f87200dc] 00000000 00000000 00000000
        f87214a8  00000000 00000000 00000000 00000000
        f87214b8  00000000 00000000 00000000 00000000
        f87214c8  00000000 00000000 00000000 00000000
        f87214d8  00000000 00000000 00000000 00000000

        前16个字节是坑,坑的作用晚点再说。之后就是三个 scopetable_entry,被我用大括号扩起来了。对照前面的汇编码可以发现,scopetable_entry::lpfnFilter 和 scopetable_entry::lpfnHandler 就是汇编码中的空洞处的代码。其中,第三个 scopetable_entry::lpfnFilter 是 NULL,对照代码可以发现,是因为这是一个 __try & __finally 块,没有 lpfnFilter。

        汇编代码很简单,注释里也有详细的分析过程了,我不再多啰嗦。只提两点:
        1. EXCEPTION_REGISTRATION::scopetable 指针被用 __security_cookie 进行了异或加密。
        2. EXCEPTION_REGISTRATION::scopetable 并不直接指向 scopetable_entry 数组,在第一个 scopetable_entry 之前有 16 个字节的坑。后续分析中会看到,它的主要作用是帮助验证 scopetable 是否被破坏。第三个 DWORD,即上文中的 ffffffd4 是一个偏移量,后续的分析过程中会看得很清楚。
2011-10-5 12:54
0
雪    币: 342
活跃值: (199)
能力值: ( LV7,RANK:100 )
在线值:
发帖
回帖
粉丝
3
二、MSC 提供的 EXCEPTION_REGISTRATION::handler 函数
        之前咱们有说过 EXCEPTION_REGISTRATION::handler 指向由 MSC 编译器提供的一个函数,这个函数内部负责调用 scopetable[?]->lpfnFilter/lpfnHandler。这个函数通常为 module!_except_handler?,其中module为模块名,? 表示某数字。在分析过程中发现,有的模块完整实现了该函数,有的模块直接使用了系统提供的 nt!_except_handler?。不知道是因为版本的问题,还是编译选项的问题。我没有深究。
        我继续以 passhThrough 模块为例,来说明这个函数。
        首先需要再次说明一下我的注释习惯:后续列出来的反汇编代码中,最左边的:<>符号表示跳转,是我在分析的过程中为了方便理解流程手写的。其中 < 表示跳转源,> 是跳转目标,: 用于组成连接线。
        为了方便对照,我把经过整理的 PassThrough!_except_handler4 的原型列在这里:

        EXCEPTION_DISPOSITION _except_handler4 (
            PEXCEPTION_RECORD pExceptionRecord,
            PEXCEPTION_REGISTRATION pExceptionRegistration,
            PCONTEXT,
            PDISPATCHER_CONTEXT
        );

        反汇编代码:
[font=Consolas][color=#000000]    kd[/color][color=#0A246A]> [/color][color=#000000]uf PassThrough!_except_handler4
                  PassThrough!_except_handler4 [/color][color=#0A246A][[/color][color=#000000]d[/color][color=#0A246A]:[/color][color=#000000]\[/color][color=#800080]5359[/color][color=#000000]\minkernel\crts\crtw32\misc\i386\chandler4.c @ [/color][color=#800080]255[/color][color=#0A246A]]:
                    [/color][color=#000000]f8720390  [/color][color=#0A246A]mov     [/color][color=#FF8000]edi[/color][color=#0A246A],[/color][color=#FF8000]edi
                    [/color][color=#000000]f8720392  [/color][color=#0A246A]push    [/color][color=#FF8000]ebp
                    [/color][color=#000000]f8720393  [/color][color=#0A246A]mov     [/color][color=#FF8000]ebp[/color][color=#0A246A],[/color][color=#FF8000]esp
                    [/color][color=#000000]f8720395  [/color][color=#0A246A]sub     [/color][color=#FF8000]esp[/color][color=#0A246A],[/color][color=#800080]14h
                    [/color][color=#000000]f8720398  [/color][color=#0A246A]push    [/color][color=#FF8000]ebx
                    [/color][color=#000000]f8720399  [/color][color=#0A246A]mov     [/color][color=#FF8000]ebx[/color][color=#0A246A],dword ptr [[/color][color=#FF8000]ebp[/color][color=#0A246A]+[/color][color=#800080]0Ch[/color][color=#0A246A]] [/color][color=#008000]; ebx = pExceptionRegistration
                    [/color][color=#000000]f872039c  [/color][color=#0A246A]push    [/color][color=#FF8000]esi
                    [/color][color=#000000]f872039d  [/color][color=#0A246A]mov     [/color][color=#FF8000]esi[/color][color=#0A246A],dword ptr [[/color][color=#FF8000]ebx[/color][color=#0A246A]+[/color][color=#800080]8[/color][color=#0A246A]]   [/color][color=#008000]; esi = pExceptionRegistration->scopetable
                    [/color][color=#000000]f87203a0  [/color][color=#0A246A]xor     [/color][color=#FF8000]esi[/color][color=#0A246A],dword ptr [[/color][color=#000000]PassThrough!__security_cookie [/color][color=#0A246A]([/color][color=#000000]f87220b0[/color][color=#0A246A])]    [/color][color=#008000]; 用 __security_cookie 对 scopetable 解密
                    [/color][color=#000000]f87203a6  [/color][color=#0A246A]push    [/color][color=#FF8000]edi
                    [/color][color=#000000]f87203a7  [/color][color=#0A246A]mov     [/color][color=#FF8000]eax[/color][color=#0A246A],dword ptr [[/color][color=#FF8000]esi[/color][color=#0A246A]]
                    [/color][color=#000000]f87203a9  [/color][color=#0A246A]mov     byte ptr [[/color][color=#FF8000]ebp[/color][color=#0A246A]-[/color][color=#800080]1[/color][color=#0A246A]],[/color][color=#800080]0   [/color][color=#008000]; ebp-1 存放的是一个 BOOLEAN 值,用来表示是否执行过任何 scopetable_entry::lpfnFilter
                    [/color][color=#000000]f87203ad  [/color][color=#0A246A]mov     dword ptr [[/color][color=#FF8000]ebp[/color][color=#0A246A]-[/color][color=#800080]8[/color][color=#0A246A]],[/color][color=#800080]1  [/color][color=#008000]; ebp-8 被用来存放本函数的返回值,这里初始化为 ExceptionContinueSearch (1)
                    [/color][color=#000000]f87203b4  [/color][color=#0A246A]lea     [/color][color=#FF8000]edi[/color][color=#0A246A],[[/color][color=#FF8000]ebx[/color][color=#0A246A]+[/color][color=#800080]10h[/color][color=#0A246A]]        [/color][color=#008000]; edi = pExceptionRegistration->_ebp 
                    [/color][color=#000000]f87203b7  [/color][color=#0A246A]cmp     [/color][color=#FF8000]eax[/color][color=#0A246A],[/color][color=#800080]0FFFFFFFEh       [/color][color=#008000]; 检查 scopetable 中坑的第一个 DWORD 值,后续来做相关的安全处理
[/color][color=#0A246A]<                   [/color][color=#000000]f87203ba  [/color][color=#0A246A]je      [/color][color=#000000]PassThrough!_except_handler4[/color][color=#0A246A]+[/color][color=#800080]0x39 [/color][color=#0A246A]([/color][color=#000000]f87203c9[/color][color=#0A246A])
:                  
:                 [/color][color=#000000]PassThrough!_except_handler4[/color][color=#0A246A]+[/color][color=#800080]0x2c [/color][color=#0A246A][[/color][color=#000000]d[/color][color=#0A246A]:[/color][color=#000000]\[/color][color=#800080]5359[/color][color=#000000]\minkernel\crts\crtw32\misc\i386\chandler4.c @ [/color][color=#800080]315[/color][color=#0A246A]]:
:                   [/color][color=#008000]; 校验 scopetable 完整性(1)
[/color][color=#0A246A]:                   [/color][color=#000000]f87203bc  [/color][color=#0A246A]mov     [/color][color=#FF8000]ecx[/color][color=#0A246A],dword ptr [[/color][color=#FF8000]esi[/color][color=#0A246A]+[/color][color=#800080]4[/color][color=#0A246A]]
:                   [/color][color=#000000]f87203bf  [/color][color=#0A246A]add     [/color][color=#FF8000]ecx[/color][color=#0A246A],[/color][color=#FF8000]edi
[/color][color=#0A246A]:                   [/color][color=#000000]f87203c1  [/color][color=#0A246A]xor     [/color][color=#FF8000]ecx[/color][color=#0A246A],dword ptr [[/color][color=#FF8000]eax[/color][color=#0A246A]+[/color][color=#FF8000]edi[/color][color=#0A246A]]
:                   [/color][color=#000000]f87203c4  [/color][color=#0A246A]call    [/color][color=#000000]PassThrough!__security_check_cookie [/color][color=#0A246A]([/color][color=#000000]f8720638[/color][color=#0A246A])
:                 
:                 [/color][color=#000000]PassThrough!_except_handler4[/color][color=#0A246A]+[/color][color=#800080]0x39 [/color][color=#0A246A][[/color][color=#000000]d[/color][color=#0A246A]:[/color][color=#000000]\[/color][color=#800080]5359[/color][color=#000000]\minkernel\crts\crtw32\misc\i386\chandler4.c @ [/color][color=#800080]315[/color][color=#0A246A]]:
:                   [/color][color=#008000]; 校验 scopetable 完整性(2)
[/color][color=#0A246A]>                  [/color][color=#000000]f87203c9  [/color][color=#0A246A]mov     [/color][color=#FF8000]ecx[/color][color=#0A246A],dword ptr [[/color][color=#FF8000]esi[/color][color=#0A246A]+[/color][color=#800080]0Ch[/color][color=#0A246A]]
                   [/color][color=#000000]f87203cc  [/color][color=#0A246A]mov     [/color][color=#FF8000]eax[/color][color=#0A246A],dword ptr [[/color][color=#FF8000]esi[/color][color=#0A246A]+[/color][color=#800080]8[/color][color=#0A246A]]
                   [/color][color=#000000]f87203cf  [/color][color=#0A246A]add     [/color][color=#FF8000]ecx[/color][color=#0A246A],[/color][color=#FF8000]edi
                   [/color][color=#000000]f87203d1  [/color][color=#0A246A]xor     [/color][color=#FF8000]ecx[/color][color=#0A246A],dword ptr [[/color][color=#FF8000]eax[/color][color=#0A246A]+[/color][color=#FF8000]edi[/color][color=#0A246A]]
                   [/color][color=#000000]f87203d4  [/color][color=#0A246A]call    [/color][color=#000000]PassThrough!__security_check_cookie [/color][color=#0A246A]([/color][color=#000000]f8720638[/color][color=#0A246A])
                    [/color][color=#008000]; 安全工作处理完毕,开始进入异常处理流程
                   [/color][color=#000000]f87203d9  [/color][color=#0A246A]mov     [/color][color=#FF8000]eax[/color][color=#0A246A],dword ptr [[/color][color=#FF8000]ebp[/color][color=#0A246A]+[/color][color=#800080]8[/color][color=#0A246A]]     [/color][color=#008000]; eax = pExceptionRecord
                   [/color][color=#000000]f87203dc  [/color][color=#0A246A]test    byte ptr [[/color][color=#FF8000]eax[/color][color=#0A246A]+[/color][color=#800080]4[/color][color=#0A246A]],[/color][color=#800080]66h      [/color][color=#008000]; pExceptionRecord->ExceptionFlags & EXCEPTION_UNWIND,判断是异常处理过程还是展开过程
[/color][color=#0A246A]<                  [/color][color=#000000]f87203e0  [/color][color=#0A246A]jne     [/color][color=#000000]PassThrough!_except_handler4[/color][color=#0A246A]+[/color][color=#800080]0x138 [/color][color=#0A246A]([/color][color=#000000]f87204c8[/color][color=#0A246A])
:                 
:                 [/color][color=#000000]PassThrough!_except_handler4[/color][color=#0A246A]+[/color][color=#800080]0x56 [/color][color=#0A246A][[/color][color=#000000]d[/color][color=#0A246A]:[/color][color=#000000]\[/color][color=#800080]5359[/color][color=#000000]\minkernel\crts\crtw32\misc\i386\chandler4.c @ [/color][color=#800080]331[/color][color=#0A246A]]:
:                   [/color][color=#008000]; 异常处理过程
[/color][color=#0A246A]:                   [/color][color=#000000]f87203e6  [/color][color=#0A246A]mov     [/color][color=#FF8000]ecx[/color][color=#0A246A],dword ptr [[/color][color=#FF8000]ebp[/color][color=#0A246A]+[/color][color=#800080]10h[/color][color=#0A246A]]   [/color][color=#008000]; ecx = pContext
[/color][color=#0A246A]:                   [/color][color=#000000]f87203e9  [/color][color=#0A246A]lea     [/color][color=#FF8000]edx[/color][color=#0A246A],[[/color][color=#FF8000]ebp[/color][color=#0A246A]-[/color][color=#800080]14h[/color][color=#0A246A]]
:                   [/color][color=#000000]f87203ec  [/color][color=#0A246A]mov     dword ptr [[/color][color=#FF8000]ebx[/color][color=#0A246A]-[/color][color=#800080]4[/color][color=#0A246A]],[/color][color=#FF8000]edx     [/color][color=#008000]; ebx-4 是创建 EXCEPTION_REGISTRATION 时候预留的 xpointers 的空间,这里给它赋值
[/color][color=#0A246A]:                   [/color][color=#000000]f87203ef  [/color][color=#0A246A]mov     [/color][color=#FF8000]ebx[/color][color=#0A246A],dword ptr [[/color][color=#FF8000]ebx[/color][color=#0A246A]+[/color][color=#800080]0Ch[/color][color=#0A246A]]   [/color][color=#008000]; ebx = pExceptionRegistration->trylevel
[/color][color=#0A246A]:                   [/color][color=#000000]f87203f2  [/color][color=#0A246A]mov     dword ptr [[/color][color=#FF8000]ebp[/color][color=#0A246A]-[/color][color=#800080]14h[/color][color=#0A246A]],[/color][color=#FF8000]eax   [/color][color=#008000]; [ebp-14] = pExceptionRecord,即 xpointers->ExceptionRecord = pExceptionRecord
[/color][color=#0A246A]:                   [/color][color=#000000]f87203f5  [/color][color=#0A246A]mov     dword ptr [[/color][color=#FF8000]ebp[/color][color=#0A246A]-[/color][color=#800080]10h[/color][color=#0A246A]],[/color][color=#FF8000]ecx   [/color][color=#008000]; [ebp-10] = pContext,即 xpointers->ContextRecord = pContext
[/color][color=#0A246A]:                   [/color][color=#000000]f87203f8  [/color][color=#0A246A]cmp     [/color][color=#FF8000]ebx[/color][color=#0A246A],[/color][color=#800080]0FFFFFFFEh            [/color][color=#008000]; cmp pExceptionRegistration->trylevel, TRYLEVEL_INVALID
[/color][color=#0A246A]: <                 [/color][color=#000000]f87203fb  [/color][color=#0A246A]je      [/color][color=#000000]PassThrough!_except_handler4[/color][color=#0A246A]+[/color][color=#800080]0xcc [/color][color=#0A246A]([/color][color=#000000]f872045c[/color][color=#0A246A])
: :               
: :               [/color][color=#000000]PassThrough!_except_handler4[/color][color=#0A246A]+[/color][color=#800080]0x6d [/color][color=#0A246A][[/color][color=#000000]d[/color][color=#0A246A]:[/color][color=#000000]\[/color][color=#800080]5359[/color][color=#000000]\minkernel\crts\crtw32\misc\i386\chandler4.c @ [/color][color=#800080]341[/color][color=#0A246A]]:
: :                 [/color][color=#000000]f87203fd  [/color][color=#0A246A]lea     [/color][color=#FF8000]ecx[/color][color=#0A246A],[[/color][color=#FF8000]ecx[/color][color=#0A246A]]
: :               
: :               [/color][color=#000000]PassThrough!_except_handler4[/color][color=#0A246A]+[/color][color=#800080]0x70 [/color][color=#0A246A][[/color][color=#000000]d[/color][color=#0A246A]:[/color][color=#000000]\[/color][color=#800080]5359[/color][color=#000000]\minkernel\crts\crtw32\misc\i386\chandler4.c @ [/color][color=#800080]343[/color][color=#0A246A]]:
: :       >         [/color][color=#000000]f8720400  [/color][color=#0A246A]lea     [/color][color=#FF8000]eax[/color][color=#0A246A],[[/color][color=#FF8000]ebx[/color][color=#0A246A]+[/color][color=#FF8000]ebx[/color][color=#0A246A]*[/color][color=#800080]2[/color][color=#0A246A]] [/color][color=#008000]; 这里 *3,下面紧接着 *4,即 *12,实际上是为了跳过 x 个 scopetable_entry (大小为12个字节)
[/color][color=#0A246A]: :       :         [/color][color=#000000]f8720403  [/color][color=#0A246A]mov     [/color][color=#FF8000]ecx[/color][color=#0A246A],dword ptr [[/color][color=#FF8000]esi[/color][color=#0A246A]+[/color][color=#FF8000]eax[/color][color=#0A246A]*[/color][color=#800080]4[/color][color=#0A246A]+[/color][color=#800080]14h[/color][color=#0A246A]] [/color][color=#008000]; ecx = scopetable[i].lpfnFilter, 这里14h是为了跳过10h大小的坑
[/color][color=#0A246A]: :       :         [/color][color=#000000]f8720407  [/color][color=#0A246A]lea     [/color][color=#FF8000]eax[/color][color=#0A246A],[[/color][color=#FF8000]esi[/color][color=#0A246A]+[/color][color=#FF8000]eax[/color][color=#0A246A]*[/color][color=#800080]4[/color][color=#0A246A]+[/color][color=#800080]10h[/color][color=#0A246A]] [/color][color=#008000]; eax = &scopetable[i]
[/color][color=#0A246A]: :       :         [/color][color=#000000]f872040b  [/color][color=#0A246A]mov     dword ptr [[/color][color=#FF8000]ebp[/color][color=#0A246A]-[/color][color=#800080]0Ch[/color][color=#0A246A]],[/color][color=#FF8000]eax [/color][color=#008000]; ebp-0Ch 存放的是 pCurrentScopeTableEntry
[/color][color=#0A246A]: :       :         [/color][color=#000000]f872040e  [/color][color=#0A246A]mov     [/color][color=#FF8000]eax[/color][color=#0A246A],dword ptr [[/color][color=#FF8000]eax[/color][color=#0A246A]] [/color][color=#008000]; eax = scopetable[i].previousTryLevel
[/color][color=#0A246A]: :       :         [/color][color=#000000]f8720410  [/color][color=#0A246A]mov     dword ptr [[/color][color=#FF8000]ebp[/color][color=#0A246A]+[/color][color=#800080]8[/color][color=#0A246A]],[/color][color=#FF8000]eax [/color][color=#008000]; 这里是将 ebp+8 当作局部变量使用, [ebp+8] = scopetable[i].previousTryLevel
[/color][color=#0A246A]: :       :         [/color][color=#000000]f8720413  [/color][color=#0A246A]test    [/color][color=#FF8000]ecx[/color][color=#0A246A],[/color][color=#FF8000]ecx [/color][color=#008000]; 判断 scopetable[i].lpfnFilter 是否为 NULL
[/color][color=#0A246A]: : <     :         [/color][color=#000000]f8720415  [/color][color=#0A246A]je      [/color][color=#000000]PassThrough!_except_handler4[/color][color=#0A246A]+[/color][color=#800080]0x9b [/color][color=#0A246A]([/color][color=#000000]f872042b[/color][color=#0A246A])
: : :     :       
: : :     :       [/color][color=#000000]PassThrough!_except_handler4[/color][color=#0A246A]+[/color][color=#800080]0x87 [/color][color=#0A246A][[/color][color=#000000]d[/color][color=#0A246A]:[/color][color=#000000]\[/color][color=#800080]5359[/color][color=#000000]\minkernel\crts\crtw32\misc\i386\chandler4.c @ [/color][color=#800080]355[/color][color=#0A246A]]:
: : :     :         [/color][color=#008000]; scopetable[i].lpfnFilter 不为 NULL,调用它
[/color][color=#0A246A]: : :     :         [/color][color=#000000]f8720417  [/color][color=#0A246A]mov     [/color][color=#FF8000]edx[/color][color=#0A246A],[/color][color=#FF8000]edi [/color][color=#008000]; edx = pExceptionRegistration->_ebp
[/color][color=#0A246A]: : :     :         [/color][color=#000000]f8720419  [/color][color=#0A246A]call    [/color][color=#000000]PassThrough!_EH4_CallFilterFunc [/color][color=#0A246A]([/color][color=#000000]f87205d1[/color][color=#0A246A])
: : :     :         [/color][color=#000000]f872041e  [/color][color=#0A246A]mov     byte ptr [[/color][color=#FF8000]ebp[/color][color=#0A246A]-[/color][color=#800080]1[/color][color=#0A246A]],[/color][color=#800080]1 [/color][color=#008000]; [ebp-1] 表示是否执行过 lpfnFilter,它是个 BOOLEAN 值
[/color][color=#0A246A]: : :     :         [/color][color=#000000]f8720422  [/color][color=#0A246A]test    [/color][color=#FF8000]eax[/color][color=#0A246A],[/color][color=#FF8000]eax
[/color][color=#0A246A]: : : <   :         [/color][color=#000000]f8720424  [/color][color=#0A246A]jl      [/color][color=#000000]PassThrough!_except_handler4[/color][color=#0A246A]+[/color][color=#800080]0xd6 [/color][color=#0A246A]([/color][color=#000000]f8720466[/color][color=#0A246A]) [/color][color=#008000]; 如果是 EXCEPTION_CONTINUE_EXECUTION (-1) 就跳
[/color][color=#0A246A]: : : :   :       
: : : :   :       [/color][color=#000000]PassThrough!_except_handler4[/color][color=#0A246A]+[/color][color=#800080]0x96 [/color][color=#0A246A][[/color][color=#000000]d[/color][color=#0A246A]:[/color][color=#000000]\[/color][color=#800080]5359[/color][color=#000000]\minkernel\crts\crtw32\misc\i386\chandler4.c @ [/color][color=#800080]370[/color][color=#0A246A]]:
: : : : < :         [/color][color=#000000]f8720426  [/color][color=#0A246A]jg      [/color][color=#000000]PassThrough!_except_handler4[/color][color=#0A246A]+[/color][color=#800080]0xdf [/color][color=#0A246A]([/color][color=#000000]f872046f[/color][color=#0A246A]) [/color][color=#008000]; 如果是 EXCEPTION_EXECUTE_HANDLER (1) 就跳
[/color][color=#0A246A]: : : : : :       
: : : : : :       [/color][color=#000000]PassThrough!_except_handler4[/color][color=#0A246A]+[/color][color=#800080]0x98 [/color][color=#0A246A][[/color][color=#000000]d[/color][color=#0A246A]:[/color][color=#000000]\[/color][color=#800080]5359[/color][color=#000000]\minkernel\crts\crtw32\misc\i386\chandler4.c @ [/color][color=#800080]370[/color][color=#0A246A]]:
: : : : : :         [/color][color=#008000]; lpfnFilter 返回 EXCEPTION_CONTINUE_SEARCH
[/color][color=#0A246A]: : : : : :         [/color][color=#000000]f8720428  [/color][color=#0A246A]mov     [/color][color=#FF8000]eax[/color][color=#0A246A],dword ptr [[/color][color=#FF8000]ebp[/color][color=#0A246A]+[/color][color=#800080]8[/color][color=#0A246A]] [/color][color=#008000]; eax = scopetable[i].previousTryLevel 
[/color][color=#0A246A]: : : : : :       
: : : : : :       [/color][color=#000000]PassThrough!_except_handler4[/color][color=#0A246A]+[/color][color=#800080]0x9b [/color][color=#0A246A][[/color][color=#000000]d[/color][color=#0A246A]:[/color][color=#000000]\[/color][color=#800080]5359[/color][color=#000000]\minkernel\crts\crtw32\misc\i386\chandler4.c @ [/color][color=#800080]341[/color][color=#0A246A]]:
: : > : : :         [/color][color=#000000]f872042b  [/color][color=#0A246A]mov     [/color][color=#FF8000]ebx[/color][color=#0A246A],[/color][color=#FF8000]eax
[/color][color=#0A246A]: :   : : :         [/color][color=#000000]f872042d  [/color][color=#0A246A]cmp     [/color][color=#FF8000]eax[/color][color=#0A246A],[/color][color=#800080]0FFFFFFFEh [/color][color=#008000]; cmp scopetable[i].previousTryLevel, TRYLEVEL_INVALID
[/color][color=#0A246A]: :   : : <         [/color][color=#000000]f8720430  [/color][color=#0A246A]jne     [/color][color=#000000]PassThrough!_except_handler4[/color][color=#0A246A]+[/color][color=#800080]0x70 [/color][color=#0A246A]([/color][color=#000000]f8720400[/color][color=#0A246A])
: :   : :         
: :   : :         [/color][color=#000000]PassThrough!_except_handler4[/color][color=#0A246A]+[/color][color=#800080]0xa2 [/color][color=#0A246A][[/color][color=#000000]d[/color][color=#0A246A]:[/color][color=#000000]\[/color][color=#800080]5359[/color][color=#000000]\minkernel\crts\crtw32\misc\i386\chandler4.c @ [/color][color=#800080]478[/color][color=#0A246A]]:
: :   : :           [/color][color=#000000]f8720432  [/color][color=#0A246A]cmp     byte ptr [[/color][color=#FF8000]ebp[/color][color=#0A246A]-[/color][color=#800080]1[/color][color=#0A246A]],[/color][color=#800080]0 [/color][color=#008000]; 没有执行过 lpfnFilter,无需进行安全检查
[/color][color=#0A246A]: : < : :           [/color][color=#000000]f8720436  [/color][color=#0A246A]je      [/color][color=#000000]PassThrough!_except_handler4[/color][color=#0A246A]+[/color][color=#800080]0xcc [/color][color=#0A246A]([/color][color=#000000]f872045c[/color][color=#0A246A])
: : : : :         
: : : : :         [/color][color=#000000]PassThrough!_except_handler4[/color][color=#0A246A]+[/color][color=#800080]0xa8 [/color][color=#0A246A][[/color][color=#000000]d[/color][color=#0A246A]:[/color][color=#000000]\[/color][color=#800080]5359[/color][color=#000000]\minkernel\crts\crtw32\misc\i386\chandler4.c @ [/color][color=#800080]486[/color][color=#0A246A]]:
: : : : :           [/color][color=#008000]; 执行过 lpfnFilter,需要校验完整性
[/color][color=#0A246A]: : : : :   >   >   [/color][color=#000000]f8720438  [/color][color=#0A246A]mov     [/color][color=#FF8000]eax[/color][color=#0A246A],dword ptr [[/color][color=#FF8000]esi[/color][color=#0A246A]] 
: : : : :   :   :   [/color][color=#000000]f872043a  [/color][color=#0A246A]cmp     [/color][color=#FF8000]eax[/color][color=#0A246A],[/color][color=#800080]0FFFFFFFEh [/color][color=#008000]; 根据 scopetable 坑的第一个 DWORD 值判断是否需要做进一步的安全检查
[/color][color=#0A246A]: : : : : < :   :   [/color][color=#000000]f872043d  [/color][color=#0A246A]je      [/color][color=#000000]PassThrough!_except_handler4[/color][color=#0A246A]+[/color][color=#800080]0xbc [/color][color=#0A246A]([/color][color=#000000]f872044c[/color][color=#0A246A])
: : : : : : :   : 
: : : : : : :   : [/color][color=#000000]PassThrough!_except_handler4[/color][color=#0A246A]+[/color][color=#800080]0xaf [/color][color=#0A246A][[/color][color=#000000]d[/color][color=#0A246A]:[/color][color=#000000]\[/color][color=#800080]5359[/color][color=#000000]\minkernel\crts\crtw32\misc\i386\chandler4.c @ [/color][color=#800080]486[/color][color=#0A246A]]:
: : : : : : :   :   [/color][color=#008000]; 校验 scopetable 完整性(1)
[/color][color=#0A246A]: : : : : : :   :   [/color][color=#000000]f872043f  [/color][color=#0A246A]mov     [/color][color=#FF8000]ecx[/color][color=#0A246A],dword ptr [[/color][color=#FF8000]esi[/color][color=#0A246A]+[/color][color=#800080]4[/color][color=#0A246A]]
: : : : : : :   :   [/color][color=#000000]f8720442  [/color][color=#0A246A]add     [/color][color=#FF8000]ecx[/color][color=#0A246A],[/color][color=#FF8000]edi
[/color][color=#0A246A]: : : : : : :   :   [/color][color=#000000]f8720444  [/color][color=#0A246A]xor     [/color][color=#FF8000]ecx[/color][color=#0A246A],dword ptr [[/color][color=#FF8000]eax[/color][color=#0A246A]+[/color][color=#FF8000]edi[/color][color=#0A246A]]
: : : : : : :   :   [/color][color=#000000]f8720447  [/color][color=#0A246A]call    [/color][color=#000000]PassThrough!__security_check_cookie [/color][color=#0A246A]([/color][color=#000000]f8720638[/color][color=#0A246A])
: : : : : : :   : 
: : : : : : :   : [/color][color=#000000]PassThrough!_except_handler4[/color][color=#0A246A]+[/color][color=#800080]0xbc [/color][color=#0A246A][[/color][color=#000000]d[/color][color=#0A246A]:[/color][color=#000000]\[/color][color=#800080]5359[/color][color=#000000]\minkernel\crts\crtw32\misc\i386\chandler4.c @ [/color][color=#800080]486[/color][color=#0A246A]]:
: : : : : : :   :   [/color][color=#008000]; 校验 scopetable 完整性(2)
[/color][color=#0A246A]: : : : : > :   :   [/color][color=#000000]f872044c  [/color][color=#0A246A]mov     [/color][color=#FF8000]ecx[/color][color=#0A246A],dword ptr [[/color][color=#FF8000]esi[/color][color=#0A246A]+[/color][color=#800080]0Ch[/color][color=#0A246A]]
: : : : :   :   :   [/color][color=#000000]f872044f  [/color][color=#0A246A]mov     [/color][color=#FF8000]edx[/color][color=#0A246A],dword ptr [[/color][color=#FF8000]esi[/color][color=#0A246A]+[/color][color=#800080]8[/color][color=#0A246A]]
: : : : :   :   :   [/color][color=#000000]f8720452  [/color][color=#0A246A]add     [/color][color=#FF8000]ecx[/color][color=#0A246A],[/color][color=#FF8000]edi
[/color][color=#0A246A]: : : : :   :   :   [/color][color=#000000]f8720454  [/color][color=#0A246A]xor     [/color][color=#FF8000]ecx[/color][color=#0A246A],dword ptr [[/color][color=#FF8000]edx[/color][color=#0A246A]+[/color][color=#FF8000]edi[/color][color=#0A246A]] [/color][color=#008000]; 正常情况下 [edx+edi] 保存的是 __security_cookie 的值
[/color][color=#0A246A]: : : : :   :   :   [/color][color=#000000]f8720457  [/color][color=#0A246A]call    [/color][color=#000000]PassThrough!__security_check_cookie [/color][color=#0A246A]([/color][color=#000000]f8720638[/color][color=#0A246A])
: : : : :   :   : 
: : : : :   :   : [/color][color=#000000]PassThrough!_except_handler4[/color][color=#0A246A]+[/color][color=#800080]0xcc [/color][color=#0A246A][[/color][color=#000000]d[/color][color=#0A246A]:[/color][color=#000000]\[/color][color=#800080]5359[/color][color=#000000]\minkernel\crts\crtw32\misc\i386\chandler4.c @ [/color][color=#800080]495[/color][color=#0A246A]]:
: > > : :   : > :   [/color][color=#000000]f872045c  [/color][color=#0A246A]mov     [/color][color=#FF8000]eax[/color][color=#0A246A],dword ptr [[/color][color=#FF8000]ebp[/color][color=#0A246A]-[/color][color=#800080]8[/color][color=#0A246A]]
:     : :   : : :   [/color][color=#000000]f872045f  [/color][color=#0A246A]pop     [/color][color=#FF8000]edi
[/color][color=#0A246A]:     : :   : : :   [/color][color=#000000]f8720460  [/color][color=#0A246A]pop     [/color][color=#FF8000]esi
[/color][color=#0A246A]:     : :   : : :   [/color][color=#000000]f8720461  [/color][color=#0A246A]pop     [/color][color=#FF8000]ebx
[/color][color=#0A246A]:     : :   : : :   [/color][color=#000000]f8720462  [/color][color=#0A246A]mov     [/color][color=#FF8000]esp[/color][color=#0A246A],[/color][color=#FF8000]ebp
[/color][color=#0A246A]:     : :   : : :   [/color][color=#000000]f8720464  [/color][color=#0A246A]pop     [/color][color=#FF8000]ebp
[/color][color=#0A246A]:     : :   : : :   [/color][color=#000000]f8720465  [/color][color=#0A246A]ret
:     : :   : : : 
:     : :   : : : [/color][color=#000000]PassThrough!_except_handler4[/color][color=#0A246A]+[/color][color=#800080]0xd6 [/color][color=#0A246A][[/color][color=#000000]d[/color][color=#0A246A]:[/color][color=#000000]\[/color][color=#800080]5359[/color][color=#000000]\minkernel\crts\crtw32\misc\i386\chandler4.c @ [/color][color=#800080]367[/color][color=#0A246A]]:
:     : :   : : :   [/color][color=#008000]; lpfnFilter 返回 EXCEPTION_CONTINUE_EXECUTION
[/color][color=#0A246A]:     > :   : : :   [/color][color=#000000]f8720466  [/color][color=#0A246A]mov     dword ptr [[/color][color=#FF8000]ebp[/color][color=#0A246A]-[/color][color=#800080]8[/color][color=#0A246A]],[/color][color=#800080]0 [/color][color=#008000]; [ebp-8] = ExceptionContinueExecution (0)
[/color][color=#0A246A]:       :   < : :   [/color][color=#000000]f872046d  [/color][color=#0A246A]jmp     [/color][color=#000000]PassThrough!_except_handler4[/color][color=#0A246A]+[/color][color=#800080]0xa8 [/color][color=#0A246A]([/color][color=#000000]f8720438[/color][color=#0A246A])
:       :     : : 
:       :     : : [/color][color=#000000]PassThrough!_except_handler4[/color][color=#0A246A]+[/color][color=#800080]0xdf [/color][color=#0A246A][[/color][color=#000000]d[/color][color=#0A246A]:[/color][color=#000000]\[/color][color=#800080]5359[/color][color=#000000]\minkernel\crts\crtw32\misc\i386\chandler4.c @ [/color][color=#800080]396[/color][color=#0A246A]]:
:       :     : :   [/color][color=#008000]; lpfnFilter 返回 EXCEPTION_EXECUTE_HANDLER
[/color][color=#0A246A]:       >     : :   [/color][color=#000000]f872046f  [/color][color=#0A246A]mov     [/color][color=#FF8000]ecx[/color][color=#0A246A],dword ptr [[/color][color=#FF8000]ebp[/color][color=#0A246A]+[/color][color=#800080]0Ch[/color][color=#0A246A]] [/color][color=#008000]; ecx = pExceptionRegistration
[/color][color=#0A246A]:             : :   [/color][color=#000000]f8720472  [/color][color=#0A246A]call    [/color][color=#000000]PassThrough!_EH4_GlobalUnwind [/color][color=#0A246A]([/color][color=#000000]f87205fa[/color][color=#0A246A])
:             : :   [/color][color=#000000]f8720477  [/color][color=#0A246A]mov     [/color][color=#FF8000]eax[/color][color=#0A246A],dword ptr [[/color][color=#FF8000]ebp[/color][color=#0A246A]+[/color][color=#800080]0Ch[/color][color=#0A246A]] [/color][color=#008000]; eax = pExceptionRegistration
[/color][color=#0A246A]:             : :   [/color][color=#000000]f872047a  [/color][color=#0A246A]cmp     dword ptr [[/color][color=#FF8000]eax[/color][color=#0A246A]+[/color][color=#800080]0Ch[/color][color=#0A246A]],[/color][color=#FF8000]ebx [/color][color=#008000]; cmp pExceptionRegistration->trylevel
[/color][color=#0A246A]: <           : :   [/color][color=#000000]f872047d  [/color][color=#0A246A]je      [/color][color=#000000]PassThrough!_except_handler4[/color][color=#0A246A]+[/color][color=#800080]0x101 [/color][color=#0A246A]([/color][color=#000000]f8720491[/color][color=#0A246A])
: :           : : 
: :           : : [/color][color=#000000]PassThrough!_except_handler4[/color][color=#0A246A]+[/color][color=#800080]0xef [/color][color=#0A246A][[/color][color=#000000]d[/color][color=#0A246A]:[/color][color=#000000]\[/color][color=#800080]5359[/color][color=#000000]\minkernel\crts\crtw32\misc\i386\chandler4.c @ [/color][color=#800080]408[/color][color=#0A246A]]:
: :           : :   [/color][color=#000000]f872047f  [/color][color=#0A246A]push    offset [/color][color=#000000]PassThrough!__security_cookie [/color][color=#0A246A]([/color][color=#000000]f87220b0[/color][color=#0A246A])
: :           : :   [/color][color=#000000]f8720484  [/color][color=#0A246A]push    [/color][color=#FF8000]edi
[/color][color=#0A246A]: :           : :   [/color][color=#000000]f8720485  [/color][color=#0A246A]mov     [/color][color=#FF8000]edx[/color][color=#0A246A],[/color][color=#FF8000]ebx
[/color][color=#0A246A]: :           : :   [/color][color=#000000]f8720487  [/color][color=#0A246A]mov     [/color][color=#FF8000]ecx[/color][color=#0A246A],[/color][color=#FF8000]eax [/color][color=#008000]; ecx = pExceptionRegistration
[/color][color=#0A246A]: :           : :   [/color][color=#000000]f8720489  [/color][color=#0A246A]call    [/color][color=#000000]PassThrough!_EH4_LocalUnwind [/color][color=#0A246A]([/color][color=#000000]f8720614[/color][color=#0A246A])
: :           : :   [/color][color=#000000]f872048e  [/color][color=#0A246A]mov     [/color][color=#FF8000]eax[/color][color=#0A246A],dword ptr [[/color][color=#FF8000]ebp[/color][color=#0A246A]+[/color][color=#800080]0Ch[/color][color=#0A246A]]
: :           : : 
: :           : : [/color][color=#000000]PassThrough!_except_handler4[/color][color=#0A246A]+[/color][color=#800080]0x101 [/color][color=#0A246A][[/color][color=#000000]d[/color][color=#0A246A]:[/color][color=#000000]\[/color][color=#800080]5359[/color][color=#000000]\minkernel\crts\crtw32\misc\i386\chandler4.c @ [/color][color=#800080]417[/color][color=#0A246A]]:
: >           : :   [/color][color=#000000]f8720491  [/color][color=#0A246A]mov     [/color][color=#FF8000]ecx[/color][color=#0A246A],dword ptr [[/color][color=#FF8000]ebp[/color][color=#0A246A]+[/color][color=#800080]8[/color][color=#0A246A]]   [/color][color=#008000]; ecx = scopetable[i].previousTryLevel 
[/color][color=#0A246A]:             : :   [/color][color=#000000]f8720494  [/color][color=#0A246A]mov     dword ptr [[/color][color=#FF8000]eax[/color][color=#0A246A]+[/color][color=#800080]0Ch[/color][color=#0A246A]],[/color][color=#FF8000]ecx [/color][color=#008000]; pExceptionRegistration->trylevel = scopetable[i].previousTryLevel 
[/color][color=#0A246A]:             : :   [/color][color=#000000]f8720497  [/color][color=#0A246A]mov     [/color][color=#FF8000]eax[/color][color=#0A246A],dword ptr [[/color][color=#FF8000]esi[/color][color=#0A246A]]
:             : :   [/color][color=#000000]f8720499  [/color][color=#0A246A]cmp     [/color][color=#FF8000]eax[/color][color=#0A246A],[/color][color=#800080]0FFFFFFFEh
[/color][color=#0A246A]: <           : :   [/color][color=#000000]f872049c  [/color][color=#0A246A]je      [/color][color=#000000]PassThrough!_except_handler4[/color][color=#0A246A]+[/color][color=#800080]0x11b [/color][color=#0A246A]([/color][color=#000000]f87204ab[/color][color=#0A246A])
: :           : : 
: :           : : [/color][color=#000000]PassThrough!_except_handler4[/color][color=#0A246A]+[/color][color=#800080]0x10e [/color][color=#0A246A][[/color][color=#000000]d[/color][color=#0A246A]:[/color][color=#000000]\[/color][color=#800080]5359[/color][color=#000000]\minkernel\crts\crtw32\misc\i386\chandler4.c @ [/color][color=#800080]431[/color][color=#0A246A]]:
: :           : :   [/color][color=#008000]; 校验 scopetable 完整性(1)
[/color][color=#0A246A]: :           : :   [/color][color=#000000]f872049e  [/color][color=#0A246A]mov     [/color][color=#FF8000]ecx[/color][color=#0A246A],dword ptr [[/color][color=#FF8000]esi[/color][color=#0A246A]+[/color][color=#800080]4[/color][color=#0A246A]]
: :           : :   [/color][color=#000000]f87204a1  [/color][color=#0A246A]add     [/color][color=#FF8000]ecx[/color][color=#0A246A],[/color][color=#FF8000]edi
[/color][color=#0A246A]: :           : :   [/color][color=#000000]f87204a3  [/color][color=#0A246A]xor     [/color][color=#FF8000]ecx[/color][color=#0A246A],dword ptr [[/color][color=#FF8000]eax[/color][color=#0A246A]+[/color][color=#FF8000]edi[/color][color=#0A246A]]
: :           : :   [/color][color=#000000]f87204a6  [/color][color=#0A246A]call    [/color][color=#000000]PassThrough!__security_check_cookie [/color][color=#0A246A]([/color][color=#000000]f8720638[/color][color=#0A246A])
: :           : : 
: :           : : [/color][color=#000000]PassThrough!_except_handler4[/color][color=#0A246A]+[/color][color=#800080]0x11b [/color][color=#0A246A][[/color][color=#000000]d[/color][color=#0A246A]:[/color][color=#000000]\[/color][color=#800080]5359[/color][color=#000000]\minkernel\crts\crtw32\misc\i386\chandler4.c @ [/color][color=#800080]431[/color][color=#0A246A]]:
: :           : :   [/color][color=#008000]; 校验 scopetable 完整性(2)
[/color][color=#0A246A]: >           : :   [/color][color=#000000]f87204ab  [/color][color=#0A246A]mov     [/color][color=#FF8000]ecx[/color][color=#0A246A],dword ptr [[/color][color=#FF8000]esi[/color][color=#0A246A]+[/color][color=#800080]0Ch[/color][color=#0A246A]]
:             : :   [/color][color=#000000]f87204ae  [/color][color=#0A246A]mov     [/color][color=#FF8000]edx[/color][color=#0A246A],dword ptr [[/color][color=#FF8000]esi[/color][color=#0A246A]+[/color][color=#800080]8[/color][color=#0A246A]]
:             : :   [/color][color=#000000]f87204b1  [/color][color=#0A246A]add     [/color][color=#FF8000]ecx[/color][color=#0A246A],[/color][color=#FF8000]edi
[/color][color=#0A246A]:             : :   [/color][color=#000000]f87204b3  [/color][color=#0A246A]xor     [/color][color=#FF8000]ecx[/color][color=#0A246A],dword ptr [[/color][color=#FF8000]edx[/color][color=#0A246A]+[/color][color=#FF8000]edi[/color][color=#0A246A]]
:             : :   [/color][color=#000000]f87204b6  [/color][color=#0A246A]call    [/color][color=#000000]PassThrough!__security_check_cookie [/color][color=#0A246A]([/color][color=#000000]f8720638[/color][color=#0A246A])
:             : :   [/color][color=#008000]; 调用 lpfnHandler
[/color][color=#0A246A]:             : :   [/color][color=#000000]f87204bb  [/color][color=#0A246A]mov     [/color][color=#FF8000]eax[/color][color=#0A246A],dword ptr [[/color][color=#FF8000]ebp[/color][color=#0A246A]-[/color][color=#800080]0Ch[/color][color=#0A246A]] [/color][color=#008000]; eax = l_pCurrentScopeTableEntry
[/color][color=#0A246A]:             : :   [/color][color=#000000]f87204be  [/color][color=#0A246A]mov     [/color][color=#FF8000]ecx[/color][color=#0A246A],dword ptr [[/color][color=#FF8000]eax[/color][color=#0A246A]+[/color][color=#800080]8[/color][color=#0A246A]]   [/color][color=#008000]; ecx = l_pCurrentScopeTableEntry->lpfnHandler
[/color][color=#0A246A]:             : :   [/color][color=#000000]f87204c1  [/color][color=#0A246A]mov     [/color][color=#FF8000]edx[/color][color=#0A246A],[/color][color=#FF8000]edi                 [/color][color=#008000]; edx = pExceptionRegistration->_ebp
[/color][color=#0A246A]:             : :   [/color][color=#000000]f87204c3  [/color][color=#0A246A]call    [/color][color=#000000]PassThrough!_EH4_TransferToHandler [/color][color=#0A246A]([/color][color=#000000]f87205e8[/color][color=#0A246A]) [/color][color=#008000]; 这里不会返回!!
[/color][color=#0A246A]:             : : 
:             : : [/color][color=#000000]PassThrough!_except_handler4[/color][color=#0A246A]+[/color][color=#800080]0x138 [/color][color=#0A246A][[/color][color=#000000]d[/color][color=#0A246A]:[/color][color=#000000]\[/color][color=#800080]5359[/color][color=#000000]\minkernel\crts\crtw32\misc\i386\chandler4.c @ [/color][color=#800080]456[/color][color=#0A246A]]:
>             : :   [/color][color=#000000]f87204c8  [/color][color=#0A246A]mov     [/color][color=#FF8000]edx[/color][color=#0A246A],[/color][color=#800080]0FFFFFFFEh
              [/color][color=#0A246A]: :   [/color][color=#000000]f87204cd  [/color][color=#0A246A]cmp     dword ptr [[/color][color=#FF8000]ebx[/color][color=#0A246A]+[/color][color=#800080]0Ch[/color][color=#0A246A]],[/color][color=#FF8000]edx [/color][color=#008000]; cmp pExceptionRegistration->trylevel, TRYLEVEL_INVALID
              [/color][color=#0A246A]< :   [/color][color=#000000]f87204d0  [/color][color=#0A246A]je      [/color][color=#000000]PassThrough!_except_handler4[/color][color=#0A246A]+[/color][color=#800080]0xcc [/color][color=#0A246A]([/color][color=#000000]f872045c[/color][color=#0A246A])
                : 
                : [/color][color=#000000]PassThrough!_except_handler4[/color][color=#0A246A]+[/color][color=#800080]0x142 [/color][color=#0A246A][[/color][color=#000000]d[/color][color=#0A246A]:[/color][color=#000000]\[/color][color=#800080]5359[/color][color=#000000]\minkernel\crts\crtw32\misc\i386\chandler4.c @ [/color][color=#800080]467[/color][color=#0A246A]]:
                :   [/color][color=#008000]; pExceptionRegistration->trylevel 不等于 TRYLEVEL_INVALID,开始局部展开
                [/color][color=#0A246A]:   [/color][color=#000000]f87204d2  [/color][color=#0A246A]push    offset [/color][color=#000000]PassThrough!__security_cookie [/color][color=#0A246A]([/color][color=#000000]f87220b0[/color][color=#0A246A])
                :   [/color][color=#000000]f87204d7  [/color][color=#0A246A]push    [/color][color=#FF8000]edi      [/color][color=#008000]; pExceptionRegistration->_ebp
                [/color][color=#0A246A]:   [/color][color=#000000]f87204d8  [/color][color=#0A246A]mov     [/color][color=#FF8000]ecx[/color][color=#0A246A],[/color][color=#FF8000]ebx  [/color][color=#008000]; ecx = pExceptionRegistration
                [/color][color=#0A246A]:   [/color][color=#000000]f87204da  [/color][color=#0A246A]call    [/color][color=#000000]PassThrough!_EH4_LocalUnwind [/color][color=#0A246A]([/color][color=#000000]f8720614[/color][color=#0A246A])
                <   [/color][color=#000000]f87204df  [/color][color=#0A246A]jmp     [/color][color=#000000]PassThrough!_except_handler4[/color][color=#0A246A]+[/color][color=#800080]0xa8 [/color][color=#0A246A]([/color][color=#000000]f8720438[/color][color=#0A246A])
[/color][/font]


        这个函数代码不长。主要分为两个大分支,一个分支处理异常,一个分支处理展开(参考地址 f87203dc 处的 test 指令)。
        处理异常的代码负责遍历 scopetable,依次调用 scopetable_entry::lpfnFilter(参考 f8720419 处代码),并针对不同的返回值做出不同的处理:
        1. 返回 EXCEPTION_CONTINUE_EXECUTION,则说明异常已经被刚刚调用的 lpfnFilter 修复。返回 ExceptionContinueExecution。
        2. 返回 EXCEPTION_CONTINUE_SEARCH,则继续遍历下一个 scopetable_entry。
        3. 返回 EXCEPTION_EXECUTE_HANDLER,则说明当前 scopetable_entry::lpfnHandler 负责处理该异常。于是调用它。
        对于展开的代码,则直接开始局部展开,即对 scopetable 进行展开。
        更具体的信息,请参考上面反汇编代码中我附的注释。

        有几个小点需要说一下:
        1. 该函数多处使用 scopetable 中坑内的数据进行安全检查。这些操作对理解该函数流程没有帮助,可以忽略。如果觉得上面代码不纯净,可以参考我后续的附录1《Ntfs!_except_handler3 的反汇编代码》,这个函数流程更清晰简单。
        2. 一旦有某 scopetable_entry::lpfnFilter 返回 EXCEPTION_EXECUTE_HANDLER,就会进行全局展开和局部展开。展开结束后会调用该 scopetable_entry::lpfnHandler,该函数即为 _except 处理域,该函数形式是一个函数,实际上只是一段不返回的代码。即这段代码中没有 ret 指令。执行完整个 _except 处理域后,会接着执行其后的指令,并不会返回 _except_handler4。
        3. 该函数既启动展开,又负责展开,于是会出现类似于“重入”的现象。理解的过程中容易扰乱思路。

        PassThrough!_except_handler4 在执行过程中可能会调用这几个函数:
        PassThrough!_EH4_CallFilterFunc、
        PassThrough!_EH4_TransferToHandler、
        PassThrough!_EH4_GlobalUnwind、
        PassThrough!_EH4_LocalUnwind
        这几个函数名很明白的说明了它们的功能:
        PassThrough!_EH4_CallFilterFunc 负责调用 scopetable_entry::lpfnFilter;
        PassThrough!_EH4_TransferToHandler 负责调用 scopetable_entry::lpfnFilter;
        PassThrough!_EH4_GlobalUnwind 负责全局展开;
        PassThrough!_EH4_LocalUnwind 负责局部展开。

        来看看 _EH4_CallFilterFunc 和 _EH4_TransferToHandler 的反汇编代码,都很短。剩余两个展开相关的函数稍后咱们再来分析。

[font=Consolas][color=#000000]    kd[/color][color=#0A246A]> [/color][color=#000000]uf PassThrough!_EH4_CallFilterFunc
        PassThrough!_EH4_CallFilterFunc [/color][color=#0A246A][[/color][color=#000000]d[/color][color=#0A246A]:[/color][color=#000000]\[/color][color=#800080]5359[/color][color=#000000]\minkernel\crts\crtw32\misc\i386\exsup4.asm @ [/color][color=#800080]408[/color][color=#0A246A]]:
          [/color][color=#000000]f87205d1  [/color][color=#0A246A]push    [/color][color=#FF8000]ebp
          [/color][color=#000000]f87205d2  [/color][color=#0A246A]push    [/color][color=#FF8000]esi
          [/color][color=#000000]f87205d3  [/color][color=#0A246A]push    [/color][color=#FF8000]edi
          [/color][color=#000000]f87205d4  [/color][color=#0A246A]push    [/color][color=#FF8000]ebx
          [/color][color=#000000]f87205d5  [/color][color=#0A246A]mov     [/color][color=#FF8000]ebp[/color][color=#0A246A],[/color][color=#FF8000]edx
          [/color][color=#000000]f87205d7  [/color][color=#0A246A]xor     [/color][color=#FF8000]eax[/color][color=#0A246A],[/color][color=#FF8000]eax
          [/color][color=#000000]f87205d9  [/color][color=#0A246A]xor     [/color][color=#FF8000]ebx[/color][color=#0A246A],[/color][color=#FF8000]ebx
          [/color][color=#000000]f87205db  [/color][color=#0A246A]xor     [/color][color=#FF8000]edx[/color][color=#0A246A],[/color][color=#FF8000]edx
          [/color][color=#000000]f87205dd  [/color][color=#0A246A]xor     [/color][color=#FF8000]esi[/color][color=#0A246A],[/color][color=#FF8000]esi
          [/color][color=#000000]f87205df  [/color][color=#0A246A]xor     [/color][color=#FF8000]edi[/color][color=#0A246A],[/color][color=#FF8000]edi
          [/color][color=#000000]f87205e1  [/color][color=#0A246A]call    [/color][color=#FF8000]ecx [/color][color=#008000]; lpfnFilter();
          [/color][color=#000000]f87205e3  [/color][color=#0A246A]pop     [/color][color=#FF8000]ebx
          [/color][color=#000000]f87205e4  [/color][color=#0A246A]pop     [/color][color=#FF8000]edi
          [/color][color=#000000]f87205e5  [/color][color=#0A246A]pop     [/color][color=#FF8000]esi
          [/color][color=#000000]f87205e6  [/color][color=#0A246A]pop     [/color][color=#FF8000]ebp
          [/color][color=#000000]f87205e7  [/color][color=#0A246A]ret

    [/color][color=#000000]kd[/color][color=#0A246A]> [/color][color=#000000]uf PassThrough!_EH4_TransferToHandler
        PassThrough!_EH4_TransferToHandler [/color][color=#0A246A][[/color][color=#000000]d[/color][color=#0A246A]:[/color][color=#000000]\[/color][color=#800080]5359[/color][color=#000000]\minkernel\crts\crtw32\misc\i386\exsup4.asm @ [/color][color=#800080]450[/color][color=#0A246A]]:
          [/color][color=#000000]f87205e8  [/color][color=#0A246A]mov     [/color][color=#FF8000]ebp[/color][color=#0A246A],[/color][color=#FF8000]edx
          [/color][color=#000000]f87205ea  [/color][color=#0A246A]mov     [/color][color=#FF8000]esi[/color][color=#0A246A],[/color][color=#FF8000]ecx [/color][color=#008000]; esi = lpfnHandler
          [/color][color=#000000]f87205ec  [/color][color=#0A246A]mov     [/color][color=#FF8000]eax[/color][color=#0A246A],[/color][color=#FF8000]ecx
          [/color][color=#000000]f87205ee  [/color][color=#0A246A]xor     [/color][color=#FF8000]eax[/color][color=#0A246A],[/color][color=#FF8000]eax
          [/color][color=#000000]f87205f0  [/color][color=#0A246A]xor     [/color][color=#FF8000]ebx[/color][color=#0A246A],[/color][color=#FF8000]ebx
          [/color][color=#000000]f87205f2  [/color][color=#0A246A]xor     [/color][color=#FF8000]ecx[/color][color=#0A246A],[/color][color=#FF8000]ecx
          [/color][color=#000000]f87205f4  [/color][color=#0A246A]xor     [/color][color=#FF8000]edx[/color][color=#0A246A],[/color][color=#FF8000]edx
          [/color][color=#000000]f87205f6  [/color][color=#0A246A]xor     [/color][color=#FF8000]edi[/color][color=#0A246A],[/color][color=#FF8000]edi
          [/color][color=#000000]f87205f8  [/color][color=#0A246A]jmp     [/color][color=#FF8000]esi     [/color][color=#008000]; jmp lpfnHandler
[/color][/font]


        到这里,咱们就以 PassThrough!_except_handler4 为例分析完了 MSC 提供的 EXCEPTION_REGISTRATION::handler 函数。这个过程中多次接触到一个名为“展开”的概念,这就是咱们要讲的第三个部分。
2011-10-5 12:55
0
雪    币: 342
活跃值: (199)
能力值: ( LV7,RANK:100 )
在线值:
发帖
回帖
粉丝
4
三、展开 (unwind)
        为了说明这个概念,需要先回顾下异常发生后的处理流程。

        我们假设一系列使用 SEH 的函数调用流程:
        func1 -> func2 -> func3。在 func3 执行的过程中触发了异常。

        看看分发异常流程 RtlRaiseException -> RtlDispatchException -> RtlpExecuteHandlerForException
        RtlDispatchException 会遍历异常链表,对每个 EXCEPTION_REGISTRATION 都调用 RtlpExecuteHandlerForException。
        RtlpExecuteHandlerForException 会调用 EXCEPTION_REGISTRATION::handler,也就是 PassThrough!_except_handler4。如咱们上面分析,该函数内部遍历 EXCEPTION_REGISTRATION::scopetable,如果遇到有 scopetable_entry::lpfnFilter 返回 EXCEPTION_EXECUTE_HANDLER,那么 scopetable_entry::lpfnHandler 就会被调用,来处理该异常。
        因为 lpfnHandler 不会返回到 PassThrough!_except_handler4,于是执行完 lpfnHandler 后,就会从 lpfnHandler 之后的代码继续执行下去。也就是说,假设 func3 中触发了一个异常,该异常被 func1 中的 __except 处理块处理了,那 __except 处理块执行完毕后,就从其后的指令继续执行下去,即异常处理完毕后,接着执行的就是 func1 的代码。不会再回到 func2 或者 func3,这样就有个问题,func2 和 func3 中占用的资源怎么办?这些资源比如申请的内存是不会自动释放的,岂不是会有资源泄漏问题?

        这就需要用到“展开”了。
        说白了,所谓“展开”就是进行清理。(注:这里的清理主要包含动态分配的资源的清理,栈空间是由 func1 的“mov esp,ebp” 这类操作顺手清理的。当时我被“谁来清理栈空间”这个问题困扰了很久……)
       
        那这个展开工作由谁来完成呢?由 func1 来完成肯定不合适,毕竟 func2 和 func3 有没有申请资源、申请了哪些资源,func1 无从得知。于是这个展开工作还得要交给 func2 和 func3 自己来完成。

        展开分为两种:“全局展开”和“局部展开”。
        全局展开是指针对异常链表中的某一段,局部展开针对指定 EXCEPTION_REGISTRATION。用上面的例子来讲,局部展开就是针对 func3 或 func2 (某一个函数)内部进行清理,全局展开就是 func2 和 func3 的局部清理的总和。再归纳一下,局部展开是指具体某一函数内部的清理,而全局展开是指,从异常触发点(func3)到异常处理点(func1)之间所有函数(包含异常触发点 func3)的局部清理的总和。

        来看反汇编代码:
[font=Consolas][color=#000000]    kd[/color][color=#0A246A]> [/color][color=#000000]uf PassThrough!_EH4_GlobalUnwind
        PassThrough!_EH4_GlobalUnwind [/color][color=#0A246A][[/color][color=#000000]d[/color][color=#0A246A]:[/color][color=#000000]\[/color][color=#800080]5359[/color][color=#000000]\minkernel\crts\crtw32\misc\i386\exsup4.asm @ [/color][color=#800080]485[/color][color=#0A246A]]:
          [/color][color=#000000]f87205fa   [/color][color=#0A246A]push    [/color][color=#FF8000]ebp
          [/color][color=#000000]f87205fb   [/color][color=#0A246A]mov     [/color][color=#FF8000]ebp[/color][color=#0A246A],[/color][color=#FF8000]esp
          [/color][color=#000000]f87205fd   [/color][color=#0A246A]push    [/color][color=#FF8000]ebx
          [/color][color=#000000]f87205fe   [/color][color=#0A246A]push    [/color][color=#FF8000]esi
          [/color][color=#000000]f87205ff   [/color][color=#0A246A]push    [/color][color=#FF8000]edi
          [/color][color=#000000]f8720600   [/color][color=#0A246A]push    [/color][color=#800080]0   [/color][color=#008000]; pReturnValue
          [/color][color=#000000]f8720602   [/color][color=#0A246A]push    [/color][color=#800080]0   [/color][color=#008000]; pExceptionRecord
          [/color][color=#000000]f8720604   [/color][color=#0A246A]push    offset [/color][color=#000000]PassThrough!_EH4_GlobalUnwind[/color][color=#0A246A]+[/color][color=#800080]0x15 [/color][color=#0A246A]([/color][color=#000000]f872060f[/color][color=#0A246A]) [/color][color=#008000]; pReturnEip
          [/color][color=#000000]f8720609   [/color][color=#0A246A]push    [/color][color=#FF8000]ecx [/color][color=#008000]; pExceptionRegistration
          [/color][color=#000000]f872060a   [/color][color=#0A246A]call    [/color][color=#000000]PassThrough!RtlUnwind [/color][color=#0A246A]([/color][color=#000000]f8720678[/color][color=#0A246A])
          [/color][color=#000000]f872060f   [/color][color=#0A246A]pop     [/color][color=#FF8000]edi
          [/color][color=#000000]f8720610   [/color][color=#0A246A]pop     [/color][color=#FF8000]esi
          [/color][color=#000000]f8720611   [/color][color=#0A246A]pop     [/color][color=#FF8000]ebx
          [/color][color=#000000]f8720612   [/color][color=#0A246A]pop     [/color][color=#FF8000]ebp
          [/color][color=#000000]f8720613   [/color][color=#0A246A]ret
[/color][/font]


        RtlUnwind 的原型:
        VOID RtlUnwind(
            PEXCEPTION_REGISTRATION pExceptionRegistration
            PVOID pReturnEip
            PEXCEPTION_RECORD pExceptionRecord,
            PVOID pReturnValue
        );

[font=Consolas][color=#000000]    kd[/color][color=#0A246A]> [/color][color=#000000]uf PassThrough!RtlUnwind [/color][color=#008000]; 提示:此函数 wrk 提供了实现源码
                  [/color][color=#000000]nt!RtlUnwind [/color][color=#0A246A][c:[/color][color=#000000]\wrk\wrk[/color][color=#0A246A]-[/color][color=#000000]v1.2\base\ntos\rtl\i386\exdsptch.c @ [/color][color=#800080]423[/color][color=#0A246A]]:
                    [/color][color=#800080]80867358  [/color][color=#0A246A]push    [/color][color=#FF8000]ebp
                    [/color][color=#800080]80867359  [/color][color=#0A246A]mov     [/color][color=#FF8000]ebp[/color][color=#0A246A],[/color][color=#FF8000]esp
                    [/color][color=#800080]8086735b  [/color][color=#0A246A]sub     [/color][color=#FF8000]esp[/color][color=#0A246A],[/color][color=#800080]37Ch
                    80867361  [/color][color=#0A246A]mov     [/color][color=#FF8000]eax[/color][color=#0A246A],dword ptr [[/color][color=#000000]nt!__security_cookie [/color][color=#0A246A]([/color][color=#800080]80895388[/color][color=#0A246A])]
                    [/color][color=#800080]80867366  [/color][color=#0A246A]push    [/color][color=#FF8000]esi
                    [/color][color=#800080]80867367  [/color][color=#0A246A]mov     [/color][color=#FF8000]esi[/color][color=#0A246A],dword ptr [[/color][color=#FF8000]ebp[/color][color=#0A246A]+[/color][color=#800080]10h[/color][color=#0A246A]] [/color][color=#008000]; esi = pExceptionRecord
                    [/color][color=#800080]8086736a  [/color][color=#0A246A]mov     dword ptr [[/color][color=#FF8000]ebp[/color][color=#0A246A]-[/color][color=#800080]4[/color][color=#0A246A]],[/color][color=#FF8000]eax
                    [/color][color=#800080]8086736d  [/color][color=#0A246A]push    [/color][color=#FF8000]edi
                    [/color][color=#800080]8086736e  [/color][color=#0A246A]lea     [/color][color=#FF8000]eax[/color][color=#0A246A],[[/color][color=#FF8000]ebp[/color][color=#0A246A]-[/color][color=#800080]2D8h[/color][color=#0A246A]] [/color][color=#008000]; [ebp-2D8h] = l_pHighLimit
                    [/color][color=#800080]80867374  [/color][color=#0A246A]push    [/color][color=#FF8000]eax
                    [/color][color=#800080]80867375  [/color][color=#0A246A]lea     [/color][color=#FF8000]eax[/color][color=#0A246A],[[/color][color=#FF8000]ebp[/color][color=#0A246A]-[/color][color=#800080]2D4h[/color][color=#0A246A]] [/color][color=#008000]; [ebp-2D4h] = l_pLowLimit
                    [/color][color=#800080]8086737b  [/color][color=#0A246A]push    [/color][color=#FF8000]eax
                    [/color][color=#800080]8086737c  [/color][color=#0A246A]call    [/color][color=#000000]nt!RtlpGetStackLimits [/color][color=#0A246A]([/color][color=#800080]80887cdc[/color][color=#0A246A])
                    [/color][color=#800080]80867381  [/color][color=#0A246A]xor     [/color][color=#FF8000]edi[/color][color=#0A246A],[/color][color=#FF8000]edi
                    [/color][color=#800080]80867383  [/color][color=#0A246A]cmp     [/color][color=#FF8000]esi[/color][color=#0A246A],[/color][color=#FF8000]edi [/color][color=#008000]; pExceptionRecord 是否为 NULL
[/color][color=#0A246A]<                   [/color][color=#800080]80867385  [/color][color=#0A246A]jne     [/color][color=#000000]nt!RtlUnwind[/color][color=#0A246A]+[/color][color=#800080]0x5a [/color][color=#0A246A]([/color][color=#800080]808673b2[/color][color=#0A246A])
:                 
:                 [/color][color=#000000]nt!RtlUnwind[/color][color=#0A246A]+[/color][color=#800080]0x2f [/color][color=#0A246A][c:[/color][color=#000000]\wrk\wrk[/color][color=#0A246A]-[/color][color=#000000]v1.2\base\ntos\rtl\i386\exdsptch.c @ [/color][color=#800080]452[/color][color=#0A246A]]:
:                   [/color][color=#800080]80867387  [/color][color=#0A246A]mov     [/color][color=#FF8000]eax[/color][color=#0A246A],dword ptr [[/color][color=#FF8000]ebp[/color][color=#0A246A]+[/color][color=#800080]4[/color][color=#0A246A]]
:                   [/color][color=#800080]8086738a  [/color][color=#0A246A]lea     [/color][color=#FF8000]esi[/color][color=#0A246A],[[/color][color=#FF8000]ebp[/color][color=#0A246A]-[/color][color=#800080]37Ch[/color][color=#0A246A]] [/color][color=#008000]; ebp-37Ch 是局部变量 l_ExceptionRecord
[/color][color=#0A246A]:                   [/color][color=#800080]80867390  [/color][color=#0A246A]mov     dword ptr [[/color][color=#FF8000]ebp[/color][color=#0A246A]-[/color][color=#800080]37Ch[/color][color=#0A246A]],[/color][color=#800080]0C0000027h [/color][color=#008000]; l_ExceptionRecord.ExceptionCode = STATUS_UNWIND
[/color][color=#0A246A]:                   [/color][color=#800080]8086739a  [/color][color=#0A246A]mov     dword ptr [[/color][color=#FF8000]ebp[/color][color=#0A246A]-[/color][color=#800080]378h[/color][color=#0A246A]],[/color][color=#FF8000]edi [/color][color=#008000]; l_ExceptionRecord.ExceptionFlags = 0
[/color][color=#0A246A]:                   [/color][color=#800080]808673a0  [/color][color=#0A246A]mov     dword ptr [[/color][color=#FF8000]ebp[/color][color=#0A246A]-[/color][color=#800080]374h[/color][color=#0A246A]],[/color][color=#FF8000]edi [/color][color=#008000]; l_ExceptionRecord.ExceptionRecord = NULL
[/color][color=#0A246A]:                   [/color][color=#800080]808673a6  [/color][color=#0A246A]mov     dword ptr [[/color][color=#FF8000]ebp[/color][color=#0A246A]-[/color][color=#800080]370h[/color][color=#0A246A]],[/color][color=#FF8000]eax [/color][color=#008000]; l_ExceptionRecord.ExceptionAddress = ret_addr (PassThrough!RtlUnwind 执行完毕后的返回地址)
[/color][color=#0A246A]:                   [/color][color=#800080]808673ac  [/color][color=#0A246A]mov     dword ptr [[/color][color=#FF8000]ebp[/color][color=#0A246A]-[/color][color=#800080]36Ch[/color][color=#0A246A]],[/color][color=#FF8000]edi [/color][color=#008000]; l_ExceptionRecord.ExceptionInformation[0] = 0;
[/color][color=#0A246A]:                 
:                 [/color][color=#000000]nt!RtlUnwind[/color][color=#0A246A]+[/color][color=#800080]0x5a [/color][color=#0A246A][c:[/color][color=#000000]\wrk\wrk[/color][color=#0A246A]-[/color][color=#000000]v1.2\base\ntos\rtl\i386\exdsptch.c @ [/color][color=#800080]462[/color][color=#0A246A]]:
>                   [/color][color=#800080]808673b2  [/color][color=#0A246A]cmp     dword ptr [[/color][color=#FF8000]ebp[/color][color=#0A246A]+[/color][color=#800080]8[/color][color=#0A246A]],[/color][color=#FF8000]edi [/color][color=#008000]; pExceptionRegistration 是否为 NULL
 [/color][color=#0A246A]<                  [/color][color=#800080]808673b5  [/color][color=#0A246A]je      [/color][color=#000000]nt!RtlUnwind[/color][color=#0A246A]+[/color][color=#800080]0x65 [/color][color=#0A246A]([/color][color=#800080]808673bd[/color][color=#0A246A])
 :                
 :                [/color][color=#000000]nt!RtlUnwind[/color][color=#0A246A]+[/color][color=#800080]0x5f [/color][color=#0A246A][c:[/color][color=#000000]\wrk\wrk[/color][color=#0A246A]-[/color][color=#000000]v1.2\base\ntos\rtl\i386\exdsptch.c @ [/color][color=#800080]463[/color][color=#0A246A]]:
 :                  [/color][color=#800080]808673b7  [/color][color=#0A246A]or      dword ptr [[/color][color=#FF8000]esi[/color][color=#0A246A]+[/color][color=#800080]4[/color][color=#0A246A]],[/color][color=#800080]2 [/color][color=#008000]; l_ExceptionRecord.ExceptionFlags |= EXCEPTION_UNWINDING (0x2)
 [/color][color=#0A246A]:<                 [/color][color=#800080]808673bb  [/color][color=#0A246A]jmp     [/color][color=#000000]nt!RtlUnwind[/color][color=#0A246A]+[/color][color=#800080]0x69 [/color][color=#0A246A]([/color][color=#800080]808673c1[/color][color=#0A246A])
 ::               
 ::               [/color][color=#000000]nt!RtlUnwind[/color][color=#0A246A]+[/color][color=#800080]0x65 [/color][color=#0A246A][c:[/color][color=#000000]\wrk\wrk[/color][color=#0A246A]-[/color][color=#000000]v1.2\base\ntos\rtl\i386\exdsptch.c @ [/color][color=#800080]466[/color][color=#0A246A]]:
 >:                 [/color][color=#800080]808673bd  [/color][color=#0A246A]or      dword ptr [[/color][color=#FF8000]esi[/color][color=#0A246A]+[/color][color=#800080]4[/color][color=#0A246A]],[/color][color=#800080]6 [/color][color=#008000]; l_ExceptionRecord.ExceptionFlags |= EXCEPTION_UNWINDING | EXCEPTION_EXIT_UNWIND (0x2 | 0x4)
  [/color][color=#0A246A]:               
  :               [/color][color=#000000]nt!RtlUnwind[/color][color=#0A246A]+[/color][color=#800080]0x69 [/color][color=#0A246A][c:[/color][color=#000000]\wrk\wrk[/color][color=#0A246A]-[/color][color=#000000]v1.2\base\ntos\rtl\i386\exdsptch.c @ [/color][color=#800080]466[/color][color=#0A246A]]:
  >                 [/color][color=#800080]808673c1  [/color][color=#0A246A]push    [/color][color=#FF8000]ebx
                    [/color][color=#800080]808673c2  [/color][color=#0A246A]lea     [/color][color=#FF8000]eax[/color][color=#0A246A],[[/color][color=#FF8000]ebp[/color][color=#0A246A]-[/color][color=#800080]2D0h[/color][color=#0A246A]] [/color][color=#008000]; ebp-2D0 是局部变量 l_Context
                    [/color][color=#800080]808673c8  [/color][color=#0A246A]push    [/color][color=#FF8000]eax
                    [/color][color=#800080]808673c9  [/color][color=#0A246A]mov     dword ptr [[/color][color=#FF8000]ebp[/color][color=#0A246A]-[/color][color=#800080]2D0h[/color][color=#0A246A]],[/color][color=#800080]10007h [/color][color=#008000]; lContext.ContextFlags = CONTEXT_i386 | CONTEXT_CONTROL | CONTEXT_INTEGER | CONTEXT_SEGMENTS (0x10000 | 0x1 | 0x2 | 0x3)

                    [/color][color=#800080]808673d3  [/color][color=#0A246A]call    [/color][color=#000000]nt!RtlpCaptureContext [/color][color=#0A246A]([/color][color=#800080]80887c50[/color][color=#0A246A])
                    [/color][color=#800080]808673d8  [/color][color=#0A246A]mov     [/color][color=#FF8000]eax[/color][color=#0A246A],dword ptr [[/color][color=#FF8000]ebp[/color][color=#0A246A]+[/color][color=#800080]14h[/color][color=#0A246A]] [/color][color=#008000]; eax = ReturnValue
                    [/color][color=#800080]808673db  [/color][color=#0A246A]add     dword ptr [[/color][color=#FF8000]ebp[/color][color=#0A246A]-[/color][color=#800080]20Ch[/color][color=#0A246A]],[/color][color=#800080]10h [/color][color=#008000]; -20C = -2D0+C4, lContext.Esp += 0x10
                    [/color][color=#800080]808673e2  [/color][color=#0A246A]mov     dword ptr [[/color][color=#FF8000]ebp[/color][color=#0A246A]-[/color][color=#800080]220h[/color][color=#0A246A]],[/color][color=#FF8000]eax [/color][color=#008000]; -220 = -2D0+B0, lContext.Eax = ReturnValue
                    [/color][color=#800080]808673e8  [/color][color=#0A246A]call    [/color][color=#000000]nt!RtlpGetRegistrationHead [/color][color=#0A246A]([/color][color=#800080]80887d04[/color][color=#0A246A])
                    [/color][color=#800080]808673ed  [/color][color=#0A246A]mov     [/color][color=#FF8000]ebx[/color][color=#0A246A],[/color][color=#FF8000]eax [/color][color=#008000]; ebx = 异常链表头,这里暂命名为 l_pExceptionRegistration
[/color][color=#0A246A]<                   [/color][color=#800080]808673ef  [/color][color=#0A246A]jmp     [/color][color=#000000]nt!RtlUnwind[/color][color=#0A246A]+[/color][color=#800080]0x1d1 [/color][color=#0A246A]([/color][color=#800080]80867529[/color][color=#0A246A])
:                 
:                 [/color][color=#000000]nt!RtlUnwind[/color][color=#0A246A]+[/color][color=#800080]0x9c [/color][color=#0A246A][c:[/color][color=#000000]\wrk\wrk[/color][color=#0A246A]-[/color][color=#000000]v1.2\base\ntos\rtl\i386\exdsptch.c @ [/color][color=#800080]500[/color][color=#0A246A]]:
:              >    [/color][color=#800080]808673f4  [/color][color=#0A246A]cmp     [/color][color=#FF8000]ebx[/color][color=#0A246A],dword ptr [[/color][color=#FF8000]ebp[/color][color=#0A246A]+[/color][color=#800080]8[/color][color=#0A246A]] [/color][color=#008000]; cmp l_pExceptionRegistration,pExceptionRegistration 
[/color][color=#0A246A]:<             :    [/color][color=#800080]808673f7  [/color][color=#0A246A]jne     [/color][color=#000000]nt!RtlUnwind[/color][color=#0A246A]+[/color][color=#800080]0xb0 [/color][color=#0A246A]([/color][color=#800080]80867408[/color][color=#0A246A])
::             :  
::             :  [/color][color=#000000]nt!RtlUnwind[/color][color=#0A246A]+[/color][color=#800080]0xa1 [/color][color=#0A246A][c:[/color][color=#000000]\wrk\wrk[/color][color=#0A246A]-[/color][color=#000000]v1.2\base\ntos\rtl\i386\exdsptch.c @ [/color][color=#800080]501[/color][color=#0A246A]]:
::             :    [/color][color=#008000]; pExceptionRegistration 等于 l_pExceptionRegistration,说明展开完毕
[/color][color=#0A246A]::             :    [/color][color=#800080]808673f9  [/color][color=#0A246A]push    [/color][color=#FF8000]edi [/color][color=#008000]; TestAlert = FALSE
[/color][color=#0A246A]::             :    [/color][color=#800080]808673fa  [/color][color=#0A246A]lea     [/color][color=#FF8000]eax[/color][color=#0A246A],[[/color][color=#FF8000]ebp[/color][color=#0A246A]-[/color][color=#800080]2D0h[/color][color=#0A246A]] [/color][color=#008000]; eax = &l_Context
[/color][color=#0A246A]::             :    [/color][color=#800080]80867400  [/color][color=#0A246A]push    [/color][color=#FF8000]eax
[/color][color=#0A246A]::             :    [/color][color=#800080]80867401  [/color][color=#0A246A]call    [/color][color=#000000]nt!ZwContinue [/color][color=#0A246A]([/color][color=#800080]8082c0b8[/color][color=#0A246A]) [/color][color=#008000];  这里不会返回
[/color][color=#0A246A]::<            :    [/color][color=#800080]80867406  [/color][color=#0A246A]jmp     [/color][color=#000000]nt!RtlUnwind[/color][color=#0A246A]+[/color][color=#800080]0xe6 [/color][color=#0A246A]([/color][color=#800080]8086743e[/color][color=#0A246A])
:::            :  
:::            :  [/color][color=#000000]nt!RtlUnwind[/color][color=#0A246A]+[/color][color=#800080]0xb0 [/color][color=#0A246A][c:[/color][color=#000000]\wrk\wrk[/color][color=#0A246A]-[/color][color=#000000]v1.2\base\ntos\rtl\i386\exdsptch.c @ [/color][color=#800080]509[/color][color=#0A246A]]:
:>:            :    [/color][color=#800080]80867408  [/color][color=#0A246A]cmp     dword ptr [[/color][color=#FF8000]ebp[/color][color=#0A246A]+[/color][color=#800080]8[/color][color=#0A246A]],[/color][color=#FF8000]edi [/color][color=#008000]; cmp pExceptionRegistration, NULL
[/color][color=#0A246A]: :<           :    [/color][color=#800080]8086740b  [/color][color=#0A246A]je      [/color][color=#000000]nt!RtlUnwind[/color][color=#0A246A]+[/color][color=#800080]0xe6 [/color][color=#0A246A]([/color][color=#800080]8086743e[/color][color=#0A246A])
: ::           :  
: ::           :  [/color][color=#000000]nt!RtlUnwind[/color][color=#0A246A]+[/color][color=#800080]0xb5 [/color][color=#0A246A][c:[/color][color=#000000]\wrk\wrk[/color][color=#0A246A]-[/color][color=#000000]v1.2\base\ntos\rtl\i386\exdsptch.c @ [/color][color=#800080]509[/color][color=#0A246A]]:
: ::           :    [/color][color=#800080]8086740d  [/color][color=#0A246A]cmp     dword ptr [[/color][color=#FF8000]ebp[/color][color=#0A246A]+[/color][color=#800080]8[/color][color=#0A246A]],[/color][color=#FF8000]ebx [/color][color=#008000]; cmp pExceptionRegistration,l_pExceptionRegistration
[/color][color=#0A246A]: ::<          :    [/color][color=#800080]80867410  [/color][color=#0A246A]jae     [/color][color=#000000]nt!RtlUnwind[/color][color=#0A246A]+[/color][color=#800080]0xe6 [/color][color=#0A246A]([/color][color=#800080]8086743e[/color][color=#0A246A])
: :::          :  
: :::          :  [/color][color=#000000]nt!RtlUnwind[/color][color=#0A246A]+[/color][color=#800080]0xba [/color][color=#0A246A][c:[/color][color=#000000]\wrk\wrk[/color][color=#0A246A]-[/color][color=#000000]v1.2\base\ntos\rtl\i386\exdsptch.c @ [/color][color=#800080]514[/color][color=#0A246A]]:
: :::          :    [/color][color=#008000]; pExceptionRegistration 在 l_pExceptionRegistration 之下,即 pExceptionRegistration 超出了异常链表的栈范围
[/color][color=#0A246A]: :::          :    [/color][color=#800080]80867412  [/color][color=#0A246A]lea     [/color][color=#FF8000]eax[/color][color=#0A246A],[[/color][color=#FF8000]ebp[/color][color=#0A246A]-[/color][color=#800080]32Ch[/color][color=#0A246A]] [/color][color=#008000]; ebp-32Ch 是局部变量 l_ExceptionRecord
[/color][color=#0A246A]: :::          :    [/color][color=#800080]80867418  [/color][color=#0A246A]push    [/color][color=#FF8000]eax
[/color][color=#0A246A]: :::          :    [/color][color=#800080]80867419  [/color][color=#0A246A]mov     dword ptr [[/color][color=#FF8000]ebp[/color][color=#0A246A]-[/color][color=#800080]32Ch[/color][color=#0A246A]],[/color][color=#800080]0C0000029h [/color][color=#008000]; l_ExceptionRecord.ExceptionCode = STATUS_INVALID_UNWIND_TARGET
[/color][color=#0A246A]: :::          :    [/color][color=#800080]80867423  [/color][color=#0A246A]mov     dword ptr [[/color][color=#FF8000]ebp[/color][color=#0A246A]-[/color][color=#800080]328h[/color][color=#0A246A]],[/color][color=#800080]1          [/color][color=#008000]; l_ExceptionRecord.ExceptionFlags = EXCEPTION_NONCONTINUABLE (1)
[/color][color=#0A246A]: :::          :    [/color][color=#800080]8086742d  [/color][color=#0A246A]mov     dword ptr [[/color][color=#FF8000]ebp[/color][color=#0A246A]-[/color][color=#800080]324h[/color][color=#0A246A]],[/color][color=#FF8000]esi        [/color][color=#008000]; l_ExceptionRecord.ExceptionRecord = &l_ExceptionRecord
[/color][color=#0A246A]: :::          :    [/color][color=#800080]80867433  [/color][color=#0A246A]mov     dword ptr [[/color][color=#FF8000]ebp[/color][color=#0A246A]-[/color][color=#800080]31Ch[/color][color=#0A246A]],[/color][color=#FF8000]edi        [/color][color=#008000]; l_ExceptionRecord.NumberParameters = 0
[/color][color=#0A246A]: :::          :    [/color][color=#800080]80867439  [/color][color=#0A246A]call    [/color][color=#000000]nt!RtlRaiseException [/color][color=#0A246A]([/color][color=#800080]80887a94[/color][color=#0A246A])
: :::          :  
: :::          :  [/color][color=#000000]nt!RtlUnwind[/color][color=#0A246A]+[/color][color=#800080]0xe6 [/color][color=#0A246A][c:[/color][color=#000000]\wrk\wrk[/color][color=#0A246A]-[/color][color=#000000]v1.2\base\ntos\rtl\i386\exdsptch.c @ [/color][color=#800080]530[/color][color=#0A246A]]:
: >>>          :    [/color][color=#800080]8086743e  [/color][color=#0A246A]cmp     [/color][color=#FF8000]ebx[/color][color=#0A246A],dword ptr [[/color][color=#FF8000]ebp[/color][color=#0A246A]-[/color][color=#800080]2D4h[/color][color=#0A246A]] [/color][color=#008000]; cmp l_pExceptionRegistration, l_pLowLimit
[/color][color=#0A246A]:              :    [/color][color=#800080]80867444  [/color][color=#0A246A]lea     [/color][color=#FF8000]edi[/color][color=#0A246A],[[/color][color=#FF8000]ebx[/color][color=#0A246A]+[/color][color=#800080]8[/color][color=#0A246A]] [/color][color=#008000]; edi = l_pExceptionRegistration->scopetable_entry
[/color][color=#0A246A]:    <         :    [/color][color=#800080]80867447  [/color][color=#0A246A]jb      [/color][color=#000000]nt!RtlUnwind[/color][color=#0A246A]+[/color][color=#800080]0x162 [/color][color=#0A246A]([/color][color=#800080]808674ba[/color][color=#0A246A]) [/color][color=#008000]; l_pExceptionRegistration 低于线程栈底,跳到错误处理
[/color][color=#0A246A]:    :         :  
:    :         :  [/color][color=#000000]nt!RtlUnwind[/color][color=#0A246A]+[/color][color=#800080]0xf1 [/color][color=#0A246A][c:[/color][color=#000000]\wrk\wrk[/color][color=#0A246A]-[/color][color=#000000]v1.2\base\ntos\rtl\i386\exdsptch.c @ [/color][color=#800080]530[/color][color=#0A246A]]:
:    :         :    [/color][color=#800080]80867449  [/color][color=#0A246A]cmp     [/color][color=#FF8000]edi[/color][color=#0A246A],dword ptr [[/color][color=#FF8000]ebp[/color][color=#0A246A]-[/color][color=#800080]2D8h[/color][color=#0A246A]] [/color][color=#008000]; cmp l_pExceptionRegistration->scopetable_entry,l_pHighLimit
[/color][color=#0A246A]:    :<        :    [/color][color=#800080]8086744f  [/color][color=#0A246A]ja      [/color][color=#000000]nt!RtlUnwind[/color][color=#0A246A]+[/color][color=#800080]0x162 [/color][color=#0A246A]([/color][color=#800080]808674ba[/color][color=#0A246A]) [/color][color=#008000]; l_pExceptionRegistration 高于线程栈顶,跳到错误处理
[/color][color=#0A246A]:    ::        :  
:    ::        :  [/color][color=#000000]nt!RtlUnwind[/color][color=#0A246A]+[/color][color=#800080]0xf9 [/color][color=#0A246A][c:[/color][color=#000000]\wrk\wrk[/color][color=#0A246A]-[/color][color=#000000]v1.2\base\ntos\rtl\i386\exdsptch.c @ [/color][color=#800080]530[/color][color=#0A246A]]:
:    ::        :    [/color][color=#008000]; l_pExceptionRegistration 处于合法栈中,检查它是否正确对齐
[/color][color=#0A246A]:    ::        :    [/color][color=#800080]80867451  [/color][color=#0A246A]test    [/color][color=#FF8000]bl[/color][color=#0A246A],[/color][color=#800080]3 [/color][color=#008000]; 检查 l_pExceptionRegistration 是否4字节对齐
[/color][color=#0A246A]:    ::<       :    [/color][color=#800080]80867454  [/color][color=#0A246A]jne     [/color][color=#000000]nt!RtlUnwind[/color][color=#0A246A]+[/color][color=#800080]0x1a2 [/color][color=#0A246A]([/color][color=#800080]808674fa[/color][color=#0A246A]) [/color][color=#008000]; 没对齐,跳到错误处理
[/color][color=#0A246A]:    :::       :  
:    :::       :  [/color][color=#000000]nt!RtlUnwind[/color][color=#0A246A]+[/color][color=#800080]0x102 [/color][color=#0A246A][c:[/color][color=#000000]\wrk\wrk[/color][color=#0A246A]-[/color][color=#000000]v1.2\base\ntos\rtl\i386\exdsptch.c @ [/color][color=#800080]580[/color][color=#0A246A]]:
:    :::       :    [/color][color=#008000]; 进行局部展开
[/color][color=#0A246A]:    :::       :    [/color][color=#800080]8086745a  [/color][color=#0A246A]push    dword ptr [[/color][color=#FF8000]ebx[/color][color=#0A246A]+[/color][color=#800080]4[/color][color=#0A246A]] [/color][color=#008000]; l_pExceptionRegistration->Handler
[/color][color=#0A246A]:    :::       :    [/color][color=#800080]8086745d  [/color][color=#0A246A]lea     [/color][color=#FF8000]eax[/color][color=#0A246A],[[/color][color=#FF8000]ebp[/color][color=#0A246A]-[/color][color=#800080]2DCh[/color][color=#0A246A]] [/color][color=#008000]; 这里是局部变量 l_DispatchContext
[/color][color=#0A246A]:    :::       :    [/color][color=#800080]80867463  [/color][color=#0A246A]push    [/color][color=#FF8000]eax [/color][color=#008000];
[/color][color=#0A246A]:    :::       :    [/color][color=#800080]80867464  [/color][color=#0A246A]lea     [/color][color=#FF8000]eax[/color][color=#0A246A],[[/color][color=#FF8000]ebp[/color][color=#0A246A]-[/color][color=#800080]2D0h[/color][color=#0A246A]] [/color][color=#008000]; eax = &l_Context
[/color][color=#0A246A]:    :::       :    [/color][color=#800080]8086746a  [/color][color=#0A246A]push    [/color][color=#FF8000]eax [/color][color=#008000]; l_Context
[/color][color=#0A246A]:    :::       :    [/color][color=#800080]8086746b  [/color][color=#0A246A]push    [/color][color=#FF8000]ebx [/color][color=#008000]; l_pExceptionRegistration
[/color][color=#0A246A]:    :::       :    [/color][color=#800080]8086746c  [/color][color=#0A246A]push    [/color][color=#FF8000]esi [/color][color=#008000]; &l_ExceptionRecord
[/color][color=#0A246A]:    :::       :    [/color][color=#800080]8086746d  [/color][color=#0A246A]call    [/color][color=#000000]nt!RtlpExecuteHandlerForUnwind [/color][color=#0A246A]([/color][color=#800080]80887b54[/color][color=#0A246A]) [/color][color=#008000]; 内部调用 l_pExceptionRegistration->Handler
[/color][color=#0A246A]:    :::       :    [/color][color=#800080]80867472  [/color][color=#0A246A]dec     [/color][color=#FF8000]eax
[/color][color=#0A246A]:    :::<      :    [/color][color=#800080]80867473  [/color][color=#0A246A]je      [/color][color=#000000]nt!RtlUnwind[/color][color=#0A246A]+[/color][color=#800080]0x156 [/color][color=#0A246A]([/color][color=#800080]808674ae[/color][color=#0A246A]) [/color][color=#008000]; 如果返回 ExceptionContinueSearch 则跳转
[/color][color=#0A246A]:    ::::      :  
:    ::::      :  [/color][color=#000000]nt!RtlUnwind[/color][color=#0A246A]+[/color][color=#800080]0x11d [/color][color=#0A246A][c:[/color][color=#000000]\wrk\wrk[/color][color=#0A246A]-[/color][color=#000000]v1.2\base\ntos\rtl\i386\exdsptch.c @ [/color][color=#800080]586[/color][color=#0A246A]]:
:    ::::      :    [/color][color=#800080]80867475  [/color][color=#0A246A]dec     [/color][color=#FF8000]eax
[/color][color=#0A246A]:    ::::      :    [/color][color=#800080]80867476  [/color][color=#0A246A]dec     [/color][color=#FF8000]eax
[/color][color=#0A246A]:    :::: <    :    [/color][color=#800080]80867477  [/color][color=#0A246A]je      [/color][color=#000000]nt!RtlUnwind[/color][color=#0A246A]+[/color][color=#800080]0x150 [/color][color=#0A246A]([/color][color=#800080]808674a8[/color][color=#0A246A]) [/color][color=#008000]; 如果返回 ExceptionCollidedUnwind 则跳转
[/color][color=#0A246A]:    :::: :    :  
:    :::: :    :  [/color][color=#000000]nt!RtlUnwind[/color][color=#0A246A]+[/color][color=#800080]0x121 [/color][color=#0A246A][c:[/color][color=#000000]\wrk\wrk[/color][color=#0A246A]-[/color][color=#000000]v1.2\base\ntos\rtl\i386\exdsptch.c @ [/color][color=#800080]621[/color][color=#0A246A]]:
:    :::: :    :    [/color][color=#008000]; 返回 ExceptionContinueSearch 和 ExceptionCollidedUnwind 之外的非法值
[/color][color=#0A246A]:    :::: :    :    [/color][color=#800080]80867479  [/color][color=#0A246A]and     dword ptr [[/color][color=#FF8000]ebp[/color][color=#0A246A]-[/color][color=#800080]31Ch[/color][color=#0A246A]],[/color][color=#800080]0          [/color][color=#008000]; l_ExceptionRecord.NumberParameters = 0
[/color][color=#0A246A]:    :::: :    :    [/color][color=#800080]80867480  [/color][color=#0A246A]lea     [/color][color=#FF8000]eax[/color][color=#0A246A],[[/color][color=#FF8000]ebp[/color][color=#0A246A]-[/color][color=#800080]32Ch[/color][color=#0A246A]] [/color][color=#008000]; eax = &l_ExceptionRecord
[/color][color=#0A246A]:    :::: :    :    [/color][color=#800080]80867486  [/color][color=#0A246A]push    [/color][color=#FF8000]eax
[/color][color=#0A246A]:    :::: :    :    [/color][color=#800080]80867487  [/color][color=#0A246A]mov     dword ptr [[/color][color=#FF8000]ebp[/color][color=#0A246A]-[/color][color=#800080]32Ch[/color][color=#0A246A]],[/color][color=#800080]0C0000026h [/color][color=#008000]; l_ExceptionRecord.ExceptionCode = STATUS_INVALID_DISPOSITION
[/color][color=#0A246A]:    :::: :    :    [/color][color=#800080]80867491  [/color][color=#0A246A]mov     dword ptr [[/color][color=#FF8000]ebp[/color][color=#0A246A]-[/color][color=#800080]328h[/color][color=#0A246A]],[/color][color=#800080]1          [/color][color=#008000]; l_ExceptionRecord.ExceptionFlags = EXCEPTION_NONCONTINUABLE (1)
[/color][color=#0A246A]:    :::: :    :    [/color][color=#800080]8086749b  [/color][color=#0A246A]mov     dword ptr [[/color][color=#FF8000]ebp[/color][color=#0A246A]-[/color][color=#800080]324h[/color][color=#0A246A]],[/color][color=#FF8000]esi        [/color][color=#008000]; l_ExceptionRecord.ExceptionRecord = &l_ExceptionRecord
[/color][color=#0A246A]:    :::: :    :    [/color][color=#800080]808674a1  [/color][color=#0A246A]call    [/color][color=#000000]nt!RtlRaiseException [/color][color=#0A246A]([/color][color=#800080]80887a94[/color][color=#0A246A])
:    ::::<:    :    [/color][color=#800080]808674a6  [/color][color=#0A246A]jmp     [/color][color=#000000]nt!RtlUnwind[/color][color=#0A246A]+[/color][color=#800080]0x156 [/color][color=#0A246A]([/color][color=#800080]808674ae[/color][color=#0A246A])
:    ::::::    :  
:    ::::::    :  [/color][color=#000000]nt!RtlUnwind[/color][color=#0A246A]+[/color][color=#800080]0x150 [/color][color=#0A246A][c:[/color][color=#000000]\wrk\wrk[/color][color=#0A246A]-[/color][color=#000000]v1.2\base\ntos\rtl\i386\exdsptch.c @ [/color][color=#800080]608[/color][color=#0A246A]]:
:    ::::::    :    [/color][color=#008000]; RtlpExecuteHandlerForUnwind 返回 ExceptionCollidedUnwind,从 l_DispatchContext.RegistrationPointer 继续处理
[/color][color=#0A246A]:    :::::>    :    [/color][color=#800080]808674a8  [/color][color=#0A246A]mov     [/color][color=#FF8000]ebx[/color][color=#0A246A],dword ptr [[/color][color=#FF8000]ebp[/color][color=#0A246A]-[/color][color=#800080]2DCh[/color][color=#0A246A]] [/color][color=#008000]; l_pExceptionRegistration = l_DispatchContext.RegistrationPointer
[/color][color=#0A246A]:    :::::     :  
:    :::::     :  [/color][color=#000000]nt!RtlUnwind[/color][color=#0A246A]+[/color][color=#800080]0x156 [/color][color=#0A246A][c:[/color][color=#000000]\wrk\wrk[/color][color=#0A246A]-[/color][color=#000000]v1.2\base\ntos\rtl\i386\exdsptch.c @ [/color][color=#800080]630[/color][color=#0A246A]]:
:    :::::     :    [/color][color=#008000]; 局部展开完毕,从异常链表中摘除 l_pExceptionRegistration
[/color][color=#0A246A]:    :::>>     :    [/color][color=#800080]808674ae  [/color][color=#0A246A]mov     [/color][color=#FF8000]eax[/color][color=#0A246A],[/color][color=#FF8000]ebx [/color][color=#008000]; eax = l_pExceptionRegistration
[/color][color=#0A246A]:    :::       :    [/color][color=#800080]808674b0  [/color][color=#0A246A]mov     [/color][color=#FF8000]ebx[/color][color=#0A246A],dword ptr [[/color][color=#FF8000]ebx[/color][color=#0A246A]] [/color][color=#008000]; l_pExceptionRegistration = l_pExceptionRegistration.prev
[/color][color=#0A246A]:    :::       :    [/color][color=#800080]808674b2  [/color][color=#0A246A]push    [/color][color=#FF8000]eax
[/color][color=#0A246A]:    :::       :    [/color][color=#800080]808674b3  [/color][color=#0A246A]call    [/color][color=#000000]nt!RtlpUnlinkHandler [/color][color=#0A246A]([/color][color=#800080]80887c10[/color][color=#0A246A]) [/color][color=#008000]; 摘除
[/color][color=#0A246A]:    :::<      :    [/color][color=#800080]808674b8  [/color][color=#0A246A]jmp     [/color][color=#000000]nt!RtlUnwind[/color][color=#0A246A]+[/color][color=#800080]0x1cf [/color][color=#0A246A]([/color][color=#800080]80867527[/color][color=#0A246A])
:    ::::      :  
:    ::::      :  [/color][color=#000000]nt!RtlUnwind[/color][color=#0A246A]+[/color][color=#800080]0x162 [/color][color=#0A246A][c:[/color][color=#000000]\wrk\wrk[/color][color=#0A246A]-[/color][color=#000000]v1.2\base\ntos\rtl\i386\exdsptch.c @ [/color][color=#800080]540[/color][color=#0A246A]]:
:    ::::      :    [/color][color=#008000]; l_pExceptionRegistration 并不处在当前线程栈中,这种情况不一定是出错,有可能当前正在执行 DPC。
[/color][color=#0A246A]:    ::::      :    [/color][color=#008000]; 当时还需要检查是否对齐,不对齐就一定是出错
[/color][color=#0A246A]:    >>::      :    [/color][color=#800080]808674ba  [/color][color=#0A246A]test    [/color][color=#FF8000]bl[/color][color=#0A246A],[/color][color=#800080]3 [/color][color=#008000]; 检查 l_pExceptionRegistration 是否4字节对齐
[/color][color=#0A246A]:      ::<     :    [/color][color=#800080]808674bd  [/color][color=#0A246A]jne     [/color][color=#000000]nt!RtlUnwind[/color][color=#0A246A]+[/color][color=#800080]0x1a2 [/color][color=#0A246A]([/color][color=#800080]808674fa[/color][color=#0A246A])
:      :::     :  
:      :::     :  [/color][color=#000000]nt!RtlUnwind[/color][color=#0A246A]+[/color][color=#800080]0x167 [/color][color=#0A246A][c:[/color][color=#000000]\wrk\wrk[/color][color=#0A246A]-[/color][color=#000000]v1.2\base\ntos\rtl\i386\exdsptch.c @ [/color][color=#800080]540[/color][color=#0A246A]]:
:      :::     :    [/color][color=#008000]; 如果当前正在执行 DPC,那 IRQL 一定不得低于 DISPATCH_LEVEL(难道不是应该一定等于 DISPATCH_LEVEL ?)
[/color][color=#0A246A]:      :::     :    [/color][color=#800080]808674bf  [/color][color=#0A246A]call    dword ptr [[/color][color=#000000]nt!_imp__KeGetCurrentIrql [/color][color=#0A246A]([/color][color=#800080]8080102c[/color][color=#0A246A])]
:      :::     :    [/color][color=#800080]808674c5  [/color][color=#0A246A]cmp     [/color][color=#FF8000]al[/color][color=#0A246A],[/color][color=#800080]2 [/color][color=#008000]; DISPATCH_LEVEL (2)
[/color][color=#0A246A]:      :::<    :    [/color][color=#800080]808674c7  [/color][color=#0A246A]jb      [/color][color=#000000]nt!RtlUnwind[/color][color=#0A246A]+[/color][color=#800080]0x1a2 [/color][color=#0A246A]([/color][color=#800080]808674fa[/color][color=#0A246A]) [/color][color=#008000]; 低于 DISPATCH_LEVEL,跳到错误处理点
[/color][color=#0A246A]:      ::::    :  
:      ::::    :  [/color][color=#000000]nt!RtlUnwind[/color][color=#0A246A]+[/color][color=#800080]0x171 [/color][color=#0A246A][c:[/color][color=#000000]\wrk\wrk[/color][color=#0A246A]-[/color][color=#000000]v1.2\base\ntos\rtl\i386\exdsptch.c @ [/color][color=#800080]542[/color][color=#0A246A]]:
:      ::::    :    [/color][color=#800080]808674c9  [/color][color=#0A246A]mov     [/color][color=#FF8000]eax[/color][color=#0A246A],dword ptr [/color][color=#FF8000]fs[/color][color=#0A246A]:[[/color][color=#800080]00000020h[/color][color=#0A246A]] [/color][color=#008000]; eax = 当前 CPU 的 KPCR::Prcb
[/color][color=#0A246A]:      ::::    :    [/color][color=#800080]808674cf  [/color][color=#0A246A]cmp     byte ptr [[/color][color=#FF8000]eax[/color][color=#0A246A]+[/color][color=#800080]95Ah[/color][color=#0A246A]],[/color][color=#800080]0 [/color][color=#008000]; KPCR::Prcb->DpcRoutineActive (BOOLEAN 类型)
[/color][color=#0A246A]:      ::::    :    [/color][color=#800080]808674d6  [/color][color=#0A246A]mov     [/color][color=#FF8000]ecx[/color][color=#0A246A],dword ptr [[/color][color=#FF8000]eax[/color][color=#0A246A]+[/color][color=#800080]948h[/color][color=#0A246A]] [/color][color=#008000]; ecx = KPCR::Prcb->DpcStack
[/color][color=#0A246A]:      ::::<   :    [/color][color=#800080]808674dc  [/color][color=#0A246A]je      [/color][color=#000000]nt!RtlUnwind[/color][color=#0A246A]+[/color][color=#800080]0x1a2 [/color][color=#0A246A]([/color][color=#800080]808674fa[/color][color=#0A246A]) [/color][color=#008000]; 当前不是在执行 DPC,跳到错误处理点
[/color][color=#0A246A]:      :::::   :  
:      :::::   :  [/color][color=#000000]nt!RtlUnwind[/color][color=#0A246A]+[/color][color=#800080]0x186 [/color][color=#0A246A][c:[/color][color=#000000]\wrk\wrk[/color][color=#0A246A]-[/color][color=#000000]v1.2\base\ntos\rtl\i386\exdsptch.c @ [/color][color=#800080]547[/color][color=#0A246A]]:
:      :::::   :    [/color][color=#008000]; KPCR::Prcb->DpcRoutineActive 为 TRUE,当前异常是由 DpcRoutine 触发
[/color][color=#0A246A]:      :::::   :    [/color][color=#800080]808674de  [/color][color=#0A246A]cmp     [/color][color=#FF8000]edi[/color][color=#0A246A],[/color][color=#FF8000]ecx [/color][color=#008000]; 比较 l_pExceptionRegistration->scopetable_entry 和 DPC 栈顶
[/color][color=#0A246A]:      :::::<  :    [/color][color=#800080]808674e0  [/color][color=#0A246A]ja      [/color][color=#000000]nt!RtlUnwind[/color][color=#0A246A]+[/color][color=#800080]0x1a2 [/color][color=#0A246A]([/color][color=#800080]808674fa[/color][color=#0A246A]) [/color][color=#008000]; 高出 DPC 栈顶,跳到错误处理点
[/color][color=#0A246A]:      ::::::  :  
:      ::::::  :  [/color][color=#000000]nt!RtlUnwind[/color][color=#0A246A]+[/color][color=#800080]0x18a [/color][color=#0A246A][c:[/color][color=#000000]\wrk\wrk[/color][color=#0A246A]-[/color][color=#000000]v1.2\base\ntos\rtl\i386\exdsptch.c @ [/color][color=#800080]547[/color][color=#0A246A]]:
:      ::::::  :    [/color][color=#800080]808674e2  [/color][color=#0A246A]lea     [/color][color=#FF8000]eax[/color][color=#0A246A],[[/color][color=#FF8000]ecx[/color][color=#0A246A]-[/color][color=#800080]3000h[/color][color=#0A246A]] [/color][color=#008000]; eax = KPCR::Prcb->DpcStack - KERNEL_STACK_SIZE, 即 DPC 栈底
[/color][color=#0A246A]:      ::::::  :    [/color][color=#800080]808674e8  [/color][color=#0A246A]cmp     [/color][color=#FF8000]ebx[/color][color=#0A246A],[/color][color=#FF8000]eax [/color][color=#008000]; 比较 l_pExceptionRegistration 和 DPC 栈底
[/color][color=#0A246A]:      ::::::< :    [/color][color=#800080]808674ea  [/color][color=#0A246A]jb      [/color][color=#000000]nt!RtlUnwind[/color][color=#0A246A]+[/color][color=#800080]0x1a2 [/color][color=#0A246A]([/color][color=#800080]808674fa[/color][color=#0A246A]) [/color][color=#008000]; 低于 DPC 栈底,跳到错误处理点
[/color][color=#0A246A]:      ::::::: :  
:      ::::::: :  [/color][color=#000000]nt!RtlUnwind[/color][color=#0A246A]+[/color][color=#800080]0x194 [/color][color=#0A246A][c:[/color][color=#000000]\wrk\wrk[/color][color=#0A246A]-[/color][color=#000000]v1.2\base\ntos\rtl\i386\exdsptch.c @ [/color][color=#800080]555[/color][color=#0A246A]]:
:      ::::::: :    [/color][color=#800080]808674ec  [/color][color=#0A246A]mov     dword ptr [[/color][color=#FF8000]ebp[/color][color=#0A246A]-[/color][color=#800080]2D8h[/color][color=#0A246A]],[/color][color=#FF8000]ecx [/color][color=#008000]; l_pHighLimit = DPC 栈顶
[/color][color=#0A246A]:      ::::::: :    [/color][color=#800080]808674f2  [/color][color=#0A246A]mov     dword ptr [[/color][color=#FF8000]ebp[/color][color=#0A246A]-[/color][color=#800080]2D4h[/color][color=#0A246A]],[/color][color=#FF8000]eax [/color][color=#008000]; l_pLowLimit = DPC 栈底
[/color][color=#0A246A]:      :::::::<:    [/color][color=#800080]808674f8  [/color][color=#0A246A]jmp     [/color][color=#000000]nt!RtlUnwind[/color][color=#0A246A]+[/color][color=#800080]0x1cf [/color][color=#0A246A]([/color][color=#800080]80867527[/color][color=#0A246A])
:      :::::::::  
:      :::::::::  [/color][color=#000000]nt!RtlUnwind[/color][color=#0A246A]+[/color][color=#800080]0x1a2 [/color][color=#0A246A][c:[/color][color=#000000]\wrk\wrk[/color][color=#0A246A]-[/color][color=#000000]v1.2\base\ntos\rtl\i386\exdsptch.c @ [/color][color=#800080]564[/color][color=#0A246A]]:
:      :::::::::    [/color][color=#008000]; 栈错误
[/color][color=#0A246A]:      >:>>>>>::    [/color][color=#800080]808674fa  [/color][color=#0A246A]and     dword ptr [[/color][color=#FF8000]ebp[/color][color=#0A246A]-[/color][color=#800080]31Ch[/color][color=#0A246A]],[/color][color=#800080]0
[/color][color=#0A246A]:       :     ::    [/color][color=#800080]80867501  [/color][color=#0A246A]lea     [/color][color=#FF8000]eax[/color][color=#0A246A],[[/color][color=#FF8000]ebp[/color][color=#0A246A]-[/color][color=#800080]32Ch[/color][color=#0A246A]]   [/color][color=#008000]; eax = &l_ExceptionRecord
[/color][color=#0A246A]:       :     ::    [/color][color=#800080]80867507  [/color][color=#0A246A]push    [/color][color=#FF8000]eax
[/color][color=#0A246A]:       :     ::    [/color][color=#800080]80867508  [/color][color=#0A246A]mov     dword ptr [[/color][color=#FF8000]ebp[/color][color=#0A246A]-[/color][color=#800080]32Ch[/color][color=#0A246A]],[/color][color=#800080]0C0000028h [/color][color=#008000]; l_ExceptionRecord.ExceptionCode = STATUS_BAD_STACK
[/color][color=#0A246A]:       :     ::    [/color][color=#800080]80867512  [/color][color=#0A246A]mov     dword ptr [[/color][color=#FF8000]ebp[/color][color=#0A246A]-[/color][color=#800080]328h[/color][color=#0A246A]],[/color][color=#800080]1          [/color][color=#008000]; l_ExceptionRecord.ExceptionFlags = EXCEPTION_NONCONTINUABLE (1)
[/color][color=#0A246A]:       :     ::    [/color][color=#800080]8086751c  [/color][color=#0A246A]mov     dword ptr [[/color][color=#FF8000]ebp[/color][color=#0A246A]-[/color][color=#800080]324h[/color][color=#0A246A]],[/color][color=#FF8000]esi        [/color][color=#008000]; l_ExceptionRecord.ExceptionRecord = &l_ExceptionRecord
[/color][color=#0A246A]:       :     ::    [/color][color=#800080]80867522  [/color][color=#0A246A]call    [/color][color=#000000]nt!RtlRaiseException [/color][color=#0A246A]([/color][color=#800080]80887a94[/color][color=#0A246A])
:       :     ::  
:       :     ::  [/color][color=#000000]nt!RtlUnwind[/color][color=#0A246A]+[/color][color=#800080]0x1cf [/color][color=#0A246A][c:[/color][color=#000000]\wrk\wrk[/color][color=#0A246A]-[/color][color=#000000]v1.2\base\ntos\rtl\i386\exdsptch.c @ [/color][color=#800080]493[/color][color=#0A246A]]:
:       >     >:    [/color][color=#800080]80867527  [/color][color=#0A246A]xor     [/color][color=#FF8000]edi[/color][color=#0A246A],[/color][color=#FF8000]edi
[/color][color=#0A246A]:              :  
:              :  [/color][color=#000000]nt!RtlUnwind[/color][color=#0A246A]+[/color][color=#800080]0x1d1 [/color][color=#0A246A][c:[/color][color=#000000]\wrk\wrk[/color][color=#0A246A]-[/color][color=#000000]v1.2\base\ntos\rtl\i386\exdsptch.c @ [/color][color=#800080]493[/color][color=#0A246A]]:
>              :    [/color][color=#800080]80867529  [/color][color=#0A246A]cmp     [/color][color=#FF8000]ebx[/color][color=#0A246A],[/color][color=#800080]0FFFFFFFFh [/color][color=#008000]; cmp l_pExceptionRegistration, EXCEPTION_CHAIN_END
               [/color][color=#0A246A]<    [/color][color=#800080]8086752c  [/color][color=#0A246A]jne     [/color][color=#000000]nt!RtlUnwind[/color][color=#0A246A]+[/color][color=#800080]0x9c [/color][color=#0A246A]([/color][color=#800080]808673f4[/color][color=#0A246A])
                  
                  [/color][color=#000000]nt!RtlUnwind[/color][color=#0A246A]+[/color][color=#800080]0x1da [/color][color=#0A246A][c:[/color][color=#000000]\wrk\wrk[/color][color=#0A246A]-[/color][color=#000000]v1.2\base\ntos\rtl\i386\exdsptch.c @ [/color][color=#800080]647[/color][color=#0A246A]]:
                    [/color][color=#800080]80867532  [/color][color=#0A246A]cmp     dword ptr [[/color][color=#FF8000]ebp[/color][color=#0A246A]+[/color][color=#800080]8[/color][color=#0A246A]],[/color][color=#800080]0FFFFFFFFh [/color][color=#008000]; cmp pExceptionRegistration, EXCEPTION_CHAIN_END
                    [/color][color=#800080]80867536  [/color][color=#0A246A]pop     [/color][color=#FF8000]ebx
                    [/color][color=#800080]80867537  [/color][color=#0A246A]lea     [/color][color=#FF8000]eax[/color][color=#0A246A],[[/color][color=#FF8000]ebp[/color][color=#0A246A]-[/color][color=#800080]2D0h[/color][color=#0A246A]] [/color][color=#008000]; eax = &l_Context
                    [/color][color=#800080]8086753d  [/color][color=#0A246A]push    [/color][color=#FF8000]edi [/color][color=#008000]; bTestAlert = FALSE 或 bFirstChance = FALSE
                    [/color][color=#800080]8086753e  [/color][color=#0A246A]push    [/color][color=#FF8000]eax
[/color][color=#0A246A]<                   [/color][color=#800080]8086753f  [/color][color=#0A246A]jne     [/color][color=#000000]nt!RtlUnwind[/color][color=#0A246A]+[/color][color=#800080]0x1f0 [/color][color=#0A246A]([/color][color=#800080]80867548[/color][color=#0A246A])
:                 
:                 [/color][color=#000000]nt!RtlUnwind[/color][color=#0A246A]+[/color][color=#800080]0x1e9 [/color][color=#0A246A][c:[/color][color=#000000]\wrk\wrk[/color][color=#0A246A]-[/color][color=#000000]v1.2\base\ntos\rtl\i386\exdsptch.c @ [/color][color=#800080]656[/color][color=#0A246A]]:
:                   [/color][color=#008000]; 展开整个异常链表
[/color][color=#0A246A]:                   [/color][color=#800080]80867541  [/color][color=#0A246A]call    [/color][color=#000000]nt!ZwContinue [/color][color=#0A246A]([/color][color=#800080]8082c0b8[/color][color=#0A246A])
:<                  [/color][color=#800080]80867546  [/color][color=#0A246A]jmp     [/color][color=#000000]nt!RtlUnwind[/color][color=#0A246A]+[/color][color=#800080]0x1f6 [/color][color=#0A246A]([/color][color=#800080]8086754e[/color][color=#0A246A])
::                
::                [/color][color=#000000]nt!RtlUnwind[/color][color=#0A246A]+[/color][color=#800080]0x1f0 [/color][color=#0A246A][c:[/color][color=#000000]\wrk\wrk[/color][color=#0A246A]-[/color][color=#000000]v1.2\base\ntos\rtl\i386\exdsptch.c @ [/color][color=#800080]667[/color][color=#0A246A]]:
::                  [/color][color=#008000]; pExceptionRegistration 等于 EXCEPTION_CHAIN_END。
[/color][color=#0A246A]::                  [/color][color=#008000]; 没有理解这里触发异常是为什么,但是不妨碍分析异常处理流程。
[/color][color=#0A246A]>:                  [/color][color=#800080]80867548  [/color][color=#0A246A]push    [/color][color=#FF8000]esi [/color][color=#008000]; &l_ExceptionRecord
 [/color][color=#0A246A]:                  [/color][color=#800080]80867549  [/color][color=#0A246A]call    [/color][color=#000000]nt!ZwRaiseException [/color][color=#0A246A]([/color][color=#800080]8082ccd4[/color][color=#0A246A])
 :                
 :                [/color][color=#000000]nt!RtlUnwind[/color][color=#0A246A]+[/color][color=#800080]0x1f6 [/color][color=#0A246A][c:[/color][color=#000000]\wrk\wrk[/color][color=#0A246A]-[/color][color=#000000]v1.2\base\ntos\rtl\i386\exdsptch.c @ [/color][color=#800080]671[/color][color=#0A246A]]:
 >                  [/color][color=#800080]8086754e  [/color][color=#0A246A]mov     [/color][color=#FF8000]ecx[/color][color=#0A246A],dword ptr [[/color][color=#FF8000]ebp[/color][color=#0A246A]-[/color][color=#800080]4[/color][color=#0A246A]]
                    [/color][color=#800080]80867551  [/color][color=#0A246A]pop     [/color][color=#FF8000]edi
                    [/color][color=#800080]80867552  [/color][color=#0A246A]pop     [/color][color=#FF8000]esi
                    [/color][color=#800080]80867553  [/color][color=#0A246A]call    [/color][color=#000000]nt!__security_check_cookie [/color][color=#0A246A]([/color][color=#800080]80874e87[/color][color=#0A246A])
                    [/color][color=#800080]80867558  [/color][color=#0A246A]leave
                    [/color][color=#800080]80867559  [/color][color=#0A246A]ret     [/color][color=#800080]10h

        [/color][color=#000000]kd[/color][color=#0A246A]> [/color][color=#000000]uf [/color][color=#800080]80887be9 [/color][color=#008000]; RtlpExecuteHandlerForUnwind 的异常处理函数 
        [/color][color=#000000]nt!ExecuteHandler2[/color][color=#0A246A]+[/color][color=#800080]0x61 [/color][color=#0A246A][C:[/color][color=#000000]\wrk\wrk[/color][color=#0A246A]-[/color][color=#000000]v1.2\base\ntos\rtl\i386\xcptmisc.asm @ [/color][color=#800080]329[/color][color=#0A246A]]:
          [/color][color=#800080]80887be9  [/color][color=#0A246A]mov     [/color][color=#FF8000]ecx[/color][color=#0A246A],dword ptr [[/color][color=#FF8000]esp[/color][color=#0A246A]+[/color][color=#800080]4[/color][color=#0A246A]] [/color][color=#008000]; ecx = pExceptionRecord
          [/color][color=#800080]80887bed  [/color][color=#0A246A]test    dword ptr [[/color][color=#FF8000]ecx[/color][color=#0A246A]+[/color][color=#800080]4[/color][color=#0A246A]],[/color][color=#800080]6   [/color][color=#008000]; test pExceptionRecord->ExceptionFlags, EXCEPTION_UNWINDING | EXCEPTION_EXIT_UNWIND
          [/color][color=#800080]80887bf4  [/color][color=#0A246A]mov     [/color][color=#FF8000]eax[/color][color=#0A246A],[/color][color=#800080]1 [/color][color=#008000]; eax = ExceptionContinueSearch
          [/color][color=#800080]80887bf9  [/color][color=#0A246A]je      [/color][color=#000000]nt!ExecuteHandler2[/color][color=#0A246A]+[/color][color=#800080]0x85 [/color][color=#0A246A]([/color][color=#800080]80887c0d[/color][color=#0A246A])

        [/color][color=#000000]nt!ExecuteHandler2[/color][color=#0A246A]+[/color][color=#800080]0x73 [/color][color=#0A246A][C:[/color][color=#000000]\wrk\wrk[/color][color=#0A246A]-[/color][color=#000000]v1.2\base\ntos\rtl\i386\xcptmisc.asm @ [/color][color=#800080]341[/color][color=#0A246A]]:
          [/color][color=#008000]; 展开过程中 Handler 触发异常
          [/color][color=#800080]80887bfb  [/color][color=#0A246A]mov     [/color][color=#FF8000]ecx[/color][color=#0A246A],dword ptr [[/color][color=#FF8000]esp[/color][color=#0A246A]+[/color][color=#800080]8[/color][color=#0A246A]]   [/color][color=#008000]; ecx = pExceptionRegistration
          [/color][color=#800080]80887bff  [/color][color=#0A246A]mov     [/color][color=#FF8000]edx[/color][color=#0A246A],dword ptr [[/color][color=#FF8000]esp[/color][color=#0A246A]+[/color][color=#800080]10h[/color][color=#0A246A]] [/color][color=#008000]; edx = pDispatcherContext
          [/color][color=#800080]80887c03  [/color][color=#0A246A]mov     [/color][color=#FF8000]eax[/color][color=#0A246A],dword ptr [[/color][color=#FF8000]ecx[/color][color=#0A246A]+[/color][color=#800080]8[/color][color=#0A246A]]   [/color][color=#008000]; eax = pExceptionRegistration->prev
          [/color][color=#800080]80887c06  [/color][color=#0A246A]mov     dword ptr [[/color][color=#FF8000]edx[/color][color=#0A246A]],[/color][color=#FF8000]eax     [/color][color=#008000]; pDispatcherContext->RegistrationPointer = pExceptionRegistration->prev,
                                                    ; 然后 pDispatcherContext->RegistrationPointer 就是展开过程中正在被展开的
                                                    ; 那个 EXCEPTION_REGISTRATION_RECORD
          [/color][color=#800080]80887c08  [/color][color=#0A246A]mov     [/color][color=#FF8000]eax[/color][color=#0A246A],[/color][color=#800080]3 [/color][color=#008000]; eax = ExceptionCollidedUnwind

        [/color][color=#000000]nt!ExecuteHandler2[/color][color=#0A246A]+[/color][color=#800080]0x85 [/color][color=#0A246A][C:[/color][color=#000000]\wrk\wrk[/color][color=#0A246A]-[/color][color=#000000]v1.2\base\ntos\rtl\i386\xcptmisc.asm @ [/color][color=#800080]349[/color][color=#0A246A]]:
          [/color][color=#800080]80887c0d  [/color][color=#0A246A]ret     [/color][color=#800080]10h


    [/color][color=#000000]kd[/color][color=#0A246A]> [/color][color=#000000]uf RtlpExecuteHandlerForUnwind
        nt!RtlpExecuteHandlerForUnwind [/color][color=#0A246A][C:[/color][color=#000000]\wrk\wrk[/color][color=#0A246A]-[/color][color=#000000]v1.2\base\ntos\rtl\i386\xcptmisc.asm @ [/color][color=#800080]142[/color][color=#0A246A]]:
          [/color][color=#800080]80887b54  [/color][color=#0A246A]mov     [/color][color=#FF8000]edx[/color][color=#0A246A],offset [/color][color=#000000]nt!ExecuteHandler2[/color][color=#0A246A]+[/color][color=#800080]0x61 [/color][color=#0A246A]([/color][color=#800080]80887be9[/color][color=#0A246A])
          [/color][color=#800080]80887b59  [/color][color=#0A246A]lea     [/color][color=#FF8000]ecx[/color][color=#0A246A],[[/color][color=#FF8000]ecx[/color][color=#0A246A]]
          [/color][color=#800080]80887b5c  [/color][color=#0A246A]push    [/color][color=#FF8000]ebx
          [/color][color=#800080]80887b5d  [/color][color=#0A246A]push    [/color][color=#FF8000]esi
          [/color][color=#800080]80887b5e  [/color][color=#0A246A]push    [/color][color=#FF8000]edi
          [/color][color=#800080]80887b5f  [/color][color=#0A246A]xor     [/color][color=#FF8000]eax[/color][color=#0A246A],[/color][color=#FF8000]eax
          [/color][color=#800080]80887b61  [/color][color=#0A246A]xor     [/color][color=#FF8000]ebx[/color][color=#0A246A],[/color][color=#FF8000]ebx
          [/color][color=#800080]80887b63  [/color][color=#0A246A]xor     [/color][color=#FF8000]esi[/color][color=#0A246A],[/color][color=#FF8000]esi
          [/color][color=#800080]80887b65  [/color][color=#0A246A]xor     [/color][color=#FF8000]edi[/color][color=#0A246A],[/color][color=#FF8000]edi
          [/color][color=#800080]80887b67  [/color][color=#0A246A]push    dword ptr [[/color][color=#FF8000]esp[/color][color=#0A246A]+[/color][color=#800080]20h[/color][color=#0A246A]] [/color][color=#008000]; pExceptionRoutine
          [/color][color=#800080]80887b6b  [/color][color=#0A246A]push    dword ptr [[/color][color=#FF8000]esp[/color][color=#0A246A]+[/color][color=#800080]20h[/color][color=#0A246A]] [/color][color=#008000]; pDispatcherContext
          [/color][color=#800080]80887b6f  [/color][color=#0A246A]push    dword ptr [[/color][color=#FF8000]esp[/color][color=#0A246A]+[/color][color=#800080]20h[/color][color=#0A246A]] [/color][color=#008000]; pContext
          [/color][color=#800080]80887b73  [/color][color=#0A246A]push    dword ptr [[/color][color=#FF8000]esp[/color][color=#0A246A]+[/color][color=#800080]20h[/color][color=#0A246A]] [/color][color=#008000]; pExceptionRegistration
          [/color][color=#800080]80887b77  [/color][color=#0A246A]push    dword ptr [[/color][color=#FF8000]esp[/color][color=#0A246A]+[/color][color=#800080]20h[/color][color=#0A246A]] [/color][color=#008000]; pExceptionRecord
          [/color][color=#800080]80887b7b  [/color][color=#0A246A]call    [/color][color=#000000]nt!ExecuteHandler2 [/color][color=#0A246A]([/color][color=#800080]80887b88[/color][color=#0A246A])
          [/color][color=#800080]80887b80  [/color][color=#0A246A]pop     [/color][color=#FF8000]edi
          [/color][color=#800080]80887b81  [/color][color=#0A246A]pop     [/color][color=#FF8000]esi
          [/color][color=#800080]80887b82  [/color][color=#0A246A]pop     [/color][color=#FF8000]ebx
          [/color][color=#800080]80887b83  [/color][color=#0A246A]ret     [/color][color=#800080]14h

    [/color][color=#000000]kd[/color][color=#0A246A]> [/color][color=#000000]uf nt!ExecuteHandler2
        nt!ExecuteHandler2 [/color][color=#0A246A][C:[/color][color=#000000]\wrk\wrk[/color][color=#0A246A]-[/color][color=#000000]v1.2\base\ntos\rtl\i386\xcptmisc.asm @ [/color][color=#800080]188[/color][color=#0A246A]]:
          [/color][color=#800080]80887b88  [/color][color=#0A246A]push    [/color][color=#FF8000]ebp
          [/color][color=#800080]80887b89  [/color][color=#0A246A]mov     [/color][color=#FF8000]ebp[/color][color=#0A246A],[/color][color=#FF8000]esp
          [/color][color=#800080]80887b8b  [/color][color=#0A246A]push    dword ptr [[/color][color=#FF8000]ebp[/color][color=#0A246A]+[/color][color=#800080]0Ch[/color][color=#0A246A]] [/color][color=#008000]; pExceptionRegistration
          [/color][color=#800080]80887b8e  [/color][color=#0A246A]push    [/color][color=#FF8000]edx                 [/color][color=#008000]; _EXCEPTION_REGISTRATION_RECORD::Handler (nt!ExecuteHandler2+0x61 (80887be9))
          [/color][color=#800080]80887b8f  [/color][color=#0A246A]push    dword ptr [/color][color=#FF8000]fs[/color][color=#0A246A]:[[/color][color=#800080]0[/color][color=#0A246A]]    [/color][color=#008000]; _EXCEPTION_REGISTRATION_RECORD::Next
          [/color][color=#800080]80887b96  [/color][color=#0A246A]mov     dword ptr [/color][color=#FF8000]fs[/color][color=#0A246A]:[[/color][color=#800080]0[/color][color=#0A246A]],[/color][color=#FF8000]esp[/color][color=#008000]; 注意:这里使用的是原始版本的异常处理
          [/color][color=#800080]80887b9d  [/color][color=#0A246A]push    dword ptr [[/color][color=#FF8000]ebp[/color][color=#0A246A]+[/color][color=#800080]14h[/color][color=#0A246A]] [/color][color=#008000]; pDispatcherContext
          [/color][color=#800080]80887ba0  [/color][color=#0A246A]push    dword ptr [[/color][color=#FF8000]ebp[/color][color=#0A246A]+[/color][color=#800080]10h[/color][color=#0A246A]] [/color][color=#008000]; pContext
          [/color][color=#800080]80887ba3  [/color][color=#0A246A]push    dword ptr [[/color][color=#FF8000]ebp[/color][color=#0A246A]+[/color][color=#800080]0Ch[/color][color=#0A246A]] [/color][color=#008000]; pExceptionRegistration
          [/color][color=#800080]80887ba6  [/color][color=#0A246A]push    dword ptr [[/color][color=#FF8000]ebp[/color][color=#0A246A]+[/color][color=#800080]8[/color][color=#0A246A]]   [/color][color=#008000]; pExceptionRecord
          [/color][color=#800080]80887ba9  [/color][color=#0A246A]mov     [/color][color=#FF8000]ecx[/color][color=#0A246A],dword ptr [[/color][color=#FF8000]ebp[/color][color=#0A246A]+[/color][color=#800080]18h[/color][color=#0A246A]] [/color][color=#008000]; ecx = pExceptionRoutine
          [/color][color=#800080]80887bac  [/color][color=#0A246A]call    [/color][color=#FF8000]ecx [/color][color=#008000]; pExceptionRoutine(...),即 pExceptionRegistration->handler(...)
          [/color][color=#800080]80887bae  [/color][color=#0A246A]mov     [/color][color=#FF8000]esp[/color][color=#0A246A],dword ptr [/color][color=#FF8000]fs[/color][color=#0A246A]:[[/color][color=#800080]0[/color][color=#0A246A]]
          [/color][color=#800080]80887bb5  [/color][color=#0A246A]pop     dword ptr [/color][color=#FF8000]fs[/color][color=#0A246A]:[[/color][color=#800080]0[/color][color=#0A246A]]    [/color][color=#008000]; 摘掉当前 _EXCEPTION_REGISTRATION_RECORD
          [/color][color=#800080]80887bbc  [/color][color=#0A246A]mov     [/color][color=#FF8000]esp[/color][color=#0A246A],[/color][color=#FF8000]ebp
          [/color][color=#800080]80887bbe  [/color][color=#0A246A]pop     [/color][color=#FF8000]ebp
          [/color][color=#800080]80887bbf  [/color][color=#0A246A]ret     [/color][color=#800080]14h[/color][/font]


        代码不长,主要功能也不复杂:从异常链表头开始遍历,一直遍历到指定 EXCEPTION_REGISTRATION_RECORD,对每个遍历到的 EXCEPTION_REGISTRATION_RECORD,执行 RtlpExecuteHandlerForUnwind 进行局部展开。
        这段代码里有一个细节我没想明白,或者我想复杂了。在 nt!RtlUnwind 地址 80867401 处,当展开到指定 EXCEPTION_REGISTRATION 后,RtlUnwind 通过 ZwContinue 返回,而不是使用 ret 指令。通过静态分析和动态分析我都没有找到用 ZwContinue 的好处,或者不可替代的原因。如果有朋友有不同的结论,请分享一下。
        在分析全局展开时发生一件很囧的事,我反汇编完成,梳理流程的时候,总感觉“这个逻辑怎么这么熟悉,貌似在哪见过~ 难道 wrk 里有源码?”,翻开 wrk,果然有…… 不过话说回来,在反汇编分析过程让我对一些细节理解的更深刻了(也只能这么安慰自己了……)。

        下面我们来看看局部展开。
        在前面讲 PassThrough!_except_handler4 时,有提到该函数既负责处理异常也负责局部展开。其区分功能的标志就是判断 EXCEPTION_RECORD::ExceptionFlags 是否包含 EXCEPTION_UNWIND 标志位。可以参考 PassThrough!_except_handler4 中地址为 f87203dc 的指令:
        f87203dc  test    byte ptr [eax+4],66h      ; pExceptionRecord->ExceptionFlags & EXCEPTION_UNWIND,判断是异常处理过程还是展开过程
       
        该标志是在 RtlUnwind 中被设置的,可以参考 RtlUnwind 中地址为 808673b7 和 808673bd 出的指令:
        808673b7  or      dword ptr [esi+4],2 ; l_ExceptionRecord.ExceptionFlags |= EXCEPTION_UNWINDING (0x2)
        808673bd  or      dword ptr [esi+4],6 ; l_ExceptionRecord.ExceptionFlags |= EXCEPTION_UNWINDING | EXCEPTION_EXIT_UNWIND (0x2 | 0x4)

        反汇编代码:

        首先是我整理的 _EH4_LocalUnwind 的原型:
       VOID fastcall _EH4_LocalUnwind(
            PEXCEPTION_REGISTRATION pExceptionRegistartion,
            ULONG ulUntilTryLevel
            )

[font=Consolas][color=#000000]    kd[/color][color=#0A246A]> [/color][color=#000000]uf PassThrough!_EH4_LocalUnwind
        PassThrough!_EH4_LocalUnwind [/color][color=#0A246A][[/color][color=#000000]d[/color][color=#0A246A]:[/color][color=#000000]\[/color][color=#800080]5359[/color][color=#000000]\minkernel\crts\crtw32\misc\i386\exsup4.asm @ [/color][color=#800080]529[/color][color=#0A246A]]:
          [/color][color=#000000]f8720614  [/color][color=#0A246A]push    [/color][color=#FF8000]ebp
          [/color][color=#000000]f8720615  [/color][color=#0A246A]mov     [/color][color=#FF8000]ebp[/color][color=#0A246A],dword ptr [[/color][color=#FF8000]esp[/color][color=#0A246A]+[/color][color=#800080]8[/color][color=#0A246A]] [/color][color=#008000]; ebp = pExceptionRegistartion->_ebp
          [/color][color=#000000]f8720619  [/color][color=#0A246A]push    [/color][color=#FF8000]edx [/color][color=#008000]; ulUntilTryLevel
          [/color][color=#000000]f872061a  [/color][color=#0A246A]push    [/color][color=#FF8000]ecx [/color][color=#008000]; pExceptionRegistartion
          [/color][color=#000000]f872061b  [/color][color=#0A246A]push    dword ptr [[/color][color=#FF8000]esp[/color][color=#0A246A]+[/color][color=#800080]14h[/color][color=#0A246A]] [/color][color=#008000]; push __security_cookie
          [/color][color=#000000]f872061f  [/color][color=#0A246A]call    [/color][color=#000000]PassThrough!_local_unwind4 [/color][color=#0A246A]([/color][color=#000000]f87204ec[/color][color=#0A246A])
          [/color][color=#000000]f8720624  [/color][color=#0A246A]add     [/color][color=#FF8000]esp[/color][color=#0A246A],[/color][color=#800080]0Ch
          [/color][color=#000000]f8720627  [/color][color=#0A246A]pop     [/color][color=#FF8000]ebp
          [/color][color=#000000]f8720628  [/color][color=#0A246A]ret     [/color][color=#800080]8

    [/color][color=#000000]PassThrough!_EH4_LocalUnwind 的原型:
       VOID local_unwind4[/color][color=#0A246A](
           [/color][color=#000000]PEXCEPTION_REGSTRATION pExceptionRegstration[/color][color=#0A246A],
           [/color][color=#000000]ULONG ulUntilTryLevel
           [/color][color=#0A246A])

    [/color][color=#000000]kd[/color][color=#0A246A]> [/color][color=#000000]uf PassThrough!_local_unwind4
      PassThrough!_local_unwind4 [/color][color=#0A246A][[/color][color=#000000]d[/color][color=#0A246A]:[/color][color=#000000]\[/color][color=#800080]5359[/color][color=#000000]\minkernel\crts\crtw32\misc\i386\exsup4.asm @ [/color][color=#800080]177[/color][color=#0A246A]]:
        [/color][color=#000000]f87204ec  [/color][color=#0A246A]push    [/color][color=#FF8000]ebx
        [/color][color=#000000]f87204ed  [/color][color=#0A246A]push    [/color][color=#FF8000]esi
        [/color][color=#000000]f87204ee  [/color][color=#0A246A]push    [/color][color=#FF8000]edi
        [/color][color=#000000]f87204ef  [/color][color=#0A246A]mov     [/color][color=#FF8000]edx[/color][color=#0A246A],dword ptr [[/color][color=#FF8000]esp[/color][color=#0A246A]+[/color][color=#800080]10h[/color][color=#0A246A]] [/color][color=#008000]; edx = __security_cookie
        [/color][color=#000000]f87204f3  [/color][color=#0A246A]mov     [/color][color=#FF8000]eax[/color][color=#0A246A],dword ptr [[/color][color=#FF8000]esp[/color][color=#0A246A]+[/color][color=#800080]14h[/color][color=#0A246A]] [/color][color=#008000]; eax = pExceptionRegistartion
        [/color][color=#000000]f87204f7  [/color][color=#0A246A]mov     [/color][color=#FF8000]ecx[/color][color=#0A246A],dword ptr [[/color][color=#FF8000]esp[/color][color=#0A246A]+[/color][color=#800080]18h[/color][color=#0A246A]] [/color][color=#008000]; ecx = ulUntilTryLevel
        [/color][color=#000000]f87204fb  [/color][color=#0A246A]push    [/color][color=#FF8000]ebp
        [/color][color=#000000]f87204fc  [/color][color=#0A246A]push    [/color][color=#FF8000]edx [/color][color=#008000]; __security_cookie
        [/color][color=#000000]f87204fd  [/color][color=#0A246A]push    [/color][color=#FF8000]eax [/color][color=#008000]; pExceptionRegistartion
        [/color][color=#000000]f87204fe  [/color][color=#0A246A]push    [/color][color=#FF8000]ecx [/color][color=#008000]; ulUntilTryLevel
        [/color][color=#000000]f87204ff  [/color][color=#0A246A]push    [/color][color=#FF8000]ecx [/color][color=#008000]; 这里压入的值后续被 f8720513 处的指令修改
        [/color][color=#000000]f8720500  [/color][color=#0A246A]push    offset [/color][color=#000000]PassThrough!_unwind_handler4 [/color][color=#0A246A]([/color][color=#000000]f872056f[/color][color=#0A246A]) [/color][color=#008000]; _EXCEPTION_REGISTRATION_RECORD::handler
        [/color][color=#000000]f8720505  [/color][color=#0A246A]push    dword ptr [/color][color=#FF8000]fs[/color][color=#0A246A]:[[/color][color=#800080]0[/color][color=#0A246A]]  [/color][color=#008000]; _EXCEPTION_REGISTRATION_RECORD::prev, 注意这里使用的是原始版本
        [/color][color=#000000]f872050c  [/color][color=#0A246A]mov     [/color][color=#FF8000]eax[/color][color=#0A246A],dword ptr [[/color][color=#000000]PassThrough!__security_cookie [/color][color=#0A246A]([/color][color=#000000]f87220b0[/color][color=#0A246A])]
        [/color][color=#000000]f8720511  [/color][color=#0A246A]xor     [/color][color=#FF8000]eax[/color][color=#0A246A],[/color][color=#FF8000]esp [/color][color=#008000]; 这里是用 esp 来异或,而 esp 此时指向新 _EXCEPTION_REGISTRATION_RECORD
        [/color][color=#000000]f8720513  [/color][color=#0A246A]mov     dword ptr [[/color][color=#FF8000]esp[/color][color=#0A246A]+[/color][color=#800080]8[/color][color=#0A246A]],[/color][color=#FF8000]eax [/color][color=#008000]; [esp+8] 被赋予加密后的 __security_cookie
        [/color][color=#000000]f8720517  [/color][color=#0A246A]mov     dword ptr [/color][color=#FF8000]fs[/color][color=#0A246A]:[[/color][color=#800080]0[/color][color=#0A246A]],[/color][color=#FF8000]esp
      
      [/color][color=#000000]PassThrough!_local_unwind4[/color][color=#0A246A]+[/color][color=#800080]0x32 [/color][color=#0A246A][[/color][color=#000000]d[/color][color=#0A246A]:[/color][color=#000000]\[/color][color=#800080]5359[/color][color=#000000]\minkernel\crts\crtw32\misc\i386\exsup4.asm @ [/color][color=#800080]209[/color][color=#0A246A]]:
   >>   [/color][color=#000000]f872051e  [/color][color=#0A246A]mov     [/color][color=#FF8000]eax[/color][color=#0A246A],dword ptr [[/color][color=#FF8000]esp[/color][color=#0A246A]+[/color][color=#800080]30h[/color][color=#0A246A]] [/color][color=#008000]; eax = pExceptionRegistartion
   [/color][color=#0A246A]::   [/color][color=#000000]f8720522  [/color][color=#0A246A]mov     [/color][color=#FF8000]ebx[/color][color=#0A246A],dword ptr [[/color][color=#FF8000]eax[/color][color=#0A246A]+[/color][color=#800080]8[/color][color=#0A246A]]   [/color][color=#008000]; ebx = pExceptionRegistration->scopetable, 将 ebx 假称为 l_pCurScopeEntry
   [/color][color=#0A246A]::   [/color][color=#000000]f8720525  [/color][color=#0A246A]mov     [/color][color=#FF8000]ecx[/color][color=#0A246A],dword ptr [[/color][color=#FF8000]esp[/color][color=#0A246A]+[/color][color=#800080]2Ch[/color][color=#0A246A]] [/color][color=#008000]; ecx = &__security_cookie
   [/color][color=#0A246A]::   [/color][color=#000000]f8720529  [/color][color=#0A246A]xor     [/color][color=#FF8000]ebx[/color][color=#0A246A],dword ptr [[/color][color=#FF8000]ecx[/color][color=#0A246A]]     [/color][color=#008000]; 解密 scopetable
   [/color][color=#0A246A]::   [/color][color=#000000]f872052b  [/color][color=#0A246A]mov     [/color][color=#FF8000]esi[/color][color=#0A246A],dword ptr [[/color][color=#FF8000]eax[/color][color=#0A246A]+[/color][color=#800080]0Ch[/color][color=#0A246A]] [/color][color=#008000]; esi = pExceptionRegistration->trylevel
   [/color][color=#0A246A]::   [/color][color=#000000]f872052e  [/color][color=#0A246A]cmp     [/color][color=#FF8000]esi[/color][color=#0A246A],[/color][color=#800080]0FFFFFFFEh [/color][color=#008000]; cmp pExceptionRegistration->trylevel,TRYLEVEL_NONE
[/color][color=#0A246A]<  ::   [/color][color=#000000]f8720531  [/color][color=#0A246A]je      [/color][color=#000000]PassThrough!_local_unwind4[/color][color=#0A246A]+[/color][color=#800080]0x75 [/color][color=#0A246A]([/color][color=#000000]f8720561[/color][color=#0A246A]) [/color][color=#008000]; pExceptionRegistration->trylevel 等于 TRYLEVEL_NONE,无需遍历,返回
[/color][color=#0A246A]:  :: 
:  :: [/color][color=#000000]PassThrough!_local_unwind4[/color][color=#0A246A]+[/color][color=#800080]0x47 [/color][color=#0A246A][[/color][color=#000000]d[/color][color=#0A246A]:[/color][color=#000000]\[/color][color=#800080]5359[/color][color=#000000]\minkernel\crts\crtw32\misc\i386\exsup4.asm @ [/color][color=#800080]216[/color][color=#0A246A]]:
:  ::   [/color][color=#000000]f8720533  [/color][color=#0A246A]mov     [/color][color=#FF8000]edx[/color][color=#0A246A],dword ptr [[/color][color=#FF8000]esp[/color][color=#0A246A]+[/color][color=#800080]34h[/color][color=#0A246A]] [/color][color=#008000]; edx = ulUntilTryLevel
[/color][color=#0A246A]:  ::   [/color][color=#000000]f8720537  [/color][color=#0A246A]cmp     [/color][color=#FF8000]edx[/color][color=#0A246A],[/color][color=#800080]0FFFFFFFEh [/color][color=#008000]; cmp ulUntilTryLevel, TRYLEVEL_NONE
[/color][color=#0A246A]:< ::   [/color][color=#000000]f872053a  [/color][color=#0A246A]je      [/color][color=#000000]PassThrough!_local_unwind4[/color][color=#0A246A]+[/color][color=#800080]0x54 [/color][color=#0A246A]([/color][color=#000000]f8720540[/color][color=#0A246A])
:: :: 
:: :: [/color][color=#000000]PassThrough!_local_unwind4[/color][color=#0A246A]+[/color][color=#800080]0x50 [/color][color=#0A246A][[/color][color=#000000]d[/color][color=#0A246A]:[/color][color=#000000]\[/color][color=#800080]5359[/color][color=#000000]\minkernel\crts\crtw32\misc\i386\exsup4.asm @ [/color][color=#800080]219[/color][color=#0A246A]]:
:: ::   [/color][color=#000000]f872053c  [/color][color=#0A246A]cmp     [/color][color=#FF8000]esi[/color][color=#0A246A],[/color][color=#FF8000]edx [/color][color=#008000]; cmp pExceptionRegistration->trylevel, ulUntilTryLevel
[/color][color=#0A246A]::<::   [/color][color=#000000]f872053e  [/color][color=#0A246A]jbe     [/color][color=#000000]PassThrough!_local_unwind4[/color][color=#0A246A]+[/color][color=#800080]0x75 [/color][color=#0A246A]([/color][color=#000000]f8720561[/color][color=#0A246A]) [/color][color=#008000]; 已经遍历到指定 scopetable_entry 了,返回
[/color][color=#0A246A]::::: 
::::: [/color][color=#000000]PassThrough!_local_unwind4[/color][color=#0A246A]+[/color][color=#800080]0x54 [/color][color=#0A246A][[/color][color=#000000]d[/color][color=#0A246A]:[/color][color=#000000]\[/color][color=#800080]5359[/color][color=#000000]\minkernel\crts\crtw32\misc\i386\exsup4.asm @ [/color][color=#800080]221[/color][color=#0A246A]]:
:>:::   [/color][color=#000000]f8720540  [/color][color=#0A246A]lea     [/color][color=#FF8000]esi[/color][color=#0A246A],[[/color][color=#FF8000]esi[/color][color=#0A246A]+[/color][color=#FF8000]esi[/color][color=#0A246A]*[/color][color=#800080]2[/color][color=#0A246A]]
: :::   [/color][color=#000000]f8720543  [/color][color=#0A246A]lea     [/color][color=#FF8000]ebx[/color][color=#0A246A],[[/color][color=#FF8000]ebx[/color][color=#0A246A]+[/color][color=#FF8000]esi[/color][color=#0A246A]*[/color][color=#800080]4[/color][color=#0A246A]+[/color][color=#800080]10h[/color][color=#0A246A]] [/color][color=#008000]; ebx - pExceptionRegistration->scopetable[pExceptionRegistration->trylevel]
[/color][color=#0A246A]: :::   [/color][color=#000000]f8720547  [/color][color=#0A246A]mov     [/color][color=#FF8000]ecx[/color][color=#0A246A],dword ptr [[/color][color=#FF8000]ebx[/color][color=#0A246A]] [/color][color=#008000]; ecx = l_pCurScopeEntry->previousTryLevel
[/color][color=#0A246A]: :::   [/color][color=#000000]f8720549  [/color][color=#0A246A]mov     dword ptr [[/color][color=#FF8000]eax[/color][color=#0A246A]+[/color][color=#800080]0Ch[/color][color=#0A246A]],[/color][color=#FF8000]ecx [/color][color=#008000]; pExceptionRegistration->trylevel = ebx->l_pCurScopeEntry->previousTryLevel
[/color][color=#0A246A]: :::   [/color][color=#000000]f872054c  [/color][color=#0A246A]cmp     dword ptr [[/color][color=#FF8000]ebx[/color][color=#0A246A]+[/color][color=#800080]4[/color][color=#0A246A]],[/color][color=#800080]0 [/color][color=#008000]; cmp pExceptionRegistration->lpfnFilter,NULL
[/color][color=#0A246A]: :<:   [/color][color=#000000]f8720550  [/color][color=#0A246A]jne     [/color][color=#000000]PassThrough!_local_unwind4[/color][color=#0A246A]+[/color][color=#800080]0x32 [/color][color=#0A246A]([/color][color=#000000]f872051e[/color][color=#0A246A])
: : : 
: : : [/color][color=#000000]PassThrough!_local_unwind4[/color][color=#0A246A]+[/color][color=#800080]0x66 [/color][color=#0A246A][[/color][color=#000000]d[/color][color=#0A246A]:[/color][color=#000000]\[/color][color=#800080]5359[/color][color=#000000]\minkernel\crts\crtw32\misc\i386\exsup4.asm @ [/color][color=#800080]240[/color][color=#0A246A]]:
: : :   [/color][color=#000000]f8720552  [/color][color=#0A246A]mov     [/color][color=#FF8000]ecx[/color][color=#0A246A],[/color][color=#800080]1
[/color][color=#0A246A]: : :   [/color][color=#000000]f8720557  [/color][color=#0A246A]mov     [/color][color=#FF8000]eax[/color][color=#0A246A],dword ptr [[/color][color=#FF8000]ebx[/color][color=#0A246A]+[/color][color=#800080]8[/color][color=#0A246A]] [/color][color=#008000]; eax = pExceptionRegistration->lpfnHandler
[/color][color=#0A246A]: : :   [/color][color=#000000]f872055a  [/color][color=#0A246A]call    [/color][color=#000000]PassThrough!_NLG_Call [/color][color=#0A246A]([/color][color=#000000]f8720630[/color][color=#0A246A]) [/color][color=#008000]; 调用 pExceptionRegistration->lpfnHandler
[/color][color=#0A246A]: : <   [/color][color=#000000]f872055f  [/color][color=#0A246A]jmp     [/color][color=#000000]PassThrough!_local_unwind4[/color][color=#0A246A]+[/color][color=#800080]0x32 [/color][color=#0A246A]([/color][color=#000000]f872051e[/color][color=#0A246A])
: :   
: :   [/color][color=#000000]PassThrough!_local_unwind4[/color][color=#0A246A]+[/color][color=#800080]0x75 [/color][color=#0A246A][[/color][color=#000000]d[/color][color=#0A246A]:[/color][color=#000000]\[/color][color=#800080]5359[/color][color=#000000]\minkernel\crts\crtw32\misc\i386\exsup4.asm @ [/color][color=#800080]248[/color][color=#0A246A]]:
> >     [/color][color=#000000]f8720561  [/color][color=#0A246A]pop     dword ptr [/color][color=#FF8000]fs[/color][color=#0A246A]:[[/color][color=#800080]0[/color][color=#0A246A]]
        [/color][color=#000000]f8720568  [/color][color=#0A246A]add     [/color][color=#FF8000]esp[/color][color=#0A246A],[/color][color=#800080]18h
        [/color][color=#000000]f872056b  [/color][color=#0A246A]pop     [/color][color=#FF8000]edi
        [/color][color=#000000]f872056c  [/color][color=#0A246A]pop     [/color][color=#FF8000]esi
        [/color][color=#000000]f872056d  [/color][color=#0A246A]pop     [/color][color=#FF8000]ebx
        [/color][color=#000000]f872056e  [/color][color=#0A246A]ret
      
        [/color][color=#000000]kd[/color][color=#0A246A]> [/color][color=#000000]uf PassThrough!_NLG_Call
        PassThrough!_NLG_Call [/color][color=#0A246A][[/color][color=#000000]d[/color][color=#0A246A]:[/color][color=#000000]\[/color][color=#800080]5359[/color][color=#000000]\minkernel\crts\crtw32\misc\i386\nlgsupp.asm @ [/color][color=#800080]120[/color][color=#0A246A]]:
          [/color][color=#000000]f8720630  [/color][color=#0A246A]call    [/color][color=#FF8000]eax
          [/color][color=#000000]f8720632  [/color][color=#0A246A]ret
[/color][/font]


        PassThrough!_EH4_LocalUnwind 中 f8720500 处的指令用到的异常处理函数 PassThrough!_unwind_handler4 的反汇编代码:

[font=Consolas][color=#000000]    kd[/color][color=#0A246A]> [/color][color=#000000]uf PassThrough!_unwind_handler4
        PassThrough!_unwind_handler4 [/color][color=#0A246A][[/color][color=#000000]d[/color][color=#0A246A]:[/color][color=#000000]\[/color][color=#800080]5359[/color][color=#000000]\minkernel\crts\crtw32\misc\i386\exsup4.asm @ [/color][color=#800080]294[/color][color=#0A246A]]:
          [/color][color=#000000]f872056f  [/color][color=#0A246A]mov     [/color][color=#FF8000]ecx[/color][color=#0A246A],dword ptr [[/color][color=#FF8000]esp[/color][color=#0A246A]+[/color][color=#800080]4[/color][color=#0A246A]] [/color][color=#008000]; ecx = pExceptionRecord
          [/color][color=#000000]f8720573  [/color][color=#0A246A]test    dword ptr [[/color][color=#FF8000]ecx[/color][color=#0A246A]+[/color][color=#800080]4[/color][color=#0A246A]],[/color][color=#800080]6   [/color][color=#008000]; test pExceptionRecord->ExceptionFlags, EXCEPTION_UNWINDING | EXCEPTION_EXIT_UNWIND
          [/color][color=#000000]f872057a  [/color][color=#0A246A]mov     [/color][color=#FF8000]eax[/color][color=#0A246A],[/color][color=#800080]1 [/color][color=#008000]; eax = ExceptionContinueSearch (1)
          [/color][color=#000000]f872057f  [/color][color=#0A246A]je      [/color][color=#000000]PassThrough!_unwind_handler4[/color][color=#0A246A]+[/color][color=#800080]0x45 [/color][color=#0A246A]([/color][color=#000000]f87205b4[/color][color=#0A246A])

        [/color][color=#000000]PassThrough!_unwind_handler4[/color][color=#0A246A]+[/color][color=#800080]0x12 [/color][color=#0A246A][[/color][color=#000000]d[/color][color=#0A246A]:[/color][color=#000000]\[/color][color=#800080]5359[/color][color=#000000]\minkernel\crts\crtw32\misc\i386\exsup4.asm @ [/color][color=#800080]307[/color][color=#0A246A]]:
          [/color][color=#008000]; 在展开过程中又触发了异常,那么处理该新异常(实际操作只是做展开,即清理掉该异常占用的资源,并没有真正处理该异常)
          [/color][color=#000000]f8720581  [/color][color=#0A246A]mov     [/color][color=#FF8000]eax[/color][color=#0A246A],dword ptr [[/color][color=#FF8000]esp[/color][color=#0A246A]+[/color][color=#800080]8[/color][color=#0A246A]] [/color][color=#008000]; eax = pExceptionRegistration
          [/color][color=#000000]f8720585  [/color][color=#0A246A]mov     [/color][color=#FF8000]ecx[/color][color=#0A246A],dword ptr [[/color][color=#FF8000]eax[/color][color=#0A246A]+[/color][color=#800080]8[/color][color=#0A246A]] [/color][color=#008000]; ecx = __security_cookie, 注意这里不是 __pExceptionRegistration->scopetable
          [/color][color=#000000]f8720588  [/color][color=#0A246A]xor     [/color][color=#FF8000]ecx[/color][color=#0A246A],[/color][color=#FF8000]eax [/color][color=#008000]; 这里用 pExceptionRegistration 解密,PassThrough!_local_unwind4 中也正是用它进行加密的
                                    ; 参考 f8720511 处的指令
          [/color][color=#000000]f872058a  [/color][color=#0A246A]call    [/color][color=#000000]PassThrough!__security_check_cookie [/color][color=#0A246A]([/color][color=#000000]f8720638[/color][color=#0A246A])
          [/color][color=#000000]f872058f  [/color][color=#0A246A]push    [/color][color=#FF8000]ebp
          [/color][color=#000000]f8720590  [/color][color=#0A246A]mov     [/color][color=#FF8000]ebp[/color][color=#0A246A],dword ptr [[/color][color=#FF8000]eax[/color][color=#0A246A]+[/color][color=#800080]18h[/color][color=#0A246A]] [/color][color=#008000]; eax+18h 是被 PassThrough!_local_unwind4 压入栈的 ebp,
                                                    ; 参考 f87204fb 处的指令
          [/color][color=#000000]f8720593  [/color][color=#0A246A]push    dword ptr [[/color][color=#FF8000]eax[/color][color=#0A246A]+[/color][color=#800080]0Ch[/color][color=#0A246A]] [/color][color=#008000]; push ulUntilTryLevel
          [/color][color=#000000]f8720596  [/color][color=#0A246A]push    dword ptr [[/color][color=#FF8000]eax[/color][color=#0A246A]+[/color][color=#800080]10h[/color][color=#0A246A]] [/color][color=#008000]; pExceptionRegistartion
          [/color][color=#000000]f8720599  [/color][color=#0A246A]push    dword ptr [[/color][color=#FF8000]eax[/color][color=#0A246A]+[/color][color=#800080]14h[/color][color=#0A246A]] [/color][color=#008000]; __security_cookie
          [/color][color=#000000]f872059c  [/color][color=#0A246A]call    [/color][color=#000000]PassThrough!_local_unwind4 [/color][color=#0A246A]([/color][color=#000000]f87204ec[/color][color=#0A246A])
          [/color][color=#000000]f87205a1  [/color][color=#0A246A]add     [/color][color=#FF8000]esp[/color][color=#0A246A],[/color][color=#800080]0Ch
          [/color][color=#000000]f87205a4  [/color][color=#0A246A]pop     [/color][color=#FF8000]ebp
          [/color][color=#000000]f87205a5  [/color][color=#0A246A]mov     [/color][color=#FF8000]eax[/color][color=#0A246A],dword ptr [[/color][color=#FF8000]esp[/color][color=#0A246A]+[/color][color=#800080]8[/color][color=#0A246A]] [/color][color=#008000]; eax = pExceptionRegistration
          [/color][color=#000000]f87205a9  [/color][color=#0A246A]mov     [/color][color=#FF8000]edx[/color][color=#0A246A],dword ptr [[/color][color=#FF8000]esp[/color][color=#0A246A]+[/color][color=#800080]10h[/color][color=#0A246A]] [/color][color=#008000]; edx = pDispatcherContext (调整 pDispatcherContext,改变遍历顺序)
          [/color][color=#000000]f87205ad  [/color][color=#0A246A]mov     dword ptr [[/color][color=#FF8000]edx[/color][color=#0A246A]],[/color][color=#FF8000]eax   [/color][color=#008000]; pDispatcherContext->RegistrationPointer = pExceptionRegistration
          [/color][color=#000000]f87205af  [/color][color=#0A246A]mov     [/color][color=#FF8000]eax[/color][color=#0A246A],[/color][color=#800080]3 [/color][color=#008000]; eax = ExceptionCollidedUnwind (3)

        [/color][color=#000000]PassThrough!_unwind_handler4[/color][color=#0A246A]+[/color][color=#800080]0x45 [/color][color=#0A246A][[/color][color=#000000]d[/color][color=#0A246A]:[/color][color=#000000]\[/color][color=#800080]5359[/color][color=#000000]\minkernel\crts\crtw32\misc\i386\exsup4.asm @ [/color][color=#800080]336[/color][color=#0A246A]]:
          [/color][color=#000000]f87205b4  [/color][color=#0A246A]ret
[/color][/font]


        到这里概要流程就讲完了。在处理异常和展开过程中多处涉及到遍历操作,咱们来总结一下这些遍历操作。
        1. 在异常处理过程中,每个被"卷入是非"的异常都至少会遍历异常链表两次(如果发生嵌套异常,比如在展开过程中
EXCEPTION_REGISTRATION_RECORD::Handler 又触发异常,则会遍历更多次。不过这也可以算作是一个新异常了。看如何理解。)。
        一次是在 RtlDispatchException 中,遍历的目的是找到愿意处理该异常的 _EXCEPTION_REGISTRATION_RECORD。
        另一次是在展开过程中、RtlUnwind 函数内,遍历的目录是为了对每个遍历到的 EXCEPTION_REGISTRATION_RECORD 进行局部展开。
        2. 同样的,每个被"卷入是非"的异常的 scopetable 也会被遍历至少两次,
        一次是在 modulename!_except_handler? 中,遍历目的也是找到愿意处理该异常的 scopetable_entry。
        另一次是在展开过程中、_local_unwind4 函数内,遍历的目的是找到所有指定范围内的 scopetable_entry::lpfnFilter 为 NULL 的 scopetable_entry,调用它们的 lpfnHandler (即 __finally 处理块)。

        在展开过程中,__finally 代码块会被执行,在执行过程中有可能触发新的异常,增强版通过返回 ExceptionCollidedUnwind (3) 来标识这种情况(参考 PassThrough!_unwind_handler4 中 f87205af 处的指令)。咱来回顾下这类返回值:

[font=Consolas][color=#000000]    [/color][color=#0A246A]typedef [/color][color=#000000]enum _EXCEPTION_DISPOSITION {
        ExceptionContinueExecution[/color][color=#0A246A],
        [/color][color=#000000]ExceptionContinueSearch[/color][color=#0A246A],
        [/color][color=#000000]ExceptionNestedException[/color][color=#0A246A],
        [/color][color=#000000]ExceptionCollidedUnwind
    } EXCEPTION_DISPOSITION[/color][color=#008000];
[/color][/font]


        前面的代码中已经展示了上述4中的三种:
        ExceptionContinueExecution 表示继续执行(异常已经被修复);
        ExceptionContinueSearch 表示继续搜索(当前搜索到的异常注册信息不处理);
        ExceptionCollidedUnwind 表示在展开过程中再次触发异常。
        ExceptionNestedException 呢?到目前咱们还没有遇到过,什么情况会用到它?
       
        从字面上看 ExceptionNestedException 大概意思是“嵌套的异常”,是不是可以理解为“处理异常过程中再次触发的异常”?比如类似于 ExceptionCollidedUnwind,只不过 ExceptionCollidedUnwind 是在展开过程。而 ExceptionNestedException 是在处理异常过程中?
        咱们顺着这个思路去寻找,首先来看 PassThrough!_except_handler4,它是异常处理的入口了。处理和展开都是它负责的。可是翻遍了它和它的工具函数的反汇编码也没有找到它直接返回或者通过注册异常处理信息来间接返回。于是我决定继续向上层即调用者方向搜寻,于是找到了如下汇编码:

[font=Consolas][color=#000000]        kd[/color][color=#0A246A]> [/color][color=#000000]uf RtlpExecuteHandlerForException
        nt!RtlpExecuteHandlerForException [/color][color=#0A246A][C:[/color][color=#000000]\wrk\wrk[/color][color=#0A246A]-[/color][color=#000000]v1.2\base\ntos\rtl\i386\xcptmisc.asm @ [/color][color=#800080]87[/color][color=#0A246A]]:
          [/color][color=#800080]80887b4c  [/color][color=#0A246A]mov     [/color][color=#FF8000]edx[/color][color=#0A246A],offset [/color][color=#000000]nt!ExecuteHandler2[/color][color=#0A246A]+[/color][color=#800080]0x3a [/color][color=#0A246A]([/color][color=#800080]80887bc2[/color][color=#0A246A])
          [/color][color=#800080]80887b51  [/color][color=#0A246A]jmp     [/color][color=#000000]nt!ExecuteHandler [/color][color=#0A246A]([/color][color=#800080]80887b5c[/color][color=#0A246A])

        [/color][color=#000000]nt!ExecuteHandler [/color][color=#0A246A][C:[/color][color=#000000]\wrk\wrk[/color][color=#0A246A]-[/color][color=#000000]v1.2\base\ntos\rtl\i386\xcptmisc.asm @ [/color][color=#800080]160[/color][color=#0A246A]]:
          [/color][color=#800080]80887b5c  [/color][color=#0A246A]push    [/color][color=#FF8000]ebx
          [/color][color=#800080]80887b5d  [/color][color=#0A246A]push    [/color][color=#FF8000]esi
          [/color][color=#800080]80887b5e  [/color][color=#0A246A]push    [/color][color=#FF8000]edi
          [/color][color=#800080]80887b5f  [/color][color=#0A246A]xor     [/color][color=#FF8000]eax[/color][color=#0A246A],[/color][color=#FF8000]eax
          [/color][color=#800080]80887b61  [/color][color=#0A246A]xor     [/color][color=#FF8000]ebx[/color][color=#0A246A],[/color][color=#FF8000]ebx
          [/color][color=#800080]80887b63  [/color][color=#0A246A]xor     [/color][color=#FF8000]esi[/color][color=#0A246A],[/color][color=#FF8000]esi
          [/color][color=#800080]80887b65  [/color][color=#0A246A]xor     [/color][color=#FF8000]edi[/color][color=#0A246A],[/color][color=#FF8000]edi
          [/color][color=#800080]80887b67  [/color][color=#0A246A]push    dword ptr [[/color][color=#FF8000]esp[/color][color=#0A246A]+[/color][color=#800080]20h[/color][color=#0A246A]]
          [/color][color=#800080]80887b6b  [/color][color=#0A246A]push    dword ptr [[/color][color=#FF8000]esp[/color][color=#0A246A]+[/color][color=#800080]20h[/color][color=#0A246A]]
          [/color][color=#800080]80887b6f  [/color][color=#0A246A]push    dword ptr [[/color][color=#FF8000]esp[/color][color=#0A246A]+[/color][color=#800080]20h[/color][color=#0A246A]]
          [/color][color=#800080]80887b73  [/color][color=#0A246A]push    dword ptr [[/color][color=#FF8000]esp[/color][color=#0A246A]+[/color][color=#800080]20h[/color][color=#0A246A]]
          [/color][color=#800080]80887b77  [/color][color=#0A246A]push    dword ptr [[/color][color=#FF8000]esp[/color][color=#0A246A]+[/color][color=#800080]20h[/color][color=#0A246A]]
          [/color][color=#800080]80887b7b  [/color][color=#0A246A]call    [/color][color=#000000]nt!ExecuteHandler2 [/color][color=#0A246A]([/color][color=#800080]80887b88[/color][color=#0A246A])
          [/color][color=#800080]80887b80  [/color][color=#0A246A]pop     [/color][color=#FF8000]edi
          [/color][color=#800080]80887b81  [/color][color=#0A246A]pop     [/color][color=#FF8000]esi
          [/color][color=#800080]80887b82  [/color][color=#0A246A]pop     [/color][color=#FF8000]ebx
          [/color][color=#800080]80887b83  [/color][color=#0A246A]ret     [/color][color=#800080]14h

        [/color][color=#000000]kd[/color][color=#0A246A]> [/color][color=#000000]uf ExecuteHandler2
        nt!ExecuteHandler2 [/color][color=#0A246A][C:[/color][color=#000000]\wrk\wrk[/color][color=#0A246A]-[/color][color=#000000]v1.2\base\ntos\rtl\i386\xcptmisc.asm @ [/color][color=#800080]188[/color][color=#0A246A]]:
          [/color][color=#800080]80887b88  [/color][color=#0A246A]push    [/color][color=#FF8000]ebp
          [/color][color=#800080]80887b89  [/color][color=#0A246A]mov     [/color][color=#FF8000]ebp[/color][color=#0A246A],[/color][color=#FF8000]esp
          [/color][color=#800080]80887b8b  [/color][color=#0A246A]push    dword ptr [[/color][color=#FF8000]ebp[/color][color=#0A246A]+[/color][color=#800080]0Ch[/color][color=#0A246A]]
          [/color][color=#800080]80887b8e  [/color][color=#0A246A]push    [/color][color=#FF8000]edx
          [/color][color=#800080]80887b8f  [/color][color=#0A246A]push    dword ptr [/color][color=#FF8000]fs[/color][color=#0A246A]:[[/color][color=#800080]0[/color][color=#0A246A]]
          [/color][color=#800080]80887b96  [/color][color=#0A246A]mov     dword ptr [/color][color=#FF8000]fs[/color][color=#0A246A]:[[/color][color=#800080]0[/color][color=#0A246A]],[/color][color=#FF8000]esp [/color][color=#008000]; 注册新的异常处理结构
          [/color][color=#800080]80887b9d  [/color][color=#0A246A]push    dword ptr [[/color][color=#FF8000]ebp[/color][color=#0A246A]+[/color][color=#800080]14h[/color][color=#0A246A]]
          [/color][color=#800080]80887ba0  [/color][color=#0A246A]push    dword ptr [[/color][color=#FF8000]ebp[/color][color=#0A246A]+[/color][color=#800080]10h[/color][color=#0A246A]]
          [/color][color=#800080]80887ba3  [/color][color=#0A246A]push    dword ptr [[/color][color=#FF8000]ebp[/color][color=#0A246A]+[/color][color=#800080]0Ch[/color][color=#0A246A]]
          [/color][color=#800080]80887ba6  [/color][color=#0A246A]push    dword ptr [[/color][color=#FF8000]ebp[/color][color=#0A246A]+[/color][color=#800080]8[/color][color=#0A246A]]
          [/color][color=#800080]80887ba9  [/color][color=#0A246A]mov     [/color][color=#FF8000]ecx[/color][color=#0A246A],dword ptr [[/color][color=#FF8000]ebp[/color][color=#0A246A]+[/color][color=#800080]18h[/color][color=#0A246A]]
          [/color][color=#800080]80887bac  [/color][color=#0A246A]call    [/color][color=#FF8000]ecx
          [/color][color=#800080]80887bae  [/color][color=#0A246A]mov     [/color][color=#FF8000]esp[/color][color=#0A246A],dword ptr [/color][color=#FF8000]fs[/color][color=#0A246A]:[[/color][color=#800080]0[/color][color=#0A246A]]
          [/color][color=#800080]80887bb5  [/color][color=#0A246A]pop     dword ptr [/color][color=#FF8000]fs[/color][color=#0A246A]:[[/color][color=#800080]0[/color][color=#0A246A]]
          [/color][color=#800080]80887bbc  [/color][color=#0A246A]mov     [/color][color=#FF8000]esp[/color][color=#0A246A],[/color][color=#FF8000]ebp
          [/color][color=#800080]80887bbe  [/color][color=#0A246A]pop     [/color][color=#FF8000]ebp
          [/color][color=#800080]80887bbf  [/color][color=#0A246A]ret     [/color][color=#800080]14h

        [/color][color=#000000]kd[/color][color=#0A246A]> [/color][color=#000000]uf [/color][color=#800080]80887bc2 [/color][color=#008000]; ExecuteHandler2 使用的异常处理函数
        [/color][color=#000000]nt!ExecuteHandler2[/color][color=#0A246A]+[/color][color=#800080]0x3a [/color][color=#0A246A][C:[/color][color=#000000]\wrk\wrk[/color][color=#0A246A]-[/color][color=#000000]v1.2\base\ntos\rtl\i386\xcptmisc.asm @ [/color][color=#800080]268[/color][color=#0A246A]]:
          [/color][color=#800080]80887bc2  [/color][color=#0A246A]mov     [/color][color=#FF8000]ecx[/color][color=#0A246A],dword ptr [[/color][color=#FF8000]esp[/color][color=#0A246A]+[/color][color=#800080]4[/color][color=#0A246A]]
          [/color][color=#800080]80887bc6  [/color][color=#0A246A]test    dword ptr [[/color][color=#FF8000]ecx[/color][color=#0A246A]+[/color][color=#800080]4[/color][color=#0A246A]],[/color][color=#800080]6
          80887bcd  [/color][color=#0A246A]mov     [/color][color=#FF8000]eax[/color][color=#0A246A],[/color][color=#800080]1 [/color][color=#008000]; eax = ExceptionContinueSearch (1)
          [/color][color=#800080]80887bd2  [/color][color=#0A246A]jne     [/color][color=#000000]nt!ExecuteHandler2[/color][color=#0A246A]+[/color][color=#800080]0x5e [/color][color=#0A246A]([/color][color=#800080]80887be6[/color][color=#0A246A])

        [/color][color=#000000]nt!ExecuteHandler2[/color][color=#0A246A]+[/color][color=#800080]0x4c [/color][color=#0A246A][C:[/color][color=#000000]\wrk\wrk[/color][color=#0A246A]-[/color][color=#000000]v1.2\base\ntos\rtl\i386\xcptmisc.asm @ [/color][color=#800080]279[/color][color=#0A246A]]:
          [/color][color=#800080]80887bd4  [/color][color=#0A246A]mov     [/color][color=#FF8000]ecx[/color][color=#0A246A],dword ptr [[/color][color=#FF8000]esp[/color][color=#0A246A]+[/color][color=#800080]8[/color][color=#0A246A]]
          [/color][color=#800080]80887bd8  [/color][color=#0A246A]mov     [/color][color=#FF8000]edx[/color][color=#0A246A],dword ptr [[/color][color=#FF8000]esp[/color][color=#0A246A]+[/color][color=#800080]10h[/color][color=#0A246A]]
          [/color][color=#800080]80887bdc  [/color][color=#0A246A]mov     [/color][color=#FF8000]eax[/color][color=#0A246A],dword ptr [[/color][color=#FF8000]ecx[/color][color=#0A246A]+[/color][color=#800080]8[/color][color=#0A246A]]
          [/color][color=#800080]80887bdf  [/color][color=#0A246A]mov     dword ptr [[/color][color=#FF8000]edx[/color][color=#0A246A]],[/color][color=#FF8000]eax
          [/color][color=#800080]80887be1  [/color][color=#0A246A]mov     [/color][color=#FF8000]eax[/color][color=#0A246A],[/color][color=#800080]2 [/color][color=#008000]; eax = ExceptionNestedException (2)

        [/color][color=#000000]nt!ExecuteHandler2[/color][color=#0A246A]+[/color][color=#800080]0x5e [/color][color=#0A246A][C:[/color][color=#000000]\wrk\wrk[/color][color=#0A246A]-[/color][color=#000000]v1.2\base\ntos\rtl\i386\xcptmisc.asm @ [/color][color=#800080]287[/color][color=#0A246A]]:
          [/color][color=#800080]80887be6  [/color][color=#0A246A]ret     [/color][color=#800080]10h
[/color][/font]


        RtlpExecuteHandlerForException 函数是在 RtlDispatchException 中被调用。RtlDispatchException 在遍历异常链过程中并不直接调用 EXCEPTION_REGISTRATION_RECORD::Handler,而是通过 RtlpExecuteHandlerForException 来间接调用。RtlpExecuteHandlerForException 通过 ExecuteHandler2 建立一个异常处理块。
        PassThrough!_except_handler4 处理异常的过程中,如果再次触发异常,则会由地址为 80887bc2 的异常处理函数返回 ExceptionNestedException。因为这几个函数都很简单,而且跟之前分析的函数很类似,不再赘述。

        分析完这些,我有个疑问还是没有解开,我个人一直很奇怪增强版的使用方式为何不能这样:
        __try
        {
        }
        __except()
        {
        }
        __finally
        {
        }
        其中 __except 过滤块和处理块可以省略。
        但是很遗憾,MSC 中 __except 和 __finally 只能选其一。(当然,咱们可以用双层 __try 来实现同样的效果,但是总感觉不太爽,特别是会导致代码块被迫缩进两次)
        在分析的过程中我也发现我希望的这种方式更合理一些,__except 负责处理异常,在处理异常代码中被执行。如果没有处理异常,那么在展开过程中 __finally 代码块被执行,做一些清理操作。这样两者都存在,各负责各的,不是更好吗?不知道是不是什么历史原因。

        还有一个地方我也觉得不太完美。我们分析原始版本的时候发现,原始版本自身并没有直接使用展开,RtlDispatchException 等异常处理函数并没有直接调用 RtlUnwind。后者实际上是在增强版中才用到。我个人感觉这种模型并不完美,原始版本并没有自成体系,而是与增强版纠结在一起,没有很好的分层。

        另外,在实际应用中 SEH 机制可能会导致很难分析的内存泄漏。我们来看一个例子,
        调用流程:func1 -> func2
        其中,func1 的代码如下:
        VOID Func1()
        {
            __try
            {
                Func2();
            }
            __except(EXCEPTION_EXECUTE_HANDLER)
            {
                // 一些善后处理
            }
        }
       
        Func2 没有应用 SEH,它申请了一块内存,对这块内存进行操作,然后释放该内存。但是在操作内存时候触发异常,异常被 Func1 处理了,但是因为 Func2 没有 __finally 处理块,于是展开过程中 Func2 并没有机会去释放这块内存。结果就是:程序依然“正常”的在运行,但是实际上已经造成内存泄漏。随着程序执行,泄漏的资源可能越来越多。最后导致严重的系统故障。
       遇到这种问题,程序猿通过静态分析是很难找到泄漏的原因的。

        到这里差不多就啰嗦完了。最后,来一段总结。

        本文只是我分析 x86 下 windows 异常处理机制过程的一些笔记的集合。因为兴趣的原因,我只分析了内核部分,应用层 SEH 我没有琢磨。感兴趣的朋友可以参考《软件调试》中的相关内容,貌似挺详细的。
        后续我会抽时间再琢磨琢磨 x64 下 windows 的异常处理机制,前段时间查阅 x64 资料的时候看到其异常处理机制调整了很多,比如 EXCEPTION_REGISTRATION 不在是放在栈上,而是做成表。如果内部实现改变的较多,我会再写一份笔记来分享。sinister 师傅有过这么一段话,我很认同:
        “交流都是建立在平等的基础上,在抱怨氛围和环境不好的同时应该先想一想自己究竟付出了多少?只知索取不愿付出的人也就不用抱怨了,要怪也只能怪自己。发自己心得的人无非是两种目的,一是引发一些讨论,好纠正自己错误的认识,以便从中获取更多的知识使自己进步的更快。二是做一份备忘,当自己遗忘的时候能够马上找到相关资料。”
        其中提到的两种目的我都有 :-)
        还是那句老话,FIXME。
2011-10-5 12:58
0
雪    币: 342
活跃值: (199)
能力值: ( LV7,RANK:100 )
在线值:
发帖
回帖
粉丝
5
附录1 《Ntfs!_except_handler3 的反汇编代码》

[font=Consolas][color=#000000]         kd[/color][color=#0A246A]> [/color][color=#000000]uf Ntfs!_except_handler3
         [/color][color=#008000];nt!_except_handler3 [d:\dnsrv\base\crts\crtw32\misc\i386\exsup3.asm @ 172]:
           [/color][color=#800080]80872c00  [/color][color=#0A246A]push    [/color][color=#FF8000]ebp
           [/color][color=#800080]80872c01  [/color][color=#0A246A]mov     [/color][color=#FF8000]ebp[/color][color=#0A246A],[/color][color=#FF8000]esp
           [/color][color=#800080]80872c03  [/color][color=#0A246A]sub     [/color][color=#FF8000]esp[/color][color=#0A246A],[/color][color=#800080]8
           80872c06  [/color][color=#0A246A]push    [/color][color=#FF8000]ebx
           [/color][color=#800080]80872c07  [/color][color=#0A246A]push    [/color][color=#FF8000]esi
           [/color][color=#800080]80872c08  [/color][color=#0A246A]push    [/color][color=#FF8000]edi
           [/color][color=#800080]80872c09  [/color][color=#0A246A]push    [/color][color=#FF8000]ebp
           [/color][color=#800080]80872c0a  [/color][color=#0A246A]cld
           [/color][color=#800080]80872c0b  [/color][color=#0A246A]mov     [/color][color=#FF8000]ebx[/color][color=#0A246A],dword ptr [[/color][color=#FF8000]ebp[/color][color=#0A246A]+[/color][color=#800080]0Ch[/color][color=#0A246A]] [/color][color=#008000]; pExceptionRegistration
           [/color][color=#800080]80872c0e  [/color][color=#0A246A]mov     [/color][color=#FF8000]eax[/color][color=#0A246A],dword ptr [[/color][color=#FF8000]ebp[/color][color=#0A246A]+[/color][color=#800080]8[/color][color=#0A246A]]   [/color][color=#008000]; pExceptionRecord
           [/color][color=#800080]80872c11  [/color][color=#0A246A]test    dword ptr [[/color][color=#FF8000]eax[/color][color=#0A246A]+[/color][color=#800080]4[/color][color=#0A246A]],[/color][color=#800080]6     [/color][color=#008000]; test pExceptionRecord->ExceptionFlags, (EXCEPTION_UNWINDING | EXCEPTION_EXIT_UNWIND)
[/color][color=#0A246A]<          [/color][color=#800080]80872c18  [/color][color=#0A246A]jne     [/color][color=#000000]nt!_except_handler3[/color][color=#0A246A]+[/color][color=#800080]0xc9 [/color][color=#0A246A]([/color][color=#800080]80872cc9[/color][color=#0A246A])
:        
:        [/color][color=#008000];nt!_except_handler3+0x1e [d:\dnsrv\base\crts\crtw32\misc\i386\exsup3.asm @ 202]:
[/color][color=#0A246A]:          [/color][color=#008000]; ebp-8 和 ebp-4 是一个类型为 PEXCEPTION_POINTERS 的结构体,称之为 l_ExceptionPointers
[/color][color=#0A246A]:          [/color][color=#800080]80872c1e  [/color][color=#0A246A]mov     dword ptr [[/color][color=#FF8000]ebp[/color][color=#0A246A]-[/color][color=#800080]8[/color][color=#0A246A]],[/color][color=#FF8000]eax   [/color][color=#008000]; l_ExceptionPointers->ExceptionRecord = pExceptionRecord
[/color][color=#0A246A]:          [/color][color=#800080]80872c21  [/color][color=#0A246A]mov     [/color][color=#FF8000]eax[/color][color=#0A246A],dword ptr [[/color][color=#FF8000]ebp[/color][color=#0A246A]+[/color][color=#800080]10h[/color][color=#0A246A]] [/color][color=#008000]; eax = pContext
[/color][color=#0A246A]:          [/color][color=#800080]80872c24  [/color][color=#0A246A]mov     dword ptr [[/color][color=#FF8000]ebp[/color][color=#0A246A]-[/color][color=#800080]4[/color][color=#0A246A]],[/color][color=#FF8000]eax   [/color][color=#008000]; l_ExceptionPointers->ContextRecord = pContext
[/color][color=#0A246A]:          [/color][color=#800080]80872c27  [/color][color=#0A246A]lea     [/color][color=#FF8000]eax[/color][color=#0A246A],[[/color][color=#FF8000]ebp[/color][color=#0A246A]-[/color][color=#800080]8[/color][color=#0A246A]]             [/color][color=#008000]; eax = lException
[/color][color=#0A246A]:          [/color][color=#800080]80872c2a  [/color][color=#0A246A]mov     dword ptr [[/color][color=#FF8000]ebx[/color][color=#0A246A]-[/color][color=#800080]4[/color][color=#0A246A]],[/color][color=#FF8000]eax   [/color][color=#008000]; ebx-4 指向 pExceptionRegistration 所在栈上类型为 PEXCEPTION_POINTERS 的变量
[/color][color=#0A246A]:                            [/color][color=#008000]; 具体栈的构造形式请参考当时建立 pExceptionRegistration 的代码
[/color][color=#0A246A]:                            [/color][color=#008000]; 这里是赋值给该 PEXCEPTION_POINTERS 变量,以提供给 GetExceptionInformation 和 GetExceptionCode 使用
[/color][color=#0A246A]:          [/color][color=#800080]80872c2d  [/color][color=#0A246A]mov     [/color][color=#FF8000]esi[/color][color=#0A246A],dword ptr [[/color][color=#FF8000]ebx[/color][color=#0A246A]+[/color][color=#800080]0Ch[/color][color=#0A246A]] [/color][color=#008000]; esi = pExceptionRegistration->trylevel
[/color][color=#0A246A]:          [/color][color=#800080]80872c30  [/color][color=#0A246A]mov     [/color][color=#FF8000]edi[/color][color=#0A246A],dword ptr [[/color][color=#FF8000]ebx[/color][color=#0A246A]+[/color][color=#800080]8[/color][color=#0A246A]]   [/color][color=#008000]; edi = pExceptionRegistration->scopetable
[/color][color=#0A246A]:          [/color][color=#800080]80872c33  [/color][color=#0A246A]push    [/color][color=#FF8000]ebx
[/color][color=#0A246A]:          [/color][color=#800080]80872c34  [/color][color=#0A246A]call    [/color][color=#000000]nt!_ValidateEH3RN [/color][color=#0A246A]([/color][color=#800080]8087cde8[/color][color=#0A246A])
:          [/color][color=#800080]80872c39  [/color][color=#0A246A]add     [/color][color=#FF8000]esp[/color][color=#0A246A],[/color][color=#800080]4
[/color][color=#0A246A]:          [/color][color=#800080]80872c3c  [/color][color=#0A246A]or      [/color][color=#FF8000]eax[/color][color=#0A246A],[/color][color=#FF8000]eax
[/color][color=#0A246A]:<         [/color][color=#800080]80872c3e  [/color][color=#0A246A]je      [/color][color=#000000]nt!_except_handler3[/color][color=#0A246A]+[/color][color=#800080]0xbb [/color][color=#0A246A]([/color][color=#800080]80872cbb[/color][color=#0A246A])
::       
::       [/color][color=#008000];nt!_except_handler3+0x40 [d:\dnsrv\base\crts\crtw32\misc\i386\exsup3.asm @ 218]:
[/color][color=#0A246A]::    >    [/color][color=#800080]80872c40  [/color][color=#0A246A]cmp     [/color][color=#FF8000]esi[/color][color=#0A246A],[/color][color=#800080]0FFFFFFFFh  [/color][color=#008000]; cmp pExceptionRegistration->trylevel, TRYLEVEL_NONE
[/color][color=#0A246A]::<   :    [/color][color=#800080]80872c43  [/color][color=#0A246A]je      [/color][color=#000000]nt!_except_handler3[/color][color=#0A246A]+[/color][color=#800080]0xc2 [/color][color=#0A246A]([/color][color=#800080]80872cc2[/color][color=#0A246A])
:::   :  
:::   :  [/color][color=#008000];nt!_except_handler3+0x45 [d:\dnsrv\base\crts\crtw32\misc\i386\exsup3.asm @ 220]:
[/color][color=#0A246A]:::   :    [/color][color=#800080]80872c45  [/color][color=#0A246A]lea     [/color][color=#FF8000]ecx[/color][color=#0A246A],[[/color][color=#FF8000]esi[/color][color=#0A246A]+[/color][color=#FF8000]esi[/color][color=#0A246A]*[/color][color=#800080]2[/color][color=#0A246A]]              [/color][color=#008000]; esi *= 3; 下面要将 eis*4,总共 esi*12,这是因为 scopetable_entry 大小是12
[/color][color=#0A246A]:::   :    [/color][color=#800080]80872c48  [/color][color=#0A246A]mov     [/color][color=#FF8000]eax[/color][color=#0A246A],dword ptr [[/color][color=#FF8000]edi[/color][color=#0A246A]+[/color][color=#FF8000]ecx[/color][color=#0A246A]*[/color][color=#800080]4[/color][color=#0A246A]+[/color][color=#800080]4[/color][color=#0A246A]]  [/color][color=#008000]; eax = pExceptionRegistration->scopetable[i].lpfnFilter
[/color][color=#0A246A]:::   :    [/color][color=#800080]80872c4c  [/color][color=#0A246A]or      [/color][color=#FF8000]eax[/color][color=#0A246A],[/color][color=#FF8000]eax
[/color][color=#0A246A]:::<  :    [/color][color=#800080]80872c4e  [/color][color=#0A246A]je      [/color][color=#000000]nt!_except_handler3[/color][color=#0A246A]+[/color][color=#800080]0xa9 [/color][color=#0A246A]([/color][color=#800080]80872ca9[/color][color=#0A246A]) [/color][color=#008000]; lpfnFilter 为 NULL 则跳转
[/color][color=#0A246A]::::  :  
::::  :  [/color][color=#008000];nt!_except_handler3+0x50 [d:\dnsrv\base\crts\crtw32\misc\i386\exsup3.asm @ 226]:
[/color][color=#0A246A]::::  :    [/color][color=#800080]80872c50  [/color][color=#0A246A]push    [/color][color=#FF8000]esi
[/color][color=#0A246A]::::  :    [/color][color=#800080]80872c51  [/color][color=#0A246A]push    [/color][color=#FF8000]ebp
[/color][color=#0A246A]::::  :    [/color][color=#800080]80872c52  [/color][color=#0A246A]lea     [/color][color=#FF8000]ebp[/color][color=#0A246A],[[/color][color=#FF8000]ebx[/color][color=#0A246A]+[/color][color=#800080]10h[/color][color=#0A246A]] [/color][color=#008000]; ebp = pExceptionRegistration->_ebp
[/color][color=#0A246A]::::  :    [/color][color=#800080]80872c55  [/color][color=#0A246A]xor     [/color][color=#FF8000]ebx[/color][color=#0A246A],[/color][color=#FF8000]ebx
[/color][color=#0A246A]::::  :    [/color][color=#800080]80872c57  [/color][color=#0A246A]xor     [/color][color=#FF8000]ecx[/color][color=#0A246A],[/color][color=#FF8000]ecx
[/color][color=#0A246A]::::  :    [/color][color=#800080]80872c59  [/color][color=#0A246A]xor     [/color][color=#FF8000]edx[/color][color=#0A246A],[/color][color=#FF8000]edx
[/color][color=#0A246A]::::  :    [/color][color=#800080]80872c5b  [/color][color=#0A246A]xor     [/color][color=#FF8000]esi[/color][color=#0A246A],[/color][color=#FF8000]esi
[/color][color=#0A246A]::::  :    [/color][color=#800080]80872c5d  [/color][color=#0A246A]xor     [/color][color=#FF8000]edi[/color][color=#0A246A],[/color][color=#FF8000]edi
[/color][color=#0A246A]::::  :    [/color][color=#800080]80872c5f  [/color][color=#0A246A]call    [/color][color=#FF8000]eax           [/color][color=#008000]; pExceptionRegistration->scopetable[i].lpfnFilter()
[/color][color=#0A246A]::::  :    [/color][color=#800080]80872c61  [/color][color=#0A246A]pop     [/color][color=#FF8000]ebp
[/color][color=#0A246A]::::  :    [/color][color=#800080]80872c62  [/color][color=#0A246A]pop     [/color][color=#FF8000]esi
[/color][color=#0A246A]::::  :    [/color][color=#800080]80872c63  [/color][color=#0A246A]mov     [/color][color=#FF8000]ebx[/color][color=#0A246A],dword ptr [[/color][color=#FF8000]ebp[/color][color=#0A246A]+[/color][color=#800080]0Ch[/color][color=#0A246A]] [/color][color=#008000]; ebx = pExceptionRegistration
[/color][color=#0A246A]::::  :    [/color][color=#800080]80872c66  [/color][color=#0A246A]or      [/color][color=#FF8000]eax[/color][color=#0A246A],[/color][color=#FF8000]eax
[/color][color=#0A246A]::::< :    [/color][color=#800080]80872c68  [/color][color=#0A246A]je      [/color][color=#000000]nt!_except_handler3[/color][color=#0A246A]+[/color][color=#800080]0xa9 [/color][color=#0A246A]([/color][color=#800080]80872ca9[/color][color=#0A246A]) [/color][color=#008000]; EXCEPTION_CONTINUE_SEARCH
[/color][color=#0A246A]::::: :  
::::: :  [/color][color=#008000];nt!_except_handler3+0x6a [d:\dnsrv\base\crts\crtw32\misc\i386\exsup3.asm @ 245]:
[/color][color=#0A246A]::::: :    [/color][color=#008000]; 如果 lpfnFilter 返回 EXCEPTION_CONTINUE_EXECUTION,跳过下面的展开操作
[/color][color=#0A246A]:::::<:    [/color][color=#800080]80872c6a  [/color][color=#0A246A]js      [/color][color=#000000]nt!_except_handler3[/color][color=#0A246A]+[/color][color=#800080]0xb4 [/color][color=#0A246A]([/color][color=#800080]80872cb4[/color][color=#0A246A]) [/color][color=#008000]; EXCEPTION_CONTINUE_EXECUTION
[/color][color=#0A246A]:::::::  
:::::::  [/color][color=#008000];nt!_except_handler3+0x6c [d:\dnsrv\base\crts\crtw32\misc\i386\exsup3.asm @ 249]:
[/color][color=#0A246A]:::::::    [/color][color=#008000]; lpfnFilter 返回 EXCEPTION_EXECUTE_HANDLER,开始展开
[/color][color=#0A246A]:::::::    [/color][color=#800080]80872c6c  [/color][color=#0A246A]mov     [/color][color=#FF8000]edi[/color][color=#0A246A],dword ptr [[/color][color=#FF8000]ebx[/color][color=#0A246A]+[/color][color=#800080]8[/color][color=#0A246A]] [/color][color=#008000]; edi = pExceptionRegistration->scopetable
[/color][color=#0A246A]:::::::    [/color][color=#800080]80872c6f  [/color][color=#0A246A]push    [/color][color=#FF8000]ebx
[/color][color=#0A246A]:::::::    [/color][color=#800080]80872c70  [/color][color=#0A246A]call    [/color][color=#000000]nt!__global_unwind2 [/color][color=#0A246A]([/color][color=#800080]80872520[/color][color=#0A246A])
:::::::    [/color][color=#800080]80872c75  [/color][color=#0A246A]add     [/color][color=#FF8000]esp[/color][color=#0A246A],[/color][color=#800080]4
[/color][color=#0A246A]:::::::
:::::::    [/color][color=#800080]80872c78  [/color][color=#0A246A]lea     [/color][color=#FF8000]ebp[/color][color=#0A246A],[[/color][color=#FF8000]ebx[/color][color=#0A246A]+[/color][color=#800080]10h[/color][color=#0A246A]] [/color][color=#008000]; ebp = pExceptionRegistration->_ebp
[/color][color=#0A246A]:::::::    [/color][color=#800080]80872c7b  [/color][color=#0A246A]push    [/color][color=#FF8000]esi [/color][color=#008000]; 展开到当前 trylevel 为止(不包含本 scopetable_entry)
[/color][color=#0A246A]:::::::    [/color][color=#800080]80872c7c  [/color][color=#0A246A]push    [/color][color=#FF8000]ebx
[/color][color=#0A246A]:::::::    [/color][color=#800080]80872c7d  [/color][color=#0A246A]call    [/color][color=#000000]nt!__local_unwind2 [/color][color=#0A246A]([/color][color=#800080]8087257b[/color][color=#0A246A])
:::::::    [/color][color=#800080]80872c82  [/color][color=#0A246A]add     [/color][color=#FF8000]esp[/color][color=#0A246A],[/color][color=#800080]8
[/color][color=#0A246A]:::::::
:::::::    [/color][color=#800080]80872c85  [/color][color=#0A246A]lea     [/color][color=#FF8000]ecx[/color][color=#0A246A],[[/color][color=#FF8000]esi[/color][color=#0A246A]+[/color][color=#FF8000]esi[/color][color=#0A246A]*[/color][color=#800080]2[/color][color=#0A246A]]
:::::::    [/color][color=#800080]80872c88  [/color][color=#0A246A]push    [/color][color=#800080]1
[/color][color=#0A246A]:::::::    [/color][color=#800080]80872c8a  [/color][color=#0A246A]mov     [/color][color=#FF8000]eax[/color][color=#0A246A],dword ptr [[/color][color=#FF8000]edi[/color][color=#0A246A]+[/color][color=#FF8000]ecx[/color][color=#0A246A]*[/color][color=#800080]4[/color][color=#0A246A]+[/color][color=#800080]8[/color][color=#0A246A]]  [/color][color=#008000]; pExceptionRegistration->scopetable[i].lpfnHandler
[/color][color=#0A246A]:::::::    [/color][color=#800080]80872c8e  [/color][color=#0A246A]call    [/color][color=#000000]nt!_NLG_Notify [/color][color=#0A246A]([/color][color=#800080]80872617[/color][color=#0A246A])
:::::::    [/color][color=#800080]80872c93  [/color][color=#0A246A]mov     [/color][color=#FF8000]eax[/color][color=#0A246A],dword ptr [[/color][color=#FF8000]edi[/color][color=#0A246A]+[/color][color=#FF8000]ecx[/color][color=#0A246A]*[/color][color=#800080]4[/color][color=#0A246A]]  [/color][color=#008000]; 
[/color][color=#0A246A]:::::::    [/color][color=#800080]80872c96  [/color][color=#0A246A]mov     dword ptr [[/color][color=#FF8000]ebx[/color][color=#0A246A]+[/color][color=#800080]0Ch[/color][color=#0A246A]],[/color][color=#FF8000]eax      [/color][color=#008000]; pExceptionRegistration->trylevel = RegistrationPointer->scopetable[i].previousTryLevel
[/color][color=#0A246A]:::::::    [/color][color=#800080]80872c99  [/color][color=#0A246A]mov     [/color][color=#FF8000]eax[/color][color=#0A246A],dword ptr [[/color][color=#FF8000]edi[/color][color=#0A246A]+[/color][color=#FF8000]ecx[/color][color=#0A246A]*[/color][color=#800080]4[/color][color=#0A246A]+[/color][color=#800080]8[/color][color=#0A246A]]  [/color][color=#008000]; pExceptionRegistration->scopetable[i].lpfnHandler 
[/color][color=#0A246A]:::::::    [/color][color=#800080]80872c9d  [/color][color=#0A246A]xor     [/color][color=#FF8000]ebx[/color][color=#0A246A],[/color][color=#FF8000]ebx
[/color][color=#0A246A]:::::::    [/color][color=#800080]80872c9f  [/color][color=#0A246A]xor     [/color][color=#FF8000]ecx[/color][color=#0A246A],[/color][color=#FF8000]ecx
[/color][color=#0A246A]:::::::    [/color][color=#800080]80872ca1  [/color][color=#0A246A]xor     [/color][color=#FF8000]edx[/color][color=#0A246A],[/color][color=#FF8000]edx
[/color][color=#0A246A]:::::::    [/color][color=#800080]80872ca3  [/color][color=#0A246A]xor     [/color][color=#FF8000]esi[/color][color=#0A246A],[/color][color=#FF8000]esi
[/color][color=#0A246A]:::::::    [/color][color=#800080]80872ca5  [/color][color=#0A246A]xor     [/color][color=#FF8000]edi[/color][color=#0A246A],[/color][color=#FF8000]edi
[/color][color=#0A246A]:::::::    [/color][color=#800080]80872ca7  [/color][color=#0A246A]call    [/color][color=#FF8000]eax [/color][color=#008000]; pExceptionRegistration->scopetable[i].lpfnHandler(); 这里不会返回的!!
[/color][color=#0A246A]:::::::  
:::::::  [/color][color=#008000];nt!_except_handler3+0xa9 [d:\dnsrv\base\crts\crtw32\misc\i386\exsup3.asm @ 285]:
[/color][color=#0A246A]:::::::    [/color][color=#008000]; 找到 scopetable 中的下一个 scopetable_entry,继续循环
[/color][color=#0A246A]:::>>::    [/color][color=#800080]80872ca9  [/color][color=#0A246A]mov     [/color][color=#FF8000]edi[/color][color=#0A246A],dword ptr [[/color][color=#FF8000]ebx[/color][color=#0A246A]+[/color][color=#800080]8[/color][color=#0A246A]]
:::  ::    [/color][color=#800080]80872cac  [/color][color=#0A246A]lea     [/color][color=#FF8000]ecx[/color][color=#0A246A],[[/color][color=#FF8000]esi[/color][color=#0A246A]+[/color][color=#FF8000]esi[/color][color=#0A246A]*[/color][color=#800080]2[/color][color=#0A246A]]
:::  ::    [/color][color=#800080]80872caf  [/color][color=#0A246A]mov     [/color][color=#FF8000]esi[/color][color=#0A246A],dword ptr [[/color][color=#FF8000]edi[/color][color=#0A246A]+[/color][color=#FF8000]ecx[/color][color=#0A246A]*[/color][color=#800080]4[/color][color=#0A246A]] 
:::  :<    [/color][color=#800080]80872cb2  [/color][color=#0A246A]jmp     [/color][color=#000000]nt!_except_handler3[/color][color=#0A246A]+[/color][color=#800080]0x40 [/color][color=#0A246A]([/color][color=#800080]80872c40[/color][color=#0A246A])
:::  :   
:::  :   [/color][color=#008000];nt!_except_handler3+0xb4 [d:\dnsrv\base\crts\crtw32\misc\i386\exsup3.asm @ 291]:
[/color][color=#0A246A]:::  >     [/color][color=#800080]80872cb4  [/color][color=#0A246A]mov     [/color][color=#FF8000]eax[/color][color=#0A246A],[/color][color=#800080]0 [/color][color=#008000]; eax = ExceptionContinueExecution (0)
[/color][color=#0A246A]:::   <    [/color][color=#800080]80872cb9  [/color][color=#0A246A]jmp     [/color][color=#000000]nt!_except_handler3[/color][color=#0A246A]+[/color][color=#800080]0xde [/color][color=#0A246A]([/color][color=#800080]80872cde[/color][color=#0A246A])
:::   :  
:::   :  [/color][color=#008000];nt!_except_handler3+0xbb [d:\dnsrv\base\crts\crtw32\misc\i386\exsup3.asm @ 295]:
[/color][color=#0A246A]:>:   :    [/color][color=#800080]80872cbb  [/color][color=#0A246A]mov     [/color][color=#FF8000]eax[/color][color=#0A246A],dword ptr [[/color][color=#FF8000]ebp[/color][color=#0A246A]+[/color][color=#800080]8[/color][color=#0A246A]]
: :   :    [/color][color=#800080]80872cbe  [/color][color=#0A246A]or      dword ptr [[/color][color=#FF8000]eax[/color][color=#0A246A]+[/color][color=#800080]4[/color][color=#0A246A]],[/color][color=#800080]8
[/color][color=#0A246A]: :   :  
: :   :  [/color][color=#008000];nt!_except_handler3+0xc2 [d:\dnsrv\base\crts\crtw32\misc\i386\exsup3.asm @ 298]:
[/color][color=#0A246A]: >   :    [/color][color=#800080]80872cc2  [/color][color=#0A246A]mov     [/color][color=#FF8000]eax[/color][color=#0A246A],[/color][color=#800080]1 [/color][color=#008000]; eax = ExceptionContinueSearch (1)
[/color][color=#0A246A]:     :<   [/color][color=#800080]80872cc7  [/color][color=#0A246A]jmp     [/color][color=#000000]nt!_except_handler3[/color][color=#0A246A]+[/color][color=#800080]0xde [/color][color=#0A246A]([/color][color=#800080]80872cde[/color][color=#0A246A])
:     ::  
>     :: [/color][color=#008000];nt!_except_handler3+0xc9 [d:\dnsrv\base\crts\crtw32\misc\i386\exsup3.asm @ 302]:
      [/color][color=#0A246A]::   [/color][color=#008000]; 设置了(EXCEPTION_UNWINDING | EXCEPTION_EXIT_UNWIND),开始展开
      [/color][color=#0A246A]::   [/color][color=#800080]80872cc9  [/color][color=#0A246A]push    [/color][color=#FF8000]ebp
      [/color][color=#0A246A]::   [/color][color=#800080]80872cca  [/color][color=#0A246A]lea     [/color][color=#FF8000]ebp[/color][color=#0A246A],[[/color][color=#FF8000]ebx[/color][color=#0A246A]+[/color][color=#800080]10h[/color][color=#0A246A]] [/color][color=#008000];ebp = pExceptionRegistration->_ebp
      [/color][color=#0A246A]::   [/color][color=#800080]80872ccd  [/color][color=#0A246A]push    [/color][color=#800080]0FFFFFFFFh
      [/color][color=#0A246A]::   [/color][color=#800080]80872ccf  [/color][color=#0A246A]push    [/color][color=#FF8000]ebx
      [/color][color=#0A246A]::   [/color][color=#800080]80872cd0  [/color][color=#0A246A]call    [/color][color=#000000]nt!__local_unwind2 [/color][color=#0A246A]([/color][color=#800080]8087257b[/color][color=#0A246A])
      ::   [/color][color=#800080]80872cd5  [/color][color=#0A246A]add     [/color][color=#FF8000]esp[/color][color=#0A246A],[/color][color=#800080]8
      [/color][color=#0A246A]::   [/color][color=#800080]80872cd8  [/color][color=#0A246A]pop     [/color][color=#FF8000]ebp
      [/color][color=#0A246A]::   [/color][color=#800080]80872cd9  [/color][color=#0A246A]mov     [/color][color=#FF8000]eax[/color][color=#0A246A],[/color][color=#800080]1 [/color][color=#FF8000]eax [/color][color=#0A246A]= [/color][color=#000000]ExceptionContinueSearch [/color][color=#0A246A]([/color][color=#800080]1[/color][color=#0A246A])
      ::
      :: [/color][color=#008000];nt!_except_handler3+0xde [d:\dnsrv\base\crts\crtw32\misc\i386\exsup3.asm @ 313]:
      [/color][color=#0A246A]>>   [/color][color=#800080]80872cde  [/color][color=#0A246A]pop     [/color][color=#FF8000]ebp
           [/color][color=#800080]80872cdf  [/color][color=#0A246A]pop     [/color][color=#FF8000]edi
           [/color][color=#800080]80872ce0  [/color][color=#0A246A]pop     [/color][color=#FF8000]esi
           [/color][color=#800080]80872ce1  [/color][color=#0A246A]pop     [/color][color=#FF8000]ebx
           [/color][color=#800080]80872ce2  [/color][color=#0A246A]mov     [/color][color=#FF8000]esp[/color][color=#0A246A],[/color][color=#FF8000]ebp
           [/color][color=#800080]80872ce4  [/color][color=#0A246A]pop     [/color][color=#FF8000]ebp
           [/color][color=#800080]80872ce5  [/color][color=#0A246A]ret[/color][/font]
2011-10-5 12:59
0
雪    币: 342
活跃值: (199)
能力值: ( LV7,RANK:100 )
在线值:
发帖
回帖
粉丝
6
附录2 《nt!__local_unwind2 的反汇编代码》

[font=Consolas][color=#000000]      kd[/color][color=#0A246A]> [/color][color=#000000]uf __local_unwind2
      nt!__local_unwind2 [/color][color=#0A246A][[/color][color=#000000]d[/color][color=#0A246A]:[/color][color=#000000]\dnsrv\base\crts\crtw32\misc\i386\exsup.asm @ [/color][color=#800080]205[/color][color=#0A246A]]:
        [/color][color=#800080]8087257b  [/color][color=#0A246A]push    [/color][color=#FF8000]ebx
        [/color][color=#800080]8087257c  [/color][color=#0A246A]push    [/color][color=#FF8000]esi
        [/color][color=#800080]8087257d  [/color][color=#0A246A]push    [/color][color=#FF8000]edi
        [/color][color=#800080]8087257e  [/color][color=#0A246A]mov     [/color][color=#FF8000]eax[/color][color=#0A246A],dword ptr [[/color][color=#FF8000]esp[/color][color=#0A246A]+[/color][color=#800080]10h[/color][color=#0A246A]] [/color][color=#008000]; eax = pExceptionRegistration
        [/color][color=#800080]80872582  [/color][color=#0A246A]push    [/color][color=#FF8000]ebp
        [/color][color=#800080]80872583  [/color][color=#0A246A]push    [/color][color=#FF8000]eax
        [/color][color=#800080]80872584  [/color][color=#0A246A]push    [/color][color=#800080]0FFFFFFFEh
        80872586  [/color][color=#0A246A]push    offset [/color][color=#000000]nt!__unwind_handler [/color][color=#0A246A]([/color][color=#800080]80872540[/color][color=#0A246A])
        [/color][color=#800080]8087258b  [/color][color=#0A246A]push    dword ptr [/color][color=#FF8000]fs[/color][color=#0A246A]:[[/color][color=#800080]0[/color][color=#0A246A]]
        [/color][color=#800080]80872592  [/color][color=#0A246A]mov     dword ptr [/color][color=#FF8000]fs[/color][color=#0A246A]:[[/color][color=#800080]0[/color][color=#0A246A]],[/color][color=#FF8000]esp [/color][color=#008000]; __local_unwind2 自身也会构建 _EXCEPTION_REGISTRATION

      [/color][color=#000000]nt!__local_unwind2[/color][color=#0A246A]+[/color][color=#800080]0x1e [/color][color=#0A246A][[/color][color=#000000]d[/color][color=#0A246A]:[/color][color=#000000]\dnsrv\base\crts\crtw32\misc\i386\exsup.asm @ [/color][color=#800080]222[/color][color=#0A246A]]:
>       [/color][color=#800080]80872599  [/color][color=#0A246A]mov     [/color][color=#FF8000]eax[/color][color=#0A246A],dword ptr [[/color][color=#FF8000]esp[/color][color=#0A246A]+[/color][color=#800080]24h[/color][color=#0A246A]] [/color][color=#008000]; eax = pExceptionRegistration
[/color][color=#0A246A]:       [/color][color=#800080]8087259d  [/color][color=#0A246A]mov     [/color][color=#FF8000]ebx[/color][color=#0A246A],dword ptr [[/color][color=#FF8000]eax[/color][color=#0A246A]+[/color][color=#800080]8[/color][color=#0A246A]]   [/color][color=#008000]; ebx = pExceptionRegistration->scopetable
[/color][color=#0A246A]:       [/color][color=#800080]808725a0  [/color][color=#0A246A]mov     [/color][color=#FF8000]esi[/color][color=#0A246A],dword ptr [[/color][color=#FF8000]eax[/color][color=#0A246A]+[/color][color=#800080]0Ch[/color][color=#0A246A]] [/color][color=#008000]; esi = pExceptionRegistration->trylevel
[/color][color=#0A246A]:       [/color][color=#800080]808725a3  [/color][color=#0A246A]cmp     [/color][color=#FF8000]esi[/color][color=#0A246A],[/color][color=#800080]0FFFFFFFFh          [/color][color=#008000]; cmp pExceptionRegistration->trylevel, TRYLEVEL_NONE
[/color][color=#0A246A]:<      [/color][color=#800080]808725a6  [/color][color=#0A246A]je      [/color][color=#000000]nt!_NLG_Return2[/color][color=#0A246A]+[/color][color=#800080]0x2 [/color][color=#0A246A]([/color][color=#800080]808725dd[/color][color=#0A246A])
::      
::    [/color][color=#000000]nt!__local_unwind2[/color][color=#0A246A]+[/color][color=#800080]0x2d [/color][color=#0A246A][[/color][color=#000000]d[/color][color=#0A246A]:[/color][color=#000000]\dnsrv\base\crts\crtw32\misc\i386\exsup.asm @ [/color][color=#800080]228[/color][color=#0A246A]]:
::      [/color][color=#800080]808725a8  [/color][color=#0A246A]cmp     dword ptr [[/color][color=#FF8000]esp[/color][color=#0A246A]+[/color][color=#800080]28h[/color][color=#0A246A]],[/color][color=#800080]0FFFFFFFFh
[/color][color=#0A246A]::<     [/color][color=#800080]808725ad  [/color][color=#0A246A]je      [/color][color=#000000]nt!__local_unwind2[/color][color=#0A246A]+[/color][color=#800080]0x3a [/color][color=#0A246A]([/color][color=#800080]808725b5[/color][color=#0A246A])
:::   
:::   [/color][color=#000000]nt!__local_unwind2[/color][color=#0A246A]+[/color][color=#800080]0x34 [/color][color=#0A246A][[/color][color=#000000]d[/color][color=#0A246A]:[/color][color=#000000]\dnsrv\base\crts\crtw32\misc\i386\exsup.asm @ [/color][color=#800080]230[/color][color=#0A246A]]:
:::     [/color][color=#800080]808725af  [/color][color=#0A246A]cmp     [/color][color=#FF8000]esi[/color][color=#0A246A],dword ptr [[/color][color=#FF8000]esp[/color][color=#0A246A]+[/color][color=#800080]28h[/color][color=#0A246A]]
:::<    [/color][color=#800080]808725b3  [/color][color=#0A246A]jbe     [/color][color=#000000]nt!_NLG_Return2[/color][color=#0A246A]+[/color][color=#800080]0x2 [/color][color=#0A246A]([/color][color=#800080]808725dd[/color][color=#0A246A])
::::  
::::  [/color][color=#000000]nt!__local_unwind2[/color][color=#0A246A]+[/color][color=#800080]0x3a [/color][color=#0A246A][[/color][color=#000000]d[/color][color=#0A246A]:[/color][color=#000000]\dnsrv\base\crts\crtw32\misc\i386\exsup.asm @ [/color][color=#800080]234[/color][color=#0A246A]]:
::>:    [/color][color=#800080]808725b5  [/color][color=#0A246A]lea     [/color][color=#FF8000]esi[/color][color=#0A246A],[[/color][color=#FF8000]esi[/color][color=#0A246A]+[/color][color=#FF8000]esi[/color][color=#0A246A]*[/color][color=#800080]2[/color][color=#0A246A]]
:: :    [/color][color=#800080]808725b8  [/color][color=#0A246A]mov     [/color][color=#FF8000]ecx[/color][color=#0A246A],dword ptr [[/color][color=#FF8000]ebx[/color][color=#0A246A]+[/color][color=#FF8000]esi[/color][color=#0A246A]*[/color][color=#800080]4[/color][color=#0A246A]]  [/color][color=#008000]; move ecx, [pExceptionRegistration->scopetable[i].previousTryLevel]
[/color][color=#0A246A]:: :    [/color][color=#800080]808725bb  [/color][color=#0A246A]mov     dword ptr [[/color][color=#FF8000]esp[/color][color=#0A246A]+[/color][color=#800080]8[/color][color=#0A246A]],[/color][color=#FF8000]ecx      [/color][color=#008000]; 这个 esp+8 只写没读,什么情况?
[/color][color=#0A246A]:: :    [/color][color=#800080]808725bf  [/color][color=#0A246A]mov     dword ptr [[/color][color=#FF8000]eax[/color][color=#0A246A]+[/color][color=#800080]0Ch[/color][color=#0A246A]],[/color][color=#FF8000]ecx    [/color][color=#008000]; pExceptionRegistration->trylevel = ecx
[/color][color=#0A246A]:: :    [/color][color=#800080]808725c2  [/color][color=#0A246A]cmp     dword ptr [[/color][color=#FF8000]ebx[/color][color=#0A246A]+[/color][color=#FF8000]esi[/color][color=#0A246A]*[/color][color=#800080]4[/color][color=#0A246A]+[/color][color=#800080]4[/color][color=#0A246A]],[/color][color=#800080]0  [/color][color=#008000]; cmp pExceptionRegistration->scopetable->lpfnFilter, NULL
[/color][color=#0A246A]:: :<   [/color][color=#800080]808725c7  [/color][color=#0A246A]jne     [/color][color=#000000]nt!_NLG_Return2 [/color][color=#0A246A]([/color][color=#800080]808725db[/color][color=#0A246A])
:: :: 
:: :: [/color][color=#000000]nt!__local_unwind2[/color][color=#0A246A]+[/color][color=#800080]0x4e [/color][color=#0A246A][[/color][color=#000000]d[/color][color=#0A246A]:[/color][color=#000000]\dnsrv\base\crts\crtw32\misc\i386\exsup.asm @ [/color][color=#800080]243[/color][color=#0A246A]]:
:: ::   [/color][color=#008000]; RegistrationPointer->scopetable->lpfnFilter 等于 NULL,即这里是 __try & __finally 的组合
[/color][color=#0A246A]:: ::   [/color][color=#800080]808725c9  [/color][color=#0A246A]push    [/color][color=#800080]101h
[/color][color=#0A246A]:: ::   [/color][color=#800080]808725ce  [/color][color=#0A246A]mov     [/color][color=#FF8000]eax[/color][color=#0A246A],dword ptr [[/color][color=#FF8000]ebx[/color][color=#0A246A]+[/color][color=#FF8000]esi[/color][color=#0A246A]*[/color][color=#800080]4[/color][color=#0A246A]+[/color][color=#800080]8[/color][color=#0A246A]]
:: ::   [/color][color=#800080]808725d2  [/color][color=#0A246A]call    [/color][color=#000000]nt!_NLG_Notify [/color][color=#0A246A]([/color][color=#800080]80872617[/color][color=#0A246A])  [/color][color=#008000]; 这个函数对理解 SEH 不重要,可以暂时忽略
[/color][color=#0A246A]:: ::   [/color][color=#800080]808725d7  [/color][color=#0A246A]call    dword ptr [[/color][color=#FF8000]ebx[/color][color=#0A246A]+[/color][color=#FF8000]esi[/color][color=#0A246A]*[/color][color=#800080]4[/color][color=#0A246A]+[/color][color=#800080]8[/color][color=#0A246A]]    [/color][color=#008000]; pExceptionRegistration->scopetable->lpfnHandler()
[/color][color=#0A246A]:: :: 
:: :: [/color][color=#000000]nt!_NLG_Return2 [/color][color=#0A246A][[/color][color=#000000]d[/color][color=#0A246A]:[/color][color=#000000]\dnsrv\base\crts\crtw32\misc\i386\exsup.asm @ [/color][color=#800080]251[/color][color=#0A246A]]:
<: :>   [/color][color=#800080]808725db  [/color][color=#0A246A]jmp     [/color][color=#000000]nt!__local_unwind2[/color][color=#0A246A]+[/color][color=#800080]0x1e [/color][color=#0A246A]([/color][color=#800080]80872599[/color][color=#0A246A]) [/color][color=#008000]; 循环
 [/color][color=#0A246A]: :
 : :  [/color][color=#000000]nt!_NLG_Return2[/color][color=#0A246A]+[/color][color=#800080]0x2 [/color][color=#0A246A][[/color][color=#000000]d[/color][color=#0A246A]:[/color][color=#000000]\dnsrv\base\crts\crtw32\misc\i386\exsup.asm @ [/color][color=#800080]253[/color][color=#0A246A]]:
 > >    [/color][color=#800080]808725dd  [/color][color=#0A246A]pop     dword ptr [/color][color=#FF8000]fs[/color][color=#0A246A]:[[/color][color=#800080]0[/color][color=#0A246A]]
        [/color][color=#800080]808725e4  [/color][color=#0A246A]add     [/color][color=#FF8000]esp[/color][color=#0A246A],[/color][color=#800080]10h
        808725e7  [/color][color=#0A246A]pop     [/color][color=#FF8000]edi
        [/color][color=#800080]808725e8  [/color][color=#0A246A]pop     [/color][color=#FF8000]esi
        [/color][color=#800080]808725e9  [/color][color=#0A246A]pop     [/color][color=#FF8000]ebx
        [/color][color=#800080]808725ea  [/color][color=#0A246A]ret
[/color][/font]
2011-10-5 13:00
0
雪    币: 342
活跃值: (199)
能力值: ( LV7,RANK:100 )
在线值:
发帖
回帖
粉丝
7
参考资料:
        [1] wrk 源码
        [2] A Crash Course on the Depths of Win32? Structured Exception Handling, Matt Pietrek
        [3] 《Windows 内核原理与实现》潘爱民
        [4] 《软件调试》张银奎
2011-10-5 13:01
0
雪    币: 342
活跃值: (199)
能力值: ( LV7,RANK:100 )
在线值:
发帖
回帖
粉丝
8
附件是原始稿,htm 格式( SEH分析笔记(x86篇)_v1.0.2.7z)。
喜欢看离线版的朋友(比如我自己~)可以下载。
上传的附件:
2011-10-5 13:07
0
雪    币: 349
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
9
不错,收藏起来慢慢看。
ps. LZ代码用的什么字体,看着挺舒服的?
2011-10-5 13:16
0
雪    币: 1534
活跃值: (738)
能力值: ( LV8,RANK:130 )
在线值:
发帖
回帖
粉丝
10
好文,建议加精。
2011-10-5 13:49
0
雪    币: 263
活跃值: (71)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
11
多谢分享心得,好文
2011-10-5 14:09
0
雪    币: 342
活跃值: (199)
能力值: ( LV7,RANK:100 )
在线值:
发帖
回帖
粉丝
12
consolas :-)
2011-10-5 18:32
0
雪    币: 2177
活跃值: (2045)
能力值: (RANK:400 )
在线值:
发帖
回帖
粉丝
13
花了大概一个小时时间细细品读了一下LZ文章,感觉LZ对SEH的理解相当透彻啊,膜拜膜拜~
2011-10-6 16:11
0
雪    币: 1683
活跃值: (674)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
14
花了心血的,好资料,学习并感谢
2011-10-6 17:42
0
雪    币: 210
活跃值: (644)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
15
好详细,一定要仔细读读!
2011-10-6 19:46
0
雪    币: 316
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
16
辛苦,很详细
2011-10-6 20:27
0
雪    币: 693
活跃值: (108)
能力值: ( LV5,RANK:60 )
在线值:
发帖
回帖
粉丝
17
多谢楼主的分享,楼主是花了大功夫的,大家顶起来!
2011-10-7 07:17
0
雪    币: 437
活跃值: (110)
能力值: ( LV5,RANK:70 )
在线值:
发帖
回帖
粉丝
18
多谢楼主,慢慢学习
2011-10-7 08:53
0
雪    币: 7115
活跃值: (639)
能力值: (RANK:1290 )
在线值:
发帖
回帖
粉丝
19
为了你这种认真的态度,都要发帖支持你一下。。。
2011-10-7 09:47
0
雪    币: 473
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
20
花了心血的,好资料,学习并感谢
2011-10-7 12:18
0
雪    币: 6299
活跃值: (17855)
能力值: ( LV4,RANK:40 )
在线值:
发帖
回帖
粉丝
21
膜拜,研究得真仔细!
2011-10-7 19:05
0
雪    币: 94
活跃值: (25)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
22
学习一下,lz研究的确实很深入。。。
2011-10-8 10:52
0
雪    币: 238
活跃值: (23)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
23
收藏学习,谢谢
2011-10-8 12:22
0
雪    币: 270
活跃值: (97)
能力值: ( LV8,RANK:140 )
在线值:
发帖
回帖
粉丝
24
太牛了,写这么多,慢慢看
2011-10-8 12:33
0
雪    币: 88
活跃值: (11)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
25
好贴 MARK
2011-10-8 18:18
0
游客
登录 | 注册 方可回帖
返回
//