持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第7天
参考: 《深入解析Windows操作系统 第3章 系统机制 3.8 WOW64》
@[toc]
前言
Wow64子系统是微软为了让64位系统上能正常运行32位程序所创建的子系统
Wow64子系统
Wow64(64位Windows上的Win32仿真)是指允许在64位Windows上执行32位x86应用程序的软件。
它的实现方式是一组用户模式DLL,外加一些来自内核的支持,此内核支持是为了创建32位版本的数据结构,比如进程环境块(PEB)和线程环境块(TEB),这些数据结构正常情况下只有64位版本。通过Get/SetThreadContext来改变Wow64环境也是由内核实现的。
下面是负责Wow64的用户模式DLL:
- Wow64.dll:管理进程和线程的创建、钩住异常分发和Ntoskrnl..exe导出的基本系统调用。它也实现了文件系统重定向,以及注册表重定向。
- Wow64Cpu.dll:为每个正在Wow64内部运行的线程,管理它们的32位CPU环境:针对从32位到64位或者从64位到32位的CPU模式切换,提供了与处理器体系结构相关的支持。
- Wow64Win.dll:截取了Win32k.sys导出的GUI系统调用。
- IA64系统上的IA32Exec.bin和Wowia32x.dll:包含IA-32软件仿真器和它的接口库。因为Itanium处理器不能以原生方式高效地执行x86的32位指令(性能差于30%),所以有必要通过这两个额外的组件来实现软件仿真(通过二进制翻译)。
WOW64作用
-
钩住所有32转64代码和64转32位代码:Wow64钩住了所有从32位代码转变至原生64位系统的代码路径,也钩住了64位原生系统需要调用至32位用户模式代码的所有代码路径。 -
映射64/32位dll到内存:在进程创建的过程中,进程管理器(process manager)将原生的64位Ntdl.dl和针对Wow64进程的32位Ntdll.dll映射到进程地址空间中。 -
切换CPU环境到32位 并初始化:当加载器的初始化过程被调用时,它调用Wow64.dll内部的Wow64初始化代码。然后Wow64建立起32位Ntdl所要求的启动环境,将CPU模式切换到32位下,并开始执行32位加载器。从这个点开始,执行过程继续进行,就如同该进程运行在原生的32位系统上一样。 -
重定向:将所有使用32位系统功能的转为64位环境 例如钩住所有system32文件夹路径 转为使用system64文件夹
Ntdll.dll、User32.dll和Gdi32.dll的特殊32位版本位于\Windows\Syswow64文件夹下(也有一些特定的执行跨进程通信的其他DLL,比如Rpcrt44.dl)。它们调用到Wow64中,而不是发出原生的32位系统调用指令。Wow64转变到原生的64位模式下,捕获到与系统调用有关的参数(将32位指针转换为64位指针),并且发出对应的原生64位系统调用。当原生的系统调用返回时,Wow64把任何输出参数,如果有必要的话,在返回至32位模式之前从64位转换成32位格式。
WOW常见作用方向
系统文件重定向
为了维护应用程序的兼容性,以及降低从Win32到64位Windows的应用程序移植代价,系统目录名称仍然保持不变。因此,Windows\System32文件夹包含了原生的64位映像文件。因为Wow64钩住了所有的系统调用,所以,它会解释所有与路径相关的API,将Windows\System32文件夹的路径名替换为Windows\Syswow64
Wow64也将\Windows\LastGood\重定向到\Windows\LastGood\syswow64,将\Windows\Regedit.exe重定向到Windows\syswow64 Regedit.exe。通过使用系统环境变量,%PROGRAMFILES%环境变量对于32位应用程序被设置为Program Files(x86),而对于64位应用程序被设置为Program Files文件夹。CommonProgramFilesi和CommonProgramFilest(x86)环境变量也存在,它们总是指向32位的位置,而ProgramW6432和CommonProgram WP6432则无条件地指向64位位置。
注: 因为有些特定的32位应用程序可能真的需要知晓或者能够处理64位映像文件,所以,有一个虚拟的目录,\Windows\Sysnative,使得任何从32位应用程序发出的针对此目录的l/O,都免于被文件重定向。这个目录实际上并不存在,它只是一个允许访问到真正的System32目录的虚拟路径而已,即使运行在WoW64下的应用程序也不例外。
Windows\System32中有一些子目录,出于兼容性的原因,这些子目录没有被重定向,所以32位应用程序在访问这些目录时实际上是在访问真正的目录。这些目录包括:
- %windir%\system32\drivers\etc
- %windir%\system32\spool
- %windir%\system32\catrootwindir%system32\catroot2
- %windir%\system32\logfiles
- %windir%\system32\driverstore
注意: Wow64提供了一种机制来控制Wow64中内置的文件系统重定向功能,这种机制是以每个线程为基础的,通过Wow64 DisableWow64FsRedirection和Wow64RevertWow64FsRedirection函数来实施控制。该机制对于延迟加载的DLL、通过公共文件对话框来打开文件,甚至国际化方面,都存在一些问题一一因为一旦重定向被关闭,系统要么在内部加载过程中不再使用重定向,要么有些特定的只有64位的文件便无法再找到。使用c:\windows\sysnative路径或者前面介绍的其他的一致路径通常是一种更为安全的方法,可以供开发人员使用。
System32文件夹
今天反编译svchost.exe, 发现sysWow64下面的svchost是32位的,System32下的svchost是64位的。
在32位操作系统的Windows文件夹中,SYSTEM和SYSTEM32两个文件夹,分别用来存放16位和32位的DLL文件。如果按照这个规律,存放64位系统的DLL文件的文件夹应该叫:System64,但实际上存放64位DLL的文件夹依然叫:System32,同时又多了一个SysWow64文件夹现在的软件大多是32位软件,所以默认会将DLL文件放到System32文件夹中,而微软为了保障兼容性,所以无论是32位还是64位的DLL文件都是放到了System32文件夹中。
SysWow64文件夹
WoW64( windows on windows 64)
SysWow64文件夹,是64位Windows,用来存放32位Windows系统文件的地方。
这是因为32位软件并不能在64位系统中直接运行,所以微软设计了WoW64(Windows-on-Windows 64-bit),通过Wow64.dll、Wow64win.dll、Wow64cpu.dl三个DLL文件进行32位和64位系统的切换来运行32位软件。所以在64位系统中,DLL复制到System32文件夹中即可。
禁止Wow64和32的重定向
程序编译的是32位程序,而测试环境运行在64位Windows10系统上。当32位程序访问64位的System32文件目录的时候,会出现文件重定向,调用Wow64DisableWow64FsRedirection和Wow64RevertWow64FsRedirection函数来关闭和恢复文件重定向。
而且,32位程序在操作64位系统注册表的时候,也会出现注册表重定向的情况,可以在调用RegCreateKeyEx函数打开注册表的时候,设置KEY_WOW64_64KEY的注册表访问权限,以确保能正确访问64位下的注册表,不被注册表重定向。