没有合适的资源?快使用搜索试试~ 我知道了~
首页PE文件格式(大家可以参考一下)
PE文件格式(大家可以参考一下)
5星 · 超过95%的资源 需积分: 12 35 下载量 152 浏览量
更新于2023-03-03
收藏 270KB PDF 举报
Windows NT 3.1 引入了一种名为PE 文件格式的新可执行文件格式。PE 文件格式 的规范包含在了MSDN 的CD 中( Specs and Strategy, Specifications, Windows NT File Format Specifications) , 但是它非常之晦涩。 然而这一的文档并未提供足够的信息,所以开发者们无法很好地弄懂PE 格式。本 文旨在解决这一问题,它会对整个的PE 文件格式作一个十分彻底的解释,另外,本文中 还带有对所有必需结构的描述以及示范如何使用这些信息的源码示例。 为了获得PE 文件中所包含的重要信息, 我编写了一个名为PEFILE.DLL 的动态链 接库, 本文中所有出现的源码示例亦均摘自于此。这个DLL 和它的源代码都作为PEFile 示例程序的一部分包含在了CD 中( 译注:示例程序请在MSDN 中寻找,本站恕不提供), 你可以在你自己的应用程序中使用这个DLL; 同样, 你亦可以依你所愿地使用并构建它 的源码。在本文末尾,你会找到PEFILE.DLL 的函数导出列表和一个如何使用它们的说明。 我觉得你会发现这些函数会让你从容应付PE 文件格式的。 介绍
资源详情
资源推荐
PE 文 件 格 式 详 解
文 件 格 式 详 解文 件 格 式 详 解
文 件 格 式 详 解 (上
上上
上 )
作 者 : MSDN
译 者 : 李 马 (http://home.nuc.edu.cn/~titilima)
摘 要
摘 要摘 要
摘 要
Windows NT 3.1 引 入 了 一 种 名 为 PE 文 件 格 式 的 新 可 执 行 文 件 格 式 。 PE 文 件 格 式
的 规 范 包 含 在 了 MSDN 的 CD 中 ( Specs and Strategy, Specifications, Windows NT File
Format Specifications) , 但 是 它 非 常 之 晦 涩 。
然 而 这 一 的 文 档 并 未 提 供 足 够 的 信 息 ,所 以 开 发 者 们 无 法 很 好 地 弄 懂 PE 格 式 。 本
文 旨 在 解 决 这 一 问 题 ,它 会 对 整 个 的 PE 文 件 格 式 作 一 个 十 分 彻 底 的 解 释 ,另 外 ,本 文 中
还 带 有 对 所 有 必 需 结 构 的 描 述 以 及 示 范 如 何 使 用 这 些 信 息 的 源 码 示 例 。
为 了 获 得 PE 文 件 中 所 包 含 的 重 要 信 息 , 我 编 写 了 一 个 名 为 PEFILE.DLL 的 动 态 链
接 库 , 本 文 中 所 有 出 现 的 源 码 示 例 亦 均 摘 自 于 此 。 这 个 DLL 和 它 的 源 代 码 都 作 为 PEFile
示 例 程 序 的 一 部 分 包 含 在 了 CD 中( 译 注 :示 例 程 序 请 在 MSDN 中 寻 找 ,本 站 恕 不 提 供 ),
你 可 以 在 你 自 己 的 应 用 程 序 中 使 用 这 个 DLL; 同 样 , 你 亦 可 以 依 你 所 愿 地 使 用 并 构 建 它
的 源 码 。在 本 文 末 尾 ,你 会 找 到 PEFILE.DLL 的 函 数 导 出 列 表 和 一 个 如 何 使 用 它 们 的 说 明 。
我 觉 得 你 会 发 现 这 些 函 数 会 让 你 从 容 应 付 PE 文 件 格 式 的 。
介 绍
介 绍介 绍
介 绍
Windows 操 作 系 统 家 族 最 近 增 加 的 Windows NT 为 开 发 环 境 和 应 用 程 序 本 身 带 来
了 很 大 的 改 变 ,这 之 中 一 个 最 为 重 大 的 当 属 PE 文 件 格 式 了 。新 的 PE 文 件 格 式 主 要 来 自
于 UNIX 操 作 系 统 所 通 用 的 COFF 规 范 , 同 时 为 了 保 证 与 旧 版 本 MS-DOS 及 Windows 操
作 系 统 的 兼 容 , PE 文 件 格 式 也 保 留 了 MS-DOS 中 那 熟 悉 的 MZ 头 部 。
在 本 文 之 中 , PE 文 件 格 式 是 以 自 顶 而 下 的 顺 序 解 释 的 。 在 你 从 头 开 始 研 究 文 件 内
容 的 过 程 之 中 , 本 文 会 详 细 讨 论 PE 文 件 的 每 一 个 组 成 部 分 。
许 多 单 独 的 文 件 成 分 定 义 都 来 自 于 Microsoft Win32 SDK 开 发 包 中 的 WINNT.H 文
件 , 在 这 个 文 件 中 你 会 发 现 用 来 描 述 文 件 头 部 和 数 据 目 录 等 各 种 成 分 的 结 构 类 型 定 义 。
但 是 , 在 WINNT.H 中 缺 少 对 PE 文 件 结 构 足 够 的 定 义 , 在 这 种 情 况 下 , 我 定 义 了 自 己 的
结 构 来 存 取 文 件 数 据 。 你 会 在 PEFILE.DLL 工 程 的 PEFILE.H 中 找 到 这 些 结 构 的 定 义 , 整
套 的 PEFILE.H 开 发 文 件 包 含 在 PEFile 示 例 程 序 之 中 。
本 文 配 套 的 示 例 程 序 除 了 PEFILE.DLL 示 例 代 码 之 外 ,还 有 一 个 单 独 的 Win32 示 例
应 用 程 序 ,名 为 EXEVIEW.EXE。创 建 这 一 示 例 目 的 有 二 :首 先 ,我 需 要 测 试 PEFILE.DLL
的 函 数 ,并 且 某 些 情 况 要 求 我 同 时 查 看 多 个 文 件 ;其 次 ,很 多 解 决 PE 文 件 格 式 的 工 作 和
直 接 观 看 数 据 有 关 。例 如 ,要 弄 懂 导 入 地 址 名 称 表 是 如 何 构 成 的 ,我 就 得 同 时 查 看 .idata
段 头 部 、导 入 映 像 数 据 目 录 、可 选 头 部 以 及 当 前 的 .idata 段 实 体 ,而 EXEVIEW.EXE 就 是
查 看 这 些 信 息 的 最 佳 示 例 。
闲 话 少 叙 , 让 我 们 开 始 吧 。
PE 文 件 结 构
文 件 结 构文 件 结 构
文 件 结 构
PE 文 件 格 式 被 组 织 为 一 个 线 性 的 数 据 流 , 它 由 一 个 MS-DOS 头 部 开 始 , 接 着 是 一
个 是 模 式 的 程 序 残 余 以 及 一 个 PE 文 件 标 志 ,这 之 后 紧 接 着 PE 文 件 头 和 可 选 头 部 。这 些
之 后 是 所 有 的 段 头 部 , 段 头 部 之 后 跟 随 着 所 有 的 段 实 体 。 文 件 的 结 束 处 是 一 些 其 它 的 区
域 ,其 中 是 一 些 混 杂 的 信 息 ,包 括 重 分 配 信 息 、符 号 表 信 息 、行 号 信 息 以 及 字 串 表 数 据 。
我 将 所 有 这 些 成 分 列 于 图 1。
图
图图
图 1.PE 文 件 映 像 结 构
文 件 映 像 结 构文 件 映 像 结 构
文 件 映 像 结 构
从 MS-DOS 文 件 头 结 构 开 始 ,我 将 按 照 PE 文 件 格 式 各 成 分 的 出 现 顺 序 依 次 对 其 进
行 讨 论 , 并 且 讨 论 的 大 部 分 是 以 示 例 代 码 为 基 础 来 示 范 如 何 获 得 文 件 的 信 息 的 。 所 有 的
源 码 均 摘 自 PEFILE.DLL 模 块 的 PEFILE.C 文 件 。 这 些 示 例 都 利 用 了 Windows NT 最 酷 的
特 色 之 一 ——内 存 映 射 文 件 , 这 一 特 色 允 许 用 户 使 用 一 个 简 单 的 指 针 来 存 取 文 件 中 所 包
含 的 数 据 , 因 此 所 有 的 示 例 都 使 用 了 内 存 映 射 文 件 来 存 取 PE 文 件 中 的 数 据 。
注 意 : 请 查 阅 本 文 末 尾 关 于 如 何 使 用 PEFILE.DLL 的 那 一 段 。
MS-DOS 头 部
头 部头 部
头 部 /实 模 式 头 部
实 模 式 头 部实 模 式 头 部
实 模 式 头 部
如 上 所 述 ,PE 文 件 格 式 的 第 一 个 组 成 部 分 是 MS-DOS 头 部 。在 PE 文 件 格 式 中 ,它
并 非 一 个 新 概 念 , 因 为 它 与 MS-DOS 2.0 以 来 就 已 有 的 MS-DOS 头 部 是 完 全 一 样 的 。 保
留 这 个 相 同 结 构 的 最 主 要 原 因 是 , 当 你 尝 试 在 Windows 3.1 以 下 或 MS-DOS 2.0 以 上 的
系 统 下 装 载 一 个 文 件 的 时 候 , 操 作 系 统 能 够 读 取 这 个 文 件 并 明 白 它 是 和 当 前 系 统 不 相 兼
容 的 。 换 句 话 说 , 当 你 在 MS-DOS 6.0 下 运 行 一 个 Windows NT 可 执 行 文 件 时 , 你 会 得
到 这 样 一 条 消 息 : “This program cannot be run in DOS mode.”如 果 MS-DOS 头 部 不 是
作 为 PE 文 件 格 式 的 第 一 部 分 的 话 ,操 作 系 统 装 载 文 件 的 时 候 就 会 失 败 ,并 提 供 一 些 完 全
没 用 的 信 息 , 例 如 : “The name specified is not recognized as an internal or external
command, operable program or batch file.”
MS-DOS 头 部 占 据 了 PE 文 件 的 头 64 个 字 节 , 描 述 它 内 容 的 结 构 如 下 :
//WINNT.H
typedef struct _IMAGE_DOS_HEADER { // DOS 的.EXE 头部
USHORT e_magic; // 魔术数字
USHORT e_cblp; // 文件最后页的字 节数
USHORT e_cp; // 文 件 页 数
USHORT e_crlc; // 重定义元素个数
USHORT e_cparhdr; // 头部 尺 寸 , 以段落为单位
USHORT e_minalloc; // 所需 的 最 小 附加段
USHORT e_maxalloc; // 所需 的 最 大 附加段
USHORT e_ss; // 初 始 的 SS 值( 相对偏 移 量 )
USHORT e_sp; // 初 始 的 SP 值
USHORT e_csum; // 校验和
USHORT e_ip; // 初 始 的 IP 值
USHORT e_cs; // 初 始 的 CS 值( 相对偏 移 量 )
USHORT e_lfarlc; // 重分配 表 文 件 地址
USHORT e_ovno; // 覆盖号
USHORT e_res[4]; // 保留字
USHORT e_oemid; // OEM 标识 符 (相对 e_oeminfo)
USHORT e_oeminfo; // OEM 信息
USHORT e_res2[10]; // 保留 字
LONG e_lfanew; // 新 exe 头部的文 件 地 址
} IMAGE_DOS_HEADER, *PIMAGE_DOS_HEADER;
第 一 个 域 e_magic, 被 称 为 魔 术 数 字 , 它 被 用 于 表 示 一 个 MS-DOS 兼 容 的 文 件 类 型 。 所
有 MS-DOS 兼 容 的 可 执 行 文 件 都 将 这 个 值 设 为 0x5A4D, 表 示 ASCII 字 符 MZ。 MS-DOS
头 部 之 所 以 有 的 时 候 被 称 为 MZ 头 部 , 就 是 这 个 缘 故 。 还 有 许 多 其 它 的 域 对 于 MS-DOS
操 作 系 统 来 说 都 有 用 , 但 是 对 于 Windows NT 来 说 , 这 个 结 构 中 只 有 一 个 有 用 的 域 ——
最 后 一 个 域 e_lfnew, 一 个 4 字 节 的 文 件 偏 移 量 , PE 文 件 头 部 就 是 由 它 定 位 的 。 对 于
Windows NT 的 PE 文 件 来 说 , PE 文 件 头 部 是 紧 跟 在 MS-DOS 头 部 和 实 模 式 程 序 残 余 之
后 的 。
实 模 式 残 余 程 序
实 模 式 残 余 程 序实 模 式 残 余 程 序
实 模 式 残 余 程 序
实 模 式 残 余 程 序 是 一 个 在 装 载 时 能 够 被 MS-DOS 运 行 的 实 际 程 序 。 对 于 一 个
MS-DOS 的 可 执 行 映 像 文 件 ,应 用 程 序 就 是 从 这 里 执 行 的 。对 于 Windows、OS/2、Windows
NT 这 些 操 作 系 统 来 说 ,MS-DOS 残 余 程 序 就 代 替 了 主 程 序 的 位 置 被 放 在 这 里 。这 种 残 余
程 序 通 常 什 么 也 不 做 , 而 只 是 输 出 一 行 文 本 , 例 如 : “This program requires Microsoft
Windows v3.1 or greater.”当 然 , 用 户 可 以 在 此 放 入 任 何 的 残 余 程 序 , 这 就 意 味 着 你 可
能 经 常 看 到 像 这 样 的 东 西 : “You can''t run a Windows NT application on OS/2, it''s
simply not possible.”
当 为 Windows 3.1 构 建 一 个 应 用 程 序 的 时 候 , 链 接 器 将 向 你 的 可 执 行 文 件 中 链 接
一 个 名 为 WINSTUB.EXE 的 默 认 残 余 程 序 。 你 可 以 用 一 个 基 于 MS-DOS 的 有 效 程 序 取 代
WINSTUB,并 且 用 STUB 模 块 定 义 语 句 指 示 链 接 器 ,这 样 就 能 够 取 代 链 接 器 的 默 认 行 为 。
为 Windows NT 开 发 的 应 用 程 序 可 以 通 过 使 用 -STUB:链 接 器 选 项 来 实 现 。
PE 文 件 头 部 与 标 志
文 件 头 部 与 标 志文 件 头 部 与 标 志
文 件 头 部 与 标 志
PE 文 件 头 部 是 由 MS-DOS 头 部 的 e_lfanew 域 定 位 的 ,这 个 域 只 是 给 出 了 文 件 的 偏
移 量 ,所 以 要 确 定 PE 头 部 的 实 际 内 存 映 射 地 址 ,就 需 要 添 加 文 件 的 内 存 映 射 基 地 址 。例
如 , 以 下 的 宏 是 包 含 在 PEFILE.H 源 文 件 之 中 的 :
//PEFILE.H
#define NTSIGNATURE(a) ((LPVOID)((BYTE *)a + \
((PIMAGE_DOS_HEADER)a)->e_lfanew))
在 处 理 PE 文 件 信 息 的 时 候 ,我 发 现 文 件 之 中 有 些 位 置 需 要 经 常 查 阅 。既 然 这 些 位 置 仅 仅
是 对 文 件 的 偏 移 量 , 那 么 用 宏 来 实 现 这 些 定 位 就 比 较 容 易 , 因 为 它 们 较 之 函 数 有 更 好 的
表 现 。
请 注 意 这 个 宏 所 获 得 的 是 PE 文 件 标 志 , 而 并 非 PE 文 件 头 部 的 偏 移 量 。 那 是 由 于
自 Windows 与 OS/2 的 可 执 行 文 件 开 始 ,.EXE 文 件 都 被 赋 予 了 目 标 操 作 系 统 的 标 志 。对
于 Windows NT 的 PE 文 件 格 式 而 言 , 这 一 标 志 在 PE 文 件 头 部 结 构 之 前 。 在 Windows
和 OS/2 的 某 些 版 本 中 ,这一 标 志 是 文 件 头 的 第 一 个 字 。同 样 ,对 于 PE 文 件 格 式 ,Windows
NT 使 用 了 一 个 DWORD 值 。
以 上 的 宏 返 回 了 文 件 标 志 的 偏 移 量 ,而 不 管 它 是 哪 种 类 型 的 可 执 行 文 件 。所 以 ,文
件 头 部 是 在 DWORD 标 志 之 后 , 还 是 在 WORD 标 志 处 , 是 由 这 个 标 志 是 否 Windows NT
文 件 标 志 所 决 定 的 。 要 解 决 这 个 问 题 , 我 编 写 了 ImageFileType 函 数 ( 如 下 ) , 它 返 回
了 映 像 文 件 的 类 型 :
//PEFILE.C
DWORD WINAPI ImageFileType (LPVOID lpFile)
{
/* 首 先 出 现 的 是 DOS 文 件标志 */
if (*(USHORT *)lpFile == IMAGE_DOS_SIGNATURE)
{
/* 由 DOS 头部决 定 PE 文件头部的 位 置 */
if (LOWORD (*(DWORD *)NTSIGNATURE (lpFile)) ==
IMAGE_OS2_SIGNATURE ||
LOWORD (*(DWORD *)NTSIGNATURE (lpFile)) ==
IMAGE_OS2_SIGNATURE_LE)
return (DWORD)LOWORD(*(DWORD *)NTSIGNATURE (lpFile));
else if (*(DWORD *)NTSIGNATURE (lpFile) ==
IMAGE_NT_SIGNATURE)
return IMAGE_NT_SIGNATURE;
else
return IMAGE_DOS_SIGNATURE;
}
else
/* 不明文件种 类 */
return 0;
}
以 上 列 出 的 代 码 立 即 告 诉 了 你 NTSIGNATURE 宏 有 多 么 有 用 。 对 于 比 较 不 同 文 件 类 型 并
且 返 回 一 个 适 当 的 文 件 种 类 来 说 ,这 个 宏 就 会 使 这 两 件 事 变 得 非 常 简 单 。WINNT.H 之 中
定 义 的 四 种 不 同 文 件 类 型 有 :
//WINNT.H
#define IMAGE_DOS_SIGNATURE 0x5A4D // MZ
#define IMAGE_OS2_SIGNATURE 0x454E // NE
#define IMAGE_OS2_SIGNATURE_LE 0x454C // LE
#define IMAGE_NT_SIGNATURE 0x00004550 // PE00
首 先 ,Windows 的 可 执 行 文 件 类 型 没 有 出 现 在 这 一 列 表 中 ,这 一 点 看 起 来 很 奇 怪 。但 是 ,
在 稍 微 研 究 一 下 之 后 , 就 能 得 到 原 因 了 : 除 了 操 作 系 统 版 本 规 范 的 不 同 之 外 , Windows
的 可 执 行 文 件 和 OS/2 的 可 执 行 文 件 实 在 没 有 什 么 区 别 。 这 两 个 操 作 系 统 拥 有 相 同 的 可
执 行 文 件 结 构 。
剩余32页未读,继续阅读
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功