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