PE文件與虛擬內存間的映射

(1)靜態反彙編工具看到的PE文件中某條指令的位置是相當於磁盤文件而言的,即所謂的文件偏移,我們可能還需要知道這條指令在內存中所處的位置,即虛擬內存地址(VA)。

(2)反之,在調試時看到的某條指令的地址是虛擬內存地址,我們也經常需要回到PE文件中找到這條指令對應的機器碼。

爲此,我們需要弄清楚PE文件地址和虛擬內存地址之間的映射關係。首先,我們先看幾個重要的概念。

<1>文件偏移地址(File Offset Address)

   數據在PE文件中的地址叫文件偏移地址。這是文件在磁盤上存放時相對於文件開頭的偏移。

<2>裝載基址(Image Base)

   PE裝入內存時的基地址。默認情況下,EXE文件在內存中的基地址0x00400000,DLL文件是0x10000000。這些位置可以通過修改編譯選項來更改。

<3>虛擬內存地址(Virtual Address,VA)

   PE文件中的指令被裝入內存後的地址。

<4>相對虛擬地址(Relative Virtual Address,RVA)

   相對虛擬地址是內存地址相對於映射基址的偏移量。

   虛擬內存地址、映射基址、相對虛擬內存地址三者之間有如下關係。


文件偏移是相對於文件開始處0字節的偏移,RVA(相對虛擬地址)則是相對於裝載基址0x00400000處的偏移。由於操作系統在進行裝載時基本上保持PE中的各種數據結構,所以文件偏移地址和RVA有很大的一致性。

   之所以說基本上一致是因爲還有一些細微的差異。這些差異是由於文件數據的存放單位與內存數據存放單位不同而造成的。

   (1)PE文件中的數據按照磁盤數據標準存放,以0x200字節爲基本單位進行組織。當一個數據節(section)不足0x200字節時,不足的地方將被0x00填充;當一個數據節超過0x200字節時,下一個0x200塊將分配給這個節使用。因此PE數據節的大小永遠是0x200的整數倍。

   (2)當代碼裝入內存後,將按照內存數據標準存放,並以0x1000字節位基本單位進行組織。類似的,不足將被補全,若超出將分配下一個0x1000爲其所用。因此,內存中的節總是0x1000的整數倍。


(表一)中列出的文件偏移地址和RVA之間的對應關係可以讓大家更直接地理解這種細微的差異

   由於內存中數據節相對於裝載基址的偏移量和文件中數據節的偏移量有上述差異,所以進行文件偏移到虛擬內存地址之間的換算時,還要看所轉換的地址位於第幾個節內。

   我們把這種由存儲單位差異引起的節基址差稱作節偏移,在上例中:

   .text節偏移=0x1000-0x400=0xc00

   .rdata節偏移=0x7000-0x6200=0xE00

   .data節偏移=0x9000-0x7400=0x1C00

   .rsrc節偏移=0x2D000-0x7800=0x25800

   文件偏移地址與虛擬內存地址之間的換算關係可以用下面的公式來計算。

   文件偏移地址=虛擬內存地址(VA)-裝載基址(Image Base)-節偏移=RVA-節偏移


發佈了56 篇原創文章 · 獲贊 21 · 訪問量 26萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章