65.9K
CodeProject 正在变化。 阅读更多。
Home

解析 PE (EXE, DLL, OCX 文件) 和新的依赖关系查看器

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.55/5 (19投票s)

2009年6月2日

CDDL

3分钟阅读

viewsIcon

105035

downloadIcon

8521

关于 PE 数据结构的简要基本说明,附带示例

引言

我将介绍一个新的依赖关系查看器,它具有新的外观,但我的目标不是向您介绍一个依赖关系查看器,而是让您熟悉 PE (Portable Executable) 格式。 我希望你们都听说过 PE,它只不过是我们的 Windows 可执行文件 (EXE, DLL, OCX 等),实际上它继承自 COFF (通用对象文件格式),COFF 用于 UNIX 中的对象文件和可执行文件。

通过这篇文章,我让您熟悉编写自己的依赖关系查看器的代码,以便您可以自定义并制作自己的依赖关系查看器。 除此之外,您还可以了解 PE,以及如何简单地解析 PE 文件。 为了更好地说明,我附带了一个名为 ExeInside 的应用程序和源代码。

背景

选择“Portable Executable”这个术语是因为目的是为所有版本的 Windows(在所有支持的 CPU 上)提供一种通用的文件格式。 在很大程度上,这一目标已经实现,Windows NT 及其后代、Windows 95 及其后代和 Windows CE 使用了相同的格式。

要熟悉 PE 格式,首先要熟悉一些数据结构,这些数据结构用于管理 Windows 可执行文件内部的数据。

  • PE 标头
  • PE 节
  • 导入
  • 导出
  • 资源
  • 闭运算

Using the Code

在编译代码之前,请确保您已正确安装 Microsoft Platform SDK。 当前项目是为 Visual Studio 6.0 制作的,但可以转换为更高版本。

下面提到的所有结构都定义在 WINNT.h 文件中。 由于 PE 文件基本上以 MS DOS 标头 MZ 标头开头,为了获得更多知识,例如导入和导出标头,您需要根据偏移量进行进一步解析,这样您甚至可以获得调试信息。

让我介绍一下用于 PE 文件格式编码的常用数据结构

我只解释一些数据结构,如果您需要更多信息,可以参考 MSDN。

IMAGE_DOS_HEADER:数据结构保存 DOS 的标头,或者简单地说,是我们可以从中获取参考以获取 PE 文件内容的起始地址。

IMAGE_OPTIONAL_HEADER:该数据结构保存导入和导出地址,它根据偏移量保存导入和导出的起始地址。

_IMAGE_EXPORT_DIRECTORY:此数据结构保存导出地址,基于此地址,我们可以获取 PE 文件的导出函数。

IMAGE_IMPORT_DESCRIPTOR:此数据结构保存导入地址,基于此地址,我们可以获取 PE 文件的导入函数。

下面给出了示例说明

// This code loads a Module (say a DLL) and its start address 
// is given as the base address of the DOS header.
HMODULE hMod;
hMod = LoadLibrary( lpctszModName_i )
IMAGE_DOS_HEADER* IDH = (IMAGE_DOS_HEADER*)hMod;

// This code get the optional header from DOS 
// header based on the offset from DOS header.
IMAGE_OPTIONAL_HEADER* IOH = 
        (IMAGE_OPTIONAL_HEADER*)((BYTE*)hMod + IDH->e_lfanew + 24);
 
// This code gets the import descriptor from the base 
// address by taking the offset of start address and address of       
// IMAGE_DIRECTORY_ENTRY_IMPORT, after getting IMAGE_IMPORT_DESCRIPTOR, 
// you can get the imported functions or ordinals.
IMAGE_IMPORT_DESCRIPTOR* IID = 
       (IMAGE_IMPORT_DESCRIPTOR*)((BYTE*)hMod + 
IOH->DataDirectory[ IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress);
 
// Same as above code below will give the Export information.
_IMAGE_EXPORT_DIRECTORY* pExportDescriptor = 
               (_IMAGE_EXPORT_DIRECTORY*)((BYTE*)hMod + 
  IOH->DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress);

关注点

我给您一个带有实现的简单示例,它肯定会帮助您理解我们的依赖关系查看器是如何编码的,但永远不要与它比较,这只是一个概述。 我无法将我的代码与 Mark E. Russinovich 的代码进行比较。 撇开这些,这是我的第一篇文章,如果它对您有帮助,我肯定会写很多文章。 如果它不值得或者您有任何建议,请通知我。 我计划更多主题,如果我的上帝允许我写的话。

历史

这个 ExeInside Beta 是一个应用程序,编写它的目的只是为了理解依赖关系查看器的工作原理,并且我仍在尝试更有效地改进它,我永远不会说它完全没有错误,但它已经被测试到一定程度,并且它具有一些附加功能,例如,您可以指定一个 PE 文件(EXE、DLL、OCX)并指定一个目录,它将搜索哪些 PE 文件与指定的 PE 文件有依赖关系。

好吧,我希望您能给予合作,让它比以往更好。

欲了解更多信息,请访问并理解下面的链接,用于学习目的 http://www.skynet.ie/~caolan/pub/winresdump/winresdump/doc/pefile.html

历史

  • 2009 年 6 月 2 日:初始帖子
  • 2012 年 5 月 29 日:小修正。
© . All rights reserved.