扩展头解析
typedef struct _IMAGE_OPTIONAL_HEADER {
//
// Standard fields.
WORD Magic; //选项头类型,一般为10BH
BYTE MajorLinkerVersion; //链接程序的主版本号 可修改
BYTE MinorLinkerVersion; //链接程序的次版本号 可修改
DWORD SizeOfCode; //代码段大小 可以吃内存 改大 可修改
DWORD SizeOfInitializedData; //已初始化数据块的大小 可修改
DWORD SizeOfUninitializedData; //未初始化数据库的大小 可修改
DWORD AddressOfEntryPoint; //程序开始执行的入口地址,这是一个RVA(相对虚拟地址)
DWORD BaseOfCode; //代码段的起始RVA 一般来说 是 1000h 说明性信息 可参考不可 基址00401000
DWORD BaseOfData; //数据段的起始RVA 说明性信息 可参考不可信 数据 00402000
//
// NT additional fields.
DWORD ImageBase; //可执行文件默认装入的基地址 起点 建议装在地址非实际 可更改代价大
DWORD SectionAlignment; //内存中块的对齐值(默认的块对齐值为1000H,4KB个字节) 可更改 按照操作系统特性改 以千为单位
DWORD FileAlignment;//文件中块的对齐值(默认值为200H字节,为了保证块总是从磁盘的扇区开始的)
WORD MajorOperatingSystemVersion;//要求操作系统的最低版本号的主版本号
WORD MinorOperatingSystemVersion;//要求操作系统的最低版本号的次版本号
WORD MajorImageVersion;//该可执行文件的主版本号
WORD MinorImageVersion;//该可执行文件的次版本号
WORD MajorSubsystemVersion;//要求最低之子系统版本的主版本号 默认 0004 不可更改
WORD MinorSubsystemVersion;//要求最低之子系统版本的次版本号 默认 0000
DWORD Win32VersionValue;//保留字 默认00000000
DWORD SizeOfImage;//映像装入内存后的总尺寸 映像到内存1000 内存对齐的设定
DWORD SizeOfHeaders;//部首及块表的总大小
DWORD CheckSum;//CRC检验和 一般为00000000
WORD Subsystem;//程序使用的用户接口子系统
WORD DllCharacteristics;//DLLmain函数何时被调用,默认为0
DWORD SizeOfStackReserve;//初始化时栈大小
DWORD SizeOfStackCommit;//初始化时实际提交的栈大小
DWORD SizeOfHeapReserve;//初始化时保留的堆大小
DWORD SizeOfHeapCommit;//初始化时实际提交的堆大小
DWORD LoaderFlags;//与调试有关,默认为0
DWORD NumberOfRvaAndSizes;//数据目录结构的数目
IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES];
}
重点字段解析:
WORD magic:标志是什么类型的PE文件,32位一般是0x010B,64位文件是0x20B
DWORD AddressOfEntryPoint:就是我们常说的OEP 第一行执行代码的地方
DWORD ImageBase; 程序装载到内存的地址 文件默认00400000 我们理想的装载地址 但是可能装载不到
DWORD SizeOfImage;装载到内存的大小 一个页占0x1000 假设有3个节表加头的大小也就是0x4000
可选头-二进制
代码解析-可选头
假设已经把PE文件读到内存中 首地址是file_buff 是void*指针
PIMAGE_DOS_HEADER dos_head = PIMAGE_DOS_HEADER(file_buff);
PIMAGE_NT_HEADERS nt_head =
PIMAGE_NT_HEADERS(dos_head->e_lfanew + (LONG)file_buff);
// 获取扩展头
PIMAGE_OPTIONAL_HEADER opt_head =
PIMAGE_OPTIONAL_HEADER(&nt_head->OptionalHeader);