0

只是想更好地了解 APC。要对用户模式 ​​APC 进行排队,我们可以使用QueueUserAPC函数。那么如何排队一个特殊/正常的内核模式APC?谢谢。

4

1 回答 1

1

APC 必须仅从非分页池中分配,因为 APC 可以(通过KeInsertQueueAPC)在DPC级别的线程列表中插入 - 因此,例如,如果您从分页池中分配KAPC,插入它,然后有人尝试在DPC级别插入另一个APC - 可以分配您的分页APC数据(当插入到链表时)并作为结果蓝屏

初始化KAPC使用KeInitializeApc。如果免费的APC需要完全调用ExFreePool并且仅此而已,您可以使用 0 作为RundownRoutine。否则,您必须提供自己的RundownRoutine以进行正确清理。KernelRoutine必须始终设置,因为它几乎总是指向驱动程序中的某些功能 -在不执行APC之前不得卸载驱动程序。通常需要在KernelRoutine之后通过KeInsertQueueAPCObfDereferenceObject插入APC之前为驱动程序对象调用ObfReferenceObjectRundownRoutine将被执行(或KeInsertQueueAPC返回 false)。但是您不能“正常方式”调用ObfDereferenceObject - 这是没有意义的(如果驱动程序保留最后一个引用 - 当ObfDereferenceObject返回到您的驱动程序代码时将崩溃。您需要来自KernelRoutineRundownRoutine的汇编编写代理,它们称为 c/c++ 实现和在退出时执行对ObfDereferenceObject的jmp(但不调用!!)指令,并且堆栈必须在ObfDereferenceObject调用ret之后进行特殊重建- 代码将返回到内核代码,它调用您的驱动程序回调例程(内核或 rundown) - 所以在ObfDereferenceObject之后跳过驱动程序代码执行

有关更多详细信息 - 阅读Inside NT 的异步过程调用- 尽管这已经是非常古老的文章 - 从这次和最新的 win 10 中没有任何变化 - 都一样

于 2017-04-21T19:51:22.870 回答