PE 文件格式 详解 二

内容引用自:看雪《逆向工程原理》,http://www.blogfshare.com/pe-header-one.html 。如有错误,欢迎留言。

1、 区块表(节表)

  区块表紧跟在PE头后面,所有区块的属性都被定义在区块表中。区块表中的数据仅仅是因为属性相同被放到一起,对程序的各种方法、数据的追溯还是要用到DataDirectory。

  区块表是由一组IMAGE_SETION_HEADER结构组成,每个结构描述一个区块,各结构的排列顺序与其所描述的区块在文件中的排列顺序是一致的。

  区块表最后以一个空的IMAGE_SETION_HEADER结构作为结尾。IMAGE_SETION_HEADER (长度为28h)定义如下:

  #define IMAGE_SIZEOF_SHORT_NAME  8

  typedef strutct _IMAGE_SETION_HEADER {

    BYTE  Name[IMAGE_SIZEOF_SHORT_NAME];      //注意   此处是 8 个字节

    union {

      DWORD PhysicalAddress;

      DWORD VirtualSize;      // 区块的大小

    }

    DWORD VirtualAddress;         // 节区的 RVA 地址
    DWORD SizeOfRawData;            // 在文件中对齐后的尺寸
    DWORD PointerToRawData;        // 在文件中的偏移量
    DWORD PointerToRelocations;     // 在OBJ文件中使用,重定位的偏移,无用
    DWORD PointerToLinenumbers;   // 行号表的偏移(供调试使用地),无用
    WORD NumberOfRelocations;      // 在OBJ文件中使用,重定位项数目,无用
    WORD NumberOfLinenumbers;    // 行号表中行号的数目,无用
    DWORD Characteristics;       // 节属性如可读,可写,可执行等  

  } IMAGE_SETION_HEADER

  需要注意的点:

  Name:区块名   实际上没有任何意义,只要不重复可以任意命名,设置为特定的名字仅仅是正规编程方便查看。

  VirtualSize:对应区块的实际大小,未进行对齐处理前的大小

  VirtualAddress:对应区块装入内存中的RVA地址

  SizeOfRawData:对应区块在磁盘中的大小,在可执行文件中,该值是已经被FileAligment处理过的长度。

  PointerToRawData:对应区块在磁盘中的偏移,从文件头开始算起

  Characteristics:按位指出对应区块的属性 (bit OR),常见值如下:

  

  此处涉及到RVA to RAW,即 相对虚拟地址 到 文件物理偏移地址的转换。比如在DataDirectory中存放的为RVA地址,就需要转换为物理偏移。

  其转换方法为:RVA  - VisualAddress + PointerToRawData

2、 导入表

  导入表是要提供程序执行时需要调用的导入函数的所属DLL、函数名、内存地址等。该表在区块中,由DataDirectory第二个数组项指向。

  导入表是由一组IMAGE_IMPORT_DESCRIPTOR结构组成,结构的数量取决于程序要使用的DLL文件的数量,每一个结构对应一个DLL文件,以一个内容全为 0 的IMAGE_IMPORT_DESCRIPTOR作为结束。

  IMAGE_IMPORT_DESCRIPTOR定义:

  typedef  struct _IMAGE_IMPORT_DESCRIPTOR {

    union {

      DWORD  Characteristics;

      DWORD  OriginalFirstThunk;    #一般定义该值,指向 INT (Import Name Table)  RVA

    };

    DWORD  TimeDateStamp;

    DWORD  ForwarderChain;

    DWORD  Name;            #指向 DLL 名称 的地址   RVA

    DWORD  FirstThunk;          #指向 IAT (Import Address Table)    RVA

  } IMAGE_IMPORT_DESCRIPTOR;

  需要注意的点:

  Name :  不会直接给出DLL的名字   此处是一个RVA 地址。   该地址指向了 DLL 名称。

  OriginalFirstThunk 和 FirstThunk : 有些是相同的  有些是不同的。  虽然一个指向 INT  一个指向 IAT ,但实际这两个表均是由一系列 IMAGE_THUNK_DATA结构组成的数组。数组最后以一个全为0 的结构作为结束。

  IMAGE_THUNK_DATA 定义如下:

  typedef  _IMAGE_THUNK_DATA {

    union {

      DWORD  ForwarderString;      #RVA  指向forwarder string

      DWORD  Function;        #被导入函数的入口地址

      DWORD  Ordinal;          #该函数的序数

      DWORD  AddressOfData;      #指向 IMAGE_IMPORT_BY_NAME 结构体

    };

  } IMAGE_THUNK_DATA32

  对于可执行文件,IMAGE_THUNK_DATA 中存储的要么是 Ordinal(最高位为1,其余31位为序号)  要么是AddressOfData。在DLL中对每个函数都进行了编号,访问函数即可以通过名称访问,也可以通过编号访问(还不懂怎么根据Ordinal找到函数~~,求大神指导)。

  当IMAGE_THUNK_DATA存放的为 AddressOfData 时,该地址指向一个 IMAGE_IMPORT_BY_NAME 结构体

  IMAGE_IMPORT_BY_NAME 定义如下:

  typedef struct _IMAGE_IMPORT_BY_NAME {

    WORD  Hint;        #Ordinal    函数的序号

    BYTE  Name[1];        #此处为函数名字,实际为变长数组,以00结尾,即字符串结束符

  } IMAGE_IMPORT_BY_NAME

  常见寻找导入函数的方法:

  根据 DataDirectory 中RVA 找到 导入表的文件偏移地址, 根据 OriginalFirstThunk 找到 INT (Import Name Table), 根据 AddressOfData 找到 IMAGE_IMPORT_BY_NAME 即可找到函数名。

时间: 2024-10-09 12:14:13

PE 文件格式 详解 二的相关文章

PE文件格式详解(四)

PE文件格式详解(四) 0x00 前言 上一篇介绍了区块表的信息,以及如何在hexwrokshop找到区块表.接下来,我们继续深入了解区块,并且学会文件偏移和虚拟地址转换的知识. 0x01 区块对齐值 首先我们要知道啥事区块对齐?为啥要区块对齐?这个问题其实困扰了我很久,只能怪我操作系统没学好...我现在的理解是由于内存和磁盘存在分页的问题所以使得不同区块一般要放到不同的分页中,当然也可以多个区块合并以节省空间,但是对于不能合并的区块如代码和数据块就不得不放在不同分页上了.学过操作系统的都知道不

PE文件格式详解(上)

作者:MSDN 译者:李马 摘要 Windows NT 3.1引入了一种名为PE文件格式的新可执行文件格式.PE文件格式的规范包含在了MSDN的CD中(Specs and Strategy, Specifications, Windows NT File Format Specifications),但是它非常之晦涩.  然而这一的文档并未提供足够的信息,所以开发者们无法很好地弄懂PE格式.本文旨在解决这一问题,它会对整个的PE文件格式作一个十分彻底的解释,另外,本文中还带有对所有必需结构的描述

PE文件格式详解(下)

作者:MSDN译者:李马 预定义段 一个Windows NT的应用程序典型地拥有9个预定义段,它们是.text..bss..rdata..data..rsrc..edata..idata..pdata和.debug.一些应用程序不需要所有的这些段,同样还有一些应用程序为了自己特殊的需要而定义了更多的段.这种做法与MS-DOS和Windows 3.1中的代码段和数据段相似.事实上,应用程序定义一个独特的段的方法是使用标准编译器来指示对代码段和数据段的命名,或者使用名称段编译器选项-NT——就和Wi

PE文件格式详解(六)

0x00 前言 前面两篇讲到了输出表的内容以及涉及如何在hexWorkShop中找到输出表及输入DLL,感觉有几个地方还是没有理解好,比如由数据目录表DataDirectory[16]找到输出表表后以为找到输入DLL就完了,其实这一流程的最终功能是通过输入DLL找到输入DLL调用的函数,这一步骤是通过输出表结构中的OriginalFristThunk或者OriginalFristThunk所指向的INT或者IAT结构来找到的.这里要说明的是,虽然一般情况通过OriginalFristThunk也

PE文件结构详解(二)可执行文件头

在PE文件结构详解(一)基本概念里,解释了一些PE文件的一些基本概念,从这篇开始,将详细讲解PE文件中的重要结构. 了解一个文件的格式,最应该首先了解的就是这个文件的文件头的含义,因为几乎所有的文件格式,重要的信息都包含在头部,顺着头部的信息,可以引导系统解析整个文件.所以,我们先来认识一下PE文件的头部格式.还记得上篇里的那个图吗? DOS头和NT头就是PE文件中两个重要的文件头. 一.DOS头 DOS头的作用是兼容MS-DOS 操作系统中的可执行文件,对于32位PE文件来说,DOS所起的作用

LinuxELF文件格式详解--Linux进程的管理与调度(十二)

日期 内核版本 架构 作者 GitHub CSDN 2016-06-04 Linux-4.5 X86 & arm gatieme LinuxDeviceDrivers Linux进程管理与调度-之-进程的描述 对象文件格式 对象文件 首先,你需要知道的是所谓对象文件(Object files)有三个种类: 可重定位的对象文件(Relocatable file) 可执行的对象文件(Executable file) 可被共享的对象文件(Shared object file) 可重定位的对象文件(Re

Carbondata源码系列(二)文件格式详解

在上一章当中,写了文件的生成过程.这一章主要讲解文件格式(V3版本)的具体细节. 1.字典文件格式详解 字典文件的作用是在存储的时候将字符串等类型转换为int类型,好处主要有两点: 1.减少存储占用空间 2.用在需要group by的字段上比较合适,可以减少计算时的shuffle的数据量. 每一个字典列都有对应的三种文件.dict, .sortindex, .dictmeta文件,输出格式都是thrift格式 1.1 .dict文件 字典的值每满1000就作为一个chunk输出一次,具体的类是C

PE文件结构详解(四)PE导入表

PE文件结构详解(二)可执行文件头的最后展示了一个数组,PE文件结构详解(三)PE导出表中解释了其中第一项的格式,本篇文章来揭示这个数组中的第二项:IMAGE_DIRECTORY_ENTRY_IMPORT,即导入表. 也许大家注意到过,在IMAGE_DATA_DIRECTORY中,有几项的名字都和导入表有关系,其中包括:IMAGE_DIRECTORY_ENTRY_IMPORT,IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT,IMAGE_DIRECTORY_ENTRY_IAT

PE文件结构详解(三)PE导出表

上篇文章 PE文件结构详解(二)可执行文件头 的结尾出现了一个大数组,这个数组中的每一项都是一个特定的结构,通过函数获取数组中的项可以用RtlImageDirectoryEntryToData函数,DataDirectory中的每一项都可以用这个函数获取,函数原型如下: PVOID NTAPI RtlImageDirectoryEntryToData(PVOID Base, BOOLEAN MappedAsImage, USHORT Directory, PULONG Size); Base:模