PE文件

逆向与反汇编工具

1 分类工具

绝不要根据文件的扩展名来确定文件的类型。

1.1 file

file 命令是一个标准的实用工具,大多数*NIX 风格的操作系统和 Windows 下的 Cygwin①或MinGw②工具都带有这个实用工具。file 试图通过检查文件中的某些特定字段来确认文件的类型。

file 能够识别常见的字符串,如#!/bin/sh( shell 脚本文件)或( HTML 文档)。但是,识别那些包含非 ASCII 内容的文件要困难得多,在这种情况下, file 会设法判断该文件的结构是否符合某种已知的文件格式。多数情况下,它会搜索某些文件类型所特有的标签值(通常称为幻数③)。下面的十六进制表列出了几个用于判断常见文件类型的幻数。

幻数是一些文件格式规范所要求的特殊标签值,它表示文件符合这种规范。

image-20220927112954200

1.2 PE Tools

PE Tools①是一组用于分析 Windows 系统中正在运行的进程和可执行文件的工具。

1.3 PEiD

PEiD①是另一款 Windows 工具,它主要用于识别构建某一特定 Windows PE 二进制文件所使用的编译器,并确定任何用于模糊 Windows PE 二进制文件的工具。

PEiD 的许多其他功能与 PE Tools 的功能相同,包括显示PE文件头信息摘要、收集有关正在运行的进程的信息、执行基本的反汇编等。

2 摘要工具

目标是对二进制程序文件进行逆向工程,因此,在对文件进行初步分类后,需要用更高级的工具来提取详尽的信息。

2.1 nm

将源文件编译成目标文件时,编译器必须嵌入一些全局(外部)符号的位置信息,以便链接器在组合目标文件以创建可执行文件时,能够解析对这些符号的引用。除非被告知要去除最终的可执行文件中的符号,否则,链接器通常会将目标文件中的符号带入最终的可执行文件中。根据nm手册的描述,这一实用工具的作用是“列举目标文件中的符号”。

使用 nm 检查中间目标文件(扩展名为.o 的文件,而非可执行文件)时,默认输出结果是在这个文件中声明的任何函数和全局变量的名称。

image-20220927114212093

U,未定义符号,通常为外部符号引用。
T,在文本部分定义的符号,通常为函数名称。
t,在文本部分定义的局部符号。在 C 程序中,这个符号通常等同于一个静态函数。
D,已初始化的数据值。
C,未初始化的数据值。

2.2 ldd

ldd( list dynamic dependencies)是一个简单的实用工具,可用来列举任何可执行文件所需的动态库。

创建可执行文件时,必须解析该文件引用的任何库函数的地址。链接器通过两种方法解析对库函数的调用: 静态链接( static linking)和动态链接( dynamic linking)。链接器的命令行参数决定具体使用哪一种方法。一个可执行文件可能为静态链接、动态链接,或二者兼而有之。

静态链接的优点包括:函数调用更快一些;发布二进制文件更加容易,因为这时不需要对用户系统中库函数的可用性做出任何假设。其缺点包括:生成的可执行文件更大;如果库组件发生改变,对程序进行升级会更加困难,因为一旦库发生变化,程序就必须重新链接。

动态链接与静态链接不同。使用动态链接时,链接器不需要复制它需要的任何库。相反,链接器只需将对所需库(通常为.so 或.dll 文件)的引用插入到最终的可执行文件中。因此,这时生成的可执行文件也更小一些。而且,使用动态链接时升级库代码也变得简单多了,因为只需要维护一个库(被许多二进制文件引用),如果需要升级库代码,用新版本的库替换过时的库,就可以立即更新每一个引用该库的二进制文件。

使用动态链接的一个缺点在于,它需要更加复杂的加载过程。因为这时必须定位所有所需的库,并将其加载到内存中,而不是加载一个包含全部库代码的静态链接文件。动态链接的另一个缺点是,供应商不仅需要发布他们自己的可执行文件,而且必须发布该文件所需的所有库文件。

2.3 objdump

objdump 是 GNU binutils①工具套件的一部分,用户可以在 Linux、 FreeBSD 和 Windows(通过 Cygwin)系统中找到这个工具。 objdump 依靠二进制文件描述符库 libbfd(二进制工具的一个组件)来访问目标文件,因此,它能够解析 libbfd 支持的文件格式( ELF、 PE 等)。

另外,一个名为 readelf 的实用工具也可用于解析 ELF 文件。 readelf 的大多数功能与 objdump 相同,它们之间的主要区别在于 readelf 并不依赖 libbfd。

与专用的 ldd 不同, objdump 的功能非常多样。显示与目标文件有关的信息是 objdump 的功能。这是一个相当宽泛的目标, objdump 为此提供了大量命令行选项(超过 30 个),以提取目标文件中的各种信息。 objdump 可用于显示以下与目标文件有关的信息(以及其他更多信息)。

  •  节头部,程序文件每节的摘要信息。
  •  专用头部,程序内存分布信息,还有运行时加载器所需的其他信息,包括由 ldd 等工具生成的库列表。
  •  调试信息,提取出程序文件中的任何调试信息。
  •  符号信息,以类似 nm 的方式转储符号表信息。
  •  反汇编代码清单, objdump 对文件中标记为代码的部分执行线性扫描反汇编。

反汇编 x86代码时, objdump 可以生成 AT&T 或 Intel 语法,并可以将反汇编代码保存在文本文件中。这样的文本文件叫做反汇编死代码清单( dead listing),尽管这些文件可用于实施逆向工程,但它们很难有效导航,也无法以一致且无错的方式被修改。

2.4 otool

otool 可用于解析与 OS X Mach-O 二进制文件有关的信息,因此,可简单将其描述为 OS X系统下的类似于 objdump 的实用工具。otool 可用于显示与文件的头部和符号表有关的信息,并对文件的代码部分进行反汇编。

2.5 dumpbin

dumpbin 是微软 Visual Studio 工具套件中的一个命令行实用工具。与 otool 和 objdump 一样,dumpbin 可以显示大量与 Windows PE 文件有关的信息。

dumpbin 的其他选项可从 PE 二进制文件的各个部分提取信息,包括符号、导入的函数名、导出的函数名和反汇编代码。

2.6 c++filt

3 深度检测工具

3.1 strings

strings 实用工具专门用于提取文件中的字符串内容,通常,使用该工具不会受到文件格式的限制。

image-20220927115140247
  •  需要牢记的是,使用 strings 处理可执行文件时,默认情况下, strings 仅仅扫描文件中可加载的、经初始化的部分。使用命令行参数–a 可强制 strings 扫描整个文件。
  •  strings 不会指出字符串在文件中的位置。使用命令行参数–t 可令 strings 显示所发现的每一个字符串的文件偏移量信息。
  •  许多文件使用了其他字符集。使用命令行参数–e 可使 strings 搜索更广泛的字符,如 16位 Unicode 字符。