1. 程式人生 > >PE檔案格式學習(十四):繫結匯入表

PE檔案格式學習(十四):繫結匯入表

1.介紹

繫結匯入表的作用是加快程式的啟動速度,一個PE程式在啟動時會去載入匯入表中的dll檔案,並將匯入表的FirstThunk指向的陣列填入函式的真實地址,這需要耗去時間,繫結匯入表中儲存了匯入函式的真實地址,所以當PE在啟動時系統檢測到有繫結匯入表,就會直接將地址填入FirstThunk裡,這樣就省去了尋找真實地址的時間。
但是繫結匯入表的生效,有兩個前提條件:

  1. 程式初始化時,匯入的DLL都載入到了首選基址中
  2. 程式執行了繫結匯入操作以後,匯入DLL中引用的符號位置一直沒有變化

如果有任何一個條件沒有滿足,系統就會忽略繫結匯入操作。

2.分析

在資料目錄表中找到繫結匯入表,本例是Win7下的mspaint.exe,它的RVA是280h,大小為360,下圖是它的十六進位制資料:

我們對照它的結構體IMAGE_BOUND_IMPORT_DESCRIPTOR來分析:

typedef struct _IMAGE_BOUND_IMPORT_DESCRIPTOR {
      DWORD TimeDateStamp;     
      WORD OffsetModuleName; 
      WORD NumberOfModuleForwarderRefs;  
} IMAGE_BOUND_IMPORT_DESCRIPTOR, *PIMAGE_BOUND_IMPORT_DESCRIPTOR;

TimeDateStamp:時間戳,不多作解釋,對應上圖的0x4a5bd97e

OffsetModuleName:偏移,基址是IMAGE_BOUND_IMPORT_DESCRIPTOR的開端,對應上圖的0x00a0,0x280+0xa0就是dll名稱的位置

NumberOfModuleForwarderRefs:後面IMAGE_BOUND_FORWARDER_REF結構的數量,對應上圖的0x01

我們再來看看IMAGE_BOUND_FORWARDER_REF的結構體:

typedef struct _IMAGE_BOUND_FORWARDER_REF {
         DWORD TimeDateStamp;
         WORD OffsetModuleName;
         WORD Reserved;
} IMAGE_BOUND_FORWARDER_REF, *PIMAGE_BOUND_FORWARDER_REF;

這個結構體的內容跟上面的其實是差不多的,繫結匯入表中有一個函式轉發鏈機制,比如說KERNEL32.DLL裡面的HeapAlloc函式會轉發到NTDLL.DLL中的RtlAllocateHeap函式,一般情況下NumberOfModuleForwarderRefs為0,這個結構體對應上圖中的0x288-0x28f處的內容