什么是向量继续处理程序

逆向工程 视窗 例外
2021-07-02 03:32:07

几乎每个人都知道Vectored Exception Handlers什么,但是我找不到很多关于我今天遇到的类似“Vectored Continue Handlers”和相关函数的信息,例如AddVectoredContinueHandlerRemoveVectoredContinueHandler

的原型与 的原型AddVectoredContinueHandler非常相似AddVectoredExceptionHandler

PVOID WINAPI AddVectoredContinueHandler(
  _In_ ULONG                       FirstHandler,
  _In_ PVECTORED_EXCEPTION_HANDLER VectoredHandler
);

为了让事情变得更加混乱,它接受 a PVECTORED_EXCEPTION_HANDLER,就像那样AddVectoredExceptionHandler

Vectored Continue Handlers的目的是什么?它们是如何使用的?

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页面,包含以下段落:

向量异常处理程序是结构化异常处理的扩展。应用程序可以注册一个函数来监视或处理应用程序的所有异常。向量处理程序不是基于帧的,因此,您可以添加一个处理程序,无论您在调用帧中的哪个位置,该处理程序都会被调用。在调试器获得第一次机会通知之后,但在系统开始展开堆栈之前,向量处理程序按照它们的添加顺序被调用。

同一页面只有对添加和删除 VCH API 的简洁引用。

经过对 ntdll 的一些研究和逆向工程,我意识到 VCH 和 VEH 在实现上非常相似。例如,查看AddVectoredExceptionHandlerAddVectoredContinueHandler如何相同的,除了VectoredListIndex,指定VectorHandlerList在 VCH 的情况下它们应该添加到第二个

AddVectoredExceptionHandler VS AddVectoredContinueHandler

类似地,除了向量处理程序列表索引外RemoveVectoredExceptionHandlerRemoveVectoredContinueHandler是相同的。

在 内部RtlpAddVectoredHandlerVectoredListIndex用作 中的索引 _LdrpVectorHandlerList,这是一个链表结构的大小为 2 的数组。

在下图中我们可以看到如何VectoredListIndex乘以列表锚点对象的大小,然后添加到_LdrpVectorHandlerList,即数组的基偏移量。

VectoredListIndex 用作数组索引

现在我们进入了有趣的部分——VEH 和 VCH 有什么不同?

如果我们走上对 的交叉引用_LdrpVectorHandlerList,我们会注意到导致添加/删除功能的两个流程实际上是相同的。除了这四个 API 之外,我们只剩下一个RtlpCallVectoredHandlers未记录的函数

从名字RtlpCallVectoredHandlers上看就很明显了,但是遍历向量(根据索引选择向量)并按顺序调用所有处理程序。一旦 Vectored Handler 返回EXCEPTION_CONTINUE_EXECUTION,迭代就会因提前返回RtlpCallVectoredHandlers中断并恢复执行。

唯一的函数调用RtlpCallVectoredHandlersRtlDispatchException,它是调度异常处理程序的主要函数。

首先,它执行所有异常处理程序,从第一个向量异常处理程序开始到最后一个,然后通过所有结构化异常处理程序将它们通过堆栈展开。要返回的第一个异常处理程序EXCEPTION_CONTINUE_EXECUTION(无论是 VEH 还是 SEH 类型)将停止整个异常处理程序的执行过程。

与 VEH 一样,当 VCH 被调用时,它们会被一一调用,直到其中一个返回EXCEPTION_CONTINUE_EXECUTION(就像调用 VEH 时一样),这会RtlpCallVectoredHandlersVectored breakHandlers 调用循环发出信号这很有趣,因为这意味着首先安装 Vectored Continue Handler 可以让您隐藏后续 VCH 的异常。

向量继续处理程序在以下情况下被调用:

  1. 如果异常处理程序(VEH 或 SEH)被调用并返回 EXCEPTION_CONTINUE_EXECUTION
  2. 如果由于某种原因 SEH 验证失败(参见 SafeSEH 和相关机制),也会调用 VCH,但之后不会继续执行。这可以在导致第二次RtlpCallVectoredHandlers调用的许多流中看到,在将其移动到并返回之前,没有设置blto1并将其保持为零调用函数,然后将调用,如果返回值的alfalseKiUserExceptionDispatcherZwRaiseExceptionKiUserExceptionDispatcherfalse在此处输入图片说明