标签:image alt 因此 退出 init get context ima mamicode
Windows内核分析索引目录:https://www.cnblogs.com/onetrainee/p/11675224.html
APC
5. 用户APC执行过程
1) 用户APC函数的执行时机
当程序在零环执行完成返回三环时,其调用_KiServiceExit,此时其调用_KiDeliverApc来检查是否有派发的APC函数,然后执行。
2) 用户APC执行流程
当发现有用户APC要执行时,其处于零环,要执行必须返回三环。
执行流程为:零环->三环(执行用户APC)->零环->三环(正常退出)。
之前我们在系统调用这中提到过如何从三环进到零环,其三环现场保存在_KTRAP_FRAME(_ETHREAD+0x124)这个结构体中。
此时回去肯定不能从_KTRPA_FRAME中返回三环。
3)构建_CONTEXT结构体返回三环
返回三环时根据_KTRAP_FRAME.Eip来返回三环,因此我们想要处理用户APC,其必须修改KTrapFrame.EIP。
1> KiDiverApc函数中调用KiInitalUserApc来初始化用户APC环境
2> KiInitalUserApc函数中调用KiContextFromKframes将TrapFrame转换为CONTEXT结构体
这一步的目的是为了备份原来的TrapFrame,因为返回三环必然修改TrapFrame,因此将旧的转换为CONTEXT预先放到三环的堆栈。
3> KiInitalUserApc函数中将_APC_RECORD和_CONTEXT保存到三环的堆栈中
虽然此时处于零环,但是可以从TrapFrame.esp来获取三环的堆栈地址,然后将两者保存进去。
因为APC执行完之后还必须从三环进入零环,此时直接在堆栈进行操作进行复原即可。
1* 获取esp并计算提升堆栈大小
2* 将 _Context 写入三环地址
3* 将ApcRecord写入三环地址
4* 保存之后三环的堆栈空间
4> KiInitalUserApc函数中修改TrapFrame为返回三环做准备
其修改很多TrapFrame的值,但对于我们最重要的就是回到三环后的落脚点。
其回到KeUserApcDispatch来执行用户的APC函数,至于函数地址,ApcRecord.NormalContext存放的是真正的APC函数。
4)总结
理解上面过程,此时,我们就可以通过KiServiceExit函数利用KTrapFrame来返回用户层,其返回的就是KiInitalizeUserApc函数,然后执行用户APC。
当用户APC执行完成之后,返回零环,此时就是Context。我们直接在三环把Context再转换为KtrapFrame,这之后就很好理解了。
标签:image alt 因此 退出 init get context ima mamicode
原文地址:https://www.cnblogs.com/onetrainee/p/12600409.html