更新: :Microsoft尚未在Windows 8.1中修复它。

编辑: :这是一个 漏洞 在WOW64中-GetThreadContext()可能会在线程以长模式ring -3(用户模式)悬挂时返回陈旧内容。我建议向Microsoft使用RING-2执行翻译。然后,悬挂性将仅将线悬挂在RING-3中(如现在所做的 - 无需更改),并且RING-2中的崩溃/故障/利用不会影响内核 - 它仅影响RING-2和RING-- 3。

这样的更改将需要更改一些Winapi功能,例如WOW64GET/SETTHREADCONTEXT等。这将破坏依赖无证件功能的应用程序,但这是可以预料的。当然,翻译会较慢,因为从环-3到2环的过渡需要几个CPU周期(取决于CPU家族),但我认为操作系统的作用首先是确保正确操作的最重要的。翻译已经将开销添加到WOW64下运行的应用程序中,因此也可以预期。

我确实希望Microsoft能够解决此问题 - 否则Debuggers / Mono Apps / Boehm GC / Apps依靠WOW64下的GetThreadContext()无效(对于初学者,我已经看到Debuggers显示了Stale Stale Stack Trace)。

Edit2: : 坏消息。从我与MSFT的Alexey对话中(这里)看起来似乎根本无法修复,因为担心修复会破坏依赖无证件功能的应用程序。


原始问题

  • 有些人似乎对以下内容感到困惑。我最初认为这是由于悬挂线在内核模式代码中暂停线程的原因。不是。以下只是我最初的怀疑,事实证明与实际根本原因无关 - 这是返回的陈旧内容 GetThreadContext().

来自MSDN:

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

但是我发现的是,我在WOW64下运行的Windows 7中的32位应用 不是 用户模式代码)。 EIP显示悬浮线停在

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

由于它的ESP已更改(我知道这一点,因为,尽管ESP指向该线程的堆栈相同的页面,但它的地址比当前的堆栈指针更高)。如果我对上述返回到的指令进行断点,然后再恢复线程,我发现ESP在x86switchto64bitmode调用之前更改为值(这是正确的堆栈指针)。我还发现,当单个踏入相同的函数时,我永远无法在单个步骤的任何时候获得更高的地址ESP值。实际上,当单个步进时,ESP值在x86switchto64bitmode调用之前和之后永远不会更改。

另外,我确实通过检查(dword)-1来确保SustendThread成功。

所有这些使我相信该线程被悬挂在内核模式代码中。

什么可能导致操作系统在运行非用户模式代码时暂停线程?我如何防止这种情况?这基本上是阻止我获得线程B的实际堆栈指针B。

有帮助吗?

解决方案

我已经确认这是一个OS问题,当GetThreadContext在WOW64下调用时,返回了陈旧的内容。

更多信息在这里.

感谢所有试图回答这个问题的人。我正在与MS合作解决此问题。

其他提示

请参阅此解释: WOW64中的GetThreadContext

本文解释说,X86和AMD64模式之间的过渡是在用户模式中完成的。

您的线程在用户模式中有什么作用?打电话时似乎已经在内核模式中 SuspendThread. 。您是否有可能在您暂停它的那一刻执行系统函数?

什么可能导致操作系统在运行非用户模式代码时暂停线程?

许多系统或库调用可能会导致切换到内核模式。而且,由于在大多数情况下,由于Windows内核设计为重进入,因此从一个线程切换到另一个线程,而第一个则在内核模式中非常正常。

我如何防止这种情况?

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


另外,为什么ESP寄存器等对您来说很重要?希望您写某种调试器或与之相关的内容,因为那是什么 SuspendThread 是。

从技术上讲,当线程根本不运行时,它既不运行内核模式代码也不运行用户模式代码。因此,您的观察结果并不矛盾。

Beisdes,您不应该对此感到烦恼。如果您(在用户模式下)可以控制是否执行内核模式代码,那将是一个OS错误。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top