基础储备
0x0 分页机制
0x1 虚拟内存地址
0x2 相对虚拟内存地址:虚拟内存中用来定位某个特定位置的地址,该地址的值是这个特定位置距离某个模块基地址的偏移量;RVA是相对于模块而言的
0x3 文件偏移地址:文件偏移地址从PE文件的第一个字节开始计数,起始值为0。用十六进制工具打开文件所显示的地址就是文件偏移地址。
0x4 特殊地址:在PE结构中还有一种特殊地址,其计算方法并不是从文件头算起,也不是从内存的某个模块的基地址算起,而是从某个
特定的位置
算起(资源表)
0x5 数据目录:PE中的一个数据结构,记录了所有可能的
数据类型
(导出表、导入表、资源表、异常表、属性证书表、重定位表、调试数据、Architecture、Global Ptr、线程局部存储、加载配置表、绑定导入表、IAT、延迟导入表和CLR运行时头部)
0x6 节:存放不同类型数据(比如代码、数据、常量、资源等)的地方,不同的节具有不同的访问权限
.data
初始化的数据
.data?
未初始化的数据
.code
可执行的代码等
.reloc
重定位表数据
对齐:有的对齐是为了美观,有的对齐则是为了效率。
内存对齐
对32位的Windows XP系统来说,这个值是4KB (1000h),而对于64位操作系统来说,这个值就是8KB(2000h)。
文件对齐
以一个物理扇区的大小作为对齐粒度的值,即512字节,十六进制表示为200h
资源数据对齐
一般要求以双字(4个字节)
Unicode字符串(
宽字符串
):继ASCII字符编码后的另一种新型字符编码;ASCII码
的每个字符使用7位表示,Unicode则使用全16位表示一个字符,ASCII字符
都使用一个字节来表示字符串中的字符
typedef struct _UNICODE_STRING {
USHORT Length; // 字符串的长度(字节数)
USHORT MaximumLength; // 字符串缓冲区的长度(字节数)
PWSTR Buffer; // 字符串缓冲区
} UNICODE_STRING, *PUNICODE_STRING;
从程序员的角度看PE文件结构
提出问题:假如你是图书管理员,你会怎样管理大量的图书呢?
(1)把所有的图书随意地堆放到一间屋子里,然后在门上贴上标签如“书库一”
BookStore STRUCT
Name db 8 dup(0) ;书库的名字
Address dd ? ;书库所在地址
Count dd ? ;书库中的藏书量
BookStore ENDS
从字节码的角度看PE文件结构
从局部的角度看PE文件结构
IMAGE_DOS_HEADER
在DOS MZ头中有一个字段非常重要,即IMAGE_DOS_HEADER.e_lfanew,没有它操作系统就定位不到标准的PE头部,可执行程序也就会被操作系统认为是非法的PE映像。
e_magic(WORD) ;EXE标志,“MZ”
e_cblp(WORD) ;最后(部分)页中的字节数
e_cp(WORD) ;文件中的全部和部分页数
e_crlc(WORD) ;重定位表中的指针数
e_cparhdr(WORD) ;头部尺寸,以段落为单位
e_minalloc(WORD) ;所需的最小附加段
e_maxalloc(WORD) ;所需的最大附加段
e_ss(WORD) ;初始的SS值(相对偏移量)
e_sp(WORD) ;初始的SP值
e_csum(WORD) ;补码校验值
e_ip(WORD) ;初始的IP值
e_cs(WORD) ;初始的CS值
e_lfarlc(WORD) ;重定位表的字节偏移量
e_ovno(WORD) ;覆盖号
e_res(WORD 4) ;保留字
e_oemid(WORD) ;OEM标识符(相对e_oeminfo)
e_oeminfo(WORD) ;OEM信息
e_res2(WORD) ;保留字
e_lfanew(DWORD) ;PE头相对于文件的偏移地址
DOS Stub:
1.大小不固定
2.是该程序在DOS系统下运行的指令字节码
IMAGE_NT_HEADERS:广义上的PE头
Signature(DWORD) ;PE文件标识,“PE\0\0”
FileHeader(IMAGE_FILE_HEADER) ;PE标准头
OptionalHeader(IMAGE_OPTIONAL_HEADER32) ;PE扩展头
Signature:内容固定
IMAGE_FILE_HEADER
它记录了PE文件的全局属性,如该PE文件运行的平台、PE文件类型(是EXE文件还是DLL文件)、文件中存在的节的总数等
Machine(WORD) ;运行平台
NumberOfSections(WORD) ;PE中节的数量
TimeDateStamp(DWORD) ;文件创建日期和时间
PointerToSymbolTable(DWORD) ;指向符号表(用于调试)
NumberOfSymbols(DWORD) ;符号表中的符号数量(用于调试)
SizeOfOptionalHeader(WORD) ;扩展头结构的长度
Characteristics(WORD) ;文件属性
IMAGE_OPTIONAL_HEADER32
1.文件执行时的入口地址、文件被操作系统装入内存后的默认基地址,以及节在磁盘和内存中的对齐单位等信息均可以在此结构中找到
2.它是操作系统映像文件所独有的头部信息,因为在符合COFF规范的“.obj”目标文件中该部分并不存在
Magic(WORD) ;说明文件的类型
MajorLinkerVersion(BYTE) ;链接器版本号
MinorLinkerVersion(BYTE)
SizeOfCode(DWORD) ;所有含代码的节的总大小
SizeOfInitializedData(DWORD) ;所有含已初始化数据的节的总大小
SizeOfUninitializedData(DWORD) ;所有含未初始化数据的节的大小
AddressOfEntryPoint(DWORD) ;程序执行入口RVA
BaseOfCode(DWORD) ;代码的节的起始RVA
BaseOfData(DWORD) ;数据的节的起始RVA
ImageBase(DWORD) ;程序的建议装载地址
SectionAlignment(DWORD) ;内存中的节的对齐粒度(空间换时间)
FileAlignment(DWORD) ;文件中的节的对齐粒度
MajorOperatingSystemVersion(WORD) ;操作系统版本号
MinorOperatingSystemVersion(WORD)
MajorImageVersion(WORD) ;该PE的版本号
MinorImageVersion(WORD)
MajorSubsystemVersion(WORD) ;所需子系统的版本号
MinorSubsystemVersion(WORD)
Win32VersionValue(DWORD) ;未用
SizeOfImage(DWORD) ;内存中的整个PE映像尺寸
SizeOfHeaders(DWORD) ;所有头+节表的大小
CheckSum(DWORD) ;校验和
Subsystem(WORD) ;文件的子系统
DllCharacteristics(WORD) ;DLL文件特性
SizeOfStackReserve(DWORD) ;初始化时的栈大小
SizeOfStackCommit(DWORD) ;初始化时实际提交的栈大小
SizeOfHeapReserve(DWORD) ;初始化时保留的堆大小
SizeOfHeapCommit(DWORD) ;初始化时实际提交的堆大小
LoaderFlags(DWORD) ;与调试有关
NumberOfRvaAndSizes(DWORD) ;下面的数据目录结构的项目数量
IMAGE_DATA_DIRECTORY(16) ;数据目录
IMAGE_DATA_DIRECTORY
1.该字段定义了PE文件中出现的所有不同类型的数据的目录信息
VirtualAddress(DWORD) ;数据的起始RVA
isize(DWORD) ;数据块的长度
IMAGE_SECTION_HEADER :节表
1.每个节表项记录了PE中与某个特定的节有关的信息
Name1(db IMAGE_SIZEOF_SHORT_NAME) ;8个字节的节名
union Misc
PhysicalAddress(dd)
VirtualSize(dd) ;节区的尺寸
ends
VirtualAddress(dd) ;节区的RVA地址
SizeOfRawData(dd) ;在文件中对齐后的尺寸
PointerToRawData(dd) ;在文件中的偏移
PointerToRelocations(dd) ;在OBJ文件中使用
PointerToLinenumbers(dd) ;行号表的位置(供调试用)
NumberOfRelocations(dw) ;在OBJ文件中使用
NumberOfLinenumbers(dw) ;行号表中行号的数量
Characteristics(dd) ;节的属性