您的位置:首页 > 其它

PE文件格式学习总结

2010-02-08 18:32 627 查看
PE文件被称为可移植的执行体是Portable Execute的全称,常见的EXE、DLL、OCX、SYS、COM都是PE文件,PE文件是微软Windows操作系统上的程序文件(可能是间接被执行,如DLL),继承自unix的COFF文件格式.在微软的NT C编译器出来后微软就使用PE文件格式了。



************首先定位到+0h处
struct _IMAGE_DOS_HEADER_STRUCT
************************ 中间相隔若干
************************(以下首地址由_IMAGE_DOS_HEADER_STRUCT.e_lfanew确************************ 定)
struct _IMAGE_NT_HEADERS{
DWORD Signature;
_IMAGE_FILE_HEADERS FileHeader;
_IMAGE_OPTIONAL_HEADER ;
}
************************紧跟无需定位
struct _IMAGE_SECTION_HEADER(数组);
//数组数组的数目由_IMAGE_NT_HEADERS.FileHeader.NumberOfSections决定

******************************中间间隔若干
*****************************以下首地址由_IMAGE_OPTIONAL_HEADER. *****************************IMAGE_DATA_DIRECTORY.[2].VirtualAddress
*****************************确定。

IMAGE_IMPORT_DESCRIPTOR数组若干,由最后一个数组内容全0结束

******************************中间间隔若干
*****************************以下首地址由_IMAGE_OPTIONAL_HEADER. *****************************IMAGE_DATA_DIRECTORY.[1].VirtualAddress
*****************************确定。

IMAGE_EXPORT_DIRECTORY


1、可以通过_IMAGE_DOS_HEADER_STRUCT的e_magic==”MZ”和_IMAGE_NT_HEADERS的Signature==”PE/0/0”共同判断是否PE文件。

然后_IMAGE_DOS_HEADER_STRUCT得e_lfanew的地址指向_IMAGE_NT_HEADERS所在地址,定位_IMAGE_NT_HEADERS后可以读取_IMAGE_NT_HEADERS。

2、_IMAGE_OPTIONAL_HEADER的最后一项是IMAGE_DATA_DIRECTORY数组里面有16项,分别为Export Table,Import Table,Resources Table,Exception Table,Security Table,Base Relocation Table,Debug ,Copyright,Global Ptr,Thread Local Storage,Load configuration,Bound Import,Import Address Table,Delay Import,Com Discriptor,保留。

3、_IMAGE_FILE_HEADERS 的_IMAGE_NT_HEADERS.FileHeader.NumberOfSections表明文件区块数目。通过文件区块数目判断_IMAGE_SECTION_HEADER的数目。读完_IMAGE_SECTION_HEADER后可以直接读若干个_IMAGE_SECTION_HEADER。读出各区块的数据描述。

4、通过_IMAGE_OPTIONAL_HEADER. IMAGE_DATA_DIRECTORY.[1].VirtualAddress指向地址定位到输入表,然后通过FirstThunk定位IMAGE_THUNK_DATA,通过IMAGE_THUNK_DATA.AddressOfData判断是否为按名索引。如果AddressOfData最高位为0,低31位指向IMAGE_IMPORT_BY_NAME,可以读取函数名了。如果最高位为1则低31为为输入表的函数编号。

5、最后通过_IMAGE_OPTIONAL_HEADER. IMAGE_DATA_DIRECTORY.[0].VirtualAddress指向地址定位到输出表 IMAGE_EXPORT_DIRECTORY.AddressOfNames指向输出函数数组地址,数组内存储的是指向函数名的地址。函数名的数目由NumberOfNames决定。

(好像这个格式现在有一点改变,好像后来对对输入表,输出表格式有了改变。比如用VC6.0生成的文件用,这种方法分析就不行。但是用Windows DDK 3790.1830生成的sys文件用这种格式还是能分析出来的。有点怪。
附上文中提到的文件结构。(大部分MSDN能查到,不能查到的其实也有定义,不需要自己再定义一遍),他们中的数据说明了该文件的很多很多信息。

源代码放到CSDN资源了: http://download.csdn.net/source/2127232
一下是对某应用程序分析的结果。可以分析比如WAR3,CS的PE文件,毕竟它们出来的时间比较早,输入输出表格式还没有改变。
1 ------------检查MA-DOS文件头.
PE文件头位置0x 130.
2 ------------检查PE文件头.
Runs on Intel i386
文件区块数目 4.
文件创建日期 Thu Jun 06 00:53:20 2002
COFF符号表文件偏移位置 0.
COFF符号表符号个数 0.
IMAGE_OPTIONAL_HEADER32结构大小 e0.
文件中不存在重定位信息.
文件可执行。如果为0,一般是链接时出了问题了.
行号信息被移去.
符号信息被移去.
目标平台为32位处理机.
3 ------------检查可选文件头.
普通可执行镜像文件
链接程序的主版本号:6.
链接程序的次版本号:0.
所有含代码区块的总大小:0x ab000.
所有初始化数据块总大小:0x 3b7c000.
所有未初始化数据块总大小:0x 0.
程序执行入口:0x 84812.
代码区起始RVA:0x 1000.
数据区起始RVA:0x ac000.
程序默认装入基地址:0x 400000.
内存区块中的对齐值:0x 1000.
文件区块中的对齐值:0x 1000.
操作系统主版本号:4.
操作系统次版本号:0.
用户自定义主版本号:0.
用户自定义次版本号:0.
所需要子系统主版本号:4.
所需要子系统次版本号:0.
保留通常被设置为0.===0.
映像装入内存总尺寸0x 3c28000.
DOS头、PE头部、区块表总大小0x 1000.
映像校验和0x 0.
界面子系统含义:图形接口子系统.
DllMain()函数何时被调用,默认为0.===0.
初始化线程堆栈大小0x 100000
一开始被委派给堆栈的内存数量0x 1000
为进程默认堆保留的内存0x 100000
EXE中委派给堆的内存大小0x 1000
LoaderFlags与调试有关默认为0.===0.
数据目录的项数:16.
Export Table :
数据块起始RVA:0x c70d0.
数据块长度: 0x 45bb.
…………………………
4 ------------检查区块表.
区块名:.text.
数据块长度: 0x aaa5e.
区块RVA地址: 0x 1000.
文件对齐后的尺寸: 0x ab000.
在文件中的偏移: 0x 1000.
重定位的偏移: 0x 0.
行号表的偏移: 0x 0.
OBJ中使用重定位项数目: 0x 0.
行号表中行号的数目: 0x 0.
包含代码.
该块可以执行.
该块可读.
…………………………..
5 ------------检查输入表.
包含指向输入表的RVA: 0x c3c80.
一个32位时间标志: 0x 0.
第一个被转向的API索引一般为0.===:0x 0.
输入DLL名的地址: 0x c3f22.
转向的DLL名字: WONAuth.dll
包含指向输入表的RVA :0x ac6dc.
输入函数:
?GetCommunityId@WON_AuthCertificate1@@QB
…………………………..
包含指向输入表的RVA: 0x c3d10.
一个32位时间标志: 0x 0.
第一个被转向的API索引一般为0.===:0x 0.
输入DLL名的地址: 0x c68d0.
转向的DLL名字: WSOCK32.dll
包含指向输入表的RVA :0x ac76c.
输入函数:
低31位可以看成函数序号52
低31位可以看成函数序号101
……………………………
6 ------------检查输出表.
未使用总是为0.===0
输出表创建时间 Thu Jun 06 00:53:20 2002
主版本号,一般为0.===0
次版本号,一般为0.===0
模块的真实名称:cstrike.exe
基数:用于这个可执行文件输出表的起始序数值一般为1.===1.
AddressOfFunctions阵列中的元素个数:276.
AddressOfNames阵列中的元素个数:276.
指向函数地址数组: 0x c70f8.
函数名字的指针地址: 0x c7548.
指向输出序列号数组: 0x c7998.
输出函数名:
??0?$Dar@D@vgui@@QAE.
??0?$Dar@D@vgui@@QAE.
…………………………………..
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: