一丶节表信息,PE两种状态.以及重要两个成员解析.数组
肯定节表位置: DOS + NT头下面就是节表.spa
肯定节表数量: 节表数量在文件头中存放着.能够准确知道节表有多少个.调试
节表是一个结构体数组.没一个节表表示了数据在哪,怎么存储.code
下方是节的结构体blog
typedef struct _IMAGE_SECTION_HEADER { BYTE Name[IMAGE_SIZEOF_SHORT_NAME]; //8个字节名字.本身能够起.编译器也能够给定.不重要. union { DWORD PhysicalAddress; DWORD VirtualSize; //节数据没有对齐后的大小.也就是没有对齐.节数据有多大. } Misc; DWORD VirtualAddress; //加载到内存中的第一个字节的地址.也就是虚拟地址.节在内存中哪里开始.内存中的VA + ImageBase 才是真正的节开始位置 DWORD SizeOfRawData; //节在文件中对齐后的属性.跟是可选头中文件对齐的整数倍. sizeofRawData /文件对齐==0 DWORD PointerToRawData; //在文件中的偏移.是文件对齐成员倍数. DWORD PointerToRelocations; //一下都是调试相关. DWORD PointerToLinenumbers; // WORD NumberOfRelocations; WORD NumberOfLinenumbers; DWORD Characteristics; //节的属性 } IMAGE_SECTION_HEADER, *PIMAGE_SECTION_HEADER;
节表重要成员都标红了.咱们知道.PE文件有两种状态.一种是内存状态.一种则是文件状态.内存
而节就是分别保存了内存中节展开的位置偏移. 以及文件展开后.节数据在文件中的那个偏移位置.编译器
1.内存中节开始的位置io
咱们分别以PE两种状态.来加深一下.在内存中跟文件中节数据起始位置.编译
VirtualAddress 是内存中节展开的起始地址.咱们能够随便打开一个文件.查看内存中起始位置值是多少.class
随便打开一个文件看一下节表.能够得出.内存中偏移位置是0x1000位置.文件中节数据的位置是0x400. 偏移+ImageBase就是内存中开始的位置.咱们看一下.
能够看到机器码为: 40 30 40 00 90 ..... 那么咱们去文件中看一下,看一下节数据是否相同.
2.文件中节开始的位置
根据上方咱们观看节表.得出在文件中的偏移是0x400位置.因此跳转到文件偏移处.发现节数据跟内存的数据是同样的.
这也解释了PE在内存中展开跟在文件中是不同的.
也加深了节表中 VirtualAddress成员 以及 PointerToRawData成员了.
值得一说节表的大小是 0x28个字节.也就是两行半
观看一行半能够得出节名称.节在内存中的偏移. 以及节数据在文件中的偏移.
二丶节成员解析
根据上方节中两个重要成员咱们明白了其意思.那么咱们看看其余成员.
联合体中的成员.
联合体中的成员咱们通常看第二个.
union { DWORD PhysicalAddress; DWORD VirtualSize; //节数据没有对齐后的大小.也就是没有对齐.节数据有多大. } Misc;
VirtualSize 虚拟大小.指的就是节数据没有对齐后的大小.
换句话说就是节的数据真实大小. 可是注意,若是此成员大于SizeofRawData.那么就填0.由于实际大小数据.不可能大于对齐后的大小.
SizeOfRawData 这个成员则是对齐后的大小.好比咱们节数据大小是0x1FFC 那么对齐后的大小就是0x2000 就是按照对齐以后进行存放的.对齐是按照文件对齐进行对齐的.
根据文件对齐后的大小.那么咱们就能肯定一个节数据到底由多大.
文件中开始的位置已经有了.而后对齐后的大小也已经有了. 文件开始位置是0x400.对齐后的数据有0x2000.那么节数据大小就是从0x400开始.占0x2000大小.那么结束位置就是0x2400位置.
节的属性.也就是最后一个成员.代表了这个节是可读的可写的.仍是可读可写可执行. 具体能够查看一下宏.
三丶总结
总结来讲节表中重要成员有三个.
1.内存中起始位置
2.节数据对齐后大小
3.文件中起始位置.
根据第二个成员和第三个成员能够得出节数据从哪里结束. 计算公式 节起始位置+节数据对齐后大小 = 节结束位置.
节属性也很重要. 这个须要查询.因此必定牢记.