重读PE文件(2)

//
// Standard fields.
//
WORD Magic;//10Bh=exe Image
BYTE MajorLinkerVersion;//链接器版本号
BYTE MinorLinkerVersion;
DWORD SizeOfCode;//所有含代码的节的总大小
DWORD SizeOfInitializedData;//所有含已初始化数据的节的总大小
DWORD SizeOfUninitializedData;//所有含未初始化数据的节的大小
DWORD AddressOfEntryPoint;//程序执行入口RVA
DWORD BaseOfCode;//代码的节的起始RVA
DWORD BaseOfData;//数据的节的起始RVA
//
// NT additional fields.
//
DWORD ImageBase;//程序的建议装载地址
DWORD SectionAlignment;//内存中的节的对齐粒度
DWORD FileAlignment;//文件中的节的对齐粒度
WORD MajorOperatingSystemVersion;//操作系统主版本号
WORD MinorOperatingSystemVersion;//操作系统副版本号
WORD MajorImageVersion;//可运行于操作系统的最小版本号
WORD MinorImageVersion;//
WORD MajorSubsystemVersion;//可运行于操作系统的最小子版本号
WORD MinorSubsystemVersion;
DWORD Win32VersionValue;
DWORD SizeOfImage;//内存中整个PE映像尺寸
DWORD SizeOfHeaders;//所有头+节表的大小
DWORD CheckSum;//
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;
Magic字段,从名字就能看出来功能,是个标志字段,如果当前PE文件是可执行文件,其值应该为10B,不过据我的观察,有些DLL文件此值也是10B,但是有些DLL是另外的值,不清楚是怎么回事
MajorLinkerVersion~BaseOfData字段,这些字段中能够影响程序运行的只有AddressOfEntryPoint,其余的字段值即使改动了程序好像也还是能正确运行,但是只要AddressOfEntryPoint改动了,程序的入口就会改变
ImageBase字段,程序的建议装载地址,这个值还是不要乱改的好,改了以后不光程序不能正常运行,而且进程还结束不掉,我连icesword也用上了,就是死活不行,杯具
SectionAlignment和FileAlignment,一个表示的是内存中节的对齐粒度,一个表示的是文件中(即磁盘中)的对齐粒度,这个地方稍微有点难懂,我们可以想象,比如一段数据长度为7748(随便给的),内存对齐粒度为1000,文件对齐粒度为200,那么这么长的一段数据在磁盘中和在内存中占用的空间是不一样的,在内存中占用的空间可以计算如下,7748/1000,商为7,余数为748,那么其占用的空间为(7+1)×1000=8000,其中有1000-748=8B8字节空间的浪费,在磁盘中占用的空间计算如下:7748/200,商为3B,余数为148,那么占用空间为(3B+1)×200=7800,浪费的空间为200-148=B8字节,事实上,在后面的节表中,我们可以验证我们的计算是正确的SizeOfImage
SizeOfImage,内存中整个映像文件的尺寸,其大小等于最后一个节的RVA+节大小,很好理解,这个值也不能乱改,改了就杯具
SizeOfHeaders,所有头和节表的大小,这个大小比所有头和节表的大小大,而且这个值改动的话程序就出错了,我改了,又杯具了,这个值的大小和第一个节在文件中的偏移是一致的
NumberOfRvaAndSizes,这个值始终为10,任何文件中都不会变
下面就来到PE头中最重要的一个字段了,IMAGE_DATA_DIRECTORY ,这个字段的定义如下:
DWORD VirtualAddress;//数据的起始RVA
DWORD Size;//数据块的长度
} IMAGE_DATA_DIRECTORY, *PIMAGE_DATA_DIRECTORY;
IMAGE_DATA_DIRECTORY 字段共有16个,每一个代表的意义如下:
0: IMAGE_DIRECTORY_ENTRY_EXPORT- 导出表
1: IMAGE_DIRECTORY_ENTRY_IMPORT- 导入表
2: IMAGE_DIRECTORY_ENTRY_RESOURCE- 资源
3: IMAGE_DIRECTORY_ENTRY_EXCEPTION- 异常(具体资料不详)
4: IMAGE_DIRECTORY_ENTRY_SECURITY- 安全(具体资料不详)
5: IMAGE_DIRECTORY_ENTRY_BASERELOC- 重定位表
6: IMAGE_DIRECTORY_ENTRY_DEBUG- 调试信息
7: IMAGE_DIRECTORY_ENTRY_ARCHITECTURE -版权信息
8: IMAGE_DIRECTORY_ENTRY_GLOBALPTR -具体资料不详
9: IMAGE_DIRECTORY_ENTRY_TLS- Thread Local Storage
10: IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG- 具体资料不详
11: IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT- 具体资料不详
12: IMAGE_DIRECTORY_ENTRY_IAT- 导入函数地址表
13: IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT- 具体资料不详
14: IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR- 具体资料不详
15: 未使用
很晕,一堆具体资料不详的,很郁闷,很鄙视微软,这16个字段的值不能随意修改,改错了程序就完蛋了
这16个字段要写的内容很多,下篇再写了:)