在理解了 PE 格式之後,我們要知道這些程式碼從硬碟映射到記憶體的事。在 PE 文件加載到記憶體時,每個 Section
都要無誤地完成記憶體位置與資料偏移的映射,這個映射稱為 RVA to RAW
。
RAW
所在節區
文件偏移
IMAGE_SECTION_HEADER
( from winnt.h
) 以以下公式計算RAW - PointToRawData = RVA - VirtualAddress
=> Raw = RVA - VirtualAddress + PointToRawData
可以看到經過映射後它的位置會不一樣,這樣映射後的映象
( image ) 會根據 section header
的資料來加載起始位置、大小、讀寫權限等。因此硬碟中與記憶體中的 PE 檔案有著不同型態。
要熟悉這些轉換,才不會在之後搞錯喔
DLL
: 動態連結庫,它的用途就是讓你可以把你引用的庫進行動態連結,而不用每次都要把引用的 libary
通通裝到程式檔案裡面。讓程式都共用一份庫可以大大的減少記憶體浪費。因此 windows 設計者們因為有了 DLL 而有以下概念
不要把 libary
放進程序中。而是單獨組成 DLL 文件,需要時調用就好
DLL 在多個程序中可以共享
更新 libary
時改 DLL 就好了
而加載 DLL 的方式有兩種 :
隱式連結
: 程序開始時加載 DLL ,終止時在釋放,IAT
(載入函式表) 與這種方法有關顯示連結
: 在使用 DLL 時加載,使用完後釋放。這裡跟 動態連結&靜態連結
是不一樣的東西,千萬不能搞混。
下圖是通過觀察 notepad.exe 檢查到 CreateFileW()
函數是調用自 kernel32.dll
的。
而在 0x01001104 的資料並不是函數本身,而是獲取該處的值 ( 0x775B3140 ) 來得到函數位置。
詳細的說 : 位置 0x01001104 是在 .text
區中,是 ITA
的範圍裡。而其值 0x775B3140 是在加載到 notepad.exe 的記憶體中,對應 CreateFileW( ) ( 對應 kernel32.dll )中。
另外,普通的 DLL ImageBase
通常為 10000000 ,所以常常出現 DLL 重定位
。但是在 windows 系統文件有自身的 ImageBase 所以不會出現 DLL 重定位。