1.1 微软Windows可移植可执行文件格式

要进行恶意软件静态分析,你需要了解Windows PE文件格式,该格式描述了如.exe、.dll和.sys等当今Windows程序文件的结构,并定义了它们存储数据的方式。PE文件包含x86指令、图像和文本等数据,以及程序运行所需的元数据。

PE格式最初的设计是用来进行下面的操作。

(1)告诉Windows如何将程序加载到内存中

PE格式描述了文件的哪些块应该加载到内存中,以及在哪里加载。它还告诉你,Windows应该在程序代码里的哪个位置开始执行程序,以及哪些动态链接代码库应该加载到内存中。

(2)为运行程序提供在执行过程中可能使用的媒体(或资源)

这些资源可以包括字符串,如GUI对话框或控制台输出的字符串,以及图像或视频。

(3)提供安全数据,例如数字代码签名

Windows使用这些安全数据来确保代码出自受信任的来源。

PE格式通过利用图1-1中所示的一系列结构来完成以上工作。

图1-1 PE文件格式

如图1-1所示,PE文件格式包括一系列头(header),用来告诉操作系统如何将程序加载到内存中。它还包括一系列节(section)用来包含实际的程序数据。Windows将这些节加载到内存中,使其在内存中的偏移量与它们在磁盘上的显示位置相对应。让我们从PE头开始,来更详细地探讨这个文件结构。我们将略过对DOS头的讨论,这是20世纪80年代微软DOS操作系统的遗留产物,仅仅出于兼容性原因而存在。

1.1.1 PE头

如图1-1底部所示,在DOS头❶的上面是PE头❷,它定义了程序的一般属性,如二进制代码、图像、压缩数据和其他程序属性。它还告诉我们程序是否是针对32位或64位系统而设计的。PE头为恶意软件分析师提供了基本但有用的情景信息。例如,头里包括了时间戳字段,这个字段可以给出恶意软件作者编译文件的时间。通常恶意软件作者会使用伪造的值替换这个字段,但是有时恶意软件作者会忘记替换,就会发生这种情况。

1.1.2 可选头

可选头❸实际上在今天的PE可执行程序中无处不在,恰恰与其名称的含义相反。它定义了PE文件中程序入口点的位置,该位置指的是程序加载后运行的第一个指令。它还定义了Windows在加载PE文件、Windows子系统、目标程序(例如Windows GUI或Windows命令行)时加载到内存中的数据大小,以及有关该程序其他的高级详细信息。由于程序的入口点告诉了逆向工程师该从哪里开始进行逆向工程,这个头信息对逆向工程师来说是非常宝贵的。

1.1.3 节头

节(section)头❹描述了PE文件中包含的数据节。PE文件中的一个节是一块数据,它们在操作系统加载程序时将被映射到内存中,或者包含有关如何将程序加载到内存中的指令。换句话说,一个节是磁盘上的字节序列,它要么成为内存中一串连续字节的字符串,要么告知操作系统关于加载过程的某些方面。

节头还告诉Windows应该授予节哪些权限,比如程序在执行时,是否应该可读、可写或可执行。例如,包含x86代码的.text节通常被标记为可读和可执行的,但是不可写的,以防止程序代码在执行过程中意外修改自身。

图1-1描述了许多节,如.text和.rsrc。执行PE文件时,它们会被映射到内存中。其他如.reloc节的特殊节不会被映射到内存中,我们也将讨论这些节。下面我们来浏览图1-1中显示的节。

1. .text节

每个PE程序在其节头中包含了至少一个标记为可执行的x86代码节;这些节几乎总是命名为.text ❺。在执行第2章中的程序反汇编和逆向工程时,我们将反汇编.text节中的数据。

2. .idata节

.idata节❻,也被称为导入节,包含导入地址表(IAT),它列出了动态链接库和它们的函数。IAT是最重要的PE结构之一,在对PE二进制文件进行最初的分析时需要查看它,因为它指出了程序所调用的库,然而这些调用反过来又可能会泄露恶意软件的高级功能。

3.数据节

在PE文件结构中的数据节可以包括.rsrc、.data和.rdata等节,它们存储程序使用的鼠标光标图像、按钮图标、音频和其他媒体等。例如,图1-1中的.rsrc节❼包含了程序用于将文本呈现为字符串的可打印字符串。

.rsrc(资源)节中的信息对恶意软件分析师是非常重要的,因为通过检查PE文件中的可打印字符串、图形图像和其他资产,他们可以获得关于文件功能的重要线索。在1.3节中,你将了解如何使用icoutils工具包(包括icotool和wrestool)从恶意软件二进制文件的资源节中提取图形图像。然后,在1.4节中,你将学习如何从恶意软件资源节中提取可打印的字符串。

4. .reloc节

PE二进制文件的代码并非是与位置独立的,这意味着如果将它从预期的内存位置移动到新的内存位置,它将无法正确执行。.reloc节❽在不破坏代码的情况下通过允许移动代码来解决这个问题。如果一个PE文件的代码已被移动,它就告诉Windows操作系统将该文件的代码中进行内存地址转换,这样代码仍可以正确运行。这些转换通常涉及在内存地址中添加或减去偏移量。

虽然在你的恶意软件分析中,PE文件的.reloc节可能包含你想要使用的信息,但是我们在这本书中不会进一步讨论它,因为我们的重点是将机器学习和数据分析应用于恶意软件,而不是那种涉及重新定位的核心逆向工程。