• PE文件格式详解(二)


    0x00 前言

       上一篇讲到了PE文件头的中IMAGE_FILE_HEADER结构的第二个结构,今天从IMAGE_FILE_HEADER中第三个结构sizeOfOptionalHeader讲起。这个字段的结构名也叫做IMAGE_OPTIONAL_HEDAER讲起。

    0x01  IMAGE_OPTIONAL_HEADER概述

      其实这个结构是IMAGE_FILE_HEADER结构的补充。这两个结构合起来才能对整个PE文件头进行描述。这个结构异常复杂,但真正我们用得到的其实不多,下面来看看它的各个字段情况,如下图(左边的16位字符表示相对于文件头的偏移量):

    ypedef struct _IMAGE_OPTIONAL_HEADER 
    {
        //
        // Standard fields.  
        //
    +18h    WORD    Magic;         // 标志字, ROM 映像(0107h),普通可执行文件(010Bh)
    +1Ah    BYTE      MajorLinkerVersion;     // 链接程序的主版本号
    +1Bh    BYTE      MinorLinkerVersion;     // 链接程序的次版本号
    +1Ch    DWORD   SizeOfCode;     // 所有含代码的节的总大小
    +20h    DWORD   SizeOfInitializedData;    // 所有含已初始化数据的节的总大小
    +24h    DWORD   SizeOfUninitializedData; // 所有含未初始化数据的节的大小
    +28h    DWORD   AddressOfEntryPoint;    // 程序执行入口RVA
    +2Ch    DWORD   BaseOfCode;      // 代码的区块的起始RVA
    +30h    DWORD   BaseOfData;      // 数据的区块的起始RVA
        //
        // NT additional fields.    以下是属于NT结构增加的领域。
        //
    +34h    DWORD   ImageBase;      // 程序的首选装载地址
    +38h    DWORD   SectionAlignment;      // 内存中的区块的对齐大
    +3Ch    DWORD   FileAlignment;      // 文件中的区块的对齐大小
    +40h    WORD    MajorOperatingSystemVersion;  // 要求操作系统最低版本号的主版本号
    +42h    WORD    MinorOperatingSystemVersion;  // 要求操作系统最低版本号的副版本号
    +44h    WORD    MajorImageVersion;       // 可运行于操作系统的主版本号
    +46h    WORD    MinorImageVersion;       // 可运行于操作系统的次版本号
    +48h    WORD    MajorSubsystemVersion;  // 要求最低子系统版本的主版本号
    +4Ah    WORD    MinorSubsystemVersion;  // 要求最低子系统版本的次版本号
    +4Ch    DWORD   Win32VersionValue;       // 莫须有字段,不被病毒利用的话一般为0
    +50h    DWORD   SizeOfImage;       // 映像装入内存后的总尺寸
    +54h    DWORD   SizeOfHeaders;       // 所有头 + 区块表的尺寸大小
    +58h    DWORD   CheckSum;       // 映像的校检和
    +5Ch    WORD    Subsystem;       // 可执行文件期望的子系统
    +5Eh    WORD    DllCharacteristics;       // DllMain()函数何时被调用,默认为 0
    +60h    DWORD   SizeOfStackReserve;       // 初始化时的栈大小
    +64h    DWORD   SizeOfStackCommit;       // 初始化时实际提交的栈大小
    +68h    DWORD   SizeOfHeapReserve;        // 初始化时保留的堆大小
    +6Ch    DWORD   SizeOfHeapCommit;        // 初始化时实际提交的堆大小
    +70h    DWORD   LoaderFlags;        // 与调试有关,默认为 0 
    +74h    DWORD   NumberOfRvaAndSizes;  // 下边数据目录的项数,这个字段自Windows NT 发布以来        // 一直是16
    +78h    DWORD   DataDirctory[16];
           // 数据目录表
    } IMAGE_OPTIONAL_HEADER32, *PIMAGE_OPTIONAL_HEADER32;

    这里总共31个字段但是常用的其实就是我用红色字体标明的。

    前面我们已经知道了PE文件头在40h的位置,则上面的偏移量推断IMAGE_OPTIONAL_HEADER字段的首个字段在40h+18h=58h的地方,我们还是用hexwrokshop打开那个PE文件。Ctrl+G打开转移窗口,输入58则找到了第一个字段位置,如下图:

      对于这31个字段我们今天最为关心的是最后一个字段DataDirctory[16]我们一眼就能看出这是一个数组,其中的每个元素都是由一个叫做IMAGE_DATA_DIRECTORY的结构组成。这个叫做IMAGE_DATA_DIRACTORY的结构如下:

                                                   IMAGE_DATA_DIRACTORY    STRUC

                                                   VritualAddress    DWORD    //数据块的起始RVA

                                                  Size             DWORD   //数据块的长度

                                                   IMAGE_DATA_DIRACTORY    RENS

    下面是DataDirctory[16]即数据目录表的各个成员

       

    索引值在Windows.inc中的预定义值

    对应的数据块

    偏移量

    0

    IMAGE_DIRECTORY_ENTRY_EXPORT

    导出表

    78h

    1

    IMAGE_DIRECTORY_ENTRY_IMPORT

    导入表

    80h

    2

    IMAGE_DIRECTORY_ENTRY_RESOURCE

    资源

    88h

    3

    IMAGE_DIRECTORY_ENTRY_EXCEPTION

    异常(具体资料不详)

    90h

    4

    IMAGE_DIRECTORY_ENTRY_SECURITY

    安全(具体资料不详)

    98h

    5

    IMAGE_DIRECTORY_ENTRY_BASERELOC

    重定位表

    A0h

    6

    IMAGE_DIRECTORY_ENTRY_DEBUG

    调试信息

    A8h

    7

    IMAGE_DIRECTORY_ENTRY_ARCHITECTURE

    版权信息

    B0h

    8

    IMAGE_DIRECTORY_ENTRY_GLOBALPTR

    具体资料不详

    B8h

    9

    IMAGE_DIRECTORY_ENTRY_TLS

    Thread Local Storage

    C0h

    10

    IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG

    具体资料不详

    C8h

    11

    IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT

    具体资料不详

    D0h

    12

    IMAGE_DIRECTORY_ENTRY_IAT

    导入函数地址表

    D8h

    13

    IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT

    具体资料不详

    E0h

    14

    IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR

    具体资料不详

          E8h

    15

    未使用

    保留

      这张表的16个成员中第一个成员IMAGE_DIRECTORY_ENTRY_EXPORT(导出表)和第二个成员IMAGE_DIRECTORY_ENTRY_EXPORT(导入表)非常重要。下面我们用另一个PE文件来查看信息。由于前面的PE.exe没有输出表,所以换一个Dumped.DLL这个有输出表的来查看结构。步骤如下:

    1.Hexwrokshop打开文件,首先找到PE文件头位置,一般都是在载入起始位+3ch处,如下图所示。

     图中被选中的黑色处100h,故可知PE文件头在100h处,用快捷键跳ctrl+G跳转到该处上图标黑部分即PE文件头位置。

    2.找到了PE文件头的位置,接下来我们来找DataDirctory[16]各个成员位置。第一个成员输出表位于PE文件头+78h位置即100h+78h=178h处,如下图:

    由于每个结构都占8个字节,所以可以知道输出表的其实位置在4000h处,大小为45h

    输入表的位置位100h+80h=180h处,如下图:

    由上图可知输入表的起始位置在3000h处,大小为52h

    3.其实除了这么查找,还有一种更为简单的方式。

    我们要用到另一个工具LordPE

    步骤如下:

    1)打开lordPE,点击PE编辑器即可查看PE文件头的许多信息,如下图:

    2)再点击目录按钮即可查看数据目录表的相关信息。如下图:

    由上图我们直接就能看到输出表RVA4000h大小为45h,输入表的RVA3000h,大小为52h。这和我们计算的查找的结果一致。

  • 相关阅读:
    Linux的概念与体系
    Python快速教程
    Qt控件精讲一:按钮
    xml2-config not found
    Ubuntu 12.04更新源
    Adaboost的几个人脸检测网站
    关于matlab矩阵卷积conv2和傅里叶变换求卷积ifft2的关系
    char数组和String互转
    STL中vector的赋值,遍历,查找,删除,自定义排序——sort,push_back,find,erase
    《离散数学》-图论6.7
  • 原文地址:https://www.cnblogs.com/2f28/p/9816419.html
Copyright © 2020-2023  润新知