我反汇编了一个 DLL 并看到了一些功能。我找到了我需要的功能,它的地址是0x10001340
.
如果我将这个 dll 加载到我的应用程序中,这个地址会保持不变吗?那么我是否可以通过我的应用程序中的地址调用该函数?
我之所以问是因为我不确定:如果加载此 dll 时,主应用程序中的某些函数已经具有相同的地址怎么办?因此,也许 dll 中的函数可以在加载等时更改地址。
我反汇编了一个 DLL 并看到了一些功能。我找到了我需要的功能,它的地址是0x10001340
.
如果我将这个 dll 加载到我的应用程序中,这个地址会保持不变吗?那么我是否可以通过我的应用程序中的地址调用该函数?
我之所以问是因为我不确定:如果加载此 dll 时,主应用程序中的某些函数已经具有相同的地址怎么办?因此,也许 dll 中的函数可以在加载等时更改地址。
在 Windows 上,dll 有一个优先加载地址,但如果加载器注意到虚拟地址空间的这一部分已被使用,它就能够更改所有这些引用。这个过程称为“变基”。
“默认”基地址是在链接时指定的(/BASE
使用 Microsoft 链接器),如果您打算将 dll 与另一个具有相同基地址的 dll 一起使用,则将其设置为不同于默认值可能会很有用;这加快了加载过程,因为加载程序不必在每次加载时重新设置其中一个 dll。(IIRC 还有一些工具可以重新构建现有的 dll 并将结果保存在磁盘上)
请记住,从 Windows Vista 开始,使用指定标志编译的 dll 总是加载到随机基地址以避免某种漏洞。
您最终得到相同地址的可能性极小。DLL 链接器的默认 /BASE 参数是 0x10000000,这就是您的入口点最终到达该地址的方式。但是有许多使用默认设置链接的 DLL,实际上只有一个可以在该地址加载。稍后加载的所有其他内容都需要重新设置。
你可以为 /BASE 提供一个更好的值,但是它永远不能保证你得到你要求的加载地址。
正如 Matteo 所说,DLL 有一个首选的加载地址(在IMAGE_OPTIONAL_HEADER结构的 ImageBase 字段中指定)。当系统尝试加载 DLL 时,如果可能,它将在此地址加载它(除非启用了地址空间随机化)并且不需要“修补”。如果它无法在首选地址加载,则重新定位 DLL,这将需要修补 DLL 中的任何绝对引用以补偿重新定位。
因此,回答您的问题:不能保证 DLL 将在其首选地址加载。一旦加载后续加载将不会加载 DLL 的更多副本,因此地址不会改变。但是,一旦卸载(DLL 被引用计数),就不能保证下次它会在相同的地址加载。