-
十一 21
紧接着上一节,我们来研究下IMAGE_OPTIONAL_HEADER32,这个属于PE中附加结构信息,同样是很重要的。
我们先来看看它的结构:
typedef struct _IMAGE_OPTIONAL_HEADER { // // Standard fields. // 00h WORD Magic; //幻数,32位pe文件总为010bh 02h BYTE MajorLinkerVersion; //连接器主版本号 03h BYTE MinorLinkerVersion; //连接器副版本号 04h DWORD SizeOfCode; //代码段总大小 08h DWORD SizeOfInitializedData; //已初始化数据段总大小 0ch DWORD SizeOfUninitializedData; //未初始化数据段总大小 10h DWORD AddressOfEntryPoint; //程序执行入口地址(RVA) 14h DWORD BaseOfCode; //代码段起始地址(RVA) 18h DWORD BaseOfData; //数据段起始地址(RVA) // // NT additional fields. // 1ch DWORD ImageBase; //程序默认的装入起始地址 20h DWORD SectionAlignment; //内存中区块的对齐单位 24h DWORD FileAlignment; //文件中区块的对齐单位 28h WORD MajorOperatingSystemVersion; //所需操作系统主版本号 2ah WORD MinorOperatingSystemVersion; //所需操作系统副版本号 2ch WORD MajorImageVersion; //自定义主版本号 2eh WORD MinorImageVersion; //自定义副版本号 30h WORD MajorSubsystemVersion; //所需子系统主版本号 32h WORD MinorSubsystemVersion; //所需子系统副版本号 34h DWORD Win32VersionValue; //总是0 38h DWORD SizeOfImage; //pe文件在内存中的映像总大小 3ch DWORD SizeOfHeaders; //从pe文件开始到节表(包含节表)的总大小 40h DWORD CheckSum; //pe文件CRC校验和 44h WORD Subsystem; //用户界面使用的子系统类型 46h WORD DllCharacteristics; //为0 48h DWORD SizeOfStackReserve; //为线程的栈初始保留的虚拟内存的默认值 4ch DWORD SizeOfStackCommit; //为线程的栈初始提交的虚拟内存的大小 50h DWORD SizeOfHeapReserve; //为进程的堆保留的虚拟内存的大小 54h DWORD SizeOfHeapCommit; //为进程的堆初始提交的虚拟内存的大小 58h DWORD LoaderFlags; //为0 5ch DWORD NumberOfRvaAndSizes; //数据目录结构数组的项数,总为 00000010h 60h IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_E***IES]; //数据目录结构数组 } IMAGE_OPTIONAL_HEADER32, *PIMAGE_OPTIONAL_HEADER32;
这个结构体非常的庞大,大家通过注释可以看出,这个结构体保存了相当全面的PE附件信息。
下面针对重要内容进行一个解释:
Magic 幻数,32位pe文件总为010bh
这个常数的定义如下:
#define IMAGE_NT_OPTIONAL_HDR32_MAGIC 0x10b
#define IMAGE_NT_OPTIONAL_HDR64_MAGIC 0x20b
#define IMAGE_ROM_OPTIONAL_HDR_MAGIC 0x107
MajorLinkerVersion 连接程序的主版本号 如vc6.0的为06h
MinorLinkerVersion 连接程序的次版本号 如vc6.0的为00h
SizeOfCode pe文件代码段的大小.是FileAlignment的整数倍.
SizeOfInitializedData 所有含已初始化数据的块的大小,一般在.data段中.
SizeOfUninitializedData 所有含未初始化数据的块的大小,一般在.bss段中.
AddressOfEntryPoint 程序开始执行的地址,这是一个RVA(相对虚拟地址).对于exe文件,这里是启动代码;对于dll文件,这里是libMain()的地址.
在脱壳时第一件事就是找入口点,指的就是这个值.
BaseOfCode 代码段基地址,微软的连接程序生成的程序一般把这个值置为1000h,
BaseOfData 数据段基地址
ImageBase pe文件默认的装入地址.windows9x中exe文件为400000h,dll文件为10000000h.
SectionAlignment 内存中区块的对齐单位.区块总是对齐到这个值的整数倍.x86的32位系统上默认值位1000h
FileAlignment pe文件中区块的对齐单位.pe文件中默认值为 200h.
MajorOperatingSystemVersion
MinorOperatingSystemVersion
上面两个域是指运行这个pe文件所需的操作系统的最低版本号.windows95/98和windows nt 4.0 的内部版本号都是 4.0 ,而windows2000的内部版本号是5.0
MajorImageVersion
MinorImageVersion
上面两个域是指用户自定义的pe文件的版本号.可以通过连接程序来设置,如: LINK /VERSION:2.0 MyApp.obj一般在升级时使用.
MajorSubsystemVersion
MinorSubsystemVersion
上面两个域是指运行这个pe文件所要求的子系统的版本号.
Win32VersionValue 总是0
SizeOfImage pe文件装入内存后映像的总大小.如果SectionAlignment域和FileAlignment域相等,那么这个值也是pe文件在硬盘上的大小.
SizeOfHeaders 从文件开始到节表(包含节表)的总大小.其后是各个区段的数据.
CheckSum pe文件的CRC校验和.
Subsystem pe文件的用户界面使用的子系统类型.定义如下:#define IMAGE_SUBSYSTEM_UNKNOWN 0 // Unknown subsystem.
#define IMAGE_SUBSYSTEM_NATIVE 1 // Image doesn't require a subsystem.
#define IMAGE_SUBSYSTEM_WINDOWS_GUI 2 // Image runs in the Windows GUI subsystem.
#define IMAGE_SUBSYSTEM_WINDOWS_CUI 3 // Image runs in the Windows character subsystem.
#define IMAGE_SUBSYSTEM_OS2_CUI 5 // image runs in the OS/2 character subsystem.
#define IMAGE_SUBSYSTEM_POSIX_CUI 7 // image runs in the Posix character subsystem.
#define IMAGE_SUBSYSTEM_NATIVE_WINDOWS 8 // image is a native Win9x driver.
#define IMAGE_SUBSYSTEM_WINDOWS_CE_GUI 9 // Image runs in the Windows CE subsystem.
DllCharacteristics 总为0
SizeOfStackReserve 为线程的栈初始保留的虚拟内存的大小,默认为00100000h.如果在调用CreateThread函数时指定堆栈的大小为0,被创建的线程的堆栈的初始大小就与这个值相同.
SizeOfStackCommit 为线程的栈初始提交的虚拟内存的大小.微软的连接程序把这个值置为 1000h.
SizeOfHeapReserve 为进程的堆保留的虚拟内存的大小.默认值为 00100000h.
SizeOfHeapCommit 为进程的堆初始提交的虚拟内存的大小.微软的连接程序把这个值置为1000h.
LoaderFlags 通常为0
NumberOfRvaAndSizes 数据目录结构数组的项数,总为 00000010h
这个值定义如下:
#define IMAGE_NUMBEROF_DIRECTORY_E***IES 16
IMAGE_DATA_DIRECTORY DataDirectory[0x10] 数据目录结构数组
IMAGE_DATA_DIRECTORY结构定义如下:typedef struct _IMAGE_DATA_DIRECTORY { DWORD VirtualAddress;// 相对虚拟地址 DWORD Size; //大小 } IMAGE_DATA_DIRECTORY, *PIMAGE_DATA_DIRECTORY;
这个结构包含了pe文件中重要部分的RVA地址和大小.这个数组使操作系统的加载程序能够快速定位特定的区段.具体定义如下:#define IMAGE_DIRECTORY_E***Y_EXPORT 0 // Export Directory
#define IMAGE_DIRECTORY_E***Y_IMPORT 1 // Import Directory
#define IMAGE_DIRECTORY_E***Y_RESOURCE 2 // Resource Directory
#define IMAGE_DIRECTORY_E***Y_EXCEPTION 3 // Exception Directory
#define IMAGE_DIRECTORY_E***Y_SECURITY 4 // Security Directory
#define IMAGE_DIRECTORY_E***Y_BASERELOC 5 // Base Relocation Table
#define IMAGE_DIRECTORY_E***Y_DEBUG 6 // Debug Directory
// IMAGE_DIRECTORY_E***Y_COPYRIGHT 7 // (X86 usage)
#define IMAGE_DIRECTORY_E***Y_ARCHITECTURE 7 // Architecture Specific Data
#define IMAGE_DIRECTORY_E***Y_GLOBALPTR 8 // RVA of GP
#define IMAGE_DIRECTORY_E***Y_TLS 9 // TLS Directory
#define IMAGE_DIRECTORY_E***Y_LOAD_CONFIG 10 // Load Configuration Directory
#define IMAGE_DIRECTORY_E***Y_BOUND_IMPORT 11 // Bound Import Directory in headers
#define IMAGE_DIRECTORY_E***Y_IAT 12 // Import Address Table
#define IMAGE_DIRECTORY_E***Y_DELAY_IMPORT 13 // Delay Load Import Descriptors
#define IMAGE_DIRECTORY_E***Y_COM_DESCRIPTOR 14 // COM Runtime descriptor
通过上一节的例子。我们也依旧可以从这个结构体中读出需要的信息.


- 评论(0)
发表评论 TrackBack
◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。