什么是文件
存储数据的实体
不同的文件是给不同的软件去使用的。不同的文件主要是格式不同。
格式就是数组的排列组织方式
什么是PE文件
(Portable Executable) 可执行文件的缩写。这种类型的文件是供windows系统解析,解析完了之后能够创建出进程去运行的文件。
PE文件的头部信息(DOS头,NT头,区段表)
学习PE文件就是学习PE的格式。格式就是一堆结构体。需要记忆。为了便于记忆,需要一些辅助性的工具
PE文件格式图
010-Editor
LordPE是一个非常好用的PE解析器以及编辑器
DOS头:
可执行文件再设计的时候,考虑到了兼容性问题。在正常的可执行文件开始的部分,嵌入了一个DOS可执行文件。作用就是再MS-DOS系统下能够输出一行 这个不是运行在此系统下的。
1 | struct _IMAGE_DOS_HEADER { // DOS .EXE header |
两个重要字段:
e_magic
永远都是 0x5A4D (小端存储)
e_lfanew
是真正的可执行文件的起始部分
NT头:
1 | struct _IMAGE_NT_HEADERS { |
Signature
永远都是 0x50 0x45 0x00 0x00 (0x00004550)
IMAGE_FILE_HEADER
1 | struct _IMAGE_FILE_HEADER { |
重要字段:
NumberOfSections
区段的数量
SizeOfOptionalHeader
扩展头的大小,因为扩展头中数据目录表的个数是不确定的。所以这里需要一个大小。
有用字段:
Machine
运行平台
TimeDateStamp
时间戳 表明是再什么时候编译的
IMAGE_OPTIONAL_HEADER
扩展头
1 | struct _IMAGE_OPTIONAL_HEADER { |
非常重要的字段:
ImageBase
程序的默认加载基址
AddressOfEntryPoint
程序的入口点(EP)。
比较重要的字段:
SectionAlignment
内存对齐 0x1000 (因为一页内存是4KB)
FileAlignment
文件对齐 0x200
SizeOfImage
映像大小(这个PE文件被加载到内存 占用空间应该是多大)
SizeOfHeader
头部大小 DOS头+NT头+区块表的大小。
NumberOfRvaAndSizes
数据目录表的元素个数
DllCharacteristics
PE的一组属性。
极为重要的字段:
DataDirectory
数据目录表 描述了PE文件中16个非常重要的数据块的大小和位置。
1 | struct _IMAGE_DATA_DIRECTORY { |
- 导入表
- 导出表
- 重定位表
- 资源表
- TLS表
- ……
区段表:结构体数组,数组的元素个数由文件头中的NumberOfSections
绝定。
区段表中的一个元素描述的就是一个区段的信息:
Name
区段名PointerToRawData
在文件中的位置 FOASizeOfRawData
再文件中的大小VirtualAddress
再内存中的位置 RVAMisc.VirtualSize
再内存中的大小Characteristics
区段的属性:可读 可写 可执行 ……
1 | struct _IMAGE_SECTION_HEADER { |
FOA VA RVA
文件偏移(FOA或者Offset):某一个数据距离文件开头的偏移
虚拟地址(VA):程序在运行的时候,是将PE文件加载到进程的内存空间中。进程的这块内存空间就称之为 虚拟内存空间。32位的程序虚拟内存空间是以字节为单位的,每一个字节都有一个编号从0x0000 0000 到 0xFFFF FFFF。这些编号就是虚拟地址
相对虚拟地址(RVA):PE文件不会占满整个虚拟内存空间,而是会占用一部分。那么就会有一个起始位置,这个起始位置也称为加载基址。PE文件中的数据相对于加载基址的偏移就是相对虚拟地址
如果系统加载PE文件的时候,是将PE文件原封不动的复制到了内存中,那么某一个数据的FOA和RVA就是相等的。
关闭ASLR
1 | PIMAGE_NT_HEADERS.OptionalHeader.DllCharacteristics; |
1 | PIMAGE_NT_HEADERS.FileHeader.Characteristics; |
查看PE头示例
1 |
|