6

更新:MicrosoftはまだWindows8.1でそれを修正していません。

編集:これはWOW64のバグであることが判明しました-スレッドがロングモードのリング3(ユーザーモード)で中断されると、GetThreadContext()が古いコンテンツを返す場合があります。変換を実行するためにring-2を使用することをMicrosoftに提案しました。その場合、SuspendThreadはring-3のスレッドのみを一時停止し(現在のように-変更は必要ありません)、ring-2のクラッシュ/障害/エクスプロイトはカーネルに影響を与えません-ring-2とring-にのみ影響します3.3。

このような変更には、Wow64Get / SetThreadContextなどのいくつかのWinAPI関数の変更が必要になります。これにより、文書化されていない機能に依存するアプリが破損しますが、これは予想されることです。確かに、リング3からリング2に移行するのに数CPUサイクルかかるため、変換は遅くなります(CPUファミリによって異なります)が、正しい動作を保証するためには、OSの役割が何よりも重要だと思います。翻訳はすでにWOW64で実行されているアプリにオーバーヘッドを追加しているので、それも予想されます。

Microsoftがこの問題を修正することを願っています-そうでなければ、デバッガー/モノラルアプリ/ Boehm GC / WOW64でGetThreadContext()に依存するアプリは機能しません(初心者の場合、デバッガーが古いスタックトレースを表示するのを見ました)。

EDIT2:悪いニュース。MSFT(ここ)のAlexeyとの会話から、修正によって文書化されていない機能に依存するアプリが破損することを恐れて、まったく修正されない可能性があるように見えます。


元の質問

  • 次のことについて混乱している人もいるようです。私は当初、カーネルモードのコードでSuspendThreadがスレッドを一時停止したことが原因だと思っていました。そうではありませんでした。以下は、実際の根本原因とは何の関係もないことが判明した私の最初の疑惑でした。これは、によって返された古いコンテンツでしたGetThreadContext()

MSDNから:

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

しかし、私が見つけたのは、WOW64で実行されているWindows 7の32ビットアプリで、スレッドBでSuspendThreadを呼び出すスレッドAは、64ビットコードの実行中に一時停止できることです(ユーザーモードコードではないと思います)。EIPは、中断されたスレッドがで停止したことを示しています

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

ESPが変更された状態(ESPがそのスレッドのスタックと同じページを指しているときに、現在のスタックポインターよりもはるかに高いアドレスを取得しているため、これはわかっています)。上記が戻る命令にブレークポイントを設定し、スレッドを再開すると、ESPがX86SwitchTo64BitMode呼び出し(正しいスタックポインター)の前の値に戻ることがわかりました。また、同じ関数にシングルステップインすると、シングルステップのどの時点でもその高いアドレスESP値を取得できないこともわかりました。実際、シングルステップの場合、ESP値はX86SwitchTo64BitMode呼び出しの前後で変更されることはありません。

また、(DWORD)-1をチェックして、SuspendThreadが成功することを確認しました。

これらすべてから、スレッドはカーネルモードのコードで中断されていると私は信じています。

非ユーザーモードコードの実行中にOSがスレッドを一時停止する原因は何でしょうか?どうすればそれを防ぐことができますか?これは基本的に、スレッドBの実際の現在のスタックポインターを取得することを妨げています。アプリがWOW64の外部(ネイティブx86 OS上)で実行される場合、そのような問題は存在しないことに注意してください。

4

4 に答える 4

3

これは、WOW64でGetThreadContextが呼び出されたときに古いコンテンツを返すOSの問題であることを確認しました。

詳細はこちら

この質問に答えようとしたすべての人に感謝します。私はこれを解決するためにMSと協力しています。

于 2010-11-13T05:58:01.843 に答える
1

この説明を参照してください:Wow64のGetThreadContext

この記事では、x86モードとamd64モードの間の移行はユーザーモードで行われることを説明しています。

于 2010-11-10T13:47:33.907 に答える
0

あなたのスレッドはユーザーモードで何をしますか?を呼び出すと、すでにカーネルモードになっているようSuspendThreadです。一時停止した瞬間にシステム機能を実行している可能性はありますか?

非ユーザーモードコードの実行中にOSがスレッドを一時停止する原因は何でしょうか?

多くのシステムまたはライブラリの呼び出しにより、カーネルモードに切り替わる場合があります。また、Windowsカーネルはほとんどの場合再入可能になるように設計されているため、最初のスレッドがカーネルモードになっているときに、あるスレッドから別のスレッドに切り替えるのはごく普通のことです。

どうすればそれを防ぐことができますか?

ただのアイデア:空のループ(例for(;;);)を実行しているだけのスレッドを作成し、そのスレッドを一時停止します。これはカーネルモードで一時停止しないでください。


また、ESPレジスタなどが正しいことが重要なのはなぜですか。ある種のデバッガーまたは関連するものを作成していることを願っています。それが目的だからSuspendThreadです。

于 2010-11-10T13:29:11.390 に答える
-1

技術的には、スレッドがまったく実行されていないときは、カーネルモードコードもユーザーモードコードも実行されていません。したがって、あなたの観察はステートメントと矛盾しません。

Beisdes、これをいじってはいけません。(ユーザーモードで)カーネルモードコードを実行するかどうかを制御できれば、OSのバグになります。

于 2010-11-10T13:11:22.583 に答える