Windows 操作系统允许不同进程将相同的 DLL 映射到不同的虚拟地址,从而提高系统的安全性和稳定性。但是,如果需要在多个进程中共享数据或采用基于 DLL 的插件系统,可能需要将同一个 DLL 映射到同一个虚拟地址。
可以使用以下方法实现:
使用 /FIXED 标志编译 DLL,使其能够定位到固定的基址。
使用同一个加载器将 DLL 加载到不同的进程中,例如使用 LoadLibraryEx 函数和参数 dwFlags 设置为 DONT_RESOLVE_DLL_REFERENCES | LOAD_LIBRARY_AS_IMAGE_RESOURCE。
使用 VirtualAllocEx 和 WriteProcessMemory 函数在每个进程中手动分配和复制 DLL。
示例代码:
// 加载 DLL 并将其映射到相同的虚拟地址
HMODULE LoadDLL(DWORD processID, LPCWSTR dllPath)
{
HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, processID);
if (hProcess == NULL) {
// handle error
return NULL;
}
PVOID imageBase = NULL;
HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE | TH32CS_SNAPMODULE32, processID);
if (hSnapshot != INVALID_HANDLE_VALUE) {
MODULEENTRY32W moduleEntry;
moduleEntry.dwSize = sizeof(moduleEntry);
if (Module32FirstW(hSnapshot, &moduleEntry)) {
do {
if (wcsicmp(moduleEntry.szExePath, dllPath) == 0) {
// found the DLL already loaded in the process
imageBase = moduleEntry.modBaseAddr;
break;
}
} while (Module32NextW(hSnapshot, &moduleEntry));
}
CloseHandle(hSnapshot);
}
if (imageBase == NULL) {
// allocates and writes the DLL into the remote process
DWORD dllSize = GetFileSize(hDllFile, NULL