PE手动解析
写这个是为了个人动手练习,不当“视频观察师”。
DOS头
16进制编辑器打开,首先两字节是0x5A4D
(Ascii的MZ),在0x3C
处,是e_lfanew,两个字节,储存着PE头的偏移,此文件中是0x00E0
,找过去,发现0x5045
(Ascii的PE),是PE头标志Signature,四个字节。
PE头
PE头标志
四字节。高两字节为0x00
,低两字节为0x4550
。
PE标准头
头标志后面跟着PE标准头,二十字节。
Machine
文件的运行平台,此文件中为0x014C
,是Intel 386平台。
NumberOfSections
该PE文件中的节数量,也就是节表中的项数,两个字节。此处是0x0003
,一共三个节。
TimeDateStamp
PE文件的创建时间,四字节。此处是0x48022587
,十进制为1208100231。
PointerToSymbolTable
COFF在文件中的偏移。四字节,此处是空。
NumberOfSymbols
符号表数量,四字节。此处为空。
SizeOfOptionalHeaders
PE可选头的长度,两个字节。此处是0x00E0
。
Characteristics
可执行文件的属性,两个字节,是相关属性对应的16进制按位相或的结果。此处是0x010F
,即0x0100
(32位)、0x0001
、0x0002
(可执行)、0x0004
、0x0008
是这个文件的属性。
1 | Characteristics的可选值 |
PE可选头
上面标准头SizeOfOptionalHeader指明长度是0x00E0
,即224字节,这是32位可执行文件,一般是244字节。
Magic
魔术字,表示可选头的类型,两字节。此处是0x010B
。
MajorLinkerVersion
链接器版本号,一字节。此处是0x07
。
MinorLinkerVersion
链接器版本号,一字节,此处是0x0A
。
SizeOfCode
代码段总长度,四字节。此处是0x00007800
。
SizeOfInitializedCode
初始化的数据长度,比如全局变量,四字节。此处是0x00008800
。
SizeOfUnInitializedCode
未初始化数据的长度,四字节。此处是0.
AddressOfEntryPoint
OEP入口点偏移,四字节。此处是0x0000739D
。
BaseOfCode
代码段起始地址偏移,四字节。此处是0x00001000
。
BaseOfData
数据段起始地址偏移,四字节。此处是0x00009000
。
ImageBase
基址,四字节。此处是0x01000000
。
SectionAlignment
节被夹在到内存中按照这个值对齐,四字节。此处是0x00001000
.
FileAlignment
节在文件中按此值对齐,四字节。此处是0x00000200
MajorOperatingSystemVersion
操作系统版本号,两字节。此处是0x0005
.
MinorOperatingSystemVersion
所需最小操作系统版本号,两字节,此处是0x0001
.
MajorImageVersion
映像的版本号,两字节。此处是0x0005
.
MinorImageVersion
最小映像的版本号,两字节,此处是0x0001
.
MajorSubsystemVersion
所需子系统版本号,两字节。此处是0x0004
.
MinorSubsystemVersion
最小所需子系统版本号,两字节。此处是0x0000
.
Win32VersionValue
保留,必须为0,四字节。
SizeOfImage
映像的大小,PE加载到内存是连续的,这个值指定占用虚拟空间的大小,四字节。此处是0x00013000
.
SizeOfHeaders
所有头加节表的大小,以FileAlignment对齐,四字节。此处是0x00000400
.
CheckSum
文件校验和,四字节。此处是0x00018ADA
.
Subsystem
运行该PE文件所需的子系统,两字节。此处是0x0002
.
DllCharacteristics
DLL的文件属性,只对DLL文件有效,两字节。此处是0x0800
.
SizeOfStackReserve
四字节。此处是0x00040000
.
SizeOfStackCommit
四字节。此处是0x00011000
.
SizeOfHeapReserve
四字节。此处是0x00100000
.
SizeOfHeapCommit
四字节。此处是0x00001000
.
LoaderFlags
保留,必须为0,四字节。
NumberOfRvaAndSizes
数据目录的项数,即下面这个数组的项数,四字节。此处是0x00000010
.
IMAGE_DATA_DIRECTORY
数据目录,这是一个数组,如图都是它的。
节表
在PE可选头中的SizeOfHeaders指明了头加节表的长度,此处是0x400
,即1024字节。
而PE标准头的SizeOfOptionalHeaders指明了可选头的长度,此处是0x00E0
,即244字节。
PE标准头长度24字节。DOS头长度224字节。
所以节表长度为 1024-244-244-24=552 字节。如图所示都是节表的部分。
Name数组
八个字节,该节的名称。此处为0x00000074 7865742E
(.text).
Misc
该节在没有对齐前的真实大小,该值可能不准确,联合体,四个字节。此处为0x00007748
.
VirtualAddress
节区在内存中的偏移地址,加上ImageBase才是在内存中的真正地址,四个字节。此处是0x00001000
.
SizeOfRawData
节在内存中对齐后的大小,四个字节。此处是0x00007800
.
PointerToRawData
节在内存中的偏移,四个字节。此处是0x00000400
.
PointerToRelocations
在obj文件中使用,对exe无意义,四个字节。
PointerToLinenumbers
行号表的位置,调试时使用,四个字节。
NumberOfRelocations
在obj文件中使用,对exe无意义,两个字节。
NumberOfLinenumbers
行号表中行号的数量,调试的时候使用,两个字节。
Characteristics
表示该节的属性,四个字节。此处是0x60000020
.
后面紧跟着是.data节,就不分析了。