WOW64 実装の詳細
WOW64 エミュレーターはユーザー モードで実行されます。 32 ビット バージョンの Ntdll.dll とプロセッサのカーネルの間のインターフェイスを提供し、カーネル呼び出しをインターセプトします。 WOW64 エミュレーターは、次の DLL で構成されます。
- Wow64.dll は、コア エミュレーション インフラストラクチャと、Ntoskrnl.exe エントリ ポイント関数のサンクを提供します。
- Wow64Win.dll は、Win32k.sys エントリ ポイント関数のサンクを提供します。
- (x64 のみ) Wow64Cpu.dll は、x64 で x86 プログラムを実行するためのサポートを提供します。
- (Intel Itanium のみ)IA32Exec.binには、x86 ソフトウェア エミュレーターが含まれています。
- (Intel Itanium のみ) Wowia32x.dll は、IA32Exec.binと WOW64 の間のインターフェイスを提供します。
- (ARM64 のみ) xtajit.dll x86 ソフトウェア エミュレーターが含まれています。
- (ARM64 のみ) wowarmw.dll は、ARM64 で ARM32 プログラムを実行するためのサポートを提供します。
これらの DLL と 64 ビット バージョンの Ntdll.dllは、32 ビット プロセスに読み込むことができる唯一の 64 ビット バイナリです。 ARM 上の Windows 10 では、CHPE (コンパイル済みハイブリッド ポータブル実行可能ファイル) バイナリも x86 32 ビット プロセスに読み込まれる可能性があります。
起動時に、Wow64.dll は x86 バージョンの Ntdll.dll (または有効な場合は CHPE バージョン) を読み込み、必要なすべての 32 ビット DLL を読み込む初期化コードを実行します。 ほとんどの 32 ビット DLL は 32 ビット Windows バイナリの変更されていないコピーですが、一部はパフォーマンス上の理由から CHPE として読み込まれます。 これらの DLL の一部は、WOW64 では、通常は 64 ビット システム コンポーネントとメモリを共有するため、32 ビット Windows とは異なる動作をするように記述されています。 32 ビット制限を超えるすべてのユーザー モード アドレス空間は、システムによって予約されます。 詳細については、「WOW64 のパフォーマンスとメモリ消費量」を参照してください。
x86 システム サービス呼び出しシーケンスを使用する代わりに、システム呼び出しを行う 32 ビット バイナリは、カスタム呼び出しシーケンスを使用するように再構築されます。 この呼び出しシーケンスは、WOW64 が完全にユーザー モードのままであるため、インターセプトが低コストです。 カスタム呼び出しシーケンスが検出されると、WOW64 CPU はネイティブ 64 ビット モードに戻り、Wow64.dllに呼び出されます。 サンキングは、64 ビット カーネルへの影響を軽減し、カーネル モードのクラッシュ、データ破損、またはセキュリティ ホールを引き起こす可能性のあるサンクのバグのリスクを軽減するために、ユーザー モードで実行されます。 サンクは、32 ビット スタックから引数を抽出し、64 ビットに拡張してから、ネイティブ システム呼び出しを行います。
環境変数
32 ビット プロセスが 64 ビット プロセスによって作成される場合、または 64 ビット プロセスが 32 ビット プロセスによって作成される場合、WOW64 は次の表に示すように、作成されたプロセスの環境変数を設定します。
過程 | 環境変数 |
---|---|
64 ビット プロセス |
PROCESSOR_ARCHITECTURE=AMD64 または PROCESSOR_ARCHITECTURE=IA64 または PROCESSOR_ARCHITECTURE=ARM64 ProgramFiles=%ProgramFiles% ProgramW6432=%ProgramFiles% CommonProgramFiles=%CommonProgramFiles% CommonProgramW6432=%CommonProgramFiles% Windows Server 2008、Windows Vista、Windows Server 2003、Windows XP: ProgramW6432 および CommonProgramW6432 環境変数は、Windows 7 および Windows Server 2008 R2 以降で追加されました。 |
32 ビット プロセス |
PROCESSOR_ARCHITECTURE=x86 PROCESSOR_ARCHITEW6432=%PROCESSOR_ARCHITECTURE% ProgramFiles=%ProgramFiles(x86)% ProgramW6432=%ProgramFiles% CommonProgramFiles=%CommonProgramFiles(x86)% CommonProgramW6432=%CommonProgramFiles% |
グローバル フック
SetWindowsHookEx 関数を使用すると、次の条件が満たされた場合に DLL を別のプロセスに挿入できます。
- 32 ビット DLL は 32 ビット プロセスにのみ挿入でき、64 ビット DLL は 64 ビット プロセスにのみ挿入できます。 32 ビット DLL を 64 ビット プロセスに挿入することも、その逆に挿入することもできません。
- 32 ビット DLL と 64 ビット DLL の名前は異なる必要があります。
- DLL とプロセスのアーキテクチャが一致している必要があります。 たとえば、32 ビットの x86 DLL を 32 ビット ARM プロセスに挿入することはできません。
詳細については、「SetWindowsHookExを参照してください。
WH_MOUSE、WH_KEYBOARD、WH_JOURNAL*、WH_SHELL、および低レベルのフックは、フックを処理するスレッドではなく、フックをインストールしたスレッドで呼び出すことができます。 これらのフックの場合、32 ビット フックがフック チェーンの 64 ビット フックより前にある場合、32 ビットと 64 ビットの両方のフックが呼び出される可能性があります。 詳細については、「フックの使用」を参照してください。