WOW64 实现详细信息

WOW64 模拟器在用户模式下运行。 它提供 32 位版本的 Ntdll.dll 与处理器内核之间的接口,并截获内核调用。 WOW64 模拟器包含以下 DLL:

  • Wow64.dll为Ntoskrnl.exe入口点函数提供核心仿真基础结构和 thunk。
  • Wow64Win.dll为Win32k.sys入口点函数提供 thunk。
  • (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 二进制文件的未修改副本,但出于性能原因,有些 DLL 作为 CHPE 加载。 其中一些 DLL 在 WOW64 上与在 32 位 Windows 上的行为不同,通常是因为它们与 64 位系统组件共享内存。 超过 32 位限制的所有用户模式地址空间都由系统保留。 有关详细信息,请参阅 WOW64 下的性能和内存消耗

将重新生成进行系统调用的 32 位二进制文件以使用自定义调用序列,而不是使用 x86 系统服务调用序列。 对于 WOW64 来说,此调用序列的拦截成本较低,因为它完全保持用户模式。 检测到自定义调用序列时,WOW64 CPU 将转换回本机 64 位模式,并调用 Wow64.dll。 Thunking 是在用户模式下完成的,以减少对 64 位内核的影响,并降低 thunk 中可能导致内核模式崩溃、数据损坏或安全漏洞的 bug 的风险。 thunks 从 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: 从 Windows 7 和 Windows Server 2008 R2 开始添加了 ProgramW6432 和 CommonProgramW6432 环境变量。
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 位和 64 位 DLL 必须具有不同的名称。
  • DLL 和进程的体系结构必须匹配。 例如,不能将 32 位 x86 DLL 注入 32 位 ARM 进程。

有关详细信息,请参阅 SetWindowsHookEx

请注意,可以在安装挂钩的线程上调用 WH_MOUSEWH_KEYBOARDWH_JOURNAL*WH_SHELL和低级别挂钩,而不是在处理挂钩的线程上调用。 对于这些挂钩,如果 32 位挂钩在挂钩链中的 64 位挂钩之前,可能会同时调用 32 位和 64 位挂钩。 有关详细信息,请参阅 使用挂钩