SuspendThread WOW64挂起在内核代码中

更新 :微软尚未在Windows 8.1中解决它。

编辑 :这原来是在WOW64中的错误 – GetThreadContext()可能会返回过时的内容,当线程挂起在长模式环-3(用户模式)。 我build议微软使用ring-2来执行翻译。 然后SuspendThread只会挂起第3个环的线程(就像现在这样 – 不需要做任何改动),ring-2中的crash / fault / exploit不会影响内核 – 它只会影响ring-2和ring- 3。

这样的更改将需要更改一些WinAPI函数,如Wow64Get / SetThreadContext等。这将打破应用程序依赖于未logging的function,但这是可以预料的。 当然,由于需要花几个CPU周期才能从ring-3转换到ring-2(取决于CPU系列),转换速度会更慢,但我认为OS的angular色首先是确保正确的操作。 翻译已经增加了在WOW64下运行的应用程序的开销,所以这也是可以预料的。

我希望微软能够解决这个问题,否则在WOW64下依赖GetThreadContext()的debugging器/单声道应用程序/ Boehm GC /应用程序将无法工作(对于初学者,我已经看到debugging器显示过时的堆栈跟踪)。

编辑2 :坏消息。 从我与MSFT( 这里 )的Alexey的交谈中,看起来好像根本不可能修复,因为担心这个修复会破坏依赖于无证function的应用程序。


原来的问题

  • 有些人似乎对以下内容感到困惑。 我最初认为这是由于SuspendThread在内核模式代码中暂停一个线程。 事实并非如此。 以下只是我最初的怀疑,结果与实际的根本原因没有任何关系 – 这是GetThreadContext()返回的陈旧内容。

来自MSDN:

Suspending a thread causes the thread to stop executing user-mode (application) code.

然而,我发现我的Windows 7中运行在WOW64下的32位应用程序,在线程B上调用SuspendThread的线程可以暂停运行64位代码(我期望不是用户模式代码)。 EIP显示暂停的线程停在

 wow64cpu!X86SwitchTo64BitMode: 00000000`759c31b0 ea27369c753300 jmp 0033:759C3627 

其ESP已经改变了(我知道这是因为,当ESP指向与该线程堆栈相同的页面时,它具有比当前堆栈指针高得多的地址)。 如果我在上面返回的指令处放一个断点,然后让线程恢复,我发现ESP变回X86SwitchTo64BitMode调用之前的值(这是正确的堆栈指针)。 我还发现,当单步进入相同的function时,我无法在单步的任何点获得更高的地址ESP值。 实际上,单步执行时,ESP值在X86SwitchTo64BitMode调用前后不会改变。

此外,我确实通过检查(DWORD)-1确保SuspendThread成功。

所有这些导致我相信线程被挂起在内核模式代码中。

什么可能导致操作系统挂起一个线程,而它正在运行非用户模式代码? 我如何防止? 这基本上阻止我得到实际的线程B的当前堆栈指针。请注意,当应用程序运行在WOW64之外(在本机x86操作系统上)时,不存在这样的问题。

我已经确认这是在WOW64下调用GetThreadContext时返回陈旧内容的操作系统问题。

更多信息在这里 。

感谢大家试图回答这个问题。 我正在与MS一起解决这个问题。

看到这个解释: Wow64中的GetThreadContext

本文解释说,x86和amd64模式之间的转换是在用户模式下完成的。

你的线程在用户模式下做了什么? 当你调用SuspendThread时,它似乎已经处于内核模式。 是否有可能在你暂停的时刻执行系统功能?

什么可能导致操作系统挂起一个线程,而它正在运行非用户模式代码?

许多系统或库调用都可能导致切换到内核模式。 而且由于Windows内核在大多数情况下都是可重入的,所以在内核模式下,从一个线程切换到另一个线程是非常正常的。

我如何防止?

只是一个想法:创建一个只执行一个空循环的线程(例如for(;;); )并暂停该线程。 这个不应该被挂在内核模式下。


另外,为什么你认为ESP寄存器等是正确的? 我希望你正在编写某种调试器或相关的东西,因为这就是SuspendThread的用途。

从技术上讲,当一个线程完全不运行时,它既不运行内核模式代码,也不运行用户模式代码。 所以你的观察与这个陈述不矛盾。

贝思德,你不应该这样做。 如果你(在用户模式下)可以控制内核模式代码是否被执行,这将是一个操作系统错误。