DLL エクスポート関数を呼び出すために "call" 命令が実行されると、EIP が DLL に格納されている関数のアドレスに設定されます。同時に実行中の別のプログラムが、この同じ DLL に属する同じ関数を呼び出した場合、ジャンプ アドレスは同じになりますか?
2 に答える
簡単に言えば、場合によるということです。
DLL はセクションで編成され、各セクションは多くのプロセスで共有できます。通常、コード セクションのみが共有され ( DLL が同じベース アドレスにロードされる場合)、各プロセスにはプライベート データ セクションがあります。
DLL の利点の 1 つは、多くのプロセス間でコードを共有できることです (システムがそれらの多くのインスタンスを読み込まないため、システム メモリを節約できます)。もちろん、データは (通常は) 共有できないため、インスタンスごとに複製する必要があります。
通常、DLL コードのメモリは異なるプロセス間で共有され、同じアドレスを持つ可能性があることを意味します。Virtual Address Spaceのために「可能性がある」と言いました。メモリが共有されていても、すべてのプロセスで同じアドレスを持つことは許可されていません。簡単なテストでプロセスを何度も実行して関数アドレスを比較するには、 MSDNの次GetProcAddress
の簡単なプログラムを使用できます。
#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 のために過去数年間に何かが変わったので、この投稿も見てください。
同じ DLL を使用してプロセス間でデータを共有する必要がある場合は、共有メモリを使用することをお勧めします。例については、MSDN のこの記事を参照してください。
他のプログラム/プロセスは独自の個別のアドレス空間にマップされているため、アドレスが同じになるとは思えません。