更改可报警/可等待线程的上下文

Change context of an alertable / waitable thread

本文关键字:线程 等待 上下文      更新时间:2023-10-16

我想使用线程挂起方法将一段代码注入正在运行的模块中。

  1. SuspendThread
  2. GetThreadContext
  3. DoSomething
  4. 继续线程

我的问题是,如果我当前注入的线程处于alertable/waitable模式(WaitForSingleObject,GetMessage),会发生什么。一旦我点击ResumeThread命令会发生什么。

我想,如果不是这样,也会发生同样的事情。


假设目标线程当前处于用户模式。保存所有寄存器以备以后使用,将RIP设置为指向代码并调用ResumeThread()。在某个时刻,您的代码开始执行,执行它所做的一切,恢复保存的注入代码的所有寄存器,并让程序恢复正常操作。

现在假设目标线程正在等待。等待意味着线程执行一个系统调用,告诉调度程序在发生某些事情之前不要调度线程执行(发出事件信号等)。您保存用户模式上下文的寄存器(调用sysenter时的方式),设置RIP指向您的代码并调用ResumeThread()。这一切都很好,但调度器仍然不会安排它执行,直到满足等待条件。

当等待最终结束时,线程确实在内核模式下完成了它的业务,返回到用户模式,并不是在sysenter之后执行ret命令,而是继续执行代码。最后,您的代码恢复所有寄存器,并跳到保存的RIP(从ntdll!ZwWaitForSingleObject或其他),一切正常。

最后,假设你正在进行一次警觉的等待。这个故事和前两段差不多(你真的不需要我重复第三次,是吗?:),只是在等待函数返回之前,它会执行所有排队等待线程的用户APC-,就像没有你的干预一样-然后继续执行你的代码等。


所以基本上发生的事情是你应该预料到的:

  • 如果调用SetThreadContext(),则无论线程是否在等待,用户模式上下文都会发生更改,计算机也会相应地运行
  • 如果线程正在等待某个东西,它将继续等待相同的东西,而不管您是否调用了"SetThreadContext()"
  • 如果线程处于可报警等待状态,则在系统调用返回之前,它会确保用户APC队列为空(可能是因为有用户APC并且它调用了它们,也可能是因为队列为空并且最终出现了"常规"等待条件)。同样,无论您是否调用SetThreadContext()