天天看點

如何檢視exe或dll調用了什麼dll呢

在Windows世界中,有無數塊活動的大陸,它們都有一個共同的名字——動态連結庫。現在就讓我們走進這些神奇的活動大陸,找出它們隐藏已久的秘密吧!

初窺門徑:Windows的基石

随便打開一個系統目錄,一眼望去就能看到很多擴充名DLL的檔案,這些就是經常說的“動态連結庫”,DLL是Dynamic Link Library(即“動态連結庫”)的縮寫。從Microsoft公司推出首個版本的Windows以來,動态連結庫就一直是這個作業系統的基礎。

1.看看DLL裡有什麼

與其用晦澀的專業術語來解決DLL是什麼,不如先來看看DLL裡有什麼。DLL和EXE檔案一樣,其中包含的也是程式的二進制執行代碼和程式所需的資源(比如圖示、對話框、字元串等),可是為什麼要把代碼放在DLL裡面,而不是做成EXE呢?其實DLL中的代碼是以API函數形式出現的,通俗地說,DLL中包含的程式代碼都被做成了一個個小子產品,應用程式通過按下所需DLL中特定的按鈕,來調用DLL中這個按鈕所代表的功能。在使用“記事本”等程式時,如果要儲存檔案或打開檔案,就會彈出通用檔案對話框,讓我們選擇檔案位置。你可知道,這就是調用了系統底層DLL中的通用對話框界面。

2.系統中幾個重要的DLL

Windows中有3個非常重要的底層DLL:Kernel32.dll、User32.dll、GDI32.dll。其中Kernel32.dll顧名思義就是核心相關的功能,主要包含用于管理記憶體、程序和線程的函數;而User32.dll中包含的則是用于執行使用者界面任務的函數,比如把使用者的滑鼠點選操作傳遞給視窗,以便視窗根據使用者的點選來執行預定的事件;GDI32.dll的名稱用了縮寫,全稱是Graphical Device Interface(圖形裝置接口),包含用于畫圖和顯示文本的函數,比如要顯示一個程式視窗,就調用了其中的函數來畫這個視窗。

3.為什麼要用DLL

剛才在談到這個問題的時候,我們隻是解釋了DLL将程式代碼封裝成函數的原理。為什麼封裝成函數,就能成為系統中大量使用DLL的理由呢?

①擴充應用程式

由于DLL能被應用程式動态載入記憶體。是以,應用程式可以在需要時才将DLL載入到記憶體中,這讓程式的可維護性變得很高。比如QQ的視訊功能需要更新,那麼負責編寫QQ的程式員不必将QQ所有代碼都重寫,隻需将視訊功能相關的DLL檔案重寫即可。

②便于程式員合作

這個和我們最終使用者關系不大,僅供了解。我們都知道程式設計工具有很多,比如VB、VC、Delphi等,如果好幾個人合作來編寫一個大的程式,那麼可能有的人用VB,有的人用VC,每人負責的部分所使用的程式設計語言都不同,究竟放在哪個編譯器中進行編譯呢?這就好比一群來自各個國家的人在共同編寫一篇文章,如果他們所使用的語言都不同,寫出來的文章怎麼可能湊到一起呢?而有了DLL後,可以讓VC程式員寫一個DLL,然後VB程式員在程式中調用,無需為怎麼将它們都編譯為一個單獨的EXE而發愁了。

③節省記憶體

如果多個應用程式調用的是同一個動态連結庫,那麼這個DLL檔案不會被重複多次裝入記憶體中,而是由這些應用程式共享同一個已載入記憶體的DLL。就好比一個辦公室中,很少會為每一個員工配置一台飲水機的,而是在一個公共位置放上一個飲水機,所有需要喝水的職員都可以共用這台飲水機,降低了成本又節約了空間。

④共享程式資源

包括剛才提到過的通用檔案對話框在内,DLL檔案提供了應用程式間共享資源的可能。資源可以是程式對話框、字元串、圖示,或者聲音檔案等。

⑤解決應用程式本地化問題

在下載下傳了某個程式的漢化包後,打開漢化說明,經常可以看到用下載下傳包中的DLL檔案覆寫掉程式原來的DLL,漢化就完成了。這些程式都是将執行代碼和應用程式界面分開編寫了,是以漢化者隻需簡單地将其中和程式界面相關的DLL漢化并釋出即可。

求知若渴:探究DLL的真相

誰知道DLL裡究竟有多少函數,又有誰知道EXE調用了哪個DLL的哪些函數?其實,這個問題并不難解決。還記不記得本刊2004年第6期的《無間盜IV——盜亦有盜》中介紹的分析EXE檔案的工具Dependency Walker(以下簡稱Depends)今天我們要用它當探險工具,把DLL真相探個通通透透。

1.看看DLL裡有多少函數

第一步:下載下傳并解壓Depends,運作其中的depends.exe,然後選擇菜單“File→Open”(檔案→打開),在檔案選擇框中選中需要分析的DLL檔案并打開,此處選擇QQ目錄下的QQZip.dll。

第二步:在程式左側的樹狀欄中就列出了這個DLL使用了哪些其他DLL的功能函數(原來DLL中還可以調用其他DLL^O^),而右側的兩個分欄清單分别顯示了函數輸入及輸出表,函數輸出表即為該DLL提供給其他EXE或者DLL調用的函數的總清單。

第三步:函數輸出表的Function欄中即為輸出函數的名稱(見圖1),在QQZip.dll中共發現了2個函數:Unzip、Zip。是以可以判斷該DLL在QQ程式中負責壓縮和解壓縮的任務。

如何檢視exe或dll調用了什麼dll呢

2.審審EXE究竟用了哪個DLL

還是拿QQ來作為例子,在Depends中打開QQ.exe,這時界面左側的樹狀清單中顯示的就是QQ.exe調用的DLL清單(見圖2),如果展開這些DLL分支,還會發現其他的DLL,這就說明QQ調用的這些DLL檔案還有可能(幾乎是肯定)再調用别的DLL。這就好比買了一台新的DVD機,可能其中用的機芯是SONY的,而這個機芯裡的一個小電容又有可能是别的公司的,這是同樣的道理。

如何檢視exe或dll調用了什麼dll呢

3.用DLL看穿EXE真面目

剛才得到了QQ.exe所使用的DLL清單,其實通過這個清單,還能分析出很多别的資訊。比如其中包含MFC42.dll,是以可以判斷QQ.exe是采用VC(即Visual C++)編寫的,而包含WSOCK32.dll則說明這個程式帶有網絡通訊功能(廢話!QQ如果不能網絡通訊還有什麼用……)。以下是一個簡表,大家在分析别的EXE時可以根據其所使用的DLL來對其功能進行初步判斷。

DLL檔案名 可以判斷出的EXE資訊

MFC42.dll 使用VC5.0/6.0編寫。

VBRun*.dll “*”代表數字版本号,使用VB3.0/4.0編寫。

MSVBVM50.dll 使用VB5.0編寫,在Windows 98(SE)上自帶該DLL。

MSVBVM60.dll 使用VB6.0編寫,在Windows Me/2000/XP等系統上自帶該DLL。

ADVAPI32.dll 可能會進行系統資料庫操作。

WSOCK32.dll 具備網絡通訊功能。

WS2_32.dll 具備網絡通訊功能。

WININET.dll 具備HTTP浏覽、下載下傳等功能,典型的例子是浏覽器、下載下傳工具。

WINMM.dll 具備多媒體播放能力。

DDRAW.dll 遊戲、進階圖像處理工具。

D3D*.dll 3D遊戲,或者動畫處理工具。

4.DLL是個大寶庫

除供應用程式調用函數的DLL外,還有另一種用來儲存資源的DLL,比如QQ目錄下的QQRes.dll,用Depends打開後發現沒有任何輸出函數,難道是一個雞肋DLL?可是改用資源工具Resource Hacker(下載下傳位址:http://www.mydown.com/soft/42/42058.html)打開這個DLL後,就發現原來其中儲存了這麼多QQ的資源,包括圖示、音樂、圖檔、字元串、對話框……(見圖3)

如何檢視exe或dll調用了什麼dll呢

刨根問底:DLL的寓言

DLL引起的故障是很常見的,為什麼會引起故障?遇到故障怎麼解決?噓~偷聽一下DLL的對話,你就會明白了。

1.從搬運工談接口相容性

在Windows工地上,有一個名叫EXE的包工頭,他手下有很多稱為DLL的建築勞工。其中有一個專門負責搬運的DLL(暫且稱為“搬運工A”),每次需要搬運水泥時,包工頭EXE都隻要對他喊一聲:“來!搬。”

過了一段時間,搬運工A覺得自己的效率太低,于是從原來的每次搬1袋水泥改成了每次搬3袋水泥。改進了搬運方法後,EXE包工頭仍然每次隻是喊一聲:“來!搬。”卻不知搬運工A已經改變了搬運的方法。

但又過了一段時間,包工頭EXE把搬運工A給辭退了,從别的工地上找來了另一個DLL(暫且稱為“搬運工B”)。這個搬運工在别的工地的時候,搬運東西特别快,是以包工頭EXE決定把搬運工作給“更新”一下。但真正開始工作時,包工頭才發現出了問題……現在不管叫幾遍“來!搬。”這個新來的搬運工B都不知道究竟應該搬什麼。

上面的例子中,搬運工A改進搬運方法,但EXE調用它的方法仍不變,這就是DLL更新的原理,改進了内部的實作方法,但調用接口不變,這樣EXE檔案不用跟着更新,就能調用新版本的DLL了。而搬運工B的故事告訴我們,不管新版本的DLL效率多高,如果接口(可以了解為DLL中輸出的函數名)與原來的不一緻,那麼EXE就不知道也無法調用它了。

2.登記身份證的DLL

在系統故障中,有很多都是由于DLL檔案沒有注冊造成的,比如Windows XP的壓縮檔案夾功能出現故障就很有可能是系統目錄中的zipfldr.dll沒有注冊造成的,這類故障的解決方法也大多是運作如下指令:

regsvr32 DLL檔案名

很多人不了解為什麼要這麼做,是不是所有的DLL都能這樣做呢?

其實系統中有兩種DLL,一種是不需注冊即可使用的,另一種則是必須經過系統登入(即注冊)才能使用的。就好像一個臨時工,和一個記錄在員工名單上的長期合同工的差別一樣。如何才能區分這兩種DLL呢?方法很簡單,用剛才的Depends打開這個DLL,同樣是看函數輸出表,如果其中包含以下兩個函數(前者是注冊DLL,後者是反注冊DLL),那麼就一定是需要注冊才能使用的DLL了。

DllRegisterServer

DllUnregisterServer

而regsvr32這個指令,實際上就是調用DLL中的這兩個函數(“regsvr32 /u DLL檔案名”調用的即為DllUnregisterServer反注冊函數)。

3.插件DLL的秘密

Winamp、Foobar 2000等很多軟體都具有插件功能,從網上下載下傳一個DLL放在插件目錄下就能讓程式支援新的功能,這是怎麼做到的呢?就拿時下流行的播放軟體“千千靜聽”來舉例吧。

“千千靜聽”的插件目錄在該軟體安裝目錄下的Addin子目錄下,程式的插件目錄一般都會以“Plugins”、“Addin”來命名。在“千千靜聽”的插件目錄中有許多DLL檔案,比如tt_asf.dll、tt_rm.dll等,從檔案名中就能看出這些DLL是用來讓這個播放器支援各種不同類型的音頻檔案的。同樣,用Depends打開這些檔案,你就會發現這些檔案的輸出函數表中都包括一個同樣的函數:ttpGetSoundAddIn(見圖4)。

如何檢視exe或dll調用了什麼dll呢

這就是插件的秘密,各種支援插件功能的程式在釋出時,都會同時釋出一份插件協定,協定中規定了該程式将要調用的插件DLL中必須包含的函數名稱及相關的參數規則,然後第三方的插件程式員在編寫這個程式的插件時就根據這個插件的标準來編寫DLL的輸出函數。

①對于插件tt_asf.dll

ttplayer.exe(“千千靜聽”主程式)對tt_asf.dll說:“我要調用你的ttpGetSoundAddIn函數!”

tt_asf.dll回答:“OK。”

②如果把不相關的DLL放進AddIn目錄

ttplayer.exe對未知DLL說:“我要調用你的ttpGetSoundAddIn函數!”

tt_asf.dll回答:“那是什麼函數?從來沒聽說過!”