深入剖析Win32可移植可执行文件格式(第二部分)



深入剖析 Win32 可移植可执行文件格式 第二部分
作者:Matt Pietrek
上个月在本文的第一部分中,我首先对可移植可执行文件进行了全面的介绍.我讲了 PE 文 件的历史和组成 PE 文件头的数据结构,还讲了节表.PE 文件头和节表告诉你在可执行文件中都 包含什么类型的代码和数据,以及在哪里能找到它们. 本月我要讲一下常见的节.最后讲一下我的最新的经过彻底改进的PEDUMP程序,它可以在 2002 年 2 月的专栏中下载.如果你不熟悉PE文件的基本概念,应该首先读一下本文的第一部分. 上个月我讲了节是怎样的一个逻辑上属于一起的代码或数据块. 例如可执行文件的所有导入 信息都在一个节中. 现在让我们来看一下在可执行文件和 OBJ 文件中经常遇到的一些节. 除非特 别说明,否则下表中的节名都来自 Microsoft 的工具。
名称 .text .data .rdata .idata 描述 默认的代码节. 默认的可读/可写数据节.全局变量通常在这个节中. 默认的只读数据节.字符串常量和 C++/COM 虚表就放在这个节中. 导入表.实际上,链接器经常把.idata 节合并到其它节中(或者是明确指定的,或者是通 过链接器的默认行为).默认情况下,链接器仅在创建发行版的程序时才把.idata 节合并 到其它节中. .edata 导出表. 当创建要导出函数或数据的可执行文件时, 链接器会创建一个.EXP 文件. 这个.EXP 文件包含一个.edata 节,这个节被添加到最后的可执行文件中.与.idata 节一样,.edata 节也经常被合并到.text 节或.rdata 节中. .rsrc .bss 资源节.这个节是只读的.它不应该被命名为其它名称,也不应该被合并到其它节中. 未初始化的数据节. 在最新的链接器创建的可执行文件中很少见到. 链接器扩展可执行文件 的.data 节的 VirtualSize 域以便容纳未初始化的数据. .crt 添加到可执行文件中的数据,用来支持C++运行时库(CRT).一个比较好的例子就是用于调 用静态C++对象的构造函数和析构函数的指针.要获取更详细的信息,可以参考2001 年 1 月 的Under The Hood专栏. .tls 这个节中的数据用来支持使用\\\\_\\\\_declspec(thread)语法创建的线程局部存储变量. 它包括数 据的初始值,以及运行时需要的附加变量. .reloc 可执行文件中的基址重定位节. 通常 DLL 需要基址重定位信息而 EXE 并不需要. 在创建发行 版的程序时,链接器并不为 EXE 文件生成基址重定位信息.可以使用/FIXED 链接器选项移 除基址重定位信息. .sdata 通过全局指针(Global Pointer)相对寻址的"短(Short)"可读/可写数据.用于 IA-64 和其它使用全局指针寄存器的平台上.IA-64 平台上正常大小的全局变量在这个节中. .srdata 通过全局指针相对寻址的"短(Short)"只读数据.用于 IA-64 和其它使用全局指针寄存 器的平台上. .pdata 异常表.它包含一个 IMAGE\\\\_RUNTIME\\\\_FUNCTION\\\\_ENTRY 结构数组,这个结构与平台体系结构 相关. 数据目录中索引为 IMAGE\\\\_DIRECTORY\\\\_ENTRY\\\\_EXCEPTION 的项指向它. 用于使用基于表 的异常处理的平台,例如 IA-
  64.惟一不使用基于表的异常处理的平台是 x86(它使用的是
名称
描述 基于堆栈的异常处理).
.debug$S
OBJ 文件中的 Codeview 格式的调试符号(Symbol)信息.这是一列可变长度的 CodeView 格 式的调试符号记录.
.debug$T
OBJ 文件中的 Codeview 格式的调试类型(Type)记录.这是一列可变长度的 CodeView 格式 的调试类型记录.
.debug$P .drectve
可以在使用预编译头(Precompiled Headers)生成的 OBJ 文件中找到这个节. 这个节包含链接器指令, 并且只存在于 OBJ 文件中. 这些指令是传递到链接器命令行的 ASCII 码字符串,例如:-defaultlib:LIBC.指令之间用空格分开.
.didat
延迟加载导入数据.可以在非发行版本的可执行文件中找到.在发行版本中,延迟加载数据 被合并到其它节中.
导出表
当一个 EXE 或 DLL 导出函数或变量时,其它 EXE 或 DLL 就可以使用这些导出的函数或变量. 为了简单起见,我把导出的函数和导出的变量统称为"符号".当导出一些符号时,最起码导出 符号的地址需要能够以一种已定义好的方式被获取.每个导出的符号都有一个与之关联的序数, 它可以用来查找这个符号. 同时, 几乎总有一个 ASCII 码格式的字符串名称与这个导出的符号关 联.一般来说,导出的符号名与源文件中的符号名是一样的,尽管它们可以被修改的不一样. 通常,当可执行文件导入符号时,它使用的是符号的名称而不是它的序号.但是当通过名 称导入时, 系统仅使用这个名称去查找所需符号对应的导出序数, 然后根据这个序数值去获取相 应的地址. 如果先使用的是序数值的话查找过程会快一点. 通过名称导出和导入只是为了让程序 员使用方便罢了. 在.DEF 文件中的 Exports 节中使用 ORDINAL 关键字可以告诉链接器创建一个导入库,这个 导入库强制函数只能通过序数导入而不能通过名称导入. 我首先介绍 IMAGE\\\\_EXPORT\\\\_DIRECTORY 结构,如下表所示:
大小 DWORD DWORD 域 Characteristics TimeDateStamp 描述 导出标志.当前未定义任何值. 导出数据的创建时间.这个域的定义与 IMAGE\\\\_NT\\\\_HEADERS.FileHeader.TimeDateStamp 相同 (从 GMT 时间 1970 年 1 月 1 日 00:00 以来的总秒数). WORD WORD DWORD MajorVersion MinorVersion Name 导出数据的主版本号.未用,设置为
  0. 导出数据的次版本号.未用,设置为
  0. 与导出符号相关的 DLL 的名称 ASCII 字符串的 RVA(例如 KERNEL
  32.DLL). DWORD Base 这个域包含了这个可执行文件的导出符号所使用的序数值的起始值. 通常情况下这个值为 1, 但并不总是这样. 当通过序数查找导出符号时, 将序数值减去这个域的值就得到了这个导出符号在导出地址表 (Export Address Table ,EAT)中的索引.
大小 DWORD
域 NumberOfFunctions
描述 EAT 中的元素数.注意 EAT 中的某些元素可能为 0,这表明没有 代码/数据使用那个序数值导出.
DWORD
NumberOfNames
导出名称表(Export Names Table,ENT)中的元素数.这个域的值总 是小于或等于 NumberOfFunctions 域的值.当某些符号仅使用序数导 出时,它就小于那个域的值.如果导出序数之间有间隔,它同样也小 于那个域的值.这个域的值也是导出序数表的大小(见下文).
DWORD
AddressOfFunctions
EAT 的 RVA.EAT 中的每个元素都是一个 RVA.其中每个非 0 的 RVA 都 对应一个导出符号.
DWORD
AddressOfNames
ENT 的 RVA.ENT 中的每个元素都是一个 ASCII 码字符串的 RVA.其中 的每个 ASCII 码字符串都对应一个由名称导出的符号.这些字符串是 按一定顺序排列的.这就使得加载器在查找导出符号时可以进行二进 制搜索.名称字符串的排序是按二进制(与 C++运行时库函数 strcmp 类似),而不是与位置相关的字母表顺序.
DWORD
AddressOfNameOrdinals
导出序号表的 RVA.这个表是一个 WORD 类型的数组.它将 ENT 中的索 引映射到导出地址表中相应的元素上.
导出目录(Export Directory)指向三个数组和一个 ASCII 码字符串表.其中只有导出地 址表是必需的,它是一个由指向导出函数的指针组成的数组.导出序数是这个数组的索引(见下 图).
让我们通过例子来看一下导出表的工作原理. 下图显示了 KERNEL
  32.DLL 导出表的部分内容: exports table: Name: TimeDateStamp: Version: Ordinal base: # of Names: KERNEL
  32.dll 3B7DDFD8 -> Fri Aug 17 23:24:08 2001
  0.00 00000001 000003A0 Characteristics: 00000000
# of functions: 000003A0
Entry Pt Ordn Name
00012ADA 000082C2
1 ActivateActCtx 2 AddAtomA
remainder of exports omitted 假设你调用 GetProcAddress 来获取 KERNEL32 中的 AddAtomA 这个 API 的地址.这时系统开 始查找 KERNEL32 的 IMAGE\\\\_EXPORT\\\\_DIRECTORY 结构. 它从那里获取了导出名称表的起始地址, 知 道了在这个数组中有 0x3A0 个元素,它通过二进制搜索来查找字符串"AddAtomA". 假设加载器发现 AddAtomA 是这个数组中的第二个元素.然后它从导出序数表(Export Ordinal Table)中读取相应的第二个值.这个值就是 AddAtomA 的导出序数.将这个导出序数作 为 EAT 的索引(加上 Base 域的值),它最终获取 AddAtomA 的相对虚拟地址(RVA)是 0x82C
  2. 将此值与 KERNEL32 的加载地址相加就得到了 AddAtomA 的实际地址.
导出转发
导出表一个特别聪明的地方是它能将一个导出函数转发(Forwarding)到其它 DLL.例如 在 Windows NT,Windows 2000 和 Windows XP 中,KERNEL32 中的 HeapAlloc 函数被转发到了 NTDLL 导出的 RtlAllocHeap 函数上.转发是在链接时通过.DEF 文件中的 EXPORTS 节中的一种特 殊语法形式来实现的.对于 HeapAlloc 这个例子,KERNEL32 的.DEF 文件一定包含下面的内容: EXPORTS HeapAlloc = NTDLL.RtlAllocHeap 怎样才能区别转发的函数与正常导出的函数呢?这需要一些技巧.通常 EAT 中包含的是导 出符号的 RVA. 但是如果这个 RVA 位于导出表中 (通过相应的 DataDirectory 中的 VirtualAddress 域和 Size 域进行判断),那么它就是转发的. 当转发一个符号时,它的 RVA 很明显不能是当前模块中的代码或数据的地址.实际上,它 的 RVA 指向一个由 DLL 和转发到的符号名称组成的字符串.在前面的例子中,这个字符串就是 NTDLL.RtlAllocHeap.
导入表
与导出函数或变量相反的就是导入它们.为了与前面保持一致,我仍然使用"符号"这个 术语来指代导入的函数和变量. 导入数据被保存在 IMAGE\\\\_IMPORT\\\\_DESCRIPTOR 结构中.对应着导入表的数据目录项就指向 由这个结构组成的数组.每个 IMAGE\\\\_IMPORT\\\\_DESCRIPTOR 结构都与一个导入的可执行文件对应. 这个数组的最后一个元素的所有域都被设置为
  0.下表是这个结构的内容:
大小 DWORD 域 OriginalFirstThunk 描述 这个域的命名太不恰当.它包含导入名称表的 RVA.导入名称表是一个 IMAGE\\\\_THUNK\\\\_DATA 结构数组.这个域被设置为 0 表示 IMAGE\\\\_IMPORT\\\\_DESCRIPTOR 结构数组的结尾.
大小 DWORD
域 TimeDateStamp
描述 如果可执行文件并未绑定导入的 DLL, 这个域的值为
  0. 当使用老的绑定 类型进行绑定(参考"绑定"一节)时,这个域包含日期/时间戳.当使 用新的绑定类型进行绑定时,这个域的值为-
  1.
DWORD
ForwarderChain
这是首个转发的函数的索引. 如果没有转发的函数, 这个域被设置为-
  1. 它仅用于老的绑定类型,因为那种绑定类型不能很有效地处理转发的函 数.
DWORD DWORD
Name FirstThunk
导入的 DLL 名称字符串(ASCII 码格式)的 RVA. 导入地址表的 RVA.IAT 是一个 IMAGE\\\\_THUNK\\\\_DATA 结构数组.
每个 IMAGE\\\\_IMPORT\\\\_DESCRIPTOR 结构指向两个数组,这两个数组实际上是一样的.它们有 好几种叫法, 但最常用的名称是导入地址表 (Import Address Table, IAT) 和导入名称表 (Import Name Talbe,INT).下图显示的是可执行文件从 USER
  32.DLL 中导入一些 API 时的情况.
这两个数组的元素均为 IMAGE\\\\_THUNK\\\\_DATA 类型的结构,这个结构是一个与指针大小相同的 共用体(或者称为联合).每个 IMAGE\\\\_THUNK\\\\_DATA 结构对应着从可执行文件中导入的一个函数. 这两个数组最后都以一个值为 0 的 IMAGE\\\\_THUNK\\\\_DATA 结构作为结尾.这个共用体(实际是一个 DWORD 值)可以有如下几种含义: DWORD ForwarderString;// 转发函数字符串的 RVA(见上文) DWORD Function; DWORD Ordinal; // 导入函数的内存地址 // 导入函数的序数
DWORD AddressOfData; // IMAGE\\\\_IMPORT\\\\_BY\\\\_NAME 和导入函数名称的 RVA(见下文) IAT中的IMAGE\\\\_THUNK\\\\_DATA结构的用途可以分为两种.在可执行文件中,它们或者是导入函 数的序数,或者是一个IMAGE\\\\_IMPORT\\\\_BY\\\\_NAME结构的RVA.IMAGE\\\\_IMPORT\\\\_BY\\\\_NAME结构只是一个 WORD类型的值,它后面跟着导入函数的名称字符串.这个WORD类型的值是一个"提示(hint)", 它提示加载器导入函数的序号可能是什么. 当加载器加载可执行文件时, 它用导入函数的实际地 址来覆盖IAT中的每个元素. 这一点是理解下文的关键. 我强烈建议你读一读本期杂志中Russell Osterlund的文章??揭开Windows加载器的神秘面纱,这篇文章详细讲述了Windows加载器的行 为. 在可执行文件被加载之前,是否存在一种方法能够区分 IMAGE\\\\_THUNK\\\\_DATA 结构中到底包含 的是导入函数的序数呢, 还是 IMAGE\\\\_IMPORT\\\\_BY\\\\_NAME 结构的 RVA 呢?答案在 IMAGE\\\\_THUNK\\\\_DATA
结构的最高位.如果它为 1,那么低 31 位(在 64 位可执行文件中是低 63 位)中是导入函数的 序数. 如果最高位为 0, 那么 IMAGE\\\\_THUNK\\\\_DATA 结构的值就是 IMAGE\\\\_IMPORT\\\\_BY\\\\_NAME 结构的 RVA. 另一个数组 INT,本质上与 IAT 是一样的.它也是一个 IMAGE\\\\_THUNK\\\\_DATA 结构数组.关键 的区别在于当加载器将可执行文件加载进内存时,它并不覆盖 INT.为什么对于从 DLL 中导入的 每组 API 都需要有两个并列的数组呢?答案在于一个称为绑定(binding)的概念.当在绑定过 程(后面我会讲到)中覆盖可执行文件的 IAT 时,需要以某种方式
  •  
 

相关内容

深入剖析Win32可移植可执行文件格式(第二部分)

  深入剖析 Win32 可移植可执行文件格式 第二部分作者:Matt Pietrek上个月在本文的第一部分中,我首先对可移植可执行文件进行了全面的介绍.我讲了 PE 文 件的历史和组成 PE 文件头的数据结构,还讲了节表.PE 文件头和节表告诉你在可执行文件中都 包含什么类型的代码和数据,以及在哪里能找到它们. 本月我要讲一下常见的节.最后讲一下我的最新的经过彻底改进的PEDUMP程序,它可以在 2002 年 2 月的专栏中下载.如果你不熟悉PE文件的基本概念,应该首先读一下本文的第一部分. 上个 ...

可执行文件格式(大地小神之个人收藏)

  可执行文件格式UNIX/LINUX 平台下三种主要的可执行文件格式:a.out (assemblerand link editor output 汇编器和链接编辑器的输出)、 COFF(Common Object File Format 通用对象文件格式)、ELF (Executableand Linking Format 可执行和链接格式)。 首先是对可执行文件格式的一个综述,并通过描述 ELF 文件加 载过程以揭示可执行文件内容与加载运行操作之间的关系。随后依 此讨论了此三种文件格式,并着重 ...

03 第二部分 投标函格式B版071106final

  招标书编号:DPLNG-PL-ITT-016第二部分:投标函格式 第 1 页 共 13 页第二部分 投标函格式广东大鹏液化天然气有限公司招标书编号:DPLNG-PL-ITT-016第二部分:投标函格式 第 2 页 共 13 页目录附件A 投标函(格式) 附件B 投标保函(格式) 附件C 授权书(格式) 附件D 联合协议(如有)广东大鹏液化天然气有限公司招标书编号:DPLNG-PL-ITT-016第二部分:投标函格式 第 3 页 共 13 页附件 A 投标函( 格式) 投标函 ( 格式 )广东大鹏 ...

文件格式

  汇聚爱心、传递梦想、燃烧激情、托起希望常用文件格式一、 关于常用文件的统一格式要求 (一) 通知 通知(样本参见附件一) 1、 标题要求: 标题要居中 (较长可分为两行) 采用二号宋体加粗, , 并写明“关于 XXXX 的通知” 。 2、 正文要求:采用四号宋体或仿宋体书写,通知对象顶格写。正 文与标题间空一行,开始首行空两格。换行首行空两格。会议 性通知发布内容(如:与会人、会议地点、会议时间等)采用 大标题形式逐条列出。 3、 落款要求:采用四号宋体加粗,落款与正文间空两行,并居于 通知右下 ...

招标文件格式

  酒泉市物业管理招标文件(示范文本)第一部分投标邀请按照国务院《物业管理条例》《酒泉市物业管理条例》和《酒泉市物业管理招标 、 投标暂行办法》的规定,现决定对 务进行 (项目名称)的物业管理服(公开/邀请)招标。兹邀请合格投标人以密封标书的方式前来投标。一、招标项目的简要说明 本项目位于酒泉市 四至范围:东至 (或见附图) 。 本项目规划设计的物业类型为: 本项目总用地面积 米(其中公建用地 平方米。 本项目总建筑面积 米,地上总建筑面积 用房建筑面积 筑面积 平方米。其中地下总建筑面积 平方米( ...

通知文件格式样式

  粤府办〔2005〕92号 ━━━━━━━━━━━━━━━━━━━━━━━━━━━ 转发科技部关于国家高新技术产业 开发区技术创新纲要的通知各地级以上市人民政府,省政府各部门、各直属机构: 现将科技部制定的《国家高新技术产业开发区技术创新纲要》 (国科发火字〔2005〕16 号,以下简称《纲要》)转发给你们,经 省人民政府同意,提出如下意见,请一并认真贯彻执行。 一、进一步提高认识,高度重视高新区的技术创新工作。各地、 各有关部门要坚持科学发展观,认真把握《纲要》精神实质,切实 指导和协调高新区做 ...

资格预审文件格式

  广州南沙开发区灵新大道十二涌桥改造工程施工招标公告资格预审文件格式目录1广州南沙开发区灵新大道十二涌桥改造工程施工招标公告1、 资格预审审查表 2、 资格预审申请递交信 3、 投标单位一般情况表 4、 拟投入主要人员资历表 5、 人员履历表 6、 拟投入主要机械设备情况表 7、 近年在广州地区承建类似工程情况一览表 8、 在建工程情况一览表 9、 最新的企业资产负债表 10、 10、 资审材料原件核对表 11、 11、 投标通知书格式 12、 12、 投标复函格式 13、 13、 其它广州南沙开 ...

招投标文件格式 范文

  招标文件项目标号: 项目标号: 项目标名: 项目标名:招 标 人: 监管服务: 监管服务: 日期-1-第一章 投标邀请书某公司就某项目在交易中心进行公开招标,特邀贵单位参加。有关事项如下: 一、招标内容: 项目标号: 项目标名: 项目内容: (1)一作业区施工安装内容 1)机务专业: 2)电气专业: (2)二作业区施工安装内容 二、招标文件发售 发售时间: 2010 年 9 月 19 日至 2010 年 9 月 27 日, 每天 8:30-11:30, 14:30-17:30 (公休日除外) , ...

第二章 投标文件格式

  XX 公司 XX 工程 承包招标文件招标编号: 招标编号第一卷 商务部分 第二章 投标文件格式招标人: 招标人:XX 公司 招标代理机构: 招标代理机构:XX 招标公司 年 月 日GXTC-XXXXXXXXX 公司 XX 工程承包招标文件目录第一部分 资质及技术部分 .................................................................................................................... ...

XXX程序文件格式模版

  珠海市杰威汽车电机有限公司标题:1.目的 1.目的程序文件编 号: XXXXXX 版 本: XX 第 1 页 ,共4XXXXX 程序页规范公司对人力资源合理配置、招募、管理等相关管理过程,有效的做好选才、育才、用才、留才之人力 资源管理。确保人力资源满足质量管理体系的要求。2.适用范围 2.适用范围适用于公司所有员工。3.引用文件 3.引用文件GB/T 18305-2010 ISO/TS 16949:2009 6.2 文件控制4.术语和定义 4.术语和定义4.1 离职:包括公司辞退、公司开除、员 ...

热门内容

资讯网广告销售计划

  www.macauslot.com ????告?售??2008年2月澳?彩票有限公司 成立日期:1998年6月 公司理念:足球博彩??化 管理文化:以客?本澳?彩票有限公司 ?洲首?合法足?球博彩? ?金投注 ? ??投注 ? ?上投注? WAP投注 ???macauslot.com? 1998年投入?作 ? 2000年12月加入?球?目?大的足球市?2004年度足球投注???: 中? 香港 澳? 154? 267? 85?? (不包括非法外?,04年估??2,000?)投注客????料? ...

计算机系学生党支部2010年“十个一”活动计划

  十个一” 计算机系学生党支部 2010 年“十个一” 活动计划学生党支部是学院党组织的基层单位,是学院学生思想政 治工作能落到实处的战斗堡垒。为了提高党员的整体素质,不 断加强党性修养,增强党性观念,更好的发挥学生党员的先锋 模范作用。根据院党委的要求,并结合我系实际情况,经学生 党支部研究讨论,特制定我系 2010 年“十个一”活动计划: 活动内容: 活动内容 1、读书学习活动。深入学习实践科学发展观,促进学生成长成才,加强理论学习,开阔视野。2、观看红色电影。除理论学习外,组织党员、入党积极 ...

初中英语游戏教学初探

  2009年第15期 (总第127期)现代企业文化MODERN ENTERPRISE CUUⅢRENO.15,2009(CumulativetyNO.1 27)初中英语游戏教学初探薛发翠(廊坊市第十中学,河北廊坊065000)摘要:兴趣是学好语言的关键。激发学生学习英语的兴趣T:Oh,No,itisn’t. S2:Is thisa是初中阶段英语教学的一项重要任务。英语教学要结合学生的 生理和心理特点。创设有利于引起学生学习兴趣的教学氛围。关键词:初中英语教学;英语学习兴趣;学生心理 中图分类号:G ...

出租车夜班承包经营合同

  出租车承包经营合同甲方(出租人) : 乙方(承租人) : 为了发挥出租车的最佳效益,调动一切积极因素,保障车主利益, 增加驾驶员收入,更好地服务市民,根据《中华人民共和国合同法》 和《湖北省出租汽车客运管理办法》 ,经甲、乙双方平等协商一致,自 愿签订本合同。 第一条 为 年 甲方将享有经营收益权的出租车,车号为 月 日至 年 月 日止,为期 的夜班 (时间为 18:30-5:30)承包给乙方 第二条 乙方须向甲方缴纳人民币 从事经营活动,承包期限 个月。 元,作为安全服务质量保证金,此金在合同 ...

南陵县公安局行政权力流程图(行政许可权类)

  南陵县公安局行政权力流程图(行政许可权类)申请人提出申请 并提供有关材料出 窗口 不符合申请条件退回申请人,补齐有关 材料重新申请窗口符合申请条件受理之日起 30 日内对有关材料进行审核符合申请条件的 不符合申请条件的对符合条件的, 准予核 发 《大型群众文化体育 活动安全许可》对不符合条件的,不予核发《大 型群众文化体育活动安全许 可》 ,并书面向申请人说明理由《大型群众文化体育活动安全许可》 办理流程图申请人提出申请 并提供有关材料出 窗口 不符合申请条件退回申请人,补齐有关 材料,重新申报 ...