PeView 是一款基于C/C++开发的命令行版PE文件解析工具,专门用于解析Windows可执行文件并提供详尽的文件结构和交互式查询功能,帮助用户理解和分析目标程序的内部构成,是逆向分析和软件调试中的重要工具,本次分享工具源代码及使用方法,读者可根据自己的需要参考学习,并以此来更好的理解PE文件格式的构成。

该命令行工具提供了广泛的功能,可以查看文件结构(如DOS头、NT头、数据目录、节表)、导入导出表信息、重定位表内容,以及检测资源和执行地址转换。此外,工具还包括内置计算器功能(加法、减法)、检查文件自身的保护方式或签名验证,并提供特征识别和获取DLL函数地址的能力,满足各种PE文件分析和调试需求。
DOS头和NT头是PE文件格式的关键组成部分。DOS头位于文件开头,以“MZ”标识,包含指向PE头的偏移量。NT头紧随其后,包含文件签名、文件头(如目标架构和节数量)以及可选头(如入口点地址和映像基地址)。这两部分共同提供了Windows操作系统加载和执行可执行文件及动态链接库所需的结构信息。
1. DOS头(DOS Header)
- 位置:PE文件的开头。
- 标识符:以“MZ”开头,表示可执行文件。
- 主要字段
- e_lfanew:指向NT头的偏移量,帮助定位后续的PE结构。
2. NT头(NT Header)
- 位置:紧跟在DOS头后。
- 组成部分
- Signature:通常为“PE00”,确认文件格式为PE。
- File Header:
- Machine:目标架构(如x86、x64)。
- NumberOfSections:节的数量。
- TimeDateStamp:文件的时间戳,标识文件创建或修改的时间。
- PointerToSymbolTable:符号表的指针(通常为0)。
- NumberOfSymbols:符号数量(通常为0)。
- SizeOfOptionalHeader:可选头的大小。
- Characteristics:文件特性,如是否可执行、是否为DLL等。
- Optional Header:
- Magic:指示头的类型(32位或64位)。
- AddressOfEntryPoint:程序的入口点地址,加载时会从这里开始执行。
- ImageBase:映像基地址,指明程序在内存中加载的起始地址。
- SectionAlignment、FileAlignment:节的对齐方式,确保在内存中和文件中结构的一致性。
- SizeOfImage、SizeOfHeaders:映像和头部的总大小,用于内存分配。
3. 查询DOS/NT结构
DOS/NT头的查询非常简单,首先可以使用命令打开对应的可执行文件,当文件被打开后,使用命令可查询DOS头部数据,使用命令则可查询NT头部数据,如下输出所示;
数据目录表位于可选头中。它包含一系列指向各种重要数据结构的指针,如导入表、导出表、资源表、异常表和证书表等。每个条目都定义了对应数据的虚拟地址和大小,帮助操作系统在加载时找到和管理这些数据,确保程序的正常运行和功能调用。
1. 位置
- 可选头:数据目录表通常位于PE文件的可选头部分,具体在NT头之后。
2. 结构
数据目录表由一组结构体组成,每个结构体表示一个特定的数据目录项。每个条目包含两个字段:
- Virtual Address:指向数据在内存中的虚拟地址。
- Size:数据的大小(以字节为单位)。
3. 常见数据目录项
以下是一些常见的数据目录项:
4. 查询数据目录表结构
查询数据目录表,可在文件被打开状态下,通过执行命令获取,其输出信息中包括了,、、、等基本信息,如下输出所示;
节表位于NT头之后,包含多个节的描述信息。每个节由一个节头定义,提供有关节的名称、虚拟地址、大小、类型和属性等信息。节表帮助操作系统识别和加载不同类型的数据和代码,例如代码节、数据节和资源节,以确保程序在内存中的正确组织和访问。
节表同样是PE文件的重要组成部分,其定义了文件中的各个节(section),每个节包含特定类型的数据和代码。以下是对节表结构的详细分析:
1. 位置
- 节表位于NT头之后,紧接在可选头后面。
2. 结构
每个节由一个节头(Section Header)描述,节头通常包含以下字段:
3. 常见节类型
- .text:存放可执行代码,通常为只读。
- .data:存放全局变量和静态数据,通常为可读可写。
- .rsrc:存放程序资源,如图标和字符串。
- .bss:未初始化的数据,系统会自动分配空间。
- .reloc:存放重定位信息,用于地址修正。
4. 查询节表结构
程序中的节表查询可通过使用获取,其输出结果中包含了程序中所有的节的名称及该节在内存和文件中的偏移地址,如下输出所示;
导入表位于数据目录表中,其记录了可执行文件所依赖的外部DLL及其函数信息。每个导入表项包含DLL名称和对应的导入函数列表,帮助操作系统在加载时解析并链接这些外部依赖,以确保程序能够正确调用所需的功能和资源。
以下是导入表的基本结构和分析:
1.导入表结构
- 导入描述符(Import Descriptor)
- 每个导入表项由一个或多个导入描述符组成。
- 包含以下字段:
- :描述符的特征(通常为0)。
- :时间戳,标识DLL的版本。
- :指向转发导入的链表,通常为0。
- :DLL的名称,以字符串形式表示。
- (IAT):存储函数地址的表。
- (INT):存储函数名称的表。
- DLL名称
- 存储所依赖的DLL的名称,通常以空字符结尾的字符串形式表示。
- 导入函数列表
- 包含DLL中所需的函数,通常包括函数的序号或名称(通过名称或按序号查找)。
2.查询导入表结构
导入表的查询有多个命令,首先我们需要查询当前程序中导入了哪些动态链接库,可通过调用命令来获取到,如下输出所示;
接着我们需要查询模块内导入了哪些函数,此时可以使用命令,该命令接收一个动态链接库名称字符串,并返回该动态链接库中所导入的函数信息,如下输出所示;
当需要查询所有导入的动态链接库及函数信息时可以使用命令来实现,如下输出所示;
有时我们需要验证特定的函数是否被导入,此时可以使用来获取,若函数被导入则输出导入的详细信息,如下输出所示;
导出表同样位于数据目录表中,其用于列出可执行文件或DLL所提供的外部函数和变量。每个导出表项包含函数的名称、地址和序号,使其他程序能够调用这些导出的功能。导出表提供了模块间的接口和动态链接,使得共享代码和资源变得可行。
以下是导出表的基本结构和分析。
1.导出表的基本组成
- 导出描述符(Export Directory)
- 包含指向导出表的主要信息。
- 主要字段包括:
- :通常为0。
- :时间戳,标识导出的版本。
- :导出表的主版本号。
- :导出表的次版本号。
- :指向DLL名称的指针。
- :导出函数的基地址。
- :导出函数的数量。
- :导出名称的数量。
- :指向函数地址的表。
- :指向函数名称的表。
- :指向名称序号表的指针。
- DLL名称
- 存储DLL的名称,以空字符结尾的字符串形式表示。
- 导出函数列表
- 函数的地址和名称,可以通过名称或序号进行引用。
2.关键字段分析
- Characteristics:通常为0,用于标识导出表的有效性。
- TimeDateStamp:指示最后修改的时间,可以用于检查DLL的版本。
- Name:DLL的名称,有助于识别模块。
- Base:定义函数地址的起始点,为地址计算提供基础。
- NumberOfFunctions:表示可导出函数的总数,重要的统计信息。
- NumberOfNames:表示可导出名称的数量,通常与函数数量相同,但可以不同。
- AddressOfFunctions:实际导出函数的地址数组,程序调用时需要用到。
- AddressOfNames:函数名称的指针数组,提供名称与地址之间的映射。
- AddressOfNameOrdinals:指向名称序号的数组,帮助在导出时找到具体函数。
3.查询导出表结构
查询导出表可使用命令,一般的EXE可执行程序中并不会包含导出表,所以在查询时可自行切换到DLL模块中查询,如下输出所示;
重定位表用于在程序加载时调整地址以适应不同的内存布局。它包含重定位条目,指定了哪些地址需要被修改,通常在执行时针对非基地址加载的情况。重定位表保证了可执行文件在内存中的正确定位和地址修正,尤其对于共享库和动态链接来说非常重要。
以下是重定位表的基本结构和分析。
1.重定位表的基本组成
- 重定位目录(Relocation Directory)
- 包含重定位信息的主要字段。
- 主要字段包括:
- :重定位块的虚拟地址。
- :重定位块的大小(以字节为单位)。
- 重定位条目(Relocation Entry)
- 每个重定位块包含多个重定位条目。
- 重定位条目的格式通常包括:
- :相对于重定位块的偏移量,指示需要修改的位置。
- :重定位类型,指示如何处理该地址。
2.关键字段分析
- VirtualAddress:指示重定位信息所对应的内存地址,加载时根据此地址进行修正。
- Size:重定位块的大小,用于确定处理的范围。
- Offset:重定位条目的偏移量,具体指定需要修正的指令或数据位置。
- Type:重定位类型,常见类型包括:
- IMAGE_REL_BASED_ABSOLUTE:不需要重定位。
- IMAGE_REL_BASED_HIGH:高16位重定位。
- IMAGE_REL_BASED_LOW:低16位重定位。
- IMAGE_REL_BASED_HIGHLOW:完整32位重定位。
- IMAGE_REL_BASED_DIR64:64位重定位(在64位PE文件中)。
3.查询重定位表结构
首先我们来查询重定位表的分页情况,可使用命令得到所有的分页,如下输出所示;
如上所示在程序中有两块重定位分页。接着我们可以使用命令,该命令可通过传入一个重定位起始页RVA地址,自动输出该重定位页内的重定位项,如下输出所示;
若要查询程序中所有的重定位项,可使用命令,如下输出所示;
资源表用于存储程序所需的各种资源,如图标、位图、对话框和字符串等。资源表以层次结构组织,包含资源类型、名称和实际数据的指针,允许程序在运行时访问和管理这些外部资源。通过资源表,开发者可以轻松地在应用程序中使用多种用户界面元素和本地化内容。
以下是资源表的基本结构和分析。
1.资源表的基本组成
- 资源目录(Resource Directory)
- 包含资源的层级结构和指向具体资源的指针。
- 主要字段包括:
- :通常为0,用于指示资源的特征。
- :时间戳,标识资源的最后修改时间。
- :资源表的主版本号。
- :资源表的次版本号。
- :ID项的数量。
- :命名项的数量。
- 资源项(Resource Entry)
- 每个资源目录可以包含多个资源项。
- 每个资源项包括:
- 或:资源的名称或ID。
- :资源的类型(如图标、位图、字符串等)。
- :指向资源数据的偏移量。
- :资源数据的大小。
- 资源数据(Resource Data)
- 实际的资源内容,如位图的像素数据或字符串的文本。
2.关键字段分析
- Characteristics:指示资源的特征,通常为0,可能用于标识某些特性。
- TimeDateStamp:指示资源的最后修改时间,有助于版本控制。
- MajorVersion / MinorVersion:用于表示资源版本,便于管理不同版本的资源。
- NumberOfIdEntries / NumberOfNamedEntries:帮助管理资源目录中的条目数量,便于遍历。
- Name / Id:唯一标识资源的名称或ID,是资源查找的关键。
- Type:指示资源的类型,如(图标)、(位图)、(字符串)等。
- OffsetToData:指向实际资源数据的位置,程序加载资源时需要使用。
- Size:资源数据的大小,便于分配和管理内存。
3.查询资源表结构
查询资源表可以使用命令获取,该命令仅用于获取进程中所加载的资源信息概述,如下输出所示;
若要查询完整的资源表结构,可通过调用命令获取,如下输出所示;
1.查询十六进制文本
通过调用命令,该命令接收两个参数,分别是文件地址及需要向下遍历的长度,当参数被传入后则可输出特定程序中特定位置的十六进制机器码,如下输出所示;
2.查询文件反汇编区域
通过调用命令,该命令接收两个参数,分别是文件地址及需要向下遍历的长度,用于对特定文本区域进行反汇编,如下输出所示;
3.扫描内存挂钩状态
检查内存汇编代码是否被挂钩可以通过调用命令实现,该命令需要读入一个可执行文件并运行一个与之相对应的进程,当执行命令后会将内存中的反汇编代码与磁盘中的反汇编代码进行比对若两者不同则说明被挂钩了,若相同则说明正常,如下输出所示;
检查函数内存地址: 用于验证特定模块中的内存地址,使用命令验证。
检查保护模式: 用于检查当前打开进程所开启的保护模式,使用命令验证。
目标指纹识别: 使用命令检测目标程序硬盘特征指纹,从而判断是那个编译器生成的程序,目前特征库不全仅用于演示。
十六进制计算器: 用于计算两个十六进制数的加减法。
文件地址转虚拟地址: 将当前打开程序机器码所在地址转换成载入内存中的虚拟地址。
虚拟地址转文件地址: 将当前打开程序的内存虚拟地址转换为所在文件地址。
相对地址转文件地址: 将当前打开程序的 RVA 相对内存地址,转换成一个文件偏移地址。
到此这篇hprof文件分析工具(hprof文件怎么分析)的文章就介绍到这了,更多相关内容请继续浏览下面的相关推荐文章,希望大家都能在编程的领域有一番成就!版权声明:
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若内容造成侵权、违法违规、事实不符,请将相关资料发送至xkadmin@xkablog.com进行投诉反馈,一经查实,立即处理!
转载请注明出处,原文链接:https://www.xkablog.com/rfx/13560.html