什麼是動態鏈接庫DLL?以及DLL所需要的三個函數詳解(LoadLibrary,GetProcAddress,FreeLibrary)

一、DLL的概念

       DLL(Dynamic Link Library),動態鏈接庫文件,又稱“應用程序拓展”,是軟件文件類型,擴展名是“.dll”。在Windows中,許多應用程序並不是一個完整的可執行文件,它們被分割成一些相對獨立的動態鏈接庫,即DLL文件,放置於系統中。當我們執行某一個程序時,相應的DLL文件就會被調用。例如:kernel32.dll中含有LoadLibrary()和GetProcAddress(),ws2_32.dll中含有winsock()函數。一個應用程序可使用多個DLL文件,一個DLL文件也可能被不同的應用程序使用,這樣的DLL文件被稱爲“共享DLL文件”。

       DLL文件中存放的是各類程序的函數(子過程)實現過程,當程序需要調用函數時需要先載入DLL,然後取得函數的地址,最後進行調用。使用DLL文件的好處是程序不需要在運行之初加載所有代碼,只有在程序需要某個函數的時候才從DLL中取出。另外,使用DLL文件還可以減小程序的體積。

      通過使用 DLL,程序可以實現模塊化,由相對獨立的組件組成。 例如,一個計帳程序可以按模塊來銷售。 可以在運行時將各個模塊加載到主程序中(如果安裝了相應模塊)。因爲模塊是彼此獨立的,所以程序的加載速度更快,而且模塊只在相應的功能被請求時才加載。此外,可以更爲容易地將更新應用於各個模塊,而不會影響該程序的其他部分。 例如,您可能具有一個工資計算程序,而稅率每年都會更改。 當這些更改被隔離到 DLL 中以後,您無需重新生成或安裝整個程序就可以應用更新。

 

二、DLL故障排除工具

    Dependency Walker

    Dependency Walker 工具可以遞歸掃描以尋找程序所使用的所有依賴 DLL。 當在 Dependency Walker 中打開程序時,Dependency Walker 會執行下列檢查:

    Dependency Walker 檢查是否丟失 DLL。
    Dependency Walker 檢查是否存在無效的程序文件或 DLL。
    Dependency Walker 檢查導入函數和導出函數是否匹配。
    Dependency Walker 檢查是否存在循環依賴性錯誤。
    Dependency Walker 檢查是否存在由於針對另一不同操作系統而無效的模塊。

通過使用 Dependency Walker,您可以記錄程序使用的所有 DLL。 這可能有助於避免和更正將來可能發生的 DLL 問題。 當安裝 Microsoft Visual Studio 6.0 時,Dependency Walker 將位於以下目錄中:http://www.dependencywalker.com/(下載地址)

    DLL Universal Problem Solver

    DLL Universal Problem Solver (DUPS) 工具用於審覈、比較、記錄和顯示 DLL 信息。 下表說明了組成 DUPS 工具的實用工具:

    Dlister.exe
    該實用工具枚舉計算機中的所有 DLL,並且將此信息記錄到一個文本文件或數據庫文件中。
    Dcomp.exe
    該實用工具比較在兩個文本文件中列出的 DLL,併產生包含差異的第三個文本文件。
    Dtxt2DB.exe
    該實用工具將通過使用 Dlister.exe 實用工具和 Dcomp.exe 實用工具創建的文本文件加載到 dllHell 數據庫中。
    DlgDtxt2DB.exe
    該實用工具提供 Dtxt2DB.exe 實用工具的圖形用戶界面 (GUI) 版本。

有關 DUPS 工具的更多信息,請單擊下面的文章編號,以查看 Microsoft 知識庫中相應的文章:

使用 DUPS.exe 解決 DLL 兼容性問題

    DLL 幫助數據庫

    DLL 幫助數據庫幫助您查找由 Microsoft 軟件產品安裝的特定版本的 DLL。 有關 DLL 幫助數據庫的更多信息,請訪問下面的 Microsoft 網站:

http://support.microsoft.com/dllhelp/
 

三、動態載入 DLL

     動態載入方式是指在編譯之前並不知道將會調用哪些 DLL 函數, 完全是在運行過程中根據需要決定應調用哪些函數。

方法是:用 LoadLibrary 函數加載動態鏈接庫到內存,用 GetProcAddress函數動態獲得 DLL 函數的入口地址。當一個 DLL 文件用 LoadLibrary 顯式加載後,在任何時刻均可以通過調用 FreeLibrary 函數顯式地從內存中把它給卸載。

動態調用使用的 Windows API 函數主要有 3 個, 分別是 LoadLibrary、 GetProcAddress 和FreeLibrary。

我們分別詳細介紹這三個函數的功能,因爲無論學習編程還是逆向這是三個函數都是非常常用滴。


(1)LoadLibrary 函數

注:Delphi 中還提供了 SafeLoadLibrary 函數,它封裝了 Loadlibrary 函數,可以裝載由 Filename 參數指定的 WindowsDLL或 Linux 共享對象。它簡化了DLL的裝載並且使裝載更加安全。

[格式]:

  1. function LoadLibrary(LibFileName : PChar): Thandle;

複製代碼


[功能]:加載由參數 LibFileName 指定的 DLL 文件。

[說明]:參數 LibFileName 指定了要裝載的 DLL 文件名,如果 LibFileName 沒有包含一個路徑,系統將按照:當前目錄、Windows 目錄、Windows 系統目錄、包含當前任務可執行文件的目錄、列在 PATH 環境變量中的目錄等順序查找文件。

如果函數操作成功,將返回裝載 DLL 庫模塊的實例句柄,否則,將返回一個錯誤代碼,錯誤代碼的定義如下表所示。

 

錯誤代碼

  含義

  0   系統內存不夠,可執行文件被破壞或調用非法
  2   文件沒有被發現
  3   路徑沒有被發現
  5   企圖動態鏈接一個任務錯誤或者有一個共享或網絡保護錯誤
  6   庫需要爲每個任務建立分離的數據段  
  8   沒有足夠的內存啓動應用程序  
  10   Windows  版本不正確  
  11   可執行文件非法或不是Windows  應用程序,或在.  EXE映像中有錯誤  
  12   應用程序爲一個不同的操作系統設計(如  OS/2)  
  13   應用程序爲  MS  DOS   4. 0  設計  
  14   可執行文件的類型不知道  
  15   試圖裝載一個實模式應用程序(爲早期Windows  版本設計)
  16   試圖裝載包含可寫的多個數據段的可執行文件的第二個實例  
  19   試圖裝載一個壓縮的可執行文件(文件必須被解壓後才能被裝載)  
  20   DLL  文件非法
  21   應用程序需要  32  位擴展


假如在應用程序中用 LoadLibrary 函數裝入某一個 DLL 前, 其他應用程序已把該 DLL 裝入內存中了,則系統將不再裝入該 DLL 的另一個實例,而是使該 DLL 的“引用計數”加 1 。


(2)GetProcAddress 函數

[格式]:

  1. function GetProcAddress(Module:Thandle; ProcName:PChar): TfarProc;

複製代碼


[功能]:返回參數 Module 指定的模塊中,由參數 ProcName 指定的過程或函數的入口地址。

[說明]:參數 Module 包含被調用函數的 DLL 句柄,這個值由 LoadLibrary 返回, ProcName
是指向含有函數名的以 nil 結尾的字符串指針,或者可以是函數的次序值,但大多數情況下,用函數名是一種更穩妥的選擇。如果該函數執行成功,則返回 DLL 中由參數 ProcName 指定的過程或函數的入口地址,否則返回 nil 。


(3)FreeLibrary 函數

[格式]:

  1. procedure  FreeLibrary(Module: Thandle);

複製代碼


[說明]:將由參數 Module 指定的 DLL 文件從內存中卸載 1 次。

[說明]:Module 爲 DLL 庫的句柄。這個值由 LoadLibrary 返回。由於 DLL 在內存中只裝載一次,因此調用 FreeLibrary 首先使 DLL 的引用計數減 1,如果計數減爲 0 則卸載該 DLL。

[注意]:每調用一次 LoadLibrary 函數就應調用一次 FreeLibrary 函數,以保證不會有多餘的庫模塊在應用程序結束後仍留在內存中,否則導致內存泄漏。

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