首页
社区
课程
招聘
[原创]加密与解密(第三版)的学习笔记_第10章PE文件格式
2012-10-25 19:04 10304

[原创]加密与解密(第三版)的学习笔记_第10章PE文件格式

2012-10-25 19:04
10304
PE.zip

第十章  PE文件格式
10.1、PE文件的加载
    我们知道,在windows中,每个进程都有自己独立的内存地址空间。当程序被执行的时候,PE文件将会被PE装载器映射到相应的内存中。
    PE文件被分为不同的Setcion,每个Section中包含Code或Data,每个section按照区块对齐值来对齐。一般情况下,PE文件在磁盘中的区块对齐值是200H,PE文件在内存中的区块对齐值是1000H。具体数值大小请查看IMAGE_NT_HEADERS中的FileAlignment和SectionAlignment字段。
    区块是连续的结构。每个section在内存中都有一套属性(是否是code、是否可读或可写、是否只读或写)。
   
ImageBase(基地址):
    PE文件被映射到内存中的起始地址或句柄。
Relative Virtual Address(相对虚拟地址):
    相对于ImageBase的偏移地址。
Virtual Address(虚拟地址):
    内存中的地址。
关系:VirtualAddress  = ImageBase + Relative Virtual Address
File Offset(文件偏移地址):
  PE文件在磁盘中相对文件头的偏移地址。
  
10.2、PE文件的组成
    一个PE文件包括如下部分:DOS Header(DOS部首)、PE Header(PE文件头)、Section Table(块表)、Sections(块),如果您的PE文件是Debug版本,后面还应该有调试信息(注意:这部分不会映射到内存)。
10.3、MS-DOS头部
    DOS头文件包括DOS MZ头和DOS stub。
    每个PE文件都是以一个DOS程序开始的,用来识别是否是有效地执行体。如果不是有效地执行体,会执行DOS stub部分。
  PE文件起始于一个DOS头,其结构如下:
STRUCT IMAGE_DOS_HEADER{
  e-magic  WORD                //        DOS可执行文件’MZ’
  e_cblp   WORD
  e_cp     WORD
  e_crlc    WORD
  e_cparhdr WORD
  e_minalloc  WORD
  e_maxalloc  WORD
  e_ss     WORD
  e_sp     WORD
  e_csum   WORD
  e_lfarlc   WORD
  e_ovno   WORD
  e_res     WORD
  e_oemid    WORD
  e_res2     WORD
  e_lfanew   WORD                //指向PE文件头”PE”
};

10.4、PE文件头
  紧接着DOS stub的事PE Header。
IMAGE_NT_HEADERS STRUCT{
  Signature    DWORD
  FileHeader   IMAGE_FILE_HEADER
  OptionalHeader  IMAGE_OPTIONAL_HEADER32
};
    Signature字段:PE文件标识。默认是00004550H,ASCII码字符是“PE00”IAMGE_DOS_HEADER中的e_lfanew字段指向Signature字段的地址。

  FileHeader字段的结构如下:
IMAGE_FILE_HEADER STRUCT{
  Machine                                WORD                //运行平台
  NumberOfSections                 WORD                //文件的区块数目
  TimeDateStamp                DWORD                //文件的创建时间
  PointerToSymbolTable  DWORD        //指向符号表的指针
  NumberOfSymbols                DWORD                //符号表中的符号个数
  SizeOfOptionalHeader        WORD                //IMAGE_OPTIONAL_HEADER32结构大小
  Characteristics                        WORD                //文件属性
  
};

  OptionalHeader字段的结构如下:
IMAGE_OPTIONAL_HEADER32 STURCT{
  Magic                                WORD                //标志字
  MajorLinkerVersion        BYTE                //连接器主版本号
  MinorLinkerVersion        BYTE                //连接器次版本号
  SizeofCode                        DWORD                //所有含有代码区块的大小
  SizeOfInitializedData   DWORD                //
  SizeOfUninitializedData DWORD
  AddressOfEntryPoint  DWORD
  BaseOfCode                        DWORD
  BaseOfData                        DWORD
  ImageBase                        DWORD
  SectionAlignment                DWORD
  FileAlignment                        DWORD
  MajorOperatingSystemVersion        WORD
  MinorOperatingSystemVersion        WORD
  MajorImageVersion                WORD
  MinorImageVersion        WORD
  MajorSubsystemVersion WORD
  MinorSubsystemVersion WORD
  Win32VersionValue        DWORD
  SizeOfImage                        DWORD
  SizeOfHeaders                DWORD
  CheckSum                        DWORD
  Subsystem                        WORD
  DllCharacteristics                WORD
  SizeOfStackReserve        DWORD
  SizeOfStackCommit        DWORD
  SizeOfHeapReserve        DWORD
  SizeOfHeapCommit        DWORD
  LoaderFlags                        DWORD
  NumberOfRvalAndSizes  DWORD                //数据目录表项数
  DataDirectory                        IMAGE_DATA_DIRECTORY 16 DUP
  
};
下图是IMAGE_OPTIONAL_HEADER32结构中除最后DataDirectory字段外的前面所有字段。

  DataDirectory字段的项结构IMAGE_DATA_DIRECTORY如下:
IMAGE_DATA_DIRECTORY STURCT{
  VirtualAddress                DWORD                        //数据块的RVA
  Size                                        DWORD                        //数据项的长度
};

数据目录表成员结构顺序如下:
Export  Table
Import  Table
Resources  Table
Exception  Table
Security                Table
Base relocation Table
Debug                Table
Copyright
Global        Ptr
Thread  local  storage
Load  configuration
Bound  Import
Import  Address  Table
Delay  Import
COM  descriptor
保留

用LordPE查看PE.exe的PE结构:


10.5、区块
    紧接着IMAGE_NT_HEADERS后的是区块表,它是一个IMAGE_SECTION_HEADER结构的数组。
    区块数由IMAGE_NT_HEADERS.FileHeader.NumberOfSections定义。
IMAGE_SECTION_HEADER结构如下:
IMAGE_SECTION_HEADER{
  Name                DBYTE        8        DUP(?)                //8字节的块名
  union         Misc{
  PhysicalAddress        DWORD
  VirtualSize                DWORD
  };
  VirtualAddress                DWORD
  SizeOfRawData                DWORD
  PointerToRawData                DWORD
  PonterToRelocations        DWORD
  PointerToLinenumbers        DWORD
  NumberOfRelocations          WORD
  NumberOFLinenumbers          WORD
  Characteristics                        DWORD
};
这是“.text”区块对应的字段

这是“.rdata”区块对应的字段

这是“.data”区块对应的字段


PE文件至少有code和data  section两个区块。
    当然还有其他区块:rdata  idata  edata   rsrc   bss   crt   tls   reloc   sdata   srdata   pdata   debug$S  debug$T   debug$P   drectve   didat。每个不同的区块都有不同的用处。想深入了解的朋友可以查找相关资料。

创建区块:
#paragma  data_seg(“MY_SECTION”)

合并两个已存在区块:
/MERGE:.rdata  = .text                //合并rdata和text区块,合并后的结果放进text区块
当然有些区块不允许合并。

区块的对齐值:   
  PE文件被分为不同的Setcion,每个Section中包含Code或Data,每个section按照区块对齐值来对齐。一般情况下,PE文件在磁盘中的区块对齐值是200H,PE文件在内存中的区块对齐值是1000H。具体数值大小请查看IMAGE_NT_HEADERS中的FileAlignment和SectionAlignment字段。
  
文件偏移与虚拟地址转换:
  由于PE文件磁盘的区块对齐值和在内存中的区块对齐值不同,导致PE文件被映射到内存后,统一数据相对于文件头的偏移量不是相同的。这就存在文件偏移地址和虚拟地址的转换问题。
用LordPE查看PE.exe的区段表

_________________________________________________________________________
区块                        虚拟偏移量                        文件偏移量                        差值(dk)
__________________________________________________________________________
.text                                1000H                                400H                                0C00H
.rdata                        2000H                                600H                                 1A00H
.data                                3000H                                800H                                 2800H

计算公式:        在第N个区块中的虚拟地址是VA,要求它的文件偏移地址FileOffset:
FileOffset = VA - ImageBase - N *  0C00H
当然也可以使用LordPE提供的地址转换功能进行转换:


10.6、输入表
  可执行文件使用来自于其他DLL的代码或数据时,称为输入。当PE文件装入时,windows加载器的工作之一就是定位所有被输入的函数和数据,并且让正在被装入的文件可以使用那些地址。这个过程是通过PE文件的输入表(Import Table)来完成的,输入表中保存的是函数名和其驻留的DLL名等动态链接所需要的信息。
  输入函数:被程序调用但其执行代码又不在程序中的函数,这些函数位于相关的DLL文件中,在调用者程序中只保留相关函数信息,如函数名、DLL文件名。
  只有当PE文件被装入内存,windows加载器才将相关DLL装入内存,并将调用输入函数的指令和函数实际所处的地址联系起来。
--------------------------------------------------------------------------------------------------------
今天就先传这么多,剩下部分下次继续。这是我第一次在看雪发这么长的帖子,里面有什么错误的地方,还请各位高手指教!谢谢大家观看
--------------------------------------------------------------------------------------------------------

[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

上传的附件:
收藏
点赞0
打赏
分享
最新回复 (3)
雪    币: 89
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
honggun 2012-10-25 19:42
2
0
介绍的详细。
雪    币: 81
活跃值: (448)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
灵杰之舞 2012-12-2 18:14
3
0
楼主介绍详细
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
wajuny 2012-12-28 11:27
4
0
正在看这章,感觉PE结构应该挪到书的前面讲。
游客
登录 | 注册 方可回帖
返回