谈谈Windows Wow64

article/2025/9/26 8:27:47

本文是《深入理解Windows操作系统 (第六版) 》关于64位Windows操心系统有关Wow64部分的读书笔记,因为之前很少有接触到关于Wow64的部分,记录一下。

Wow64是允许在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和Wow32ia32x.dll:包含了IA-32软件仿真器和它的接口库,因为Itanium处理器不能以原生方式高效地执行x86的32位指令,所以通过这两个额外的组件来实现软件仿真(通过二进制翻译)。

  各个组件的依赖关系如图:

                                 

 

Wow64进程地址空间布局

   Wow64进程可以在2GB虚拟空间中运行,也可以在4GB虚拟空间中运行。如果映像文件的头部设置了大地址空间感知标志,则内存管理将4GB边界之上至用户模式边界末尾之间保留为用户模式地址空间。如果映像文件没有被标记为大地址空间感知的,则内存管理器将保留2GB之上的用户模式地址空间。

 

系统调用

Wow64勾住了所有从32位代码转变至原生64位系统的代码路径,也勾住了64位原生系统需要调用至32位用户模式代码的所有路径。在进程创建的过程中,进程管理器(process manager)将原生的64位Ntdll.dll和针对Wow64进程的32位Ntdll.dll映射到进程地址空间中。当加载器的初始化过程被调用时,它调用Wow64.dll内部的Wow64初始化代码。然后Wow64建立起32位Ntdll所要求的启动环境,将CPU模式切换至32位下,并开始执行32位加载器。从这个点开始,执行过程继续执行,就如同该进程运行在原生的32位系统之上。

Ntdll.dll,User32.dll和Gdi32.dll的特殊32位版本位于\Windows\Syswow64文件夹下。它们调用到Wow64.dll中,而不是发出原生的32位系统调用指令。Wow64转变到原生的64位模式下,并捕获到与系统调用有关的参数(将32位指针转化为64位指针),并发出对应的原生64位系统调用。当原生的系统调用返回时,Wow64把任何输出参数,如果有必要的话,在返回至32位模式之前从64位转换成32位格式。

 

异常分发

Wow64通过Ntdll.dll的KiUserExceptionDispatcher勾住了异常分发过程。无论何时当64位内核将要给一个Wow64进程分发一个异常时,Wow64会捕获住原生的异常以及用户模式下的环境记录(context record),然后准备一个32位异常和环境记录,并且按照原生32位内核所做的那样将他分发出去。

 

用户APC分发

Wow64通过Ntdll的KiUserApcDispatcher也勾住了用户模式APC的递交过程。无论何时当64位内核将要给一个Wow64进程分发一个用户模式APC时,Wow64把32位APC地址映射到一个更高的64位地址空间范围中。然后64位Ntdll捕获住原生的APC以及用户模式下的环境记录,将它映射到一个32位地址。然后为它准备一个32位用户模式APC和环境记录,并且按照原生32位内核所做的那样将它分发出去。

 

控制台支持

因为控制台是由Csrss.exe在用户模式下实现的,它只是单个原生二进制可执行文件,所以,32应用程序在64位Windows上执行不能执行控制台I/O。类似于专门有一个特殊的rpcrt4.dll用来将32位RPC适配成64位RPC,Wow64的32位kernel32.dll中有专门的代码来调用到Wow中,以便在与Csrss与Conhost.exe交互过程中对参数进行适配。

 

用户回调

Wow64截取了所有从内核到用户模式的回调。Wow64将这样的回调也按照系统调用来对待;然而,根据转换规则是按相反的顺序来完成的:输入参数从64位转换为32位,而输出参数则是在该次回调返回时从32位转换至64位。

 

文件系统重定向

为了维护应用程序的兼容性,已经降低从Win32到64位Windows的应用程序移植代价,系统目录名称仍然保持不变。因此,\Windows\System32文件夹包含了原生的64位映像文件。因为Wow64勾住了所有的系统调用,所以它会解释所有与路径相关的API,将\Windows\System32文件夹的名称替换为\Windows\Syswow64。Wow64也将\Windows\LastGood重定向到\Windows\LastGodd\Syswow64,将\Windows\Regedit.exe重定向到\Windows\syswow64\Regedit.exe。通过使用系统环境变量,%PROGRAMFILE%环境变量对于32位程序被设置为\Program File (x86),而对于64位应用程序被设置为\Program File文件夹,CommonProgramFiles和ComonProgramFiles(x86)也存在,它们总是指向32位的位置,而ProgramW6432和CommonProgramWP6432则无条件指向64位位置。

注:因为有些特定的32位程序可能真的需要知晓或者能够处理64位映像文件,所以有一个虚拟的目录,\Windows\Sysnative,使得任何从32位程序发出的针对此目录的I/O,都免于被文件重定向。这个目录实际上并不存在,它只是一个允许访问到真正的System32目录的虚拟路径而已,即使运行在Wow64下的程序也不例外。

Windows System32中有一些目录,由于兼容性的原因,这些子目录没有被重定向,所以32位程序访问这些目录的时候实际上访问的是真正的目录。这些目录包括:

  • %windir%\system32\drivers\etc
  • %windir%\system32\spool
  • %windir%\system32\catroot和%windir%system32\catroor2
  • %windir%\system32\logfiles
  • %windir%\system32\driverstore

 

注册表的重定向

应用程序和组件程序将它们的配置数据保留在注册表中。组件程序在安装的过程中,当它们被注册的时候,通常将配置数据写到注册表中。如果同样的组件即安装注册了一个32位二进制文件,又安装了一个64位二进制文件,那么,最后被注册的组件将会覆盖掉以前组件的注册,因为他们填写在相同的位置上。

为了以透明的方式解决这个问题,并且无须对32位组件进行任何代码修饰,注册表被分成了两个部分:原生的和Wow64的。在默认情况下,32位组件访问32位视图,64位组件访问64位视图,这为32位和64位组件提供了一个安全的环境,并且将32位应用程序的状态与64位应用程序的状态隔开来。

为了实现这一点,Wow64截取了所有要打开注册表的系统调用,并且重新解释这些注册表键的路径,将它们指向注册表的64位视图。Wow64在以下这些点上分裂注册:

  •  HKLM\SOFTWARE
  •  HKEY_CLASSES_ROOT

但是许多子键实际上在32位和64位之间是共享的——也就是说,并不是并非整个键巢都被分裂了。在以上的每个键下面,Wow64创建了一个称为Wow6432Node的键。在该键下面保存的是32位的配置信息。注册表的所有其他部分对于32位程序和64位程序都是共享的(比如:HKLM\SYSTEM)。

         还有一个额外的帮助,如果一个32位应用程序向注册表中写入一个以数据“%ProgramFiles%”或者“%commonprogramfiles%”为开头的REG_SZ或者REG_EXPAND_SZ值,那么Wow64将实际的值修改为”%ProgramFiles(x86)”或“commonprogramfiles(x86)”以便符合前面介绍过的文件重定向和布局结构。32位程序必须正确的写这些字符串——其他的数据都被忽略,按普通的方式写入。最后,任何包含”system32”的键被替换为“syswowo64”(针对所有的大小写),也不管大小写标志是否敏感,除非使用了KEY_WOW64_64KEY,以及该键位于“反射键”列表中。

如果应用程序需要显示的指定一个注册表键位于某个特定的视图中,那么,在RegOpenKeyEx,RegCreateKeyEx,RegOPenKeyTransacted,RegCreateKeyTransacted和RegDeleteKeyEx函数中使用以下标志可以做到这一点:

  •  KEY_WOW64_64KEY —— 从一个32位或者64位程序显示的打开一个64位键,并禁止REG_SZ或者REG_EXPAND_SZ截取转换处理。
  •  KEY_WOW64_32KEY —— 从一个32位或者64位程序显示的打开一个32位键。

 

控制请求

除了普通的读和写操作外,应用程序可以利用Windows 的DeviceIoControl API与某些设备驱动程序通过设备I/O控制函数进行通信。应用程序可能会在调用时指定一个输入或输出缓冲区。如果该缓冲区包含了与指针相关的数据,并且发送该控制请求的进程是一个Wow64进程,那么输入或输出结构的视图在32位应用程序和64位驱动程序之前是不相同的。驱动程序可以调用IoIs32bitProcess()函数来检测一个I/O请求是否从一个Wow64进程发出。

可以参考MSDN上的《Supporting 32-Bit I/O in Your 64-BitDriver》。

 

限制

Wow64不支持16位应用程序的执行(32位Windows支持),也不支持加载32位内核模式的设备驱动程序。Wow64进程只能加载32位dll,不能加载原生的64位dll。类似的,原生的64位进程不能加载32位的DLL。唯一列外的是,在跨越体系结构差异时,能够加载仅包含资源或数据的Dll,这是允许的,因为这些Dll只包含数据,不包含代码。


http://chatgpt.dhexx.cn/article/JsMGBlWL.shtml

相关文章

Windows WOW64 nativeapi 逆向详解,32程序兼容剖析

前言 windows有很多核心的原生api,其中包含sdk声明的和文档未声明的。主要由于ntdll.dll和win32u.dll(服务号0x1000-0x1FFF)导出。 WOW64 (Windows-on-Windows 64-bit)是一个Windows操作系统的子系统,用于模拟32位环境,使得32位执行程序在x64…

mysql版本wow64平台_WOW64最佳实现

WOW64简介 WOW64(Windows 32-bit On Windows 64-bit)是x64平台上运行win32应用程序的模拟器,它在系统层提供了中间层,将win32的系统调用转换成x64进行调用,并且将x64返回的结果转换成win32形式返回给win32程序。下图描述了win32程序如何在x64…

WOW64机制

WOW64: Windows On Windows64 是一种在64位OS中支持运行的32位应用程序的机制. 64位Windows中, 64位应用程序会加载64位的kernel32.dll, ntdll.dll, 32位应用程序会加载32位的kernel32.dll, ntdll.dll. WOW64则会将32位的dll文件的API请求重定向到64位的dll文件. 注意内核模式…

java for数组遍历数组_Java foreach操作(遍历)数组

语法: 我们分别使用 for 和 foreach 语句来遍历数组 运行结果: 练习: import java.util.Arrays; public class HelloWorld {public static void main(String[] args) {// 定义一个整型数组,保存成绩信息 int[] scores = { 89, 72, 64, 58, 93 }; // 对Arrays类对数组进行排…

【有趣的实验】JAVA 遍历数组的几种方式的耗时对比

一、前言 出于对遍历方式的耗时想法&#xff0c;是普通for循环、fori、foreach、迭代器 iterator、还是steam流的形式哪种耗时更少呢&#xff1f; 首先添加一个List 集合&#xff0c;这边采用ArraryList ArrayList<Integer> list new ArrayList<Integer>();list …

Java高逼格遍历数组的方式

在普通for循环遍历或取数组元素或做其他操作时&#xff0c;总会以将要超出数组最大索引作为循环结束的标志&#xff0c;也就是说每一次循环都要去判断此条件是否满足 而forEach强就强在它无需这一步流程&#xff0c;所以效率要高 但在今天我无意写出了一种这样的遍历方式&…

java遍历数组的三种方式

for循环遍历 用for循环遍历数组是很常见的一种方法&#xff0c;Java语言中通过数组的length属性可获得数组的长度。 package demo; publicclasstest{ public static void main(String[] args){ int [] array {1,2,3,4,5};for(int i 0;i < array.length;i){ System.out.print…

Java基础-遍历数组

Java基础-遍历数组 1、语法简介2、一维数组3、二维数组4、三维数组 1、语法简介 在Java中&#xff0c;对for语句的功能给予了扩充、加强&#xff0c;以便更好的遍历数组。 语法格式如下&#xff1a; for(声明循环变量:数组的名字){......... }其中&#xff0c;声明的循环变量…

JAVA 遍历数组求平均值与最大值

求平均值与最大值 实现前需要懂得如何获取数组长度实现数组遍历 例如&#xff1a; int[] array {2,3,6,8,18}; for(int i 0 ; i<array.length; i){ System.out.print(array[i] ","); } 输出结果&#xff1a;2,3,6,8,18 求最大值时则采用擂台制现默认一个数…

java遍历数组(Java遍历数组拿取对应的)

java中怎样遍历数组对象的值 int[] a {1,2,3}; for(int i0;i System.out.println(a[i]); }//定义一个string类型的一维数组 string[] namesnew string[5]; //为数组赋值 for (int i 0; i < names.length; i) { names[i]integer.tostring(i); //使用foreach遍历数组 int in…

java遍历数组最简洁的方法,java遍历数组的方式有哪些?

我们也了解Java也已经很久了&#xff0c;那今天小编想问大家是否知道java遍历数组的方式有哪些?是不是内心已经已经有答案了?让就跟着小编的步伐一起看看吧。 1. for循环遍历 这是最基本的遍历方式 通常遍历数组都是使用for循环来实现。遍历一维数组很简单&#xff0c;遍历二…

java中遍历数组方法

1循环遍历数组方法 在main主函数中给数组赋值即可调用该方法 public static void fun07(int[] array) {System.out.print("[");//输出一个左中括号if (array ! null) { //如果数组不为空&#xff0c;执行下面的语句for (int i 0; i < array.length; i) { /…

Java中数组遍历的五种方法

遍历&#xff1a;Stream遍历&#xff0c;循环遍历 //TODO 为Java提供的一种书签import java.util.Vector; import java.util.Enumeration; import java.util.Iterator; import java.util.Random;/*** 数组多种遍历偶数方法* * author 轩**/ public class Main {public static v…

Java:遍历数组的三种方法

1、for循环遍历数组 用for循环遍历数组是很常见的一种方法&#xff0c;Java语言中通过数组的length属性可获得数组的长度。 package demo;public class test {public static void main(String[] args) {int [] array {1,2,3,4,5};for(int i 0;i < array.length;i) {Syste…

java中数组遍历的三种方式

1.for循环遍历 通常遍历数组都是使用for循环来实现。遍历一维数组很简单&#xff0c;遍历二维数组需要使用双层for循环&#xff0c;通过数组的length属性可获得数组的长度。 2.Arrays工具类中toString静态方法遍历 利用Arrays工具类中的toString静态方法可以将一维数组转化为字…

Oracle--常用数据库对象(视图、序列、索引、同义词)详解

常见的数据库对象 对象描述表基本的数据存储集合&#xff0c;由行和列组成视图从表中抽出的逻辑上相关的数据集合序列提供有规律的数值索引提高查询的效率同义词给对象起别名 视图 什么是视图&#xff1f; 视图是一个 虚 表 \color{red}{虚表} 虚表视图建立在已有表的基础上…

Oracle【基础函数、视图、索引】

1. 认识oracle数据库 Oracle是非常强大的数据库软件。默认端口&#xff1a;1521。与MySQL不同的是&#xff0c;Oracle数据库的概念是一个操作系统装的就是一个大的数据库。一个数据库可以有很多个实例&#xff0c;每个实例占用一系列的进程和内存。通常一台机器只用一个实例。每…

主要是sql查询符合在圆形,多边形区域经纬度的数据

主要是sql查询符合在圆形&#xff0c;多边形区域经纬度的数据 查询 圆形 中心点 距离 drop table if exists demo; CREATE TABLE demo (id int(5) NOT NULL AUTO_INCREMENT COMMENT 主键,shop_name varchar(50) DEFAULT NULL COMMENT 商品名称,lng DECIMAL( 11, 8 ) DEFA…

mysql计算相关系数_用sql实现相关系数的计算

登录后查看更多精彩内容~ 您需要 登录 才可以下载或查看,没有帐号?立即注册 x 本帖最后由 静言_GRMC 于 2018-5-25 13:07 编辑 平时工作中要用到好多统计查询功能,一直用sql比较顺手,最近需要做相关系数方面的统计,发现除了Oracle自带了函数外,ms sql和mysql都没有自带计…

【SQL数据库基础05-2】常见约束与标识列

文章目录 常见约束01 基本概念1.1 含义&#xff1a;1.2 分类&#xff1a;六大约束1.3 添加约束的时机&#xff1a;1.4 约束的添加分类&#xff1a;1.5 主键和唯一的大对比&#xff1a;1.6 外键&#xff1a; 02 具体讲解2.1 创建表时添加约束1.添加列级约束2.添加表级约束 2.2 修…