当导出表出现在大于文件本身的文件偏移量时,dumpbin 如何读取导出表?
我正在编写一个小型 PE 阅读器,因此我在测试应用程序旁边运行 dumpbin 以确认值被正确读取。到目前为止,除了导出表之外,一切都正常。
我正在测试的文件是一个 DLL。我的应用程序以字节数组的形式读取文件,并将其传递给我的 PE 阅读器类。这些值与 dumpbin 的输出一致,包括导出数据目录的 RVA 和大小。
E000 [ 362] RVA [size] of Export Directory
问题是,字节数组的大小只有 42,496。正如您可能想象的那样,当我的 PE 读取器尝试读取 E000 (57,344) 时,我收到 IndexOutOfRangeException
。然而,dumpbin 没有这样的问题,并且可以很好地读取导出目录。是的,整个文件确实被读入字节数组。
这怎么可能?
I'm writing a little PE reader, so I run dumpbin alongside my test application to confirm that the values are being read correctly. Everything it working so far, except for the export table.
The file I'm testing with is a DLL. My application reads the file in as a byte array, which gets passed to my PE reader class. The values align with those output by dumpbin, including the RVA and size of the export data directory.
E000 [ 362] RVA [size] of Export Directory
The problem is, the byte array's size is only 42,496. As you can probably imagine, when my PE reader attempts to read at E000 (57,344), I get an IndexOutOfRangeException
. dumpbin, however, has no such problem and reads the export directory just fine. And yes, the entire file is indeed being read into the byte array.
How is this possible?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
PE文件包含“节”,节具有独立的基地址。 PE 不是连续的内存映像。每个部分都是一个连续的内存映像。
首先,您必须读取部分信息并对其布局进行内存映射。然后您将能够将部分偏移量与基于文件的偏移量对齐。
顺便说一句,考虑一下 OllyDbg,它是一个适用于 Windows 的免费软件、开源调试器和反汇编器。它可能会帮助您测试自己的软件,并且可能会通过“推出自己的软件”来实现您试图实现的目的。
dumpbin /all
输出示例:在本例中,我的 .text 部分从 RVA 1000 开始,一直延伸到 RVA CE00。指向此部分的文件指针是 400。我可以通过减去 600 将 1000-CDFF 范围内的任何 RVA 转换为文件指针。(所有数值均为十六进制。)
每当遇到“RVA”(相对虚拟地址),您可以使用以下方法将其解析为文件偏移量(或字节数组的索引):
您可能使用的另一种方法是调用
MapViewOfFileEx()
并在 dwDesiredAccess 参数中设置标志FILE_MAP_EXECUTE
。该 API 将从 PE 文件中解析节标题,并将节的内容读入相对于“模块库”的位置。模块基址是加载 PE 头的基地址。当使用
LoadLibrary()
函数加载DLL时,可以通过GetModuleInformation()
函数的MODULEINFO
成员lpBaseOfDll获得。使用
MapViewOfFileEx()
时,模块基址只是MapViewOfFileEx()
的返回值。在以这些方式加载模块的设置中,将 RVA 解析为正常的指针值是这样的:
char *
中char *
char *
转换为实际数据类型并取消引用它。在这些方法中让操作系统映射文件的一个缺点是,如果您使用此工具来调查某些可疑文件并且不确定开发人员是否对节标题采取了奇怪的自由行为,则您可能会错过一些有价值的信息让操作系统处理这部分解析。
The PE file contains "sections", and the sections have independent base addresses. The PE is not a contiguous memory image. Each section is a contiguous memory image.
First you will have to read the section information and make memory-map of their layout. Then you will be able to align the section offsets with the file-based offsets.
As an aside, consider looking at OllyDbg, which is a freeware, open-source debugger and disassembler for Windows. It will possibly help you test your own software, and might server the very purpose you are trying to fill by "rolling your own."
Example from
dumpbin /all
output:In this case, my .text section begins at RVA 1000 and extends to RVA CE00. The file pointer to this section is 400. I can translate-to-file-pointer any RVAs in the range 1000-CDFF by the work of subtracting 600. (All numeric values hexadecimal.)
Whenever you encounter an "RVA" (Relative Virtual Address), you resolve it to a file offset (or an index into your byte array), using this method:
Another approach that you might use is to call
MapViewOfFileEx()
with the flagFILE_MAP_EXECUTE
set in dwDesiredAccess argument. This API will parse the section headers from the PE file, and read the contents of the sections into their locations relative to the "module base."The module base is the base address at which the PE header will be loaded. When loading DLLs using
LoadLibrary()
functions, this can be obtained viaGetModuleInformation()
function'sMODULEINFO
member lpBaseOfDll.When using
MapViewOfFileEx()
, the module base is simply the return value fromMapViewOfFileEx()
.In the setting of loading the module in these ways, resolving the RVA to a normal pointer value is a matter of:
char *
char *
char *
to the actual datatype and dereference that.A drawback of letting the OS map the file as in these approaches is that if you are using this tool to investigate some suspect file and are not sure if a developer has taken strange liberties with the section headers, it is possible you miss some valuable information by letting the OS handle this part of the parsing.