0x00 前言
在没有接触壳之前,也不着急着做什么练习,PE文件格式还是要学一学的。
0x01 正文
1.VA&RVA
VA:进程虚拟内存的绝对地址
RVA:相对虚拟地址。从某个基准位置(ImageBase)开始的相对地址
公式:RVA+ImageBase=VA
PS:
32位Windows中,进程分配有4GB虚拟内存,因此进程中的VA范围是00000000~FFFFFFFF
2.PE头
2.1 DOS头
IMAGE_DOS_HEADER
在微软创建PE文件格式的时候,正在广泛使用DOS文件,所以考虑到对DOS文件的兼容性,于是在PE头的最前面添加了一个IMAGE_DOS_HEADER结构体,用来扩展已有的DOS EXE头。
IMAGE_DOS_HEADER结构体大小为40个字节。
python中有一个专门用来解析PE的库。
其中最为重要的有两个
一个是magic还有一个是Ifanew
magic:DOS签名,默认值MZ
ifanew:指示NT头的偏移,简单的说就是指向NT头所在的位置。
2.2 DOS存根
DOS存根在DOS头下放,是一个可选项,且大小不固定。
直白的说就是为了兼容DOS环境下运行。
2.3 NT头
IMAGE_NT_HEADERS里有三个成员变量
signature签名 值为PE
2.3.1 NT头 文件头
IMAGE_FILE_HEADERS结果题有四个重要成员。
Machine
唯一Machine码,兼容32位Intel x86芯片的Machine码为14C。
NumberOfSections
NumberOfSections用来支出文件中存在的节区数量,该数值一定要大于0。如果和实际节数不同则运行出错
SizeOfOptionalHeader
用来指出IMAGE_OPTIONAL_HEADER3结构体的长度。
Characteristics
该字段用于表示文件的属性,文件是否是可运行状态,是否为DLL,文件等信息。
0002h,不可执行。
2.3.2 NT头:可选头
IMAGE_OPTIONAL_HEADER
重要字典
Magic:
32位为Magic码为10B
64位为20B
AddressOfEntryPoint:
AddressOfEntryPoint持有PE的RVA值。指出程序最先执行的代码起始地址。
程序的相对起始位置。
使用OD进行查看
ImageBase:
进程虚拟内存的范围是0~FFFFFFFF。
EXE,DLL文件被装载到用户内存的07FFFFFFF中,SYS文件被载入内和内存的80000000FFFFFFFF。
VB/VC++?Delphi 创建好EXE文件后,ImageBase的值为00400000。DLL为1000000
PE装载器先创建进程,再将文件载入内存,然后把EIP寄存器的值设置为ImageBase+AddressOfEntryPoint
SectionAlignment,FileAlignment:
PE文件的Body部分划分为若干节区,这些节存储着不同类别的数据。FileAlignment指定了截取在磁盘文件中的最小单位,SectionAlignment制定了截取中的最小单位。
自盘文件或内存的截取大小必定为FileAligment或SectionAlignment值的整数倍
SizeOfImage:
加载PE文件到内存时,SizeOfImage指定了PE Image在虚拟内存中所占空间的大小。一般而言,文件的大小与加载到内存中的大小是不同的。
SizeOfHeader:
SizeOfHeader用来指出整个PE头的大小。值是FileAlignment的整数倍,第一节区所在位置与SizeOfHeader距文件开始偏移的量相同。
Subsystem:
区分系统驱动文件语普通的可执行文件。
DataDorectory:
由IMAGE_DATA_DIRECTORY结构体组成的数组。
2.4 节区头
节区头定义了各节区属性。
code:代码
data:数据
resource:资源
2.5 RVA to RAW
1.查找RVA的节区
2。使用公式计算文件偏移
RAW-PointerToRawData=RVA-VirtualAddress
2.6 IAT
IAT是一种表格,用来记录程序正在使用哪些库的哪些函数
5.7 DLL
动态链接库
5.7.1 加载DLL的方式
显式链接:程序使用DLL时进行加载,使用完毕之后释放内存。
隐式链接:程序开始一桶加载DLL,程序终止释放占用的内存。