我真的不明白为什么会出现这种情况。我能够正确解析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);
不知道为什么,这样做会崩溃,我该怎么做?
你的指针运算错误。 (ULONG *)pe + ...
和 (ULONGLONG *)pe + ...
不做你认为的那样。
当你推进一个指针 T*
为整数 N
,存储在指针中的地址将以 N
数目 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字节数据类型的指针,例如 BYTE
或 char
.
所以,在你的例子中,为了推进你的基本地址。pe
由 N
数目 字节数,使用 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));