PE文件格式详解(2)
来源:互联网 发布:c语言初级程序 编辑:程序博客网 时间:2024/05/16 19:15
1.NT头
接下来说一下NT头,IMAGE_NT_HEADERS。
代码 IMAGE_NT_HEADERS结构体
typedef struct _IMAGE_NT_HEADERS{
DWORD Signature; //PE Signature : 50450000 ("PE"00)
IMAGE_FILE_HEADER FileHeader;
IMAGE_OPTIONAL_HEADER32 OptionalHeader
} IMAGE_NT_HEADERS32, *PIMAGE_NT_HEADERS32;
该结构体由3个成员构成:
签名(Signature)→值为50450000h("PE"00)
文件头(File Header)
可选头(Optional Header)
依然以Notepad.exe为例,使用010 Editor打开。
可以查看其IMAGE_NT_HEADERS。
IMAGE_NT_HEADERS结构体的大小为F8,非常大,接下来分别说一下文件头和可选头两个结构体。
2.NT头:文件头
文件头是表现文件大致属性的IMAGE_FILE_HEADER 结构体
代码 IMAGE_FILE_HEADER结构体
typedef struct _IMAGE_FILE_HEADER{
WORD Machine;
WORD NumberOfSections;
DWORD TimeDateStamp;
DWORD PointToSymbolTable;
DWORF NumberOfSymbols;
WORD SizeOfOptionalHeader;
WORD Characteristics;
} IMAGE_FILE_HEADER, *PIMAGE_FILE_HEADER;
IMAGE_FILE_HEADERS结构体中有如下4种重要成员,(若设置不正确,将导致文件无法正常运行)。
#1.Machine
每个CPU都拥有唯一的Machine码,兼容32位Intel x86芯片的Machine码为14C。
定义在winnt.h文件中的Machine码。
代码 Machine码
#define IMAGE_FILE_MACHINE_UNKNOWN 0
#define IMAGE_FILE_MACHINE_I386 0x014c //Inter 386
#define IMAGE_FILE_MACHINE_R3000 0x0162 //MIPS little-endian,0x160 big-endian
#define IMAGE_FILE_MACHINE_R4000 0x0166 //MIPS little-endian
#define IMAGE_FILE_MACHINE_R10000 0x0168 //MIPS little-endian
#define IMAGE_FILE_MACHINE_WCEMIPSV2 0x0169 //MIPS little-endian WCE v2
#define IMAGE_FILE_MACHINE_ALPHA 0x0184 //Alpha_AXP
#define IMAGE_FILE_MACHINE_POWERPC 0x01F0 //IBM Powerpc Little-Endian
#define IMAGE_FILE_MACHINE_SH3 0x01a2 //SH3 little-endian
#define IMAGE_FILE_MACHINE_SH3E 0x01a4 //SH3E little-endian
#define IMAGE_FILE_MACHINE_SH4 0x01a6 //SH4 little-endian
#define IMAGE_FILE_MACHINE_ARM 0x01c0 //ARM Little-Endian
#define IMAGE_FILE_MACHINE_THUMB 0x01c2
#define IMAGE_FILE_MACHINE_IA64 0x0200 //Intel 64
#define IMAGE_FILE_MACHINE_MIPS16 0x0266 //MIPS
#define IMAGE_FILE_MACHINE_MIPSFPU 0x0366 //MIPS
#define IMAGE_FILE_MACHINE_MIPSFPU16 0x0466 //MIPS
#define IMAGE_FILE_MACHINE_ALPHA64 0x0284 //ALPHA64
#define IMAGE_FILE_MACHINE_AXP64 IMAGE_FILE_MACHINE_ALPHA64
#2.NumberOfSections
PE文件把代码、数据、资源等一句属性分类到各个节区中储存。
NumberOfSections用来指出文件中存在的节区数量。该值一定要大于0,其当定义的节区数量与实际节区不同时,将发生运行错误。
#3.SizeOfOptionalHeader
IMAGE_NT_HEADER结构体的最后一个成员为IMAGE_OPTIONAL_HEADER32结构体。SizeOfOptionalHeader成员用来之处IMAGE_OPTIONAL_HEADER32结构体的长度。IMAGE_OPTIONAL_HEADER32结构体有C语言编写而成,故其大小已经确定。Windows的PE装载器需要查看IMAGE_FILE_HEADER的SizeOfOptionalHeader值,从而识别出IMAGE_OPTIONAL_HERADER32的结构体的大小。
注:PE32+格式的文件,使用的是IMAGE_OPTIONAL_HEADER64结构体(不是IMAGE_OPTIONAL_HEADER32结构体!!!两个结构体的大小是不一样的)所以需要在 SizeOfOptionalHeader成员中明确指出结构体的大小。
#4.Characteristics
该字段用于表示文件的属性,文件是否是可运行的形态,是否为DLL文件等信息,以bit OR形式组合起来。
定义在winnt.h文件中的Characteristics值。(注意0002h与2000h)
代码 Characteristics
#define IMAGE_FILE_RELOCS_STRIPPED 0x0001 //Relocation info stripped from file.
#define IMAGE_FILE_EXECUTABLE_IMAGE 0x0002 //File is executable
//(i.e. no unresolved externel references).
#define IMAGE_FILE_LINE_NUMS_STRIPPED 0x0004 //Line numbers stripped from file.
#define IMAGE_FILE_LOCAL_SYMS_STRIPPED 0x0008 //Local symbols stripped from file.
#define IMAGE_FILE_AGGRESIVE_WS_TRIM 0x0010 //Agressively trim working set.
#define IMAGE_FILE_LARGE_ADDRESS_AWARE 0x0020 //App can handle >2gb addresses
#define IMAGE_FILE_BYTES_RESVERSED_LO 0x0080 //byte of machine word are reversed
#define IMAGE_FILE_32BIT_MACHINE 0x0100 //32 bit word machine
#define IMAGE_FILE_DEBUG_STRIPPED 0x0200 //Debugging info stripped from file in .DBG file
#define IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP 0x0400 //If Image is on removable media,
//copy and run from the swap file
#define IMAGE_FILE_NET_RUN_FROM_SWAP 0x0800 //If Image is on Net,copy and run from the swap file.
#define IMAGE_FILE_SYSTEM 0x1000 //System File
#define IMAGE_FILE_DLL 0x2000 //File is a DLL
#define IMAGE_FILE_UP_SYSTEM_ONLY 0x4000 //File should only be run on a UP machine
#define IMAGE_FILE_BYTES_REVERSED_HI 0x8000 //byte of machine word are reversed
注:PE文件中Characteristics的值有可能不是0002h(not executable),例如:*.obj的object文件及resource DLL文件等,2000h表明PE文件是否为DLL文件。
IMAGE_FILE_HEADER的TimeDateStamp成员,该成员的值不影响文件运行,用来记录编译器创建文件的时间(并不是所有的开发工具都提供了设置该值的工具,Delphi则并没有提供)。
3.NT头:可选头
IMAGE_OPTIONAL_HEADER32是PE头结构体中最大的。
代码 IMAGE_OPTIONAL_HEADER32结构体。
typedef struct _IMAGE_DATA_DIRECTORY{
DWORD VirtualAddress;
DWORD Size;
} IMAGE_DATA_DIRECTORY, *PIMAGE_DATA_DIRECTORY;
#define IMAGE_NUMBEROF_DIRECTORY_ENTRIES 16
typedef struct _IMAGE_OPTIONAL_HEADER{
WORD Magic;
BYTE MajorLinkerVersion;
BYTE MinorLinkerVersion;
DWORD SizeOfCode;
DWORD SizeOfInitializedData;
DWORD SizeOfUnitializedData;
DWORD AddressOfEntryPoint;
DWORD BaseOfCode;
DWORD BaseOfData;
DWORD ImageBase;
DWORD SectionAlignment;
DWORD FileAlignment;
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;
IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES];
} IMAGE_OPTIONAL_HEADER32, *PIMAGE_OPTIONAL_HEADER32;
IMAGE_OPTIONAL_HEADER32结构体中有如下几种重要成员,(若设置不正确,将导致文件无法正常运行)。
#1.Magic
为IMAGE_OPTIONAL_HEADER32结构体是,Magic码为10B;为IMAGE_OPTIONAL_HEADER64结构体时,Magic码为20B。
#2.AddressOfEntryPoint
AddressOfEntryPoint持有EP的RVA值。该值指出程序最先执行的代码起始地址。
#3.ImageBase
进程虚拟内存的范围为0~FFFFFFFF(32位操作系统,64位的操作系统为0~FFFFFFFFFFFFFFFF(16个))。PE文件被加载到如此大的内存中时ImageBase指出文件优先装入地址。
EXE/DLL文件被装在到用户内存的0~7FFFFFFF(32位系统)中,SYS文件被载入内核内存的80000000~FFFFFFFF中。一般而言,使用开发工具创建好EXE文件后,其ImageBase的值为00400000,DLL文件的ImageBase为100000000(可以指定为其他值)。
注:执行PE文件时,PE装载器先差un构建进程,再将文件载入内存,然后把EIP寄存器的值设置为ImageBase+AddressOfEntryPoint.
#4.SectionAlignment,FileAlignment
PE文件的Body部分划分为若干节区,这些节存储着不同类别的数据。FileAlignment指定了节区在磁盘文件中的最小单位,SectionAlignment指定了节区在内存中的最小单位(SectionAlignment与FlieAlignment的值不一定相同)。磁盘文件或内存节区的大小必定为FileAlignment或SectionAlignment的整数倍。
#5.SizeOfImage
加载PE文件到内存时,SizeOfImage指定了PE Image在虚拟内存中所占空间的大小。一般而言,文件与加载到内存之后两者的大小是不相同的。
#6.SizeOfHeader
SizeOfHeader用来指出整个PE头的大小,当然这个值也必须为FileAlignment的整数倍。第一节区所在位置与SizeOfHeader据文件开始偏移的量相同。
#7.Subsystem
这个值是用来区分系统驱动文件安(*.sys)和普通的可执行文件的(*.exe,*.dll)。
值 含义 备注
1 Driver文件 系统驱动
2 GUI文件 窗口应用程序
3 CUI文件 控制台应用程序
#8.NumberOfRvaAndSizes
NumberOfRvaAndSizes用来制定DataDirectory(IMAGE_OPTIONAL_HEADER32结构体最后一个成员)数组的个数。虽然结构体定义中明确指出了数组个数为16(#define IMAGE_NUMBEROF_DIRECTORY_ENTRIES 16)但是PE装载查看的NumberOfRvaAndSizes的值来识别数组的大小(即数组大小也可能不为16)。
#9.DataDirectory
DataDirectory是有IMAGE_DATA_DIRECTORY结构体组成的数组,数组的每项都有被定义的值。
代码 DataDirectory结构体数组
DataDirectory[0] = EXPORT Directory
DataDirectory[1] = IMPOTR Directory
DataDirectory[2] = RESOURCE Directory
DataDirectory[3] = EXCEPTION Directory
DataDirectory[4] = SECURITY Directory
DataDirectory[5] = BASERELOC Directory
DataDirectory[6] = DEBUG Directory
DataDirectory[7] = COPYRIGHT Directory
DataDirectory[8] = GLOBALPTR Directory
DataDirectory[9] = TLS Directory
DataDirectory[A] = LOAD_CONFIG Directory
DataDirectory[B] = BOUND_IMPORT Directory
DataDirectory[C] = IAT Directory
DataDirectory[D] = DELAY_IMPORT Directory
DataDirectory[E] = COM_DESCRIPTOR Directory
DataDirectory[F] = Reserver Directory
IMAGE_OPTIONAL_HEADER
使用010 Editor查看Notepad.exe的IMAGE_OPTIONAL_HEADER整个结构体。
阅读全文
0 0
- PE文件格式详解(2)
- PE文件格式详解(2)
- PE文件格式详解(2)
- PE文件格式详解(2)
- PE文件格式详解(1)
- PE文件格式详解(3)
- PE文件格式详解(4)
- PE文件格式详解(5)
- PE文件格式详解(6)
- PE文件格式详解(7)
- PE文件格式详解(一)
- PE文件格式详解(二)
- PE文件格式详解(三)
- PE文件格式详解(四)
- PE文件格式详解(五)
- PE文件格式详解(六)
- PE文件格式详解(七)
- PE文件格式详解(上)
- 浅析SimpleAdapter
- 2017.6.6测试 题二 过路费
- CSU 1809: Parenthesis <省赛真题>
- 小白成长记——Java基础之File类的使用
- hdu 6103 Kirinriki 尺取
- PE文件格式详解(2)
- 关于__stdcall和__cdecl调用方式的理解
- 第一章 Thread Management(线程管理) 下
- Kirinriki(HDU 6103)
- 用gcc3.4.5编译c++项目
- 在win7下配置Geany,使其使用 Python 3
- 极光推送
- 遍历已加载的驱动sys_魔域驱动
- 2013年计算机联考真题——确定主元