打印由PE导入的DLLs(64位)[复制] 。

问题描述 投票:1回答:1

我真的不明白为什么会出现这种情况。我能够正确解析PE格式的主要内容,除了这个。我试图打印一个特定PE使用的所有DLL。

首先,我从数据目录中获取ImportTable。

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);

不知道为什么,这样做会崩溃,我该怎么做?

c winapi portable-executable
1个回答
2
投票

你的指针运算错误。 (ULONG *)pe + ...(ULONGLONG *)pe + ... 不做你认为的那样。

当你推进一个指针 T* 为整数 N,存储在指针中的地址将以 N 数目 T 元素 - 即通过 N * sizeof(T) 数目 字节数.

当你键入 peULONG* 再加上 importDir.VirtualAddress 中存储的地址。pesizeof(ULONG) * VirtualAddress 字节数,而不是按 VirtualAddress 字节数。

同样的,当你键入投掷 peULONGLONG* 再加上 importDescriptor[0].Name 到它,你是在推进地址在 pesizeof(ULONGLONG) * Name 字节数,而不是按 Name 字节数。

在这种情况下,这不是你想要的。 PE中的虚拟地址是基础地址的绝对偏移量,所以你需要将基础地址提前通过 N 字节,而不是 N 字节,所以任何 T* 用于这种类型转换的指针需要是一个指向1字节数据类型的指针,例如 BYTEchar.

所以,在你的例子中,为了推进你的基本地址。peN 数目 字节数,使用 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));
© www.soinside.com 2019 - 2024. All rights reserved.