Dot-Net
JIT編譯後的程式碼是如何注入記憶體並執行的?
“考慮典型的 Windows x86 或 AMD64 架構,記憶體分為無法寫入的可執行部分和可寫入但無法執行的數據部分(想想 DEP)。”
“JIT 在記憶體中編譯方法,(通常)不將任何內容儲存到磁碟,而是將其移動到下一條指令指針可以到達的位置,將目前指令指針(指向 JIT)更改為指向新生成的程式碼和然後執行它。”
這兩段雖然有點過於簡單化了,但是我對JIT和Windows記憶體模型的基本理解。我也知道,當我嘗試手動將一些可執行程式碼複製到記憶體中並嘗試執行時,我通常會做不到(除非使用 DLL 注入)。
JIT 設計者是如何克服這個障礙的?他們是使用 ring-0 驅動程序還是一切都在使用者模式下完成?
只需使用 Windows VirtualProtect() API 函式即可完成。它改變了虛擬記憶體頁的屬性。從 PAGE_READWRITE 開始,JIT 編譯器可以將機器程式碼寫入 PAGE_EXECUTE_READ 以便執行。這樣做不需要特殊權限,因為該頁面由也執行 JIT 編譯器的程序擁有。