PE文件格式分析及修改

来源:互联网 发布:语音播放软件排行 编辑:程序博客网 时间:2024/05/31 18:53
PE文件格式分析及修改
From:http://hi.baidu.com/drunkdream/blog/item/6590508273ec37b60df4d271.html
2011-03-13 9:12

PE 的意思是 Portable Executable(可移植的执行体)。它是 Win32环境自身所带的执行文件格式。它的一些特性继承自Unix的Coff(common object file format)文件格式。“Portable Executable”(可移植的执行体)意味着此文件格式是跨Win32平台的;即使Windows运行在非Intel的CPU上,任何win32平台的PE装载器都能识别和使用该文件格式。

PE文件在文件系统中,与存贮在磁盘上的其它文件一样,都是二进制数据,对于操作系统来讲,可以认为是特定信息的一个载体,如果要让计算机系统执行某程序,则程序文件的载体必须符合某种特定的格式。要分析特定信息载体的格式,要求分析人员有数据分析、编码分析的能力。在Win32系统中,PE文件可以认为.exe、.dll、.sys 、.scr类型的文件,这些文件在磁盘上存贮的格式都是有一定规律的。

一、PE格式基础

下表列出了PE的总体结构

DOS MZ headerDOS stubPE headerSection tableSection 1Section 2…Section n

一个完整的PE文件,前五项是必定要有的,如果缺少或者数据出错,系统会拒绝执行该文件如下图

<IMG class=fit-image onmousewheel="javascript:return big(this)" style="ZOOM: 100%" height=121 alt="" src="/Article/UploadFiles/200812/20081218040952504.jpg" width=363 onload="javascript:if(this.width>498)this.style.width=498;" border=0> 图1 文件头格式错误

498)this.style.width=498;" border=0> 图2 格式数据错误

498)this.style.width=498;" border=0> 图3 代码错误

DOS MZ header部分是DOS时代遗留的产物,是PE文件的一个遗传基因,一个Win32程序如果在DOS下也是可以执行,只是提示:“This program cannot be run in DOS mode.”然后就结束执行,提示执行者,这个程序要在Win32系统下执行。

DOS stub 部分是DOS插桩代码,是DOS下的16位程序代码,只是为了显示上面的提示数据。这段代码是编译器在程序编译过程中自动添加的。

PE header 是真正的Win32程序的格式头部,其中包括了PE格式的各种信息,指导系统如何装载和执行此程序代码。
Section table部分是PE代码和数据的结构数据,指示装载系统代码段在哪里,数据段在哪里等。对于不同的PE文件,设计者可能要求该文件包括不同的数据的Section。所以有一个Section Table 作为索引。Section多少可以根据实际情况而不同。但至少要有一个Section。如果一个程序连代码都没有,那么他也不能称为可执行代码。在Section Table后,Section数目的多少是不定的。

二、程序的装入

当我们在explorer.exe(资源管理器)中双击某文件,执行一个可执行程序,系统会根据文件扩展名启动一个程序装载器,称之为Loader。Loader会首先检查DOS MZ Header,如果存在,就继续寻找PE header,如果这两项都不存在,就认为是DOS 16位代码,如果只存在DOS MZ Header,而其中又指示了而其中又指示了PE Header 的位置,那么Loader 就判定此文件不一个有效的PE文件,拒绝执行。

如果DOS Header 和PE Header都正常有效,那么Loader就会根据PE Header 及Section Table的指示,将相应的代码和数据映射到内存中,然后根据不同的Section进行数据的初始化,最后开始执行程序段代码。

三、PE格式高级分析

下面我们以一个真实的程序为例详细分析PE格式,分析PE格式最好有PE分析器,常用的软件是Lord PE,也有其它的分析工具和软件如PE Editor 、Stud PE等。

先分析一下磁盘文件的内容,这里我们使用UltraEdit32(UE)工具,这是一个实用的文件编辑器,可以编辑文本和二进制文件。

498)this.style.width=498;" border=0> 图4 PE文件开始的磁盘数据

在文件的一开始有两位16进制数据4D 5A,其对应的ASCII字符是MZ,这个标志就是DOS MZ Header 的标志。下面是通过Load PE列出 的DOS MZ Header

1. DOS Header

数据结构名称<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />

e_magic:

0x<?xml:namespace prefix = st1 ns = "urn:schemas-microsoft-com:office:smarttags" /><?xml:namespace prefix = st1 />5A4D->‘MZ’

e_cblp:

0x0090

e_cp:

0x0003

e_crlc:

0x0000

e_cparhdr:

0x0004

e_minalloc:

0x0000

e_maxalloc:

0xFFFF

e_ss:

0x0000

e_sp:

0x00B8

e_csum:

0x0000

e_ip:

0x0000

e_cs:

0x0000

e_lfarlc:

0x0040

e_ovno:

0x0000

e_res:

0x0000000000000000

e_oemid:

0x0000

e_oeminfo:

0x0000

e_res2:

0x0000000000000000000000000000000000000000

e_lfanew:

0x000000F8


这是一个PE文件的DOS Header,其中我们最关心的就是e_lfanew这个字段的值,它指向了PE Header 在磁盘文件中相对于文件开始的偏移地址,这里是F8。在本文件00F8h处果然找到了“PE”两个字符,那么在00F8h处就是PE Header 的有效头载荷。

2. PE Header

我们可以在winnt.h这个文件中找到关于PE文件头的定义:

typedef struct _IMAGE_NT_HEADERS{DWORD Signature;//PE文件头标志:PE\0\0。在开始DOS header的偏移3CH(e_lfanew)处所指向的地址开始IMAGE_FILE_HEADER FileHeader;//PE文件物理分布的信息IMAGE_OPTIONAL_HEADER32 OptionalHeader;//PE文件逻辑分布的信息} IMAGE_NT_HEADERS32, *PIMAGE_NT_HEADERS32;

2.1 IMAGE_FILE_HEADER和IMAGE_OPTIONAL_HEADER

typedef struct _IMAGE_FILE_HEADER{WORD Machine;//该文件运行所需要的CPU,对于Intel平台是14ChWORD NumberOfSections;//文件的节数目DWORD TimeDateStamp;//文件创建日期和时间DWORD PointerToSymbolTable;//用于调试DWORD NumberOfSymbols;//符号表中符号个数WORD SizeOfOptionalHeader;//OptionalHeader 结构大小WORD Characteristics;//文件信息标记,区分文件是exe还是dll} IMAGE_FILE_HEADER, *PIMAGE_FILE_HEADER;重要的 Characteristics值#define IMAGE_FILE_RELOCS_STRIPPED 0001h // 文件中是否存在重定位信息#define IMAGE_FILE_EXECUTABLE_IMAGE 0002h // 文件是可执行的#define IMAGE_FILE_LARGE_ADDRESS_AWARE 0020h // 程序可以触及大于2G的地址#define IMAGE_FILE_BYTES_REVERSED_LO 0080h // 保留的机器类型低位#define IMAGE_FILE_32BIT_MACHINE 0100h // 32位机器#define IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP 0400h // 不可在可移动介质上运行#define IMAGE_FILE_NET_RUN_FROM_SWAP 0800h // 不可在网络上运行#define IMAGE_FILE_SYSTEM 1000h // 系统文件#define IMAGE_FILE_DLL 2000h // 文件是一个DLL#define IMAGE_FILE_UP_SYSTEM_ONLY 4000h // 只能在单处理器计算机上运行#define IMAGE_FILE_BYTES_REVERSED_HI 8000h //保留的机器类型高位

typedef struct _IMAGE_OPTIONAL_HEADER{WORD Magic;//标志字(总是010bh)BYTE MajorLinkerVersion;//连接器高版本号BYTE MinorLinkerVersion;//连接器低版本号DWORD SizeOfCode;//代码段大小DWORD SizeOfInitializedData;//已初始化数据块大小DWORD SizeOfUninitializedData;//未初始化数据块大小DWORD AddressOfEntryPoint;//PE装载器准备运行的PE文件的第一个指令的RVA,若要改变整个执行的流程,

可以将该值指定到新的RVA,这样新RVA处的指令首先被执行。DWORD BaseOfCode;//代码段起始RVADWORD BaseOfData;//数据段起始RVADWORD ImageBase;//PE文件的装载地址DWORD SectionAlignment;//块对齐因子DWORD FileAlignment;//文件块对齐因子WORD MajorOperatingSystemVersion;//所需操作系统高位版本号WORD MinorOperatingSystemVersion;// 所需操作系统低位版本号WORD MajorImageVersion;//用户自定义高位版本号WORD MinorImageVersion;//用户自定义低位版本号WORD MajorSubsystemVersion;//win32子系统版本。若PE文件是专门为Win32设计的WORD MinorSubsystemVersion;//该子系统版本必定是4.0否则对话框不会有3维立体感DWORD Win32VersionValue;//保留值,系统没用到的,一般被作为是否感染的标志DWORD SizeOfImage;//内存中整个PE映像体的尺寸DWORD SizeOfHeaders;//所有头+节表的大小DWORD CheckSum;//校验和WORD Subsystem;//NT用来识别PE文件属于哪个子系统WORD DllCharacteristics;// 用来表示一个DLL映像是否为进程和线程的初始化及终止包含入口点的标记DWORD SizeOfStackReserve;//DWORD SizeOfStackCommit;//DWORD SizeOfHeapReserve;//DWORD SizeOfHeapCommit;////堆栈大小 这些域控制要保留的地址空间数量,并且负责栈和默认堆的申请。在默认情况下,

栈和堆都拥有1个页面的申请值以及16个页面的保留值DWORD LoaderFlags;// 告知装载器是否在装载时中止和调试,或者默认地正常运行DWORD NumberOfRvaAndSizes;// 该字段标识了接下来的DataDirectory数组个数。IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES];//IMAGE_DATA_DIRECTORY 结构数组。每个结构给出一个重要数据结构的RVA,比如引入地址表等}IMAGE_OPTIONAL_HEADER32, *PIMAGE_OPTIONAL_HEADER32;

2.2 IMAGE_DATA_DIRECTORY

typedef struct _IMAGE_DATA_DIRECTORY{DWORD VirtualAddress;//表的RVA地址DWORD Size;//大小} IMAGE_DATA_DIRECTORY, *PIMAGE_DATA_DIRECTORY;

498)this.style.width=498;" border=0> 图5 Load PE 读取的PE Header 的重要部分数据

498)this.style.width=498;" border=0> 图6 Subsystem 类型

498)this.style.width=498;" border=0>  图7 Load Pe 读取的IMAGE_DATA_DIRECTORY 信息

在IMAGE_OPTIONAL_HEADER32后部一般是16项IMAGE_DATA_DIRECTORY数据,其中最后一项是保留数据。每一项数据都有其固定的含义,并且位置不可改变。

Export Table 导出函数表,主要用于DLL中的导出函数Import Table 导入函数表,使用外部函数的数据表Resource  资源数据表Exception  异常处理表Security  安全处理数据表Relocation  重定位信息表,一般和DLL相关Debug   调试信息表Copyright  版权信息表Globalptr  机器值(MIPS GP)Tls Table  线程信息表LoadConfig  装配信息表BoundImport  输入函数绑定信息表IAT    也ImportTable对应,由Loader填写的输入函数地址DelayImport  延迟装入的函数信息COM    公用组件信息表Reserved  保留信息,系统没有使用,为以后扩展使用这16项数据,其所在位置由RVA指定,大小由Size指定。对于一般的一个可执行程序(.exe),

最重要的是导入表(Import Table和IAT)、资源数据表(Resoruce)。


原创粉丝点击