PE檔案格式詳解(4)
阿新 • • 發佈:2019-02-04
1.RVA to RAW
PE檔案載入到記憶體時,每個節區都要準確完成記憶體地址與檔案偏移的對映。這種對映便稱為RVA to RAW,實現這個過程需要經過以下的步驟。
1.查詢RVA所在節區。
2.使用公式計算出檔案偏移。
根據IMAGE_SECTION_HEADER結構體,換算公式如下。
RAW - PoniterToRawData = RVA - VirtualAddress
RAW = RVA - VirtualAddress + PointerToRawData
2.IAT(Import Address Table,匯入地址表)
IAT儲存的內容與Windows作業系統的核心進、記憶體、DLL結構等有關。(即掌握了IAT便掌握了Windows作業系統的根基)。
1.DLL(Dynamic Linked Library)
載入DLL的方式有兩種:一種是“顯式連結”(Explicit Linking),程式使用DLL時載入,使用完畢後釋放記憶體。另一種是“隱式連結”(Implicit Linking),程式開始時遍一同載入DLL,程式終止時,再釋放佔用的記憶體。IAT提供的機制便與隱式連結有關。
DLL重定位,DLL檔案的ImageBase一般為10000000.比如某個程式使用a.dll和b.dll,OE裝載器先把a.dll裝載到記憶體的10000000(ImageBase)處,然後嘗試把b.dll也裝載到該處。但是由於該地址處已經裝載了a.dll,所以PE裝載器需要查詢其他空白的記憶體空間(ex:3E000000),然後將b.dll裝載進去。這就是DLL檔案的重定位。
2.IMAGE_IMPOT_DESCRIPTOR
IMAGE_IMPORT_DESCRIPTOR結構體中記錄著PE檔案要匯入哪些庫檔案。IMAGE_OPTIONAL_HEADER32.DataDirectory[1].VirtualAddress的值即是IMAGE_IMPORT_DESCRIPTOR結構體陣列的起始地址(RVA值)。(第一個4位元組為虛擬地址,第二個4位元組為Size成員。)
注:Import:匯入,向庫提供服務(函式)。
Export:匯出,從庫向其他PE檔案提供服務(函式)。
程式碼 IMAGE_IMPORT_DESCRIPTOR
typedef struct _IMAGE_IMPORT_DESCRIPTOR{
union{
DWORD Characteristics;
DWORD OriginalFirstThunk; //INT(Import Name Table) address (RVA)
};
DWORD TimeDatastamp;
DWORD ForwarderChain;
DWORD Name; // library name string address (RVA)
DWORD FirstThunk;
// IAT( Import Address Table) address (RVA)
} IMAGE_IMPORT_DESCRIPTOR;
typedef struct _IMAGE_IMPORT_BY_NAME{
WORD Hint; // ordinal
BYTE Name[1]; // function name
string
} IMAGE_IMPORT_BY_NAME , *PIMAGE_IMPORT_BY_NAME;
執行一個普通程式時往往需要匯入多個庫,匯入多少庫就存在多少個IMAGE_IMPORT_DESCRIPTOR結構體,這些結構體形成了陣列,且結構體陣列最後以NULL結構體結束。
IMAGE_IMPORT_DESCRIPTOR的重要成員如下
專案 含義
OriginalFirstThunk INT的地址(RVA)
Name 庫名稱字串的地址(RVA)
FirstThunk IAT的地址(RVA)
注:INT與IAT是長整型(4個位元組資料型別)陣列,以NULL結束(未另外明確指出大小)。
INT中各元素的值為IMAGE_IMPORT_BY_NAME結構體指標(有時IAT也有相同的值)。
INT與IAT的大小應相同。
3.EAT
Windows作業系統中,“庫”是為了方便其他程式呼叫而集中包含相關函式的檔案(DLL/SYS)。Win32 API是最具代表性的庫,其中的kernel32.dll檔案稱為最核心的庫檔案。
EAT是一種核心機制,它使不同的應用程式可以條用庫檔案中提供的函式(即只有通過EAT才能準確求得從相應庫中匯出函式的起始地址)。PE檔案內部有且僅有一個用來說明庫EAT的IMAGE_EXPORT_DIRECTORY結構體,並且儲存著匯出資訊。
注:IAT的結構體以陣列的形式存在,且擁有多個成員。即說明PE檔案可以同時匯入多個庫。
可以在PE檔案的PE頭中查詢到IMAGE_EXPORT_DIRECTORY結構體的聞之。IMAGE_OPTIONAL_HEADER32.DataDirectory[0].VirtualAddress值即為結構身體陣列的其實地址(RVA值)。(第一個4位元組為虛擬地址,第二個4位元組為Size成員。)
程式碼
IMAGE_EXPORT_DIRECTORY結構體
typedef struct _IMAGE_EXPORT_DIRECTORY {
DWORD Characteristics;
DWORD TimeDateStamp; //creation time date stamp
WORD MajorVersion;
WORD MinorVersion;
DWORD Name;
//address of library file neme
DWORD Base; //ordinal base
DWORD NumberOfFunctions; //number of functions
DWORD NumberOfNames; //number of names
DWORD AddressOfFunctions;
//address of function start address array
DWORD AddressOfName; //address of function name string array
DWORD AddressOfNameOrdinals;
//address of ordinal array
} IMAGE_EXPORT_DIRECTORY, *PIMAGE_EXPORT_DIRECTORY;
其中結構體中的重要成員如下
專案
含義
NumberOfFunctions 實際Export函式的個數
NumberOfNames Export函式中具名的函式個數
AddressOfFunctions Export函式地址陣列(陣列元素個數=NumberOfFunctions)
AddressOfNames 函式名稱地址陣列(陣列元素個數=NumberOfNames)
AddressOfNameOrdinals
Ordinal地址陣列 (陣列元素個數=NumberOfNames)