PE文件详解(一)

论坛 期权论坛 编程之家     
选择匿名的用户   2021-6-2 08:36   11   0

PE文件详解(一)

2年 ago mqzi

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;
<strong>这里的最后一个3ch指向的是PE文件头</strong>
 

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 WORDNumberOfSections;// 文件的区块数目
+08h DWORDTimeDateStamp;// 文件创建日期和时间
+0Ch DWORD

试)

PointerToSymbolTable;

// 指向符号表(主要用于调
+10h DWORDNumberOfSymbols;// 符号表中符号个数(同上)
+14h WORDSizeOfOptionalHeader; //
IMAGE_OPTIONAL_HEADER32 结构大小

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

} IMAGE_FILE_HEADER,  *PIMAGE_FILE_HEADEr;
 

 
 

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

x86

Intel Itanium

x64

Value
IMAGE_FILE_MACHINE_I386 0 x014cIMAGE_FILE_MACHINE_IA64 0x0200IMAGE_FILE_MACHINE_AMD64 0x8664

2NumberOfSection:区块的数目。(注:区块表是紧跟在 IMAGE_NT_HEA DERS 后边的) (3TimeDataStamp:表明文件是何时被创建的。 这个值是自1970年1月1日以来用格林威治时间(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)的大小。(对于32位 PE文件,这个值通常是00 E 0h;对于64位 PE32+文件,这个值是00F0h )。 (7Characteristics:文件属性,有选择的通过几个值可以运算得到。(这些标志的有效值是定义于 winnt.h 内的IMAGE_FILE_** 的值,具体含义见下表。普通的 EXE 文件这个字段的值一般是 0100h,DLL文件这个字段的值一般是 2 10Eh。):多种属性可以通过“或运算” 使得同时拥有! The characteristics of the image. This membercan be one or more of the following values.
Meaning
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.

The file is executable (there are no unresolved external references).

COFF line numbers were stripped from the file.

COFF symbol table entries were stripped from file.

Aggressively trim the working set. This value is obsolete as of Windows 2000.

The application can handle addresses larger than 2 GB.

The bytes of the word are reversed. This flag is obsolete.

The computer supports 32-bit words.

Debugging information was removed and stored separately in another file.

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

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

The image is a system file.

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

The file should be run only on a uniprocessor computer.

The bytes of the word are reversed. This flag is obsolete.

Value
IMAGE_FILE_RELOCS_STRIPPED 0x0001IMAGE_FILE_EXECUTABLE_IMAGE 0x0002IMAGE_FILE_LINE_NUMS_STRIPPED 0x0004IMAGE_FILE_LOCAL_SYMS_STRIPPED 0x0008IMAGE_FILE_AGGRESIVE_WS_TRIM 0x0010IMAGE_FILE_LARGE_ADDRESS_AWARE 0x0020IMAGE_FILE_BYTES_REVERSED_LO 0x0080IMAGE_FILE_32BIT_MACHINE 0x0100IMAGE_FILE_DEBUG_STRIPPED 0x0200IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP 0x0400IMAGE_FILE_NET_RUN_FROM_SWAP 0x0800IMAGE_FILE_SYSTEM 0x1000IMAGE_FILE_DLL 0x2000IMAGE_FILE_UP_SYSTEM_ONLY 0x4000IMAGE_FILE_BYTES_REVERSED_HI 0x8000

 
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 字段
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) = 128DataDirectory 字段为128个字节,因为有16个IMAGE_DATA_DIRECTORY字段的结构每个结构8个字节,我们可以通过上面的  IMAGE_FILE_HEADER 结构SizeOfOptionalHeader字段的值(224)推出来,DataDirectory字段的起始为78h,optional结构的起始字段为18h,224-(78h-18h) = 128
 
<a data-cke-saved-href="http://www.cnblogs.com/xiaojinma/archive/2012/12/07/2806568.html" href="http://www.cnblogs.com/xiaojinma/archive/2012/12/07/2806568.html">有关校验和介绍</a>

参考资料:小甲鱼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)

Continue Reading

Next 手把手教你在winodwsXP下用iis建站(静态页面)

分享到 :
0 人收藏
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

积分:3875789
帖子:775174
精华:0
期权论坛 期权论坛
发布
内容

下载期权论坛手机APP