重读PE文件(2)

上一篇讲到_IMAGE_OPTIONAL_HEADER 结构了,结构的定义如下:
代码
typedef struct _IMAGE_OPTIONAL_HEADER {
    
//
    
// 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 ,这个字段的定义如下:

typedef struct _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个字段要写的内容很多,下篇再写了:)

posted @ 2010-04-01 16:47  认真做人,认真做事  阅读(474)  评论(0编辑  收藏  举报