我想使用线程挂起方法将一段代码注入正在运行的模块中。
挂起线程
GetThreadContext
做点什么
恢复线程
我的问题是,如果我当前正在注入的线程处于警报/等待模式(WaitForSingleObject,GetMessage),将会发生什么。一旦我按下ResumeThread命令,将会发生什么。
最佳答案
我想,否则会发生同样的事情。
可以说目标线程当前处于用户模式。您保存所有寄存器供以后使用,将RIP
设置为指向您的代码,然后调用ResumeThread()
。在某个时候,您的代码开始执行,执行所有操作,恢复所有已保存注入代码的寄存器,并让程序恢复其正常操作。
现在说目标线程正在等待。等待是指线程执行系统调用,该命令告诉调度程序不要调度线程执行,直到发生某些事情(发出信号等)为止。您保存用户模式上下文的寄存器(调用sysenter
时的方式),将RIP设置为指向您的代码并调用ResumeThread()
。一切都很好,但是在满足等待条件之前,调度程序仍然不会调度它的执行。
等待最终结束时,线程确实以内核模式完成其业务,返回到用户模式,并且在ret
继续执行代码之后,不再执行sysenter
命令。最后,您的代码将还原所有寄存器,并跳转到已保存的RIP
(从ntdll!ZwWaitForSingleObject
或其他任何内容),一切将继续正常进行。
最后,假设您正在执行可警告的等待。故事的内容与前两段中的内容差不多(您真的不需要我第三次重复吗,对吗?:)),除了在执行wait函数返回之前,它执行所有排队等待用户APC的操作线程-完全没有您的干预就会发生-然后继续执行您的代码等。
所以基本上发生的是您应该预期发生的事情:
如果调用SetThreadContext()
,则将更改用户模式上下文,并且计算机将相应地运行,而不管线程是否在等待。
如果线程正在等待某件事,则无论您是否调用“ SetThreadContext()”,它都会继续等待同一件事。
如果线程处于可警告的等待状态,则在系统调用返回之前,请确保用户APC队列为空(由于存在用户APC并对其进行了调用,或者因为队列为空并且最终发生了“常规”等待条件) 。再次,无论是否调用SetThreadContext()
。