原型
AddVectoredContinueHandler
的原型与AddVectoredExceptionHandler
的原型非常相似:PVOID WINAPI AddVectoredContinueHandler(
_In_ ULONG FirstHandler,
_In_ PVECTORED_EXCEPTION_HANDLER VectoredHandler
);
并且更令人困惑的是,它接受
PVECTORED_EXCEPTION_HANDLER
,就像AddVectoredExceptionHandler
一样。矢量化连续处理程序的用途是什么?如何使用它们?
#1 楼
不幸的是,这里的MSDN和Windows API文档确实很稀少,除了在MSDN中的最小描述之外,我很难找到其他任何内容。事实证明,矢量化继续处理程序保存在与一种用于矢量异常处理程序。它们是如此相似,因此该函数的原型实际上是相同的。
看一下:
PVOID WINAPI AddVectoredExceptionHandler(
_In_ ULONG FirstHandler,
_In_ PVECTORED_EXCEPTION_HANDLER VectoredHandler
);
与:
相比
PVOID WINAPI AddVectoredContinueHandler(
_In_ ULONG FirstHandler,
_In_ PVECTORED_EXCEPTION_HANDLER VectoredHandler
);
幸运的是,矢量化异常处理程序更加常用和记录。例如,MSDN上有一个有关VEH的页面,其中包含以下段落:向量异常处理程序是对结构化异常处理的扩展。应用程序可以注册一个函数来监视或处理该应用程序的所有异常。向量处理程序不是基于框架的,因此,无论您位于调用框架中的何处,都可以添加将被调用的处理程序。在调试器获得第一个机会通知之后,但在系统开始展开堆栈之前,矢量处理程序将按添加顺序被调用。
同一页面上只有简单的引用
经过对ntdll的研究和反向工程,我意识到VCH和VEH在实现上非常相似。例如,查看
AddVectoredExceptionHandler
和AddVectoredContinueHandler
(除了VectoredListIndex
)如何相同,指定在VCH情况下应将它们添加到第二个VectorHandlerList
:和
RemoveVectoredExceptionHandler
相同,但矢量处理程序列表索引相同。在
RemoveVectoredContinueHandler
内,RtlpAddVectoredHandler
用作VectoredListIndex
中的索引,它是链接列表结构的大小为2的数组。在下图中,我们可以看到如何将
_LdrpVectorHandlerList
乘以列表锚对象的大小,然后将其添加到VectoredListIndex
,它是数组的基本偏移量。现在我们进入有趣的部分-VEH和VCH在哪里不同?将会注意到,导致添加/删除功能的两个流程实际上是相同的。除了这四个API,我们只剩下另一个函数,称为
_LdrpVectorHandlerList
,未记录。从名称上很明显,但是
_LdrpVectorHandlerList
遍历向量(向量根据索引)并按顺序调用所有处理程序。一旦向量处理程序返回RtlpCallVectoredHandlers
,迭代就会因从RtlpCallVectoredHandlers
过早返回而中断,并恢复执行。EXCEPTION_CONTINUE_EXECUTION的函数是
RtlpCallVectoredHandlers
,这是分派异常处理程序的主要功能。 />首先,它执行所有异常处理程序,从第一个向量化异常处理程序开始到最后一个,然后遍历所有结构化异常处理程序,在堆栈中展开它们。第一个返回RtlpCallVectoredHandlers
(类型为VEH或SEH)的异常处理程序将停止整个异常处理程序的执行过程。像VEH一样,当调用VCH时,它们会被一个接一个地调用,直到一个它们返回
RtlDispatchException
(就像调用VEH时一样),这将向EXCEPTION_CONTINUE_EXECUTION
发出信号通知矢量处理程序调用循环EXCEPTION_CONTINUE_EXECUTION
。这很有趣,因为这意味着首先要安装Vectored Continue Handler,以便您可以隐藏后续VCH中的异常。在以下情况下会调用Vectored Continue Handler:
如果调用了异常处理程序(VEH或SEH)并返回
RtlpCallVectoredHandlers
如果由于某种原因SEH验证失败(请参阅SafeSEH和相关机制),也会调用VCH,但不会执行之后继续。
这可以在导致第二次
break
调用的许多流程中看到,而没有将EXCEPTION_CONTINUE_EXECUTION
设置为RtlpCallVectoredHandlers
并使它等于零,然后再将其移到bl
并返回1
。如果al
返回的值是false
,则调用函数KiUserExceptionDispatcher
将调用ZwRaiseException
。
评论
您说“如果调用了异常处理程序(VEH或SEH)并返回了EXCEPTION_CONTINUE_EXECUTION”。您是EXCEPTION_CONTINUE_SEARCH吗?处理异常后,调用另一个处理程序是没有意义的。
–肯索(Kentzo)
17年11月16日在22:51
@Kentzo正是矢量化继续处理程序的重点。
– NirIzr
17年11月17日在2:53
我在msdn上找到的信息(请参阅MS员工的评论)与此相反。
–肯索(Kentzo)
17年17月17日3:00
没关系:我想我误解了此评论。实际上,仅在您声明时才调用它。
–肯索(Kentzo)
17年11月18日在0:35