文件头_PE文件格式(文件头)

0641a59e58b0e7c2ed711907f17dde95.gif

PE文件是Windows操作系统下使用的可执行文件的格式,可执行系列:EXE、SCR,库系列:DLL、OCX、CPL、DRV,驱动程序:SYS、VXD 等都是PE文件


在Windows系统中,PE文件被系统加载器映射到内存中,每一个程序都有自己的虚拟空间,这个虚拟空间的内存地址称为虚拟地址(Virtual Address\VA)


相对虚拟地址(Relative Virtual Address\RVA)是一个简单的,相对于PE文件载入地址的偏移位置,它是一个相对的地址(偏移)
当PE文件在磁盘中时,某个数据位置相对于文件头的偏移量称为文件偏移地址(File Offset)
所有PE文件以64字节DOS头开始,DOS头只是为了兼容早期操作系统32f9532e7187dafc8a959bdfe4794aa1.png 
e_magic:0x5A4D,MZ标志


e_lfanew:0x000000E8,NT头偏移量cf3ef29bbebc8abc896a8a564e91d94b.png 
#define IMAGE_DOS_SIGNATURE         0x5A4D      // MZ
这里采用的小端序存储数据,地址高位存储数据的高位,地址低位存储数据的低位,是一种逆序存储方式
000000E8就是NT头的位置,与DOS头之间隔了一段DosStub数据,这个数据是可变的,所以需要e_lfanew来指定NT头的位置56a15d0642dc1cdd38f52a2fd40cc9b7.png 
NT头定义如下

typedef struct _IMAGE_NT_HEADERS {    DWORD Signature;        // PE标识    IMAGE_FILE_HEADER FileHeader;        //文件头    IMAGE_OPTIONAL_HEADER32 OptionalHeader;        //可选头} IMAGE_NT_HEADERS32, *PIMAGE_NT_HEADERS32;Signature类型为DWORD,占用4个字节#define IMAGE_NT_SIGNATURE           0x00004550   // PE00

73e87a146785d58f26db34967a323ed5.png 
文件头是表示文件大致属性的IMAGE_FILE_HEADER结构体

typedef struct _IMAGE_FILE_HEADER {    WORD    Machine;        // 2个字节,指明支持的CPU类型    WORD    NumberOfSections;        // 2个字节,指明节区数量    DWORD   TimeDateStamp;                // 4字节,编译器生成这个PE文件的时间    DWORD   PointerToSymbolTable;        // 4字节,调试符号相关,不作研究    DWORD   NumberOfSymbols;        // 4字节,调试符号相关,不作研究    WORD    SizeOfOptionalHeader;        // 2个字节,指明可选头 IMAGE_OPTIONAL_HEADER32 大小    WORD    Characteristics;        // 2个字节,表明文件属性,如DLL文件,SYS文件等} IMAGE_FILE_HEADER, *PIMAGE_FILE_HEADER;IMAGE_OPTIONAL_HEADER32是PE头结构体中最大的,定义如下typedef struct _IMAGE_OPTIONAL_HEADER {    //    // Standard fields.    //    WORD    Magic;        // 普通可执行文件为0x010B,PE32 (64位)值为0x020B    BYTE    MajorLinkerVersion;    BYTE    MinorLinkerVersion;    DWORD   SizeOfCode;        // 代码区块的大小,通常是.text区块大小    DWORD   SizeOfInitializedData;    DWORD   SizeOfUninitializedData;    DWORD   AddressOfEntryPoint;        // 程序入口点,RVA值    DWORD   BaseOfCode;        // 代码段的起始地址,RVA值,通常是.text区块的起始RVA    DWORD   BaseOfData;        // 数据段的起始地址,RVA值,通常是.data区块的起始RVA    //    // NT additional fields.    //    DWORD   ImageBase;                // PE文件在内存中首选的装载基地址    DWORD   SectionAlignment;        // PE文件装载到内存时区块的对齐大小,假设.text区块的大小为0x7748,而SectionAlignment的大小为0x1000,那么对齐后的大小为0x8000字节    DWORD   FileAlignment;                // 磁盘上PE文件中区块的对齐大小,对齐方式类似SectionAlignment    WORD    MajorOperatingSystemVersion;    WORD    MinorOperatingSystemVersion;    WORD    MajorImageVersion;    WORD    MinorImageVersion;    WORD    MajorSubsystemVersion;    WORD    MinorSubsystemVersion;    DWORD   Win32VersionValue;    DWORD   SizeOfImage;        // PE文件被装载到内存空间后总的大小,指从ImageBase到最后一个区块的大小    DWORD   SizeOfHeaders;                // Dos头、DosStub、PE头以及区块头的总大小,并进行FileAlignment对齐后的大小    DWORD   CheckSum;        // 校验和,一般的EXE文件通常为0,判断文件是否被修改    WORD    Subsystem;                // 子系统,区分系统驱动文件与普通可执行文件    WORD    DllCharacteristics;    DWORD   SizeOfStackReserve;    DWORD   SizeOfStackCommit;    DWORD   SizeOfHeapReserve;    DWORD   SizeOfHeapCommit;    DWORD   LoaderFlags;    DWORD   NumberOfRvaAndSizes;        // 指定最后一个成员是数组个数    IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES];} IMAGE_OPTIONAL_HEADER32, *PIMAGE_OPTIONAL_HEADER32;


写一个程序,关掉随机基址78e6608300228810fb987193da12e0ea.png f7b9879afdc3456d325659f59f7172e1.png 
AddressOfEntryPoint是一个RVA值,所以当程序实际被加载到内存时,对应的入口点地址的虚拟地址

(VA) = ImageBase+AddressOfEntryPoint = 0x00400000+0x000012DA = 0x004012DA9ca0d752edd903a5df5aee752947b81a.png 
子系统查看0393061adfdb2c98d0b4a3734c9018bf.png 
SizeOfImage验证
DWORD   SizeOfImage;     

 // PE文件被装载到内存空间后总的大小,指从ImageBase到最后一个区块的大小28315bf704c6bc0f528bc3d612e790d1.png bf4e631e103e5709f8efaecc3b67005b.png 
OPTIONAL_HEADER末尾是一个数据目录表数组,数组元素个数为16
各元素对应表项:

288824e25d63b8d49f789262d2c9206a.png 
IMAGE_DATA_DIRECTORY定义如下:

typedef struct _IMAGE_DATA_DIRECTORY {    DWORD   VirtualAddress;        // 数据块的起始RVA地址    DWORD   Size;                // 数据块的长度} IMAGE_DATA_DIRECTORY, *PIMAGE_DATA_DIRECTORY;

1668ee1c6b7cb00e34752c7438a3a1e6.png b85271d70be4df1f95b56710848b90dc.png 34c5eb92c3798afa9ec304d95878deee.png

c6638c2d9dcf4a45c5a9a82e05fc5c3d.png

a015eac79acbc2e3bad27c0644f63f1d.png

cfe2944d49e73e8fb07271e9ede02ea8.gif

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值