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