【问题标题】:Win32/Dll: The address that is jumped to when a DLL function is called?Win32/Dll:调用DLL函数时跳转到的地址?
【发布时间】:2012-05-12 18:02:45
【问题描述】:

当执行“调用”指令来调用 DLL 导出函数时,它会将 EIP 设置为存储在 DLL 中的函数的地址。如果同时执行的另一个程序,调用了属于同一个DLL的同一个函数,跳转地址是否相同?

【问题讨论】:

  • 为什么重要?你想解决什么问题?
  • 为什么要问这个?这些知识如何使您受益?在虚拟地址空间中,答案是“也许,但无论如何你都不应该指望它”。
  • 因为我想知道 DLL 的实例是属于进程的东西还是其他东西。如果一个DLL被多个程序同时使用,是否意味着这个DLL会有很多实例?

标签: windows winapi dll assembly x86


【解决方案1】:

简短的回答是视情况而定

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 的示例。

【讨论】:

    【解决方案2】:

    由于其他程序/进程被映射到自己单独的地址空间,我怀疑地址会相同。

    【讨论】:

      猜你喜欢
      • 2014-05-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-10-18
      • 2014-02-18
      相关资源
      最近更新 更多