關於綁定導入表

0x01 綁定導入表概念程序員

 

綁定導入表(The Bound Import Directory)。它包含了可讓加載器判斷綁定的地址是否合法的信息。描述它的數據結構是IMAGE_BOUND_IMPORT_DESCRIPTOR,目錄表就是這種結構的數組,每一項都對應一個被綁定過的DLL。windows

 

每當PE裝載器裝入PE文件時,檢查導入表並將相關DLL映射到進程空間地址。而後經過遍歷IAT裏的IMAGE_THUNK_DATA數組並用導入函數的真實地址替換它,這一步須要不少時間。若是程序員事先能正確預測函數地址,PE裝載器就不用每次裝入PE文件時都去修正IMAGE_THUNK_DATA值了,綁定導入就是這種思想的產物。api

 

當一個可執行文件被綁定(例如經過綁定程序Visual Studio的Bind.exe)時,IAT中的IMAGE_THUNK_DATA結構被導入函數的實際地址改寫了。磁盤中的可執行文件,他們的IAT裏有的存放的是相關DLL導出函數的實際內存地址。這樣可使應用程序更快的進程初始化,而且使用較少的存儲器。數組

 

在執行整個進程期間,bind程序作了兩個重要假設:數據結構

©當進程初始化時,須要的DLL實際加載到了它們的首選基地址中。函數

©自從綁定操做執行以來,DLL導出表中引用的符號位置一直沒有改變工具

 

  固然,若是上面的兩個假設中有一個是假的,IAT中全部地址均是無效的,加載器會檢查這種狀況並作出相應反應,加載器從INT表裏得到所須要的信息來解決導入API的地址問題。對於一個可執行文件的裝入,INT是不須要的。可是,若是沒有,可執行文件是不能被綁定的。微軟的連接器彷佛老是生成一個INT,可是在很長一段時間裏,Borland 的連接器(TLINK)沒有這樣作, 由Borland生成的文件是不能被綁定的。spa

 

      因爲不知用戶運行的是Windows 2000仍是Windows XP,沒法將系統DLL綁定起來,所以程序安裝時是綁定程序的最佳時機。Windows 安裝器的BindImage將作這些工做。另外,IMAGEHLP.DLL提供了BindImageEx函數。無論用什麼方式,綁定都是一個好主意。若是加載器肯定綁定信息是當前的,可執行文件的裝入會更快,若是綁定信息已經變得陳舊了,也不會影響程序的運行。code

 

      對於加載器來講,使綁定變得有效的一個關鍵步驟是肯定在IAT表中的綁定信息是不是當前的。當一個可執行文件被綁定時,被參考的DLL信息放入了文件中,加載器檢查這些信息來作一個快速的綁定有效性驗證。blog

 

      數據目錄表( DataDirectory )的第11個成員指向綁定輸入。綁定輸入以一個IMAGE_BOUND_IMPORT_DESCRIPTOR結構的數組開始,一個綁定可執行文件包含一系列這樣的結構,每一個IBID結構都指出了一個已經被綁定輸入DLL的時間/日期戳。IBID 的結構以下:

 

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

  

 

    TimeDateStamp。包含一個被導入的DLL的時間/日期戳;容許加載器快速斷定綁定是否是新的。這個成員必須和要引用的DLL的文件頭信息相吻合,不然就會加載器去手動計算新IAT,這種狀況通常發生在DLL版本不一樣時或者DLL映像被重定位時。

 

    OffsetModuleName。包含了以第一個IMAGE_BOUND_IMPORT_DESCRIPTOR爲基址,DLL名稱字符串(ASCII且以null結束)的偏移(非RVA)。

 

     NumberOfModuleForwarderRefs。是緊接着本結構後的另外一個IMAGE_BOUND_FORWARDER_REF結構數組的元素個數。

 

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

  

 

這個結構數組幹什麼用的?注意到Forwarder這個詞,咱們在導出表中的函數的轉發,就是一個函數本身不實現而是把調用請求轉發給另外一個DLL中的函數。這裏的IMAGE_BOUND_FORWARDER_REF結構就是用來記錄接受轉發的另外一個DLL的校驗信息,若是這個DLL還有導出轉發,那麼在該DLL中也有IMAGE_BOUND_FORWARDER_REF結構描述第三個DLL的校驗信息。

 

當綁定一個API被轉發到另外一個DLL時,被轉發到的DLL的有效性也要被檢查。這樣,IMAGE_BOUND_FORWARDER_REF和IMAGE_BOUND_IMPORT_DESCRIPTOR結構是交叉存取的。例如連接到HeapAlloc,它被轉向到NTDLL中的RtlAllocateHeap,而後對可執行文件運行BIND。在EXE裏,已經有一個針對KERNEL32.DLL 的IBID, 它後面跟着一個針對NTDLL.DLL 的IMAGE_BOUND_FORWARDER_REF。緊跟在後面多是另外的你輸入並綁定的針對其餘DLL的IBID。Windows目錄裏的應用程序就是典型的綁定輸入結構程序,其IAT已指向相關DLL的函數。

 

爲了方便實現,Microsoft 的一些編譯器( 如Visual Studio)都提供了bind.exe 這樣的工具,由它檢查PE文件的導入表,並用導入函數的真實地址替換IAT裏的IMAGE_THUNK_DATA值。當文件裝入時,PE裝載器一定檢查地址的有效性。若是DLL版本不一樣於PE文件存放的相關信息,或DLE須要重定位那麼裝載器認爲原先計算的地址是無效的,它一定遍歷OriginalFirstThunk 指向的數組以獲取輸入函數新地址,產生一個新的IAT,綁定輸入表去除是不會影響程序正常運行的,去除方法是將圖10.19中的綁定數據清零,而後再將目錄表中的Bound import的RVA與大小清零便可。

總結:

此數據項兩個做用:

一、根據TimeDateStamp和OffsetModuleName字段的值咱們就能夠判斷IAT表中的信息是否已通過期。

二、解決DLL轉發問題

 

0x02 綁定導入表分析

以win7x86 下記事本程序爲例:

*** wait with pending attach
Symbol search path is: srv*
Executable search path is:
ModLoad: 00120000 00150000   C:\Windows\system32\notepad.exe
ModLoad: 77a10000 77b4c000   C:\Windows\SYSTEM32\ntdll.dll
ModLoad: 765f0000 766c4000   C:\Windows\system32\kernel32.dll
ModLoad: 75a70000 75abb000   C:\Windows\system32\KERNELBASE.dll
ModLoad: 761b0000 76250000   C:\Windows\system32\ADVAPI32.dll
ModLoad: 76540000 765ec000   C:\Windows\system32\msvcrt.dll
ModLoad: 77ba0000 77bb9000   C:\Windows\SYSTEM32\sechost.dll
ModLoad: 76d10000 76db1000   C:\Windows\system32\RPCRT4.dll
ModLoad: 75fc0000 7600e000   C:\Windows\system32\GDI32.dll
ModLoad: 76c00000 76cc9000   C:\Windows\system32\USER32.dll
ModLoad: 77b80000 77b8a000   C:\Windows\system32\LPK.dll
ModLoad: 766d0000 7676d000   C:\Windows\system32\USP10.dll
ModLoad: 76770000 767eb000   C:\Windows\system32\COMDLG32.dll
ModLoad: 76250000 762a7000   C:\Windows\system32\SHLWAPI.dll
ModLoad: 74800000 7499e000   C:\Windows\WinSxS\x86_microsoft.windows.common-controls_6595b64144ccf1df_6.0.7601.17514_none_41e6975e2bd6f2b2\COMCTL32.dll
ModLoad: 76dc0000 77a0a000   C:\Windows\system32\SHELL32.dll
ModLoad: 6fd90000 6fde1000   C:\Windows\system32\WINSPOOL.DRV
ModLoad: 76aa0000 76bfc000   C:\Windows\system32\ole32.dll
ModLoad: 76a10000 76a9f000   C:\Windows\system32\OLEAUT32.dll
ModLoad: 74d70000 74d79000   C:\Windows\system32\VERSION.dll
ModLoad: 77c20000 77c3f000   C:\Windows\system32\IMM32.DLL
ModLoad: 767f0000 768bc000   C:\Windows\system32\MSCTF.dll
ModLoad: 75920000 7592c000   C:\Windows\system32\CRYPTBASE.dll
ModLoad: 74560000 745a0000   C:\Windows\system32\uxtheme.dll
ModLoad: 74270000 74283000   C:\Windows\system32\dwmapi.dll
(a70.f44): Break instruction exception - code 80000003 (first chance)
eax=7ffdd000 ebx=00000000 ecx=00000000 edx=77aaf1d3 esi=00000000 edi=00000000
eip=77a44108 esp=0143fc94 ebp=0143fcc0 iopl=0         nv up ei pl zr na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000246
ntdll!DbgBreakPoint:
77a44108 cc              int     3
 
0:001>  dt 00120000 _IMAGE_DOS_HEADER
ntdll!_IMAGE_DOS_HEADER
   +0x000 e_magic          : 0x5a4d
   +0x002 e_cblp           : 0x90
   +0x004 e_cp             : 3
   +0x006 e_crlc           : 0
   +0x008 e_cparhdr        : 4
   +0x00a e_minalloc       : 0
   +0x00c e_maxalloc       : 0xffff
   +0x00e e_ss             : 0
   +0x010 e_sp             : 0xb8
   +0x012 e_csum           : 0
   +0x014 e_ip             : 0
   +0x016 e_cs             : 0
   +0x018 e_lfarlc         : 0x40
   +0x01a e_ovno           : 0
   +0x01c e_res            : [4] 0
   +0x024 e_oemid          : 0
   +0x026 e_oeminfo        : 0
   +0x028 e_res2           : [10] 0
   +0x03c e_lfanew         : 0n224
 
0:001>  dt 00120000+e0 _IMAGE_NT_HEADERS
ntdll!_IMAGE_NT_HEADERS
   +0x000 Signature        : 0x4550
   +0x004 FileHeader       : _IMAGE_FILE_HEADER
   +0x018 OptionalHeader   : _IMAGE_OPTIONAL_HEADER
 
0:001> dt 1200f8  _IMAGE_OPTIONAL_HEADER
ntdll!_IMAGE_OPTIONAL_HEADER
   +0x000 Magic            : 0x10b
   +0x002 MajorLinkerVersion : 0x9 ''
   +0x003 MinorLinkerVersion : 0 ''
   +0x004 SizeOfCode       : 0xa800
   +0x008 SizeOfInitializedData : 0x22400
   +0x00c SizeOfUninitializedData : 0
   +0x010 AddressOfEntryPoint : 0x3689
   +0x014 BaseOfCode       : 0x1000
   +0x018 BaseOfData       : 0xc000
   +0x01c ImageBase        : 0x120000
   +0x020 SectionAlignment : 0x1000
   +0x024 FileAlignment    : 0x200
   +0x028 MajorOperatingSystemVersion : 6
   +0x02a MinorOperatingSystemVersion : 1
   +0x02c MajorImageVersion : 6
   +0x02e MinorImageVersion : 1
   +0x030 MajorSubsystemVersion : 6
   +0x032 MinorSubsystemVersion : 1
   +0x034 Win32VersionValue : 0
   +0x038 SizeOfImage      : 0x30000
   +0x03c SizeOfHeaders    : 0x400
   +0x040 CheckSum         : 0x39741
   +0x044 Subsystem        : 2
   +0x046 DllCharacteristics : 0x8140
   +0x048 SizeOfStackReserve : 0x40000
   +0x04c SizeOfStackCommit : 0x11000
   +0x050 SizeOfHeapReserve : 0x100000
   +0x054 SizeOfHeapCommit : 0x1000
   +0x058 LoaderFlags      : 0
   +0x05c NumberOfRvaAndSizes : 0x10
   +0x060 DataDirectory    : [16] _IMAGE_DATA_DIRECTORY
 
0:001> dt 0x120158+0x58 _IMAGE_DATA_DIRECTORY
ntdll!_IMAGE_DATA_DIRECTORY
   +0x000 VirtualAddress   : 0x278
   +0x004 Size             : 0x128
 
0:001> db 00120000 +0x278 l 130
00120278  7e d9 5b 4a 80 00 00 00-ad da 5b 4a 8d 00 01 00  ~.[J......[J....
00120288  db da 5b 4a 9a 00 00 00-dd d9 5b 4a a4 00 00 00  ..[J......[J....
00120298  2f db 5b 4a ae 00 00 00-6f da 5b 4a b9 00 00 00  /.[J....o.[J....
001202a8  25 da 5b 4a c4 00 00 00-01 db 5b 4a d1 00 00 00  %.[J......[J....
001202b8  4b db 5b 4a dd 00 00 00-c7 da 5b 4a ea 00 00 00  K.[J......[J....
001202c8  05 db 5b 4a f4 00 00 00-76 d9 5b 4a 00 01 00 00  ..[J....v.[J....
001202d8  ca da 5b 4a 0d 01 00 00-db da 5b 4a 9a 00 00 00  ..[J......[J....
001202e8  2b db 5b 4a 1a 01 00 00-00 00 00 00 00 00 00 00  +.[J............
001202f8  41 44 56 41 50 49 33 32-2e 64 6c 6c 00 4b 45 52  ADVAPI32.dll.KER
00120308  4e 45 4c 33 32 2e 64 6c-6c 00 4e 54 44 4c 4c 2e  NEL32.dll.NTDLL.
00120318  44 4c 4c 00 47 44 49 33-32 2e 64 6c 6c 00 55 53  DLL.GDI32.dll.US
00120328  45 52 33 32 2e 64 6c 6c-00 6d 73 76 63 72 74 2e  ER32.dll.msvcrt.
00120338  64 6c 6c 00 43 4f 4d 44-4c 47 33 32 2e 64 6c 6c  dll.COMDLG32.dll
00120348  00 53 48 45 4c 4c 33 32-2e 64 6c 6c 00 57 49 4e  .SHELL32.dll.WIN
00120358  53 50 4f 4f 4c 2e 44 52-56 00 6f 6c 65 33 32 2e  SPOOL.DRV.ole32.
00120368  64 6c 6c 00 53 48 4c 57-41 50 49 2e 64 6c 6c 00  dll.SHLWAPI.dll.
00120378  43 4f 4d 43 54 4c 33 32-2e 64 6c 6c 00 4f 4c 45  COMCTL32.dll.OLE
00120388  41 55 54 33 32 2e 64 6c-6c 00 56 45 52 53 49 4f  AUT32.dll.VERSIO
00120398  4e 2e 64 6c 6c 00 00 00-00 00 00 00 00 00 00 00  N.dll...........

  

 

分析一下,第一行4a5bd97eh爲TimeDateStamp值,80h爲當前綁定dll名的相對偏移,00h表示當前dll轉發dll個數爲0,因此也就不存在IMAGE_BOUND_FORWARDER_REF結構。

0:001> db 00120278+80
001202f8  41 44 56 41 50 49 33 32-2e 64 6c 6c 00 4b 45 52  ADVAPI32.dll.KER

  

 

第一行,右半部分,4a5bdaad爲TimeDateStamp值,8dh爲當前綁定dll名的相對偏移,01h表示當前dll轉發dll個數爲1,因此後面跟着的8個字節,爲IMAGE_BOUND_FORWARDER_REF結構。

0:001> db 00120278+8d
00120305  4b 45 52 4e 45 4c 33 32-2e 64 6c 6c 00 4e 54 44  KERNEL32.dll.NTD

  

 

能夠看到在IMAGE_BOUND_FORWARDER_REF結構中,4a5bdadbh爲TimeDateStamp值,轉發dll名字偏移爲9d,查看內存發現時ntdll,也就是說調用kernel32.dll中函數時,會轉發到ntdll中。

0:001> db 00120278+9a
00120312  4e 54 44 4c 4c 2e 44 4c-4c 00 47 44 49 33 32 2e  NTDLL.DLL.GDI32.

觀察當前保定導出表內存,發現大部分dll都沒有轉發,只有kernel32.dll轉發到ntdll.dll。

咱們接着再以加載的Kernel32.dll爲例:

0:001> dt 765f0000 _IMAGE_DOS_HEADER
ntdll!_IMAGE_DOS_HEADER
   +0x000 e_magic          : 0x5a4d
   +0x002 e_cblp           : 0x90
   +0x004 e_cp             : 3
   +0x006 e_crlc           : 0
   +0x008 e_cparhdr        : 4
   +0x00a e_minalloc       : 0
   +0x00c e_maxalloc       : 0xffff
   +0x00e e_ss             : 0
   +0x010 e_sp             : 0xb8
   +0x012 e_csum           : 0
   +0x014 e_ip             : 0
   +0x016 e_cs             : 0
   +0x018 e_lfarlc         : 0x40
   +0x01a e_ovno           : 0
   +0x01c e_res            : [4] 0
   +0x024 e_oemid          : 0
   +0x026 e_oeminfo        : 0
   +0x028 e_res2           : [10] 0
   +0x03c e_lfanew         : 0n240
0:001> dt 765f00f0 _IMAGE_NT_HEADERS
ntdll!_IMAGE_NT_HEADERS
   +0x000 Signature        : 0x4550
   +0x004 FileHeader       : _IMAGE_FILE_HEADER
   +0x018 OptionalHeader   : _IMAGE_OPTIONAL_HEADER
0:001> dt 765F0108 _IMAGE_OPTIONAL_HEADER
ntdll!_IMAGE_OPTIONAL_HEADER
   +0x000 Magic            : 0x10b
   +0x002 MajorLinkerVersion : 0x9 ''
   +0x003 MinorLinkerVersion : 0 ''
   +0x004 SizeOfCode       : 0xc5000
   +0x008 SizeOfInitializedData : 0xe000
   +0x00c SizeOfUninitializedData : 0
   +0x010 AddressOfEntryPoint : 0x4cd6f
   +0x014 BaseOfCode       : 0x1000
   +0x018 BaseOfData       : 0xc0000
   +0x01c ImageBase        : 0x765f0000
   +0x020 SectionAlignment : 0x1000
   +0x024 FileAlignment    : 0x1000
   +0x028 MajorOperatingSystemVersion : 6
   +0x02a MinorOperatingSystemVersion : 1
   +0x02c MajorImageVersion : 6
   +0x02e MinorImageVersion : 1
   +0x030 MajorSubsystemVersion : 6
   +0x032 MinorSubsystemVersion : 1
   +0x034 Win32VersionValue : 0
   +0x038 SizeOfImage      : 0xd4000
   +0x03c SizeOfHeaders    : 0x1000
   +0x040 CheckSum         : 0xdca19
   +0x044 Subsystem        : 3
   +0x046 DllCharacteristics : 0x140
   +0x048 SizeOfStackReserve : 0x40000
   +0x04c SizeOfStackCommit : 0x1000
   +0x050 SizeOfHeapReserve : 0x100000
   +0x054 SizeOfHeapCommit : 0x1000
   +0x058 LoaderFlags      : 0
   +0x05c NumberOfRvaAndSizes : 0x10
   +0x060 DataDirectory    : [16] _IMAGE_DATA_DIRECTORY
 
0:001> dt 765F0168+58  _IMAGE_DATA_DIRECTORY
ntdll!_IMAGE_DATA_DIRECTORY
   +0x000 VirtualAddress   : 0x288
   +0x004 Size             : 0x408
 
0:001> db 77a10000 +0x288
77a10288  00 00 00 00 40 00 00 42-00 00 00 00 00 00 00 00  ....@..B........
77a10298  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00  ................
77a102a8  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00  ................
77a102b8  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00  ................
77a102c8  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00  ................
77a102d8  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00  ................
77a102e8  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00  ................
77a102f8  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00  ................
 
0:001> db 77a10288+40
77a102c8  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00  ................
77a102d8  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00  ................
77a102e8  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00  ................
77a102f8  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00  ................
77a10308  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00  ................
77a10318  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00  ................
77a10328  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00  ................
77a10338  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00  ................

能夠發現,加載的kernel32.dll中,雖然存在綁定導入表,可是內容卻未空,意味着當前模塊沒有綁定其餘模塊。

相關文章
相關標籤/搜索