当执行“调用”指令以调用DLL导出函数时,它将EIP设置为DLL中存储的函数的地址。如果另一个同时执行的程序调用属于同一个DLL的同一个函数,那么跳转地址是否相同?
答案 0 :(得分:4)
简短的回答是取决于。
DLL按部分组织,每个部分可以由许多进程共享。通常只共享代码段(当DLL在相同的基址加载时),每个进程都有私有数据段。
DLL的一个优点是,您可以在多个进程之间共享代码(然后保存系统内存,因为系统不会加载它们的许多实例)。当然,数据不能(通常)共享,因此每个实例必须重复。
这意味着通常 DLL代码的内存在不同进程之间共享,然后可能具有相同的地址。由于Virtual Address Space,我说“可能”,即使共享内存,也不会授予它在每个进程上具有相同的地址。要快速测试使用GetProcAddress
并多次运行该过程来比较函数地址,您可以使用MSDN中的这个简单程序:
#include <windows.h>
#include <iostream>
void _tmain()
{
typedef void (WINAPI *PGNSI)(LPSYSTEM_INFO);
SYSTEM_INFO si;
ZeroMemory(&si, sizeof(SYSTEM_INFO));
PGNSI fnGetNativeSystemInfo = reinterpret_cast<PGNSI>(GetProcAddress(
GetModuleHandle(TEXT("kernel32.dll")), "GetNativeSystemInfo"));
std::cout << fnGetNativeSystemInfo << std::endl;
}
您应该(通常)看到每个导出函数的相同地址,但您可能不会。依靠这种行为绝不是一个好主意。好的,这是故事,但由于ASLR,过去几年发生了一些变化,请看this post。
如果您必须在使用相同DLL的进程之间共享数据,最好使用一些共享内存,请查看this article on MSDN作为示例。
答案 1 :(得分:1)
由于其他程序/进程被映射到它们自己的独立地址空间,我怀疑地址是否相同。