打印PE文件(64位)引入的DLL

3

我实在不明白为什么会出现这种情况。我能正确解析大部分PE格式,除了这个。我试着打印出一个特定PE正在使用的所有DLL。

首先,我从数据目录中获取导入表:

IMAGE_DATA_DIRECTORY importDir = (IMAGE_DATA_DIRECTORY)peHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT];

然后,我只需将其地址添加到我映射的地址上,即 MapViewOfFile 返回的地址:
PIMAGE_IMPORT_DESCRIPTOR importDescriptor =
        (PIMAGE_IMPORT_DESCRIPTOR)((ULONG *)pe + importDir.VirtualAddress);

    printf("%s\n", (ULONGLONG *)pe + importDescriptor[0].Name);

因为某些原因这个程序崩溃了,我该怎么做?


@RemyLebeau 你指的是这个吗?importDescriptor = (PIMAGE_IMPORT_DESCRIPTOR)((PBYTE)pe + importDir.VirtualAddress); 因为这个仍然会崩溃。 - Trey
请查看我刚刚发布的答案。 - Remy Lebeau
1个回答

3
您的指针算术有误。 (ULONG *)pe + ... (ULONGLONG *)pe + ... 不会做您认为它们会做的事情。
当您通过整数N推进指针T * 时,存储在指针中的地址将通过N * sizeof(T)字节数量的元素前进-即通过N * sizeof(T)个字节的数量进行前进。
当您将pe类型转换为ULONG * ,然后添加importDir.VirtualAddress 时,您正在将存储在pe中的地址向前移动 sizeof(ULONG)* VirtualAddress 字节的多个字节,而不是VirtualAddress字节的数量。
同样,当您将pe类型转换为ULONGLONG * ,然后将importDescriptor [0] .Name 添加到其中时,您正在将pe中的地址向前移动 sizeof(ULONGLONG)* Name 字节的多个字节,而不是Name字节的数量。
在这种情况下,这不是您想要的。 PE中的虚拟地址是从基地址开始的绝对偏移量,因此您需要将基地址向前移动N字节,而不是N字节的倍数,因此用于此类类型转换的任何T * 都需要指向1个字节数据类型的指针,例如BYTEchar
因此,在您的示例中,要将基地址pe向前移动bytes数量,使用BYTE *进行类型转换,例如:
PIMAGE_IMPORT_DESCRIPTOR importDescriptor =
        (PIMAGE_IMPORT_DESCRIPTOR)(((LPBYTE)pe) + importDir.VirtualAddress);
...
printf("%s\n", (char*)(((LPBYTE)pe) + importDescriptor[0].Name));

另外,您也可以使用整数算术代替指针算术,通过将基地址强制转换为整数(如ULONG_PTR (一个指针大小的 ULONG)),例如:

PIMAGE_IMPORT_DESCRIPTOR importDescriptor =
        (PIMAGE_IMPORT_DESCRIPTOR)(((ULONG_PTR)pe) + importDir.VirtualAddress);
...
printf("%s\n", (char*)(((ULONG_PTR)pe) + importDescriptor[0].Name));

好的,你解决了我的类型转换误解,我很感激,但是我向你发誓,由于某种原因这并没有起作用,我已经测试过不止一个文件。这是一个简化版:https://pastebin.com/67QqqLiL - Trey
1
那么你肯定是做错了其他事情。我们不在这里为你调试代码。你为什么不使用像ImageDirectoryEntryToData()这样的东西呢?让它来处理这个低级解析过程。 - Remy Lebeau
好的,我想独立完成这个项目以更好地理解PE格式,除了我展示的内容之外,这段代码没有太多的东西,它只是简单地打印这些字符串,但你可能是对的。 - Trey
1
我将此问题关闭为重复。请参见链接问题中的代码。在32位和64位DLL之间访问“DataDirectory”是不同的,因此这可能是您遇到的问题。 - Remy Lebeau
谢谢,问题在于我需要将 RVA 转换为文件偏移量。 - Trey
pe是什么?我猜它是内存中exe的图像基址? - BoRRis

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接