PE文件格式详解(2)

1.NT头
接下来说一下NT头,IMAGE_NT_HEADERS。

代码 IMAGE_NT_HEADERS结构体

typedef struct _IMAGE_NT_HEADERS{
    DWORD Signature;                    //PE Signature :  50450000 ("PE"00)
    IMAGE_FILE_HEADER FileHeader;
    IMAGE_OPTIONAL_HEADER32 OptionalHeader
} IMAGE_NT_HEADERS32, *PIMAGE_NT_HEADERS32;

该结构体由3个成员构成:
            签名(Signature)→ 值为50450000h("PE"00)
              文件头(File Header)
              可选头(Optional Header)

依然以Notepad.exe为例,使用010 Editor打开。

可以查看其IMAGE_NT_HEADERS。
IMAGE_NT_HEADERS结构体的大小为F8,非常大,接下来分别说一下文件头和可选头两个结构体。

2.NT头:文件头
文件头是表现文件大致属性的IMAGE_FILE_HEADER 结构体

代码 IMAGE_FILE_HEADER结构体

typedef struct _IMAGE_FILE_HEADER{
    WORD      Machine;
    WORD     NumberOfSections;
    DWORD     TimeDateStamp;
    DWORD     PointToSymbolTable;
    DWORF     NumberOfSymbols;
    WORD     SizeOfOptionalHeader;
    WORD     Characteristics;
} IMAGE_FILE_HEADER, *PIMAGE_FILE_HEADER;

IMAGE_FILE_HEADERS结构体中有如下4种重要成员,(若设置不正确,将导致文件无法正常运行)。
#1.Machine
    每个CPU都拥有唯一的Machine码,兼容32位Intel x86芯片的Machine码为14C。
    
定义在winnt.h文件中的Machine码。
代码  Machine码

#define IMAGE_FILE_MACHINE_UNKNOWN     0
#define IMAGE_FILE_MACHINE_I386                    0x014c     //Inter 386
#define IMAGE_FILE_MACHINE_R3000                0x0162     //MIPS little-endian,0x160 big-endian
#define IMAGE_FILE_MACHINE_R4000                0x0166     //MIPS little-endian
#define IMAGE_FILE_MACHINE_R10000              0x0168     //MIPS little-endian
#define IMAGE_FILE_MACHINE_WCEMIPSV2    0x0169     //MIPS little-endian WCE v2
#define IMAGE_FILE_MACHINE_ALPHA                0x0184     //Alpha_AXP
#define IMAGE_FILE_MACHINE_POWERPC        0x01F0     //IBM Powerpc Little-Endian
#define IMAGE_FILE_MACHINE_SH3                     0x01a2     //SH3 little-endian
#define IMAGE_FILE_MACHINE_SH3E                    0x01a4     //SH3E little-endian
#define IMAGE_FILE_MACHINE_SH4                      0x01a6     //SH4 little-endian
#define IMAGE_FILE_MACHINE_ARM                    0x01c0     //ARM Little-Endian
#define IMAGE_FILE_MACHINE_THUMB              0x01c2
#define IMAGE_FILE_MACHINE_IA64                    0x0200     //Intel 64
#define IMAGE_FILE_MACHINE_MIPS16              0x0266     //MIPS
#define IMAGE_FILE_MACHINE_MIPSFPU          0x0366     //MIPS
#define IMAGE_FILE_MACHINE_MIPSFPU16       0x0466     //MIPS
#define IMAGE_FILE_MACHINE_ALPHA64          0x0284     //ALPHA64
#define IMAGE_FILE_MACHINE_AXP64               IMAGE_FILE_MACHINE_ALPHA64

#2.NumberOfSections
    PE文件把代码、数据、资源等一句属性分类到各个节区中储存。
    NumberOfSections用来指出文件中存在的节区数量。该值一定要大于0,其当定义的节区数量与实际节区不同时,将发生运行错误。

#3.SizeOfOptionalHeader
    IMAGE_NT_HEADER结构体的最后一个成员为IMAGE_OPTIONAL_HEADER32结构体。SizeOfOptionalHeader成员用来之处IMAGE_OPTIONAL_HEADER32结构体的长度。IMAGE_OPTIONAL_HEADER32结构体有C语言编写而成,故其大小已经确定。Windows的PE装载器需要查看IMAGE_FILE_HEADER的SizeOfOptionalHeader值,从而识别出IMAGE_OPTIONAL_HERADER32的结构体的大小。
    注:PE32+格式的文件,使用的是IMAGE_OPTIONAL_HEADER64结构体(不是 IMAGE_OPTIONAL_HEADER32结构体!!!两个结构体的大小是不一样的 )所以需要在 SizeOfOptionalHeader成员中明确指出结构体的大小。

#4.Characteristics
该字段用于表示文件的属性,文件是否是可运行的形态,是否为DLL文件等信息,以bit OR形式组合起来。

定义在winnt.h文件中的Characteristics值。 (注意 0002h与2000h

代码 Characteristics
#define IMAGE_FILE_RELOCS_STRIPPED                              0x0001     //Relocation info stripped from file.
#define IMAGE_FILE_EXECUTABLE_IMAGE                           0x0002     //File is executable
                                                                                                                             //(i.e. no unresolved externel   references). 
#define IMAGE_FILE_LINE_NUMS_STRIPPED                     0x0004     //Line numbers stripped from file.
#define IMAGE_FILE_LOCAL_SYMS_STRIPPED                   0x0008     //Local symbols stripped from file.
#define IMAGE_FILE_AGGRESIVE_WS_TRIM                        0x0010     //Agressively trim working set.
#define IMAGE_FILE_LARGE_ADDRESS_AWARE                 0x0020     //App can handle >2gb addresses
#define IMAGE_FILE_BYTES_RESVERSED_LO                      0x0080     //byte of machine word are reversed
#define IMAGE_FILE_32BIT_MACHINE                                  0x0100     //32 bit word machine
#define IMAGE_FILE_DEBUG_STRIPPED                               0x0200     //Debugging info stripped from  file in .DBG file
#define IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP   0x0400     //If Image is on removable media,
                                                                                                                            //copy and run from the swap file
#define IMAGE_FILE_NET_RUN_FROM_SWAP                    0x0800    //If Image is on Net, copy and run from the swap file.
#define IMAGE_FILE_SYSTEM                                                   0x1000     //System File
#define IMAGE_FILE_DLL                                                            0x2000    //File is a DLL
#define IMAGE_FILE_UP_SYSTEM_ONLY                              0x4000     //File should only be run on a UP machine
#define IMAGE_FILE_BYTES_REVERSED_HI                            0x8000     //byte of machine word are reversed

注:PE文件中Characteristics的值有可能不是0002h(not executable),例如:*.obj的object文件及resource DLL文件等,2000h表明PE文件是否为DLL文件。

IMAGE_FILE_HEADER的TimeDateStamp成员,该成员的值不影响文件运行,用来记录编译器创建文件的时间(并不是所有的开发工具都提供了设置该值的工具,Delphi则并没有提供)。

3.NT头:可选头
IMAGE_OPTIONAL_HEADER32是PE头结构体中最大的。

代码 IMAGE_OPTIONAL_HEADER32结构体。

typedef struct _IMAGE_DATA_DIRECTORY{
    DWORD     VirtualAddress;
    DWORD     Size;
}     IMAGE_DATA_DIRECTORY, *PIMAGE_DATA_DIRECTORY;

#define IMAGE_NUMBEROF_DIRECTORY_ENTRIES     16

typedef struct _IMAGE_OPTIONAL_HEADER{

    WORD      Magic;
    BYTE          MajorLinkerVersion;
    BYTE          MinorLinkerVersion;
    DWORD   SizeOfCode;
    DWORD    SizeOfInitializedData;
    DWORD    SizeOfUnitializedData;
    DWORD     AddressOfEntryPoint;
    DWORD     BaseOfCode;
    DWORD     BaseOfData;
    DWORD     ImageBase;
    DWORD     SectionAlignment;
    DWORD     FileAlignment;
    WORD         MajorOperatingSystemVersion;
    WORD         MinorOperatingSystemVersion;
    WORD         MajorImageVersion;
    WORD         MinorImageVersion;
    WORD         MajorSubsystemVersion;
    WORD         MinorSubsystemVersion;
    DWORD     Win32VersionValue;
    DWORD     SizeOfImage;
    DWORD     SizeOfHeaders;
    DWORD     CheckSum;
    WORD         Subsystem;
    WORD         DllCharacteristics;
    DWORD     SizeOfStackReserve;
    DWORD     SizeOfStackCommit;
    DWORD     SizeOfHeapReserve;
    DWORD     SizeOfHeapCommit;
    DWORD     LoaderFlags;
    DWORD     NumberOfRvaAndSizes;
    IMAGE_DATA_DIRECTORY     DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES];
}     IMAGE_OPTIONAL_HEADER32, *PIMAGE_OPTIONAL_HEADER32;

IMAGE_OPTIONAL_HEADER32结构体中有如下几种重要成员,(若设置不正确,将导致文件无法正常运行)。
#1.Magic
    为IMAGE_OPTIONAL_HEADER32结构体是,Magic码为10B;为IMAGE_OPTIONAL_HEADER64结构体时,Magic码为20B。
#2.AddressOfEntryPoint
    AddressOfEntryPoint持有EP的RVA值。该值指出程序最先执行的代码起始地址。
#3.ImageBase
    进程虚拟内存的范围为0~FFFFFFFF(32位操作系统,64位的操作系统为0~FFFFFFFFFFFFFFFF(16个))。PE文件被加载到如此大的内存中时ImageBase指出文件优先装入地址。
    EXE/DLL文件被装在到用户内存的0~7FFFFFFF(32位系统)中,SYS文件被载入内核内存的80000000~FFFFFFFF中。一般而言,使用开发工具创建好EXE文件后,其ImageBase的值为00400000,DLL文件的ImageBase为100000000(可以指定为其他值)。
    注:执行PE文件时,PE装载器先差un构建进程,再将文件载入内存,然后把EIP寄存器的值设置为 ImageBase+AddressOfEntryPoint.
#4.SectionAlignment,FileAlignment
    PE文件的Body部分划分为若干节区,这些节存储着不同类别的数据。FileAlignment指定了节区在磁盘文件中的最小单位,SectionAlignment指定了节区在内存中的最小单位(SectionAlignment与FlieAlignment的值不一定相同)。磁盘文件或内存节区的大小必定为FileAlignment或SectionAlignment的整数倍。
#5.SizeOfImage
    加载PE文件到内存时,SizeOfImage指定了PE Image在虚拟内存中所占空间的大小。一般而言,文件与加载到内存之后两者的大小是不相同的。
#6.SizeOfHeader
    SizeOfHeader用来指出整个PE头的大小,当然这个值也必须为FileAlignment的整数倍。第一节区所在位置与SizeOfHeader据文件开始偏移的量相同。
#7.Subsystem
    这个值是用来区分系统驱动文件安(*.sys)和普通的可执行文件的(*.exe,*.dll)。
    值             含义                              备注
    1            Driver文件              系统驱动
    2           GUI文件                    窗口应用程序
    3           CUI文件                    控制台应用程序
#8.NumberOfRvaAndSizes
    NumberOfRvaAndSizes用来制定DataDirectory(IMAGE_OPTIONAL_HEADER32结构体最后一个成员)数组的个数。虽然结构体定义中明确指出了数组个数为16( #define IMAGE_NUMBEROF_DIRECTORY_ENTRIES     16 )但是PE装载查看的NumberOfRvaAndSizes的值来识别数组的大小(即数组大小也可能不为16)。
#9.DataDirectory
    DataDirectory是有IMAGE_DATA_DIRECTORY结构体组成的数组,数组的每项都有被定义的值。

代码 DataDirectory结构体数组   

DataDirectory[0] = EXPORT Directory
DataDirectory[1] = IMPOTR Directory
DataDirectory[2] = RESOURCE Directory
DataDirectory[3] = EXCEPTION Directory
DataDirectory[4] = SECURITY Directory
DataDirectory[5] = BASERELOC Directory
DataDirectory[6] = DEBUG Directory
DataDirectory[7] = COPYRIGHT Directory
DataDirectory[8] = GLOBALPTR Directory
DataDirectory[9] = TLS Directory
DataDirectory[A] = LOAD_CONFIG Directory
DataDirectory[B] = BOUND_IMPORT Directory
DataDirectory[C] = IAT Directory
DataDirectory[D] = DELAY_IMPORT Directory
DataDirectory[E] = COM_DESCRIPTOR Directory
DataDirectory[F] = Reserver Directory

IMAGE_OPTIONAL_HEADER
使用010 Editor查看Notepad.exe的IMAGE_OPTIONAL_HEADER整个结构体。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值