PE:
在winNT.h的image format定义
PE文件映射到内存的映射比例规则形成虚拟地址
Win API:HMODULE GetModulleHandle(LPCTSTR IpModuleName)
句柄获取PE基地址
PE文件结构:
.text:指令代码
rdata:只读数据
data:初始化数据块
idata:包含其他外来DLL函数及数据信息(即输入表)
rsrc:全部资源
不同块在磁盘和内存中空隙部分填充大小不一样
PE优点:在磁盘上的数据结构与在内存中的结构一致
加壳:在磁盘中PE文件结构加密使其混乱,但是在内存中要执行时恢复
PE相关名词:
入口点:oep(original entry point)
文件偏移地址:存储在磁盘上的pe各数据地址
虚拟地址(VA):逻辑地址,由于windows保护机制
段选择子:虚拟地址
基地址:vc++建立的exe文件基地址默认00400000h
dll文件基地址:10000000h
工具:PE Editor
结构如图:
在winnt.h中的定义:
//dos头部 _IMAGE_DOS_HEADER
(EA) typedef struct _IMAGE_DOS_HEADER { // DOS .EXE header
+0h WORD e_magic; // Magic number //DOS可执行文件标记 存放2个字节MZ(4Dh 5Ah)
WORD e_cblp; // Bytes on last page of file
WORD e_cp; // Pages in file
WORD e_crlc; // Relocations
WORD e_cparhdr; // Size of header in paragraphs
WORD e_minalloc; // Minimum extra paragraphs needed
WORD e_maxalloc; // Maximum extra paragraphs needed
WORD e_ss; // Initial (relative) SS value
WORD e_sp; // Initial SP value
WORD e_csum; // Checksum
WORD e_ip; // Initial IP value
WORD e_cs; // Initial (relative) CS value
WORD e_lfarlc; // File address of relocation table
WORD e_ovno; // Overlay number
WORD e_res[4]; // Reserved words
WORD e_oemid; // OEM identifier (for e_oeminfo)
WORD e_oeminfo; // OEM information; e_oemid specific
WORD e_res2[10]; // Reserved words
+3Ch LONG e_lfanew; // File address of new exe header //指向PE文件头 32位指针(记载PE开始地址)
} IMAGE_DOS_HEADER, *PIMAGE_DOS_HEADER;
//PE文件头 _IMAGE_NT_HEADER
PNTHeader=ImageBase + dosHeader->e_lfanew
typedef struct _IMAGE_NT_HEADER {
+0h DWORD Signature; //Signature PE标志位 PE..(4550h):开始
+4h IMAGE_FILE_HEADER FileHeader; //包含文件结构体
+18h IMAGE_OPTIONAL_HEADER OptionalHeader;
} IMAGE_NT_HEADER, *PIMAGE_NT_HEADER;
//文件结构体 _IMAGE_FILE_HEADER
typedef struct _IMAGE_FILE_HEADER {
WORD Machine; //运行平台
WORD NumberOfSections; //文件区块数目
DWORD TimeDateStamp; //文件创建日期和时间
DWORD PointerToSymbolTable;//指向符号表(用于调试)
DWORD NumberOfSymbols;
WORD SizeOfOptionalHeader; //记载IMAGE_OPTIONAL_HEADER32结构大小(32位:00E0h,64位00F0h)
WORD Characteristics; //文件属性
} IMAGE_FILE_HEADER, *PIMAGE_FILE_HEADER;
//PE文件增强结构 _IMAGE_OPTIONAL_HEADER
typedef struct _IMAGE_OPTIONAL_HEADER {
//
// Standard fields. //标准部分
//
WORD Magic;
BYTE MajorLinkerVersion;
BYTE MinorLinkerVersion;
DWORD SizeOfCode;
DWORD SizeOfInitializedData;
DWORD SizeOfUninitializedData;
+28h DWORD AddressOfEntryPoint; //程序执行入口 病毒修改该地址
DWORD BaseOfCode;
DWORD BaseOfData;
//
// NT additional fields. //添加部分
//
DWORD ImageBase; //程序首选装载地址 由windows装载器装载 exe在vc++默认00400000h /dll为10000000h(高)
+38h DWORD SectionAlignment; //内存中区块对齐大小 默认1000h(即在磁盘中一页对齐大小)内存中分页机制
+3ch DWORD FileAlignment; //文件中区块对齐大小 默认200h (即在磁盘中一页对齐大小)磁盘分页机制
WORD MajorOperatingSystemVersion;
WORD MinorOperatingSystemVersion;
WORD MajorImageVersion;
WORD MinorImageVersion;
WORD MajorSubsystemVersion;
WORD MinorSubsystemVersion;
DWORD Win32VersionValue;
DWORD SizeOfImage;
DWORD SizeOfHeaders;
DWORD CheckSum;
WORD Subsystem; //界面子系统(驱动程序/图形界面/控制台):程序类型
WORD DllCharacteristics;
DWORD SizeOfStackReserve;
DWORD SizeOfStackCommit;
DWORD SizeOfHeapReserve;
DWORD SizeOfHeapCommit;
DWORD LoaderFlags;
DWORD NumberOfRvaAndSizes;
+78h IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES];//数据目录表(数组:16项)
//本结构包括2个部分:起始地址+长度
//导入表 导出表 资源....
} IMAGE_OPTIONAL_HEADER32, *PIMAGE_OPTIONAL_HEADER32;
PE文件到内存的映射
windows装载器在装载DOS部分、PE文件头和区块表部分时不进行任何处理,而在装载区块自动按区块不同属性做不同处理
处理以下几个方面的内容:
1.内存页的属性 (如:只读/写)
2.区块的偏移地址 //在磁盘中按照IMAGE_OPTIONAL_HEADER32结构的FileAlignment字段值进行对齐,当加载到内存按照SectionAlignment对齐
3.区块的尺寸
4.不进行映射的区块 //如.reloc节,(重定位)只是给windows装载器使用,对程序是透明的
区块(节):相同属性数据的集合
节表由一系列IMAGE_SECTION_HEADER结构排列而成
//IMAGE_SECTION_HEADER结构
typedef struct _IMAGE_SECTION_HEADER {
BYTE Name[IMAGE_SIZEOF_SHORT_NAME]; //节表名,如.text
union {
DWORD PhysicalAddress;
DWORD VirtualSize; //对应区块大小
} Misc;
DWORD VirtualAddress; //装入到内存中的RVA地址 一般是1000h的整数倍
DWORD SizeOfRawData; //该区块在磁盘中的大小,该字段被FileAlignment潜规则掉了
DWORD PointerToRawData; //该区块在磁盘中的偏移量
DWORD PointerToRelocations;
DWORD PointerToLinenumbers;
WORD NumberOfRelocations;
WORD NumberOfLinenumbers;
DWORD Characteristics; //区块属性:按位指定区块属性(代码/数据/可读/可写)
} IMAGE_SECTION_HEADER, *PIMAGE_SECTION_HEADER;