二进制文件基础

堆栈大致了解之后,了解一下windows下的二进制文件。

PE文件格式

源代码被编译和链接之后形成了可执行文件。可执行文件之所以被操作系统加载运行,主要是因为他们有一个统一的格式规范。

PE(Portable Executable)是Win32下的可执行文件遵守的数据格式( 补充:Linux下的可执行文件一般是Elf的文件。)。常见的可执行文件(.exe .dll)都是典型的PE文件。

一个可执行文件不光光包含二进制文件的机器代码。还有字符串,菜单,图标,字体等一系列信息,PE文件格式规定了所有的这些信息在可执行文件中如何有规律的进行。所以说,要将一个可执行文件装入内存是一个非常难的事情。

PE文件格式把可执行文件分成若干个数据节,不同的资源呗存放在不同的节中,一个典型的PE文件包含的节如下:

  1. .text: 由编译器生成,存放二进制的机器代码,也是我们反汇编和调试的对象。
  2. .data: 初始化的数据块,如宏定义、全局变量、静态变量等。
  3. .idata:可执行文件链接的其他动态库中的有关外来函数以及信息。
  4. .rsrc: 存放程序图标资源等。

如上图所示,那四类是比较常见的节,除此之外还可能出现的有“.reloc”,“.edata”,“.tls”,“.rdata”等。

加壳概念

加壳其实应该叫做可执行程序资源压缩,是保护文件不被随意修改的一种技术。但并不是表示被加壳的程序就不能进行运行,只是无法查询和修改源代码而已,只有脱完壳之后才可以查看源代码。

加壳其实就是利用特殊的算法对程序的代码和资源进行压缩,就好像我们用WINZIP对重要文件进行加密压缩一样,他只是在程序内部进行这样的操作而已。打一个比方,如果说程序是外套,源代码等资源是人的身体的话,那壳就是位于两者之间的一件衬衫。

现在也有许多的加壳工具,这些工具在文件头中会加入一段指令,告诉CPU如何才能解压自己,只是现在CPU处理速度都是秒秒钟的那种,所以加壳与不加壳的程序运行根本看不出什么不一样,除非你想了解源代码,你就会发现你被壳拒之门外。

加壳工具分为两种:

  1. 压缩壳:其特点主要是减小软件体积大小,加密保护并不是重点。
  2. 加密壳:其种类比较多,不同的壳侧重重点不同,一些壳单纯保护程序,另一些壳也提供注册、使用限制等功能。现如今需要付款使用的软件其实就是加了壳。

虚拟内存

Windows的内存可以被分为两个层面:物理内存和虚拟内存。其中,物理内存非常复杂,需要进入Windows内核才可以看到。通常,在用户模式下,用调试器看到的都是虚拟内存。

用户启用程序使用的地址称之为虚拟地址和逻辑地址,其对应的存储空间称为虚拟内存和或逻辑地址空间。而计算机物理内存的访问地址则称为实地址和物理地址,其对应的存储空间称为物理存储空间或主存空间。程序进行虚拟地址到实地地址转换的过程叫做程序的再定位。

注:这里所说的内存是指Windows用户态内存映射机制下的虚拟内存,操作系统原理也有“虚拟内存”的概念存在,那是在实际物理内存不够时,有时候系统会把“部分硬盘空间”当作内存使用从而使得程序得到装载运行的现象,二者不能混淆。

PE文件与虚拟内存的映射

在调试漏洞时候通常要进行两部操作:

  1. 静态反汇编查看PE文件中某条指令的位置是相对于磁盘文件而言的,也就是需要知道文件偏移。
  2. 还需要知道这条指令在内存中的位置,也就是虚拟内存地址。

    为此,我们需要弄清楚PE文件地址和虚拟内存地址之间的关系,首先了解几个重要的概念。

  • (1) 文件偏移地址(File Offset)
    数据在PE文件中的地址叫文件偏移地址,这是文件在磁盘上存放时相对于文件开头的偏移。
  • (2) 装载地址(Image Base)
    PE装入内存时的基地址。默认情况下,EXE文件在内存中的基地址是0x00400000,DLL文件是0x10000000。这些位置可以通过修改编译选项进行更改。
  • (3) 虚拟内存地址(Virtual Address)
    PE文件中的指令被装入内存后的地址。
  • (4) 相对虚拟地址(Relative Virtual Address RVA)
    相对虚拟地址是内存地址相对于映射基址的偏移量。
    虚拟内存地址、映射基址和相对虚拟内存地址三者之间有如下关系:
    VA = Image Base + RVA

    在默认情况下,一般PE文件的0字节将映射到虚拟内存的0x00400000位置,这个地址就是所谓的装载基地址(Image Base)。如下图所示,

    文件偏移是相对于文件开始处0字节的偏移,RVA则是相对于装载基地址0x00400000处的偏移。由于操作系统在进行装载时基本保持PE排列结果,所以文件偏移地址和RVA很大可能一致。

    (如果有细微的差异的话,那就是由于文件数据的存放单位与内存数据存放单位不同造成的。)

  • PE文件数据是按照磁盘数据标准存放,以0x200字节为基本单位进行组织,不足则以0x00填充,超过则分配下一个0X200继续使用

  • 代码装入内存是按照内存数据存放,以0x1000字节为基本单位进行组织,不足全部补全,超过则分配下一个0x1000继续使用。

工具

Lord PE是一个查看PE文件并对之进行分析、修改的脱壳辅助软件。
如图就是这个工具的标准界面:

点击PE编辑器,随意加载如一个程序便可以查看相对信息:

点击区段进行节信息的查询:VOffset就是相对虚拟地址(RVA),ROffset是文件偏移地址。

在系统进程中,代码(.text节)将被加载到0x400000+0x11000=0x411000的虚拟地址中(装载基地址地址+RVA)。而在文件中,可以用二进制文件打开,看到对应的代码在0x10400位置。

通过这个工具可以很清楚了解我们所需要的信息(RVA,VA,文件偏移,装载基地址),对于漏洞的分析是一个很好的辅助。

Contents
  1. 1. PE文件格式
  2. 2. 加壳概念
  3. 3. 虚拟内存
  4. 4. PE文件与虚拟内存的映射
  5. 5. 工具
|