当执行“call”指令来调用DLL导出函数时,它将EIP设置为DLL中存储的函数的地址。如果同时执行的另一个程序调用属于同一个DLL的同一个函数,跳转地址会相同吗?
最佳答案
简短的回答是这取决于。
DLL 按部分组织,每个部分可以由许多进程共享。通常只有共享代码段(当 DLL 在同一基地址加载时),并且每个进程都有其私有(private)数据段。
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举个例子。
关于windows - Win32/DLL : The address that is jumped to when a DLL function is called?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10427717/