第36章 64位计算
本文最后更新于:2022年5月27日 下午
第36章64位计算
不知不觉间,64位0S得到快速普及,本章讲解代码逆向分析工程师必须学习的64位计算(64bit Computing )相关知识。
36.1 64位计算环境
80386是Intel于1985年推出的CPU芯片,它是一种32位微处理器。当时由于其价格高昂、支持的OS少,几乎没有得到普及。随着1995年微软发布32位OS Winows 95,计算机正式进人32位计算时代。Windows 95向下兼容支持16位程序,已有的DOS应用程序大部分也能够稳定运行。经过几年16位/32位混用的过渡期,OS进入Windows 2000/XP时代,32位应用程序开始成为主流,并延续至今。此过程中,CPU、OS制造厂商深刻认识到32位PC的局限(主物理内存最大为4GB ),纷纷开始开发64位版本,这就是64位CPU与64位OS共同构成的64位计算环境。
36.1.1 64位 CPU
在32位CPU时代,Intel主导着技术主流(x86 ),AMD生产x86兼容芯片,形成追击之势。但 64位CPU中出现了比较有意思的事情。Intel最初发布的64位CPU IA-64(产品名:Itanium )是一款64位的功能强大的芯片。有意思的是,全新IA-64采用了与原x86系列(IA-32 ) CPU完全不同的芯片。就像IBM的PowerPC系列一样,搭载的寄存器以及使用的指令都是完全不同的,无法与现有的IA-32直接兼容(使用模拟器可以实现间接兼容,但速度慢)。
其实,IA-64是Intel与HP合作的产物,设计的初衷可能是为了大幅提高计算机性能,霸占整个PC与服务器市场,从而抛弃了向下兼容的特性。但是想要市场(特别是PC市场)放弃向下兼容可不容易。此后AMD发布了AMD64,它是一款兼容IA-32的64位芯片。支持向下兼容的AMD64在PC市场上大受欢迎。为了应对这种情况,Intel从AMD购买使用许可,发布了与AMD64兼容的EM64T,后来改名为Intel64。最近Intel推岀的Core2 Duo、i7/i5/i3等CPU就是Intel64系列的。通常说的x64是AMD64与Intel64的合称,指的是与现有x86(IA-32 )兼容的64位CPU,主要用于普通PC和服务器。而IA-64是与x64具有完全不同形态的CPU,主要用在大型服务器与超级计算机中。
术语一览
讲解64位CPU时会遇到相当多的术语,这可能会给各位造成困惑。现将常用术语整理如下。
术语 | 说明 |
---|---|
AMD64 | AMD研制的64位CPU(直接向下兼容x86) |
EM64T | Intel研制的兼容AMD64的CPU |
Intel64 | EM64T的新名称 |
IA-64 | Intel与HP合作研发的64位CPU(可通过模拟器间接兼容x86) |
x86 | Intel的IA-32、IA-16、IA-8系列的CPU |
x64 | AMD64 & Intel64 |
36.1.2 64位OS
PC中使用的Windows 64位操作系统有Windows XP/Vista/7的64位版本。微软认为能否向下兼容32位是决定64位OS成败的关键,支持32位也被看作是64位OS的核心功能。为此,微软提供了名为WOW64的机制,现有的32位应用程序能够在这种机制下正常运行,使现有32位源码可以很容易地移植到64位系统。
LLP64数据模型
64位Windows中使用LLP64数据模型实现向下兼容,它将现有32位Windows数据模型(ILP32 )
中的指针大小更改为64位。所以将现有的32位源代码移植到64位系统时,只要在指针类型变换上
下工夫就行了
数据类型 | short | int | long | longlong | 指针 | OS |
---|---|---|---|---|---|---|
ILP32 | 16 | 32 | 32 | 64 | 32 | MS Windows 32位 |
LLP64 | 16 | 32 | 32 | 64 | 64 | MS Windows 64位 |
LP64 | 16 | 32 | 64 | 64 | 64 | UNIX 64位 |
还有一点需要注意的是,HANDLE类型大小在64位Windows中已经变为64位。
另外,64位UNIX系列使用LP64数据模型,它与LLP64的不同在于长整型类型的大小为64位。
ILP32: Integer、Long、Pointer-32位。
LLP64: LongLong、Pointer-64位。
LP64: Long、Pointer-64位
36.1.3 Win32 API
创建64位应用程序时,现有的Win32 API几乎可以照搬使用,而非另外提供一套Win64 API。开发人员不用再熟悉新增的API,没有这个负担也是非常吸引人的地方。通过诸如此类的各种考虑,轻松实现将现有32位源代码移植到64位系统。
微软为了向下兼容并未另外制作Win64,以后安装64位系统时也会一同提供Win64。
36.1.4 WOW64
现在正处于32位到64位的过渡期,在64位OS中正常运行现有的32位应用程序是重中之重。就像先前的Windows 95能够同时支持32位Windows应用程序与16位的DOS程序运行一样。WOW64(Windows On Windows 64 )是一种在64位OS中支持运行现有32位应用程序的机制。
64位Windows中,32位应用程序与64位应用程序都可以正常运行。64位应用程序会加载
kernel32.dll(64位)与ntdll.dll(64位)。而32位应用程序则会加载kernel32.dll(32位)与ntdll.dll(32位),WOW64会在中间将ntdll.dll(32位)的请求(API调用)重定向到ntdll.dll(64位)。
也就是说,64位Windows提供了32位Windows的系统环境,用来运行32位应用程序。并在中途借助WOW64将其变换为64位环境,如图36-1所示。
WOW64仅运行在用户模式下,运行在内核模式中的驱动程序(Driver)文件必须 编译成64位。内核模式中发生内存引用错误时,就会引发BSOD(Blue Screen Of Death,蓝屏死机)问题,所以为了保证系统稳定性,WOW64被限制在用户模式下运行。
文件夹结构
64位Windows的文件夹结构中,开发人员与逆向分析人员都需要明确知道一点,那就是System32文件夹。系统文件夹在64位环境中的名称也为System32,并且为了向下兼容32位,单独 提供了SysWOW64文件夹,如图36-2所示。
System32文件夹中存放着64位的系统文件,而SysWOW64文件夹中则存放着32位的系统文件。向用户提供的重要的系统文件被分别编译成64位与32位(参考图39-3、图39-4 )。
有意思的是,64位应用程序中使用GetSystemDirectory() AW查找系统文件夹,正常返回System32文件夹。32位应用程序中调用GetSystemDirectory()返回的文件夹名称也为System32,但文件夹的实际内容与SysWOW64文件夹是一样的。这是WOW64在中间截获了API调用并进行操作后返回的结果,这使32位应用程序可以正常运行。
像 System32/SysWOW64—样,Program Files 与 Program Files(x86)文件夹并不是直接重定向的对象。32位应用程序中使用SHGetSpecialFolderPath() API获取Program Files文件夹路径时,WOW64会在中间对其截获,并返回Program Files(x86)路径。32位应用程序中,SysWOW64文件夹名称看似被修改成System32,但是Program Files(x86)文件夹会原样显示。
注册表
64位Windows中的注册表分为32位注册表项与64位注册表项,如图36-5所示。
32位进程请求访问HKLM\SOFTWARE下的键时,WOW64会将其重定向到32位的HKLM\SOFTWARE\Wow6432Node下的键。有关注册表重定向的更多内容请参考下面MSDN链接。与文件系统重定向相比,注册表通常显得更加复杂。需要做精确开发与逆向分析的人员,请务必认真阅读下面链接中的内容。
http://msdn.microsoft.com/en-us/library/aa384232(v=VS.85).aspx
与文件系统不同,注册表无法完全分离为32位与64位两部分,经常出现32/64位共用的情形。有时候向32位部分写入的值会自动写入64位部分。所以对运行在WOW64环境中的程序进行逆向分析时,必须准确知道访问的究竟是注册表的哪一部分(32位还是64位)。
36.1.5 练习:WOW64Test
下面准备了一个简单的示例,用来测试WOW64。WOW64Test_x86.exe被编译为32位文件, 在WOW64模式下运行。而WOW64Test_x64.exe被编译为64位文件,运行在64位Native模式下。两个文件的源文件(WOW64Test.cpp )都是一样的0
要正常运行/调试WOW64Test_x64.exe文件,需要Windows XP/Vista/7 64位系统环境支持。
图36-6是分别运行它们得到的结果
运行示例程序可以获取以下4种信息:
“system32” path
File size of “kernel32.dll”
“Program Files” path
Create Registry Key: ”HKLM\SOFTWARE\ReverseCore“
从运行结果画面可以看到,64位WOW64Test_x64.exe从准确位置(与源代码中的内容一样)获取值并生成了注册表键。但是以WOW64模式运行的32位WOW64Test_x86.exe行为略有不同。它虽然把System32文件夹目录识别为“C:\Windows\system32”,但其内容却指向SysWOW64文件夹(从kernel32.dll的文件尺寸即可得知)。还有Program Files目录被返回为“Program Files(x86)”。
创建注册表项时,实际创建的不是HKLM\SOFTWARE\ReverseCore,而是HKLM\SOFTWARE
Wow6432Node\ReverseCore。以WOW64模式运行的32位应用程序会像这样对文件(文件夹)与
注册表进行重定向,请各位一定要注意这点。
在64位Windows环境中逐一运行示例文件,然后利用文件浏览器与注册表编辑器
查看运行结果。
36.2 编译64位文件
本节将向各位介绍编译64位PE文件(PE+或PE32+)的方法。32位与64位Windows OS中都可 以分别交叉编译(Cross Compile ) 32位/64位PE文件。最简单的方法是安装Visual Studio 2012。
Visual Studio 2012 是默认提供64位编译环境的。
36.2.1设置 Visual Studio 2012 环境
- 选择“Build” – “Configuration Manager”菜单,打开配置管理器。点击新建解决方案平台。
2.
选择“x64”平台,点击确定按钮。
3.
这时候配置管理器中的平台已经改成刚才选择的x64了,这时候编译出来的就是64位程序了。可以在工具栏的平台下拉框中快速切换目标平台。