首页
社区
课程
招聘
[原创]QueueUserAPC执行成功条件-逆向总结
2022-4-29 14:12 22298

[原创]QueueUserAPC执行成功条件-逆向总结

2022-4-29 14:12
22298

1.背景:

 使用Win32 API QueueUserAPC做注入时总是遇到明明插入成功了,但就是得不到执行的情况。为了得到原因,在Win7 x86 PAE模式下跟踪了一下QueueUserAPC的整个处理过程(初始化->插入->执行),详细分析过程我会用附件的形式给出,下面是得到的一些结论,有错误欢迎指出,一起交流。

2.过程简要分析:

2.1 KiServiceExit2:

 在系统调用、中断、异常等操作发生后,会从r3进入内核来处理,在内核处理完准备返回r3时,会调用这个函数,在函数内部会做出一些判断来决定是否要交付用户态APC,判断条件就是当前线程的ApcState.UserApcPending,这个域为1时,表示有要处理的用户态APC存在,才会继续调用KiDeliverApc,这一点很关键。

2.2 KiDeliverApc:

 这个函数进去第一件事就是判断当前线程的SpecialApcDisable域是否为1,这个域相当于一个总开关,置1表示,内核和用户态APC都不能交付,函数直接返回。如果为0,判断内核APC队列是否有内容,没有就去交付用户APC,如果有内核APC,一个循环全部交付完,但在交付内核APC过程中,一旦检查发现KernelApcDiable域为1,KiDeliverApc函数直接返回,不会向下处理用户APC了。这里可以得出结论,用户态APC必须在内核APC交付完才有机会交付。但通过QueueUserAPC插入的APC是不存在内核APC的,直接相当于内核APC交付完了。
而内核APC交付完,会开始交付用户APC,这里需要注意一下,使用QueueUserApc插入的APC,真正的回调函数是保存在NormalContext里,而NormalRoutine只是保存了一个r3执行时候的派发入口(ntdll.dll中的8号导出函数),而要执行回调函数,需要从内核返回到r3由派发函数统一派发。Windows这里采用的是劫持TrapFrame实现的回r3。

2.3 小总结:

从上面的执行过程分析得出,要想让由QueueUserApc插入的用户态APC交付成功,需要满足以下条件:

  • CurrentThread.ApcState.UserApcPending值为1
  • ApcList[1]队列不为空
  • CurrentThread.SpecialApcDisable值为0

第三点暂时不用考虑,一般都是0,但UserApcPending什么时候才能是1以及队列什么时候被插入APC?这就需要去分析QueueUserApc的初始化和插入过程了。

2.4 NtQueueApcThreadEx:

 这个函数是系统调用进来先执行的内核函数,函数内部首先判断目标线程是否是系统线程,即CrossThreadFlags.SystemThread位是否为1,如果为1函数直接返回,为0才分配KAPC结构内存并初始化。

2.5 KeInsertQueueApc:

 这个函数中判断插入的目标线程的ThreadFlags.ApcQueue位,如果这个位为0,不插入队列,直接返回。不为1,继续调用KiInsertQueueApc。

2.6 KiInsertQueueApc

 将APC插入ApcList[1]队列。这个函里面有个点,因为调用QueueUserApc环境固定为0(始终插入原始环境),也就是KAPC.ApcStateIndex始终为0,而这个函数里会把当前线程的ApcStateIndex与KAPC.ApcStateIndex做对比,因为线程在挂靠的时候ApcStateIndex为1,这样就说明无法插入一个正在挂靠的线程。接下来会去判断目标线程是不是当前线程,如果是当前线程并且是用户态APC,函数也返回了。前面条件都满足了,会判断目标线程是否处于可以被唤醒的等待状态,如果不是,函数在这里也返回了。如果是,将目标线程唤醒(从等待链表->延时就绪链表),唤醒成功后将UserApcPending置1。到这里,条件全部满足。

3 总结:

从检查顺序排列,要想QueueUserApc执行成功,目标线程需要满足以下条件:

  • 目标线程不能为系统线程
  • 目标线程ThreadFlags.ApcQueue位为1
  • 插入APC时目标线程不能为挂靠状态
  • 目标线程不能是自身线程
  • 目标线程必须为可以唤醒的等待状态(如:SleepEx(1000, TRUE))

[培训]《安卓高级研修班(网课)》月薪三万计划

上传的附件:
收藏
点赞5
打赏
分享
最新回复 (7)
雪    币: 7855
活跃值: (5040)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
mudebug 2022-4-30 13:12
2
0
感谢大佬分享
雪    币: 3525
活跃值: (3627)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
caolinkai 2022-5-5 08:43
3
0
感谢大佬分享
雪    币: 310
活跃值: (1887)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
niuzuoquan 2022-5-5 09:19
4
0
mark
雪    币: 227
活跃值: (4014)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
pysafe 2022-5-5 09:52
5
0
雪    币: 149
活跃值: (1973)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
saloyun 2022-8-31 11:56
6
0
KeTestAlertThread
雪    币: 3349
活跃值: (3372)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
fengyunabc 1 2022-8-31 14:11
7
0
感谢分享,分析得很详细!
雪    币: 1382
活跃值: (3100)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
小希希 2022-9-23 10:24
8
0
感谢分享
游客
登录 | 注册 方可回帖
返回