簡體   English   中英

PE文件如何映射到內存?

[英]How does a PE file get mapped into memory?

所以我過去幾天一直在重新研究PE格式,我還有幾個問題

  1. 數據部分是否已映射到進程的內存中,或者程序是否從磁盤讀取它?

  2. 如果確實將其映射到其內存中,那么該進程如何獲取該部分的偏移量? (和其他部分)

  3. 有沒有辦法獲取已經映射到內存的進程的入口點,而不觸及磁盤上的文件?

數據部分是否映射到進程的內存中

是。 這不太可能存活很長時間,該程序很容易寫入該部分。 這會觸發寫入時復制頁面副本,該頁面副本將獲取由頁面文件而不是PE文件支持的頁面。

該過程如何獲取該部分的偏移量?

鏈接器已經計算了該部分中變量的偏移量。 它可能是重定位的,對於具有笨拙的基址的DLL來說是常見的,這些DLL在加載DLL時已經在使用。 在這種情況下,加載器使用PE文件中的重定位表來修補代碼中的地址。 包含此類修補代碼的頁面獲得與數據部分相同的處理,它們不再由PE文件支持,並且不能在進程之間共享。

有沒有辦法獲得一個過程的入口點

整個 PE文件被映射到內存,包括其標頭。 因此,您無需讀取文件即可從內存中讀取IMAGE_OPTIONAL_HEADER.AddressOfEntryPoint。 請記住,如果您為另一個進程執行此操作會很痛苦,因為您無法直接訪問其虛擬地址空間。 你必須使用ReadProcessMemory(),這是相當少的快樂,不可能比讀取文件更快。 該文件很可能存在於文件系統緩存中。 地址空間布局隨機化功能很容易讓您頭疼,旨在使這些事情變得困難。

數據部分是否已映射到進程的內存中,或者程序是否從磁盤讀取它?

它被映射到進程的內存中。

如果確實將其映射到其內存中,那么該進程如何獲取該部分的偏移量? (和其他部分)

通過重定位表:來自可執行代碼的全局對象(數據或函數)的每次引用都使用直接尋址,在此表中有一個條目,以便加載器修補代碼,修復原始偏移量。 請注意,您可以創建沒有重定位部分的PE文件,在這種情況下,所有數據和代碼部分都有固定的偏移量,並且可執行文件具有固定的入口點。

有沒有辦法獲取已經映射到內存的進程的入口點,而不觸及磁盤上的文件?

不確定,但是如果“不接觸”你的意思是甚至不讀文件,那么你可以通過向上走來找出它。

  1. 是的,PE標頭中描述的所有部分都映射到內存中。 IMAGE_SECTION_HEADER結構告訴加載器如何映射它(該部分可以在內存中比在磁盤上大得多)。

  2. 我不太確定我是否明白你在問什么。 您是說代碼部分的代碼如何知道數據部分中的數據訪問位置? 如果模塊在首選加載地址加載,則鏈接器靜態生成的地址是正確的,否則加載器會使用重定位信息修復地址。

  3. 是的,Windows加載程序還將PE標頭加載到模塊基址的內存中。 在那里,您可以歸檔文件PE頭中的所有信息 - 也是入口點。

我可以推薦這篇關於PE格式的文章,特別是關於重定位的文章。

數據部分是否已映射到進程的內存中,或者程序是否從磁盤讀取它?

是的,Windows或Linux操作系統的動態加載程序執行之前的所有內容都必須映射到內存中。

如果確實將其映射到其內存中,那么該進程如何獲取該部分的偏移量? (和其他部分)

PE文件具有明確定義的結構,加載器使用該信息並解析該信息以獲取ImageBase周圍部分的相對虛擬地址。 此外,如果在系統上激活了ASLR - 地址隨機化功能,則加載程序必須使用重定位信息來解決這些偏移。

有沒有辦法獲取已經映射到內存的進程的入口點,而不觸及磁盤上的文件?

NOPE,用於計算OEP的操作系統的加載器使用可選頭結構的ImageBase + EntryPoint成員值,並且在啟用地址隨機化時的某些特定位置,它使用重定位表來解析所有地址。 因此,如果不解析磁盤上的PE文件,我們就無法做任何事情。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM