假設兩個行程正在使用 Kernel32.dll,Windows 是否將 DLL 映射到兩個行程中的相同虛擬地址空間?如果不是,那么分頁機制如何最終使用相同的物理地址,實際上為兩個行程加載了 DLL?我嘗試在 windows internals book 中找到此資訊,但沒有找到任何內容
uj5u.com熱心網友回復:
TL;DR:不,它可能在另一個行程的其他地方加載。
Ntdll 和 Kernel32 是特殊的,并且總是在同一個地址加載,因此最好專注于其他東西,例如 Shell32。
dll 具有所謂的首選基地址,它存盤在 PE 標頭 ( ImageBase) 中。加載程式將首先嘗試在此地址加載 dll。如果該地址范圍是空閑的,則加載將成功,無需額外作業。
如果地址不是空閑的,則加載程式必須將其加載到其他地方。在不同的地址加載通常需要重定位資訊,如果在鏈接(/FIXED)期間將其洗掉,則加載將失敗!如果其他地方有空間來加載 dll,加載器將使用重定位資訊用新的基地址修補 dll 中的給定位置。因為 dll 是作為寫時復制加載的,所以與在首選地址加載相比,這將導致額外的記憶體使用,因為需要補丁的每個記憶體頁面現在都是行程中的私有副本。這意味著您的問題的答案是否定的,如果該行程已經在其中加載了其他內容,則 dll 可能不會在不同的行程中加載??到相同的地址。
到目前為止,我只談到了裝載機。加載器在 Ntdll 中作為普通用戶模式代碼實作,不涉及檔案映射到記憶體的實際作業方式。記憶體映射檔案(在 NT 內部稱為 Sections)是作業系統內核和 CPU 硬體之間的合作。這本身就是一個完整的話題,但重要的是要知道物理記憶體和頁面/交換檔案機制與用戶模式行程如何訪問其虛擬記憶體頁面完全脫節。內核可以將物理記憶體頁面映射到行程虛擬記憶體中的零個、一個或多個位置,并且當行程訪問虛擬頁面時,CPU 將自動轉換。
最后一點,ASLR 確實使事情復雜化了一點,但是“偏移量”只會在重啟時發生變化,并且不應該對當前實作中的這個特定問題產生影響。理論上,Windows 將來可能會改變這一點,并且總是在不同的行程中將內容加載到不同的地址,但這不太可能發生,因為寫時復制的缺點。
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/446136.html
