三、展开 (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。