ARM64版Windows 11では、x86プロセス、x64プロセス、ARM64プロセスの3種類のプロセスが動作します。
ユーザーモード側のプログラムからはIsWow64Process2やGetProcessInformation(ProcessMachineTypeInfo)を使用して、どの種別のプロセスなのか判別できますが、カーネルモード側ではどのように判別するのでしょうか。
ntoskrnl.exeのエクスポート関数に、PsGetProcessMachineという関数が含まれています。これで判別できそうですが、現時点(2025/08/21)ではまだパラメータや戻り値などの情報は公開されていないようです。
WinDbgを使って、PsGetProcessMachineがどんな関数なのか見てみましょう。
0: kd> uf PsGetProcessMachine
nt!PsGetProcessMachine:
fffff801`1f0c8950 794f5800 ldrh w0,[x0,#0x7AC]
fffff801`1f0c8954 d65f03c0 ret
たったこれだけです。
関数の第一パラメータ(x0)に0x7ACを足し、そのアドレスに格納されている値をUSHORT型で戻り値(w0)として返すだけです。
第一パラメータには何を指定するのでしょうか?
Psから始まる名前のAPIには、多くの場合、EPROCESSへのポインタを渡すことが多いです。
ということは、第一パラメータはEPROCESSへのポインタではないでしょうか?
EPROCESS構造体の0x7ACが何なのか見てみましょう。
0: kd> dt _EPROCESS
nt!_EPROCESS
(省略)
+0x7a0 DxgProcess : Ptr64 Void
+0x7a8 Win32KFilterSet : Uint4B
+0x7ac Machine : Uint2B
+0x7ae MmSlabIdentity : UChar
+0x7af Spare0 : UChar
(省略)
Machineという名前のUSHORTの数値を指しています。
ということは、PsGetProcessMachineの実装は以下のようになっていると推測できます。
USHORT PsGetProcessMachine(PEPROCESS pEProcess)
{
return pEProcess->Machine;
}
実際にEPROCESS構造体のMachineメンバに何が入っているのか調べてみると、
x86プロセス ... 0x014C (IMAGE_FILE_MACHINE_I386)
x64プロセス ... 0x8664 (IMAGE_FILE_MACHINE_AMD64)
ARM64プロセス ... 0xAA64 (IMAGE_FILE_MACHINE_ARM64)
となっていました。
これでカーネル側でも、極めて高速にプロセス種別が判断できます。