PE文件详解(一)

来源:互联网 发布:电脑截图软件下载 编辑:程序博客网 时间:2024/05/19 01:59

IMAGE_DOS_HEADER STRUCT

{

+0h WORD e_magic // Magic DOS signature MZ(4Dh 5Ah) DOS 可执行文件标记

+2h WORD e_cblp     //Bytes on last page of file

+4h  WORD e_cp       // Pages in file

+6h WORD e_crlc      //Relocations

+8h  WORD e_cparhdr // Sizeof header in paragraphs

+0ah WORD e_minalloc // Minimun extra paragraphs needs

+0ch WORD e_maxalloc //Maximun extra paragraphs needs

+0eh WORD e_ss // intial(relative)SS value   DOS 代码的初始化堆栈 SS

+10h       WORD e_sp // intial SP value  DOS 代码的初始化堆栈指针SP

+12h       WORDe_csum   // Checksum

+14h       WORD e_ip // intial IP value   DOS 代码的初始化指令入口[指针 IP]

+16h       WORD e_cs // intial(relative)CS value DOS 代码的初始堆栈入口

+18h       WORD e_lfarlc   // File Address of relocation table

+1ah WORD e_ovno // Overlay number

+1ch WORD e_res[4]  // Reserved words

+24h       WORD e_oemid // OEM identifier(for e_oeminfo)

+26h       WORD e_oeminfo// OEM information;e_oemid specific

+29h       WORD e_res2[10]// Reserved words

+3ch DWORD e_lfanew //Offset to start of PE header 指向PE 文件头

} IMAGE_DOS_HEADER ENDS;
这里的最后一个3ch指向的是PE文件头

IMAGE_NT_HEADERS STRUCT

{

+0h   DWORD Signature //--》PE00

+4h IMAGE_FILE_HEADER FileHeader     //

+18h IMAGE_OPTIONAL_HEADER32 OptionalHeader //

} IMAGE_NT_HEADERS ENDS;

Signature 字段:

在一个有效的PE 文件里,Signature 字段被设置为00004550h, ASCII 码字符是

“PE00”。标志这 PE 文件头的开始。

“PE00” 字符串是PE 文件头的开始,DOS 头部的 e_lfanew字段正是指向这

里。

IMAGE_FILE_HEADER 结构

typedef  struct _IMAGE_FILE_HEADER

{

+04h WORD

Machine;

// 运行平

+06h      WORD

NumberOfSections;

// 文件的区块数目

+08h DWORD

TimeDateStamp;

// 文件创建日期和时间

+0Ch DWORD

)

PointerToSymbolTable;

// 指向符号表(主要用于调

+10h DWORD

NumberOfSymbols;

// 符号表中符号个数(同上)

+14h      WORD

SizeOfOptionalHeader;    //

IMAGE_OPTIONAL_HEADER32 结构大小

+16h      WORD  Characteristics;    // 文件属性

} IMAGE_FILE_HEADER,  *PIMAGE_FILE_HEADEr;

1Machine:可执行文件的目标 CPU类型。

Value

Meaning

IMAGE_FILE_MACHINE_I386 0 x014c

x86

IMAGE_FILE_MACHINE_IA64 0x0200

Intel Itanium

IMAGE_FILE_MACHINE_AMD64 0x8664

x64

2NumberOfSection:区块的数目。(注:区块表是紧跟在 IMAGE_NT_HEA

DERS 后边的)

3TimeDataStamp:表明文件是何时被创建的。

这个值是自197011日以来用格林威治时间(GMT)计算的秒数,这个值是比文件系统(FILESYSTEM)的日期时间更加精确的指示器。如何将这个值翻译请看:http://bbs.fishc.com/space.php?uid=9&do=blog&id=555

提示:VC的话可以用_ctime 函数或者gmtime 函数。

4PointerToSymbolTable:COFF符号表的文件偏移位置,现在基本没用了。

5NumberOfSymbols:如果有 COFF 符号表,它代表其中的符号数目,COFF

符号是一个大小固定的结构,如果想找到 COFF 符号表的结束位置,则需要这个变量。

6SizeOfOptionalHeader:紧跟着 IMAGE_FILE_HEADER后边的数据结构(I MAGE_OPTIONAL_HEADER)的大小。(对于32PE文件,这个值通常是00 E 0h;对于64PE32+文件,这个值是00F0h )

7Characteristics:文件属性,有选择的通过几个值可以运算得到。(这些标志的有效值是定义于 winnt.h 内的IMAGE_FILE_** 的值,具体含义见下表。普通的 EXE 文件这个字段的值一般是 0100hDLL文件这个字段的值一般是 2

10Eh):多种属性可以通过或运算使得同时拥有!

The characteristics of the image. This membercan be one or more of the following values.

Value

Meaning

IMAGE_FILE_RELOCS_STRIPPED 0x0001

Relocation information was stripped from the

file. The file must be loaded at its preferred base address. If the base address is not available, the loader reports an error.

IMAGE_FILE_EXECUTABLE_IMAGE

0x0002

The file is executable (there are no unresolved

external references).

IMAGE_FILE_LINE_NUMS_STRIPPED

0x0004

COFF line numbers were stripped from the

file.

IMAGE_FILE_LOCAL_SYMS_STRIPPED

0x0008

COFF symbol table entries were stripped from

file.

IMAGE_FILE_AGGRESIVE_WS_TRIM

0x0010

Aggressively trim the working set. This value is

obsolete as of Windows 2000.

IMAGE_FILE_LARGE_ADDRESS_AWARE

0x0020

The application can handle addresses larger

than 2 GB.

IMAGE_FILE_BYTES_REVERSED_LO

0x0080

The bytes of the word are reversed. This flag

is obsolete.

IMAGE_FILE_32BIT_MACHINE

0x0100

The computer supports 32-bit words.

IMAGE_FILE_DEBUG_STRIPPED

0x0200

Debugging information was removed and stored separately in another file.

IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP

0x0400

If the image is on removable media, copy it to and run it from the swap file.

IMAGE_FILE_NET_RUN_FROM_SWAP

0x0800

If the image is on the network, copy it to and run it from the swap file.

IMAGE_FILE_SYSTEM

0x1000

The image is a system file.

IMAGE_FILE_DLL

0x2000

The image is a DLL file. While it is an executable file, it cannot be run directly.

IMAGE_FILE_UP_SYSTEM_ONLY

0x4000

The file should be run only on a uniprocessor

computer.

IMAGE_FILE_BYTES_REVERSED_HI

0x8000

The bytes of the word are reversed. This flag

is obsolete.

IMAGE_OPTIONAL_HEADER 结构(下面几个重要字段务必记熟)

typedef struct _IMAGE_OPTIONAL_HEADER

{

//

// Standard fields.

//

+18h WORD Magic; // 标志字, ROM 映像(0107h,普通可执行文件(010Bh+1Ah BYTEMajorLinkerVersion; // 链接程序的主版本号

+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 IMAGE_DATA_DIRECTORY

DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES];

// 数据目录表

} IMAGE_OPTIONAL_HEADER32,*PIMAGE_OPTIONAL_HEADER32;

●  AddressOfEntryPoint 字段

指出文件被执行时的入口地址,这是一个 RVA 地址(RVA 的含

义在下一节中详细介绍)。如果在一个可执行文件上附加了一段代码并想让这段代码首先被执行,那么只需要将这个入口地址指向附加的代码就可以了。

●  ImageBase 字段

指出文件的优先装入地址。也就是说当文件被执行时,如果可能

的话,Windows优先将文件装入到由 ImageBase 字段指定的地址中,只有指定的地址已经被**模块使用时,文件才被装入到**地址中。链接器产生可执行文件的时候对应这个地址来生成机器码,所以当文件被装入这个地址时不需要进行重定位操作,装入的速度最快,如果文件被装载到**地址的话,将不得不进行重定位操作,这样就要慢一点。

对于 EXE 文件来说,由于每个文件总是使用独立的虚拟地址空间,优先装入地址不可能被**模块占据,所以 EXE 总是能够按照这个地址装入,这也意味着 EXE 文件不再需要重定位信息。对于 DLL 文件来说,由于多个 DLL 文件全部使用宿主 EXE 文件的地址空间,不能保证优先装入地址没有被**的 DLL 使用,所以 DLL 文件中必须包含重定位信息以防万一。因此,在前面介绍的 IMAGE_FILE_HEADER 结构的 Characteristics 字段中,DLL 文件对应的

IMAGE_FILE_RELOCS_STRIPPED 位总是为0,而 EXE 文件的这个标志位总是为1。

在链接的时候,可以通过对 link.exe 指定/base:address选项来自定义优先装入地址,如果不指定这个选项的话,一般 EXE 文件的默认优先装入地址被定为00400000h,而 DLL 文件的默认优先装入地址被定为10000000h。

●  SectionAlignment 字段和 FileAlignment 字段

SectionAlignment 字段指定了节被装入内存后的对齐单位。也就是说,每个节被装入的地址必定是本字段指定数值的整数倍。而 FileAlignment 字段指定了节存储在磁盘文件中时的对齐单位。

●  Subsystem 字段

指定使用界面的子系统,它的取值如表17.3所示。这个字段决定

了系统如何为程序建立初始的界面,链接时的/subsystem:**选项指定的就是这个字段的值,在前面章节的编程中我们早已知道:如果将子系统指定为 Windows CUI,那么系统会自动为程序建立一个控制台窗口,而指定为Windows GUI 的话,窗口必须由程序自己建立。

●  DataDirectory 字段

这个字段可以说是最重要的字段之一,它由16个相同的

IMAGE_DATA_DIRECTORY 结构组成,虽然PE 文件中的数据是按照装入内存

后的页属性归类而被放在不同的节中的,但是这些处于各个节中的数据按照用途可以被分为导出表、导入表、资源、重定位表等数据块,这16

IMAGE_DATA_DIRECTORY 结构就是用来定义多种不同用途的数据块的(如表 17.4所示)。IMAGE_DATA_DIRECTORY 结构的定义很简单,它仅仅指出了某种

数据块的位置和长度。

IMAGE_DATA_DIRECTORY STRUCT

VirtualAddress DWORD ? ;数据的起始RVA isize DWORD ? ;数据块的长度

IMAGE_DATA_DIRECTORY ENDS

数据目录列表的含义

在PE文件中寻找特定数据的就是从这些IMAGE_DATA_DIRECTORY结构开始的,比如要存取资源,那么必须从第3个IMAGE_DATA_DIRECTORY 结构(索引为2)中得到资源数据块的大小和位置;同理,如果要查看 PE 文件导入了哪些 DLL 文件的哪些 API 函数,那就必须首先从第2个

IMAGE_DATA_DIRECTORY 结构得到导入表的位置和大小。

注解:这边的DataDirectory 字段为128个字节,因为有16个IMAGE_DATA_DIRECTORY字段的结构每个结构8个字节,我们可以通过上面的 IMAGE_FILE_HEADER 结构SizeOfOptionalHeader字段的值(224)推出来,DataDirectory字段的起始为78h,optional结构的起始字段为18h,224-(78h-18h) = 128
有关校验和介绍
参考资料:小甲鱼PE结构详解课件(相关论坛地址)
PE图解
http://bbs.fishc.com/thread-56156-1-1.html
http://bbs.fishc.com/forum.php?mod=viewthread&tid=44672&extra=page%3D1&page=1
遗留问题:
程序是如何通过加载器用寄存器进行运行的(eip)
0 0
原创粉丝点击