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

Change context of an alertable / waitable thread

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

  1. 暂停线程
  2. 获取线程上下文
  3. 做点什么
  4. 恢复线程

我的问题是,如果我当前注入的线程处于可警报/可等待模式(WaitForSingleObject、GetMessage),会发生什么情况。一旦我点击 ResumeThread 命令会发生什么。

我想,否则会发生同样的事情。


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

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

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

最后,假设您正在执行可警告的等待。这个故事和前两段差不多(你真的不需要我重复第三次,是吗?:)),除了等待函数 returns 之前它执行所有用户APC 排队等待线程 - 与没有你干预的情况完全一样 - 然后继续执行你的代码等


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

  • 如果您调用 SetThreadContext(),则用户模式上下文会发生变化,并且计算机会相应地运行,而不管线程是否在等待。
  • 如果线程正在等待某事,它会继续等待同一件事,无论您是否调用了 'SetThreadContext()'。
  • 如果线程处于可警告等待状态,在系统调用 returns 之前,它会确保用户 APC 队列为空(因为存在用户 APC 并且它调用了它们,或者因为队列为空并且'regular' 等待条件终于发生了)。同样,无论您是否调用 SetThreadContext()