《Undocumented Windows 2000 Secrets》翻譯 --- 2(1)
盡管調(diào)試器的命令已經(jīng)注意了易記性,但有時(shí)總是難以回憶起它們。因此,我把它們都整理到了附錄A中。表A-1是其快速參考。這個(gè)表是調(diào)試器的help信息(使用?命令)的整理版。命令所需參數(shù)的類型匯總在表A-2。
前面提到過,內(nèi)核調(diào)試器執(zhí)行擴(kuò)展命令時(shí)需要一個(gè)!號(hào)作為開始。只要命令前有個(gè)!號(hào),調(diào)試器就會(huì)到已加載的擴(kuò)展DLL的導(dǎo)出列表中進(jìn)行查找。如果發(fā)現(xiàn)匹配的,就會(huì)跳轉(zhuǎn)到相應(yīng)的DLL中。圖1-7顯示了內(nèi)核調(diào)試器加載了kdextx86.dll、userkdx.dll和dbghelp.dll擴(kuò)展DLL。最后一個(gè)和i386kd.exe位于同一目錄;前兩個(gè)共有四個(gè)版本:針對(duì)Windows NT 4.0的free和checked版本(對(duì)應(yīng)子目錄為:nt4fr和nt4chk),針對(duì)Windows 2000的free和checked版本。通常,調(diào)試器在搜尋擴(kuò)展命令是會(huì)采用一個(gè)默認(rèn)的搜索順序。然而,你可以改變這個(gè)默認(rèn)設(shè)置,只需要在命令前指定模塊名稱即可,采用.符號(hào)作為分隔符。例如,kedxtx86.dll和userkdx.dll都導(dǎo)出了help命令,鍵入!help,在默認(rèn)情況下,你會(huì)得到kdextx86.dll的幫助信息。要執(zhí)行userdkx.dll的help命令,你必須輸入!userkdx.help(或者!userkdx.help –V如果你想得到更詳細(xì)的幫助信息的話)。按照此方法,只要你知道規(guī)則,你也可以編寫自己的擴(kuò)展命令。在The NT Insider(Open Systems Resources 1999a)中你能找到很棒的how-to文章。不過其針對(duì)的是WinDbg.exe而不是i386kd.exe,但兩者使用相同的擴(kuò)展DLL,大多數(shù)信息對(duì)于i386kd.exe也是有效的。
附錄A中的表A-3和A-4分別列出了kdextx86.dll和userkdx.dll的help命令的輸出信息。為了便于閱讀作了些修改和整編。你會(huì)發(fā)現(xiàn)這些表中列出的命令多于Microsoft DDK文檔中的,其中有些命令明顯有DDK文檔未提到的附加參數(shù)。
10大調(diào)試命令
表A-1到A-4列出了內(nèi)核調(diào)試器及其標(biāo)準(zhǔn)擴(kuò)展DLL提供的巨多的命令。因此,我將討論其中一些常用命令的細(xì)節(jié)。
u: 反編譯機(jī)器碼
在檢查crash dump是否正確時(shí),你已經(jīng)用過了此命令,u命令有三種格式:
1.u <from> 從地址<from>開始反編譯8個(gè)機(jī)器碼。
2.u <from> <to> 反編譯<from>到<to>之間的所有機(jī)器碼。
3.u 不提供任何參數(shù)時(shí),從上次u命令停止的位置開始反編譯。
當(dāng)然,反編譯打段代碼是十分厭煩的,但如果你只想知道在特定地址發(fā)生的事情,那這是最便捷的方法。或許u命令最令人感興趣的特性是它可以解析代碼引用到的符號(hào)----即使是目標(biāo)模塊沒有導(dǎo)出的符號(hào)。不過,使用本書光盤中的Multi-Format Visual Disassembler反編譯完整的Windows 2000可執(zhí)行體將是十分有趣的。在隨后章節(jié)中,會(huì)有關(guān)該產(chǎn)品的更多信息。
db,dw和dd:Dump Memory BYTEs、Words和DWORDs
如果你當(dāng)前感興趣的內(nèi)存數(shù)據(jù)是二進(jìn)制的,那么調(diào)試器的16進(jìn)制轉(zhuǎn)儲(chǔ)命令將能完成此任務(wù)。根據(jù)你對(duì)源地址(source address)數(shù)據(jù)類型的判斷,來選擇dd(針對(duì)BYTES)、dw(針對(duì)WORDS)、dd(針對(duì)DWORDS)。
l db 將指定內(nèi)存范圍里的數(shù)據(jù)顯示為兩個(gè)部分:左邊是16進(jìn)制表示(每2個(gè)8 bit一組),右邊是對(duì)應(yīng)的ASCI碼。
l dw 僅按照16進(jìn)制顯示(16 bit一組)
l dw 僅按照16進(jìn)制顯示(32 bit一組)
此組命令可以使用與u命令相同的參數(shù)。注意,<to>所指示的地址內(nèi)容,也會(huì)被顯示出來。如果沒有任何參數(shù),將顯示接下來的128個(gè)字節(jié)。
x:檢查符號(hào)
x命令非常重要。它可以根據(jù)已安裝的符號(hào)文件創(chuàng)建一個(gè)列表。典型的使用方式如下:
1.x *!* 顯示所有可用符號(hào)的模塊。在啟動(dòng)后,默認(rèn)只有ntoskrnl.exe的符號(hào)是可用的。其他模塊的符號(hào)可以使用.reload命令來加載。
2.x <module>!<filter> 顯示模塊<module>的符號(hào)文件中的符號(hào)名稱,<filter>可以包括通配符?和*。<module>必須屬于x *!*列出的模塊名。例如,x nt!*將列出在內(nèi)核符號(hào)文件ntoskrnl.dbg中找到的所有符號(hào),x win32k!*將列出win32k.dbg提供的符號(hào)。如果調(diào)試器報(bào)告說“Couldn’t resolve ‘X….’”,嘗試用.reload再次加載所有的符號(hào)文件。
3.x <filter> 顯示所有可用符號(hào)的一個(gè)子集,該子集不匹配<filter>表達(dá)式。本質(zhì)上,這是x <module>!<filter>的一個(gè)變形,在這里<module>!被省略了。
隨符號(hào)名一起顯示的,還有與其相關(guān)的虛擬地址。對(duì)于函數(shù)名,與其對(duì)應(yīng)的就是函數(shù)的入口地址。對(duì)于變量,就是改變量的基地址。該命令值得的注意的地方是,它可以輸出很多內(nèi)部符號(hào)(internal symbols),這些在可執(zhí)行文件的導(dǎo)出表中都是找不到的。
ln:列出最近的符號(hào)
ln是我最喜歡的一個(gè)命令。因?yàn)樗梢钥焖偾液唵蔚脑L問已安裝的符號(hào)文件。算是x命令的理想補(bǔ)充。不過后者適用于列出所有系統(tǒng)符號(hào)的地址。Ln命令則用于按照地址或名稱查找符號(hào)。
l ln <address> 顯示<address>指示的地址以及和其前后相鄰的地址的符號(hào)信息。
l ln <symbol> 將符號(hào)名解析為與其對(duì)應(yīng)的虛擬地址。其過程與ln <address>類似。
像x命令一樣,調(diào)試器知道所有導(dǎo)出的以及一些內(nèi)部的符號(hào)。因此,對(duì)于想弄清楚出現(xiàn)在反編譯列表或16進(jìn)制轉(zhuǎn)儲(chǔ)中的不明指針的確切含義的人有著非常大的幫助。注意,u、db、dw、dd也會(huì)使用符號(hào)文件。
!processfIEld:列出EPROCESS的成員
該命令前的!號(hào),意味著它來自于調(diào)試器的擴(kuò)展模塊—kdextx86.dll。該命令可顯示內(nèi)核用來代表一個(gè)進(jìn)程的EPROCESS結(jié)構(gòu)(該結(jié)構(gòu)并沒有正式的說明文檔)的成員及其偏移量。
盡管該命令僅列出了成員的偏移量,但你也能很容易的猜出其正確的類型。例如,LockEvent位于0x70處,其下一個(gè)成員的偏移量為0x80。則該成員占用了16個(gè)字節(jié),這與KEVENT結(jié)構(gòu)非常類似。如果你不知道什么是KEVENT,不要擔(dān)心,我在第7章將會(huì)討論之。
!threadfields:列出ETHREAD成員
這是kdextx86.dll提供的另一個(gè)強(qiáng)大的選項(xiàng)。和!processfields類似,它列出未文檔化的ETHREAD結(jié)構(gòu)的成員及其偏移量。內(nèi)核使用它表示一個(gè)線程。參見示例1-2
!drivers:列出已加載的Driverskdextx86.dll真是太棒了。!drivers列出了當(dāng)前運(yùn)行的內(nèi)核和文件系統(tǒng)模塊的詳細(xì)信息。如果檢查crash dump,該命令會(huì)列出系統(tǒng)崩潰那一刻的系統(tǒng)狀態(tài)。示例1-3是我機(jī)器上輸出的摘要。注意,在輸出的最后一行,導(dǎo)致Windows 2000崩潰的Driver的地址為0xBECC2000,這顯然是w2k_kill.sys引發(fā)藍(lán)屏后顯示的地址。
譯注:在新的i386kd.exe(ver: 6.3.0017.0)中,!driver命令已不被支持。取而代之的是lm命令。該命令的一般用法是:lm t n
!sel:檢查Selector的值
如果沒有爭議的話,!sel實(shí)現(xiàn)于kdextx86.dll。它用來顯示16個(gè)連續(xù)的memory selector(按地址升序排列)。你可以反復(fù)的使用此命令直到出現(xiàn)“Selector is invalid”。在第4章將討論Memory Selector,到時(shí)我會(huì)提供一個(gè)示列代碼來演示如何在你的程序中crack selectors。
譯注:
在新的調(diào)試器中,該命令已不被支持,取而代之的是:dg命令。其一般性用法為:dg.注意末尾的.符號(hào)。dg命令最多可列出256個(gè)Selector。調(diào)試器的Online Help中有詳細(xì)說明
關(guān)閉調(diào)試器
你可以通過簡單的關(guān)閉控制臺(tái)窗口來關(guān)閉內(nèi)核調(diào)試器。當(dāng)然,更好的關(guān)閉辦法是使用q命令,這兒“q”代表著quit。
更多的調(diào)試工具
在本書的光盤中,你可以找到兩個(gè)由我的e-friends貢獻(xiàn)的非常有價(jià)值的調(diào)試工具。我很高興他們?cè)试S我將完整版本放入我的光盤中。Wayne J. Radburn的 PE and COFF文件瀏覽器(PEView)是本書讀者的一個(gè)特殊免費(fèi)工具。Jean-Louis Seigne的Multi-Format Visual Disassembler(MFVDasm)一個(gè)限時(shí)版本。本節(jié)將簡單介紹這兩個(gè)工具。
MFVDASM:可視化多格式反編譯器
MFVDasm不僅僅是個(gè)匯編列表生成器。事實(shí)上,它比匯編代碼瀏覽器增加了多個(gè)很不錯(cuò)的導(dǎo)航特性。如圖1-8所示,那是我使用MFVDasm察看Windows 2000 I/O管理函數(shù)IoDetachDevice()的截圖。圖中并沒有顯示出屏幕上的顏色。例如,所有的函數(shù)表以及特定地址的jumps和calls都被顯示為紅色。針對(duì)其余地址(沒有相關(guān)導(dǎo)出符號(hào)的地址)的jumps和calls顯示為藍(lán)色。引用了從其他模塊動(dòng)態(tài)導(dǎo)出的符號(hào)的顯示為紫色。所有可到達(dá)的目標(biāo)地址(reachable destinations)都加上了下劃線,這意味著你可以通過單擊他們來滾動(dòng)代碼窗口到達(dá)其地址。使用工具欄上的Back和Forward按鈕,你能回顧看過的東東。這很像在IE中察看瀏覽過的網(wǎng)頁。
在右邊,你可以隨意選擇你想跳到的符號(hào)或目標(biāo)地址。當(dāng)然,通過單擊列頭你可以進(jìn)行排序。在最底層,MFVDasm提供了Tab頁來分別顯示符號(hào)、16進(jìn)制轉(zhuǎn)儲(chǔ)(HexDump)和重定位(Relocations)。對(duì)包含嵌入字符串的代碼段進(jìn)行反編譯時(shí)16進(jìn)制轉(zhuǎn)儲(chǔ)視圖會(huì)顯得很有用。在分析很大的文件如ntoskrnl.exe時(shí),MFVDasm不會(huì)阻塞住,和其他流行的反編譯工具一樣,得到的匯編代碼可以保存到文本文件中。PEView --- PE和COFF文件察看器
盡管MFVDasm展示了PE(Portable Executable)文件的很多內(nèi)部結(jié)構(gòu)的細(xì)節(jié),但其側(cè)重于代碼的查看。另一方面,PEView雖然不能展示比代碼段的16進(jìn)制碼更進(jìn)一步的細(xì)節(jié),但它能非常詳細(xì)的顯示文件結(jié)構(gòu)的細(xì)節(jié)。如圖1-9所示。這是我用PEView察看ntoskrnl.exe的截圖。可以看出PEView采用三種形式來顯示ntoskrnl.exe的多個(gè)部分。如果你單擊左邊的一個(gè)葉結(jié)點(diǎn),在右面就會(huì)顯示與該項(xiàng)相關(guān)的所有信息。在圖1-9種,我選擇了IMAGE_OPTIONAL_HEADER結(jié)構(gòu),該結(jié)構(gòu)是IMAGE_NT_HEADERS結(jié)構(gòu)的成員之一。譯注:還有兩段我沒有譯,和本書討論的主題無關(guān),感興趣的話,去看原文吧。J
Windows 2000調(diào)試接口
對(duì)于喜歡研究系統(tǒng)內(nèi)核的人來說,內(nèi)核調(diào)試器是一個(gè)非常強(qiáng)大的工具。不過,它的界面有些簡單。有時(shí)你可能希望有更強(qiáng)大的命令。很幸運(yùn),Windows 2000提供了兩個(gè)完整的調(diào)試接口文檔,使得你可以在你的程序中加入調(diào)試功能。這些接口遠(yuǎn)算不上豪華(但他們得到了微軟官方文檔的祝福 J)。在本節(jié)中,我將帶你進(jìn)行調(diào)試接口一日游,向你展示這些文檔可以為你做什么以及你如何從這些文檔中得到更多東東。
psapi.dll、imagehlp.dll和dbghelp.dll
長久以來,Windows NT由于缺乏對(duì)Windows 95的ToolHelp32接口的支持而備受指責(zé)。可能評(píng)論家們并不都知道Windows NT 4.0提供了其獨(dú)有的調(diào)試接口---內(nèi)建于系統(tǒng)組件psapi.dll(隨Win32 SDK一起發(fā)布)中。隨此DLL一起發(fā)布的還有imagehlp.dll和dbghelp.dll以及針對(duì)NT/2000的調(diào)試接口的官方文檔。PSAPI是Process Status Application Programming Interface的首字母縮寫,此接口提供了14個(gè)函數(shù)用于獲取有關(guān)設(shè)備驅(qū)動(dòng)程序、進(jìn)程、進(jìn)程的內(nèi)存使用情況和其加載的模塊、工作集、內(nèi)存映射文件的系統(tǒng)信息。psapi.dll同時(shí)支持ANSI和Unicode字符串。
其余兩個(gè)調(diào)試DLLs---imagehlp.dll和dgbhelp.dll涵蓋了不同的工作范圍。二者都導(dǎo)出了相似的函數(shù)集合,區(qū)別較大的是imagehlp.dll,它提供了更多函數(shù),但dbghelp.dll提供了可重新發(fā)布的組件。這意味著微軟允許你將dbghelp.dll放入你自己的調(diào)試程序的安裝包中。如果選擇使用imagehlp.dll,你必須獲取在目標(biāo)系統(tǒng)已安裝的一個(gè)。這兩個(gè)DLL都提供了豐富的函數(shù)來分析和維護(hù)PE文件。二者最顯著的特性是能很好的使用符號(hào)文件(就是你為內(nèi)核調(diào)試器準(zhǔn)備的那些)。為了指導(dǎo)你該選擇哪個(gè)DLL,我將這兩個(gè)DLL的所有導(dǎo)出函數(shù)匯總到了表1-1,N/A表示不支持。
