二,一般原理[General principles]
我希望您能對80x86系列處理器的內部結構有所瞭解,同時具有一定的編寫組譯工具的能力。對於Microsoft Windows方面的知識,您也要熟悉。
OllyDbg是運行在Windows 95、Windows 98、Windows ME、Windows NT 和 Windows 2000系統下的一個單進程、多線程的分析代碼級調試工具。它可以調試PE格式的執行檔案及動態連結程式庫,並可以對其打補丁。“代碼級”意味著您可以直接與位元、位元組或處理器指令打交道。OllyDbg 僅使用已公開的 Win32 API 函數,因此它可以在所有 Windows 作業系統及後繼版本中使用。但是由於我沒有對 XP 系統進行徹底測試,因此不能保證 OllyDbg 功能的充分發揮。注意:OllyDbg 不支援對 .NET 程式的調試。
OllyDbg不是面向編譯器的。它沒有特別的規則規定必須是哪一個編譯器產生的代碼。因此,OllyDbg可以非常好的處理通過編譯器產生的程式碼,或是直接用彙編寫入的代碼。
OllyDbg可以並行偵錯工具。您無須暫停執行程式,就可以瀏覽代碼和資料,設定斷點、停止或恢複線程,甚至直接修改記憶體。(這可以視為一種軟體調試的模式,與之相對的硬體模式則是當進程在運行時調試器被阻滯,反之亦然)。假使所需的操作比較複雜,OllyDbg會讓進程終止一小段時間,但是這種暫停對於使用者來說是透明的。
有時進程會發生非法操作。您可以把OllyDbg設定成即時[just-in-time]調試器,它會掛接出錯程式,並停在程式產生異常的地方。
通過OllyDbg,您可以調試單獨的DLL[standalone DLLs]檔案。作業系統不能直接運行 DLL 檔案,因此 OllyDbg 將一個可以載入 DLL 的小程式壓縮到資源裡,這個程式允許您調用最多10個參數的輸出函數。
OllyDbg是完全面向模組[module-oriented]的。模組[Module]包括可執行檔(副檔名通常為.EXE)和在啟動時載入或需要時動態載入的動態連結程式庫(副檔名通常為.DLL
)。在調試期間,您可以設定斷點[breakpoints]、定義新的標籤[labels]、注釋[comment]彙編指令,當某個模組從記憶體中卸載[unload]時,調試器會把這些資訊儲存在檔案中,檔案名稱就是模組的名稱,副檔名為.UDD(表示 使用者自訂檔案[User-Defined Data])當OllyDbg下一次載入該模組時,它會自動回復所有的調試資訊,而不管是哪一個程式使用這個模組。假設您正在偵錯工具Myprog1,這個程式使用了Mydll。您在 Mydll 中設定了一些斷點,然後您開始調試Myprog2,這個程式同樣使用了Mydll。這時您會發現,所有 Mydll 中的斷點依然存在,即使 Mydll 載入到不同的位置!
一些調試器把被調試進程的記憶體當作一個單一的(並且大部分是空的)大小為2 ^32位元組的地區。OllyDbg採用了與之不同的技術:在這裡,記憶體由許多獨立的塊組成,任何對記憶體內容的操作都被限制在各自的塊內。在大多數情況下,這種方式工作得很好並且方便了調試。但是,如果模組包含好幾個可執行段[executable sections],您將不能一次看到全部代碼,然而這種情況是非常少見的。
OllyDbg 是一個很佔用記憶體的程式[memory-hungry application]。它在啟動時就需要 3 MB,並且當您第一次裝載被調試的程式時還需要一到兩兆的記憶體。每一次的分析、備份、跟蹤或者檔案資料顯示都需要佔用一定的記憶體。因此當您調試一個很大的項目,發現程式管理器顯示有 40 或 60 兆記憶體被佔用時,請不要驚慌。
為了有效地調試一些不帶源碼的程式,您必須首先理解它是如何工作的。OllyDbg 包含的大量特性可以使這種理解變得非常容易。
首先,OllyDbg包含一個內建的程式碼分析器。分析器遍曆整個代碼,分出指令和資料,識別出不同的資料類型和過程,分析出標準API函數(最常用的大約有1900個)的參數並且試著猜出未知函數的參數數目。您也可以加入自己的函數說明[your own function descriptions]。它標記出程式進入點和跳轉目的地,識別出跳轉表[table-driven switches]和指向字串的指標,加入一些注釋,甚至標示出跳轉的方向等等。在分析結果的基礎上,調用樹[call tree]顯示哪些函數被指定程序呼叫(直接或間接)並且識別出遞迴調用、系統調用和葉子過程[leaf procedures]。如果需要的話,您可以設定解碼提示[decoding hints]來協助分析器解析那些不明確的代碼或資料。
OllyDbg還包含Object掃描器[Object Scanner]。如果您有庫檔案[libraries]或目標檔案[object files],掃描器會在被調試的程式中定位這些庫函數。在全部函數調用中,對標準函數的調用占很重要的一部分(據我估計可達70%)。如果您知道正要被調用的函數的功能,您就不必把注意力集中在這個函數上,可以簡單地單步步過[
step over]這個call。分析器知道400多個標準C函數,比如fopen和memcpy。然而我必須承認目前的版本的OllyDbg不能定位很短的函數(比一個return命令多不了多少的)或相似的函數(只在重定位上有不同)。
Object掃描器[Object scanner]也能夠識別輸入庫[import libraries]。如果某個DLL是按序號輸出的,您不會看到函數名,只會發現一堆無意義的神秘數字。這種DLL的開發人員通常會提供一個輸入庫來實現函數符號名與序號間的對應。讓OllyDbg使用這個輸入庫,它就會恢複原始的函數符號名。
物件導向的語言(如C++),使用了一種叫做名稱修飾[name mangling]的技術,把函數類型和參數都加入函數名中。OllyDbg 可以解碼[demangle]這種函數名,使程式更易讀。
譯者註:C++的名稱修飾是編譯器將函數的名稱轉變成為一個唯一的字串的過程,這個字串會對函數的類、其命名空間、其參數表,以及其他等等進行編碼。C++的名稱修飾適用於靜態成員函數,也適用於非靜態成員函數。靜態函數的名稱修飾的一個好處之一,是能夠在不同的類裡使用同一個名稱來聲明兩個或者更多的靜態成員函數----而不會發生名稱上的衝突。
OllyDbg完全支援 UNICODE,幾乎所有對 ASCII 字串的操作都可以同樣應用於 UNICODE。
彙編指令都是很相似的。您經常會搞不清自己是不是已經跟蹤過某一段代碼。在 OllyDbg 中您可以加入自己的標籤[labels]和注釋[comments]。這些極大地方便了調試。注意一旦您注釋了某個DLL,以後每次載入這個DLL時,注釋和標籤都有效----儘管您在調試不同的程式。
OllyDbg可以跟蹤標準的棧幀[stack frames](由PUSH EBP; MOV EBP,ESP所建立的)。現代編譯器有禁止產生標準棧架構的選項,在這種情況下分配棧[stack walk
]是不可能的。當程式運行到已知的函數時,棧視窗[stack window]解析它的參數,調用棧[Call stack]視窗顯示到達當前位置所調用函數的序列。
現代的物件導向應用程式廣泛地使用了一種叫做結構化異常處理[Structured Exception Handling,SHE]的技術。SHE視窗[SEH window] 可以顯示異常處理鏈。
多種不同的搜尋[search]選項可以讓您找到二進位代碼或資料、命令或命令序列、常量或字串、符號名或在 Run跟蹤中的一條記錄。
對於任何地址或常量,OllyDbg 可以找出參考[referencing]到該地址或常量的全部命令的列表。然後您可以在這個列表裡找出對您來說是重要的參考。舉例來說,某個函數可能被直接調用,或者經過編譯器最佳化後把地址放入寄存器間接調用,或者把地址壓入堆棧作為一個參數----沒問題,OllyDbg 會找出所有這樣的地方。它甚至能找到並列出所有和某個指定的位置有關的跳轉。(真的?哦,天哪!……)
OllyDbg 支援所有標準類型的斷點[breakpoints]----非條件和條件斷點、記憶體斷點(寫入或訪問)、硬體斷點或在整個記憶體塊上下斷點(後兩項功能只在Window ME,NT,2000,XP中有效)。條件運算式可以非常複雜(“當 [ESP+8] 的第 2 位被設定,並且 123456 位置處的字[word]小於10,或者 EAX 指向一個以“ABC”開頭的 UNICODE 字串,但跳過前10次斷點而在第11次中斷”)。您可以設定一條或多條指令,當程式暫停時由OllyDbg傳遞給外掛程式外掛程式[plugins]。除了暫停,您還可以記錄某個運算式的值(可以帶有簡短的說明),或者記錄 OllyDbg 已知的函數的參數。在Athlon 2600+、Windows2000 環境下,OllyDbg 可以每秒處理多達 25000 個條件斷點。
另一個有用的特性是跟蹤。OllyDbg 支援兩種方式的跟蹤:hit和run。在第一種情況下,它對指定範圍內的每條指令上設定斷點(比如在全部可執行代碼中)。當到達設斷的指令後,OllyDbg 清除斷點並且把該指令標記為hit。這種方法可以用來檢測某段代碼是否被執行。Hit跟蹤速度驚人的快,在一個很短時間的啟動後程式幾乎達到了全速(譯者註:這應該是與不進行調試時速度相比而言)。因為INT3斷點可能對資料有災難性的影響,所以我建議不要使用模糊識別過程。當代碼沒有被分析時Hit跟蹤是不可以使用的。
Run跟蹤[Run trace] 是一步一步地執行程式,同時記錄精確的運行曆史和所有寄存器的內容、已知的參數和可選的指令(當代碼是自修改時會有協助)。當然,這需要大量的記憶體(每個指令需要15至50個位元組,取決於調試的模式)但是可以精確地回溯和分析。您可以只在選定的一段代碼甚至是一條指令中進行Run跟蹤,或者您可以跳過無關緊要的代碼。對於每個地址,OllyDbg能夠計算這個地址在Run追蹤記錄檔中出現的次數,雖然會導致執行緩慢但是可以得到代碼執行的統計。比如說,某命令讓您在每個已識別的過程入口處進行Run跟蹤,那麼統計[profile]就會給您每個過程被調用的次數。在到達某條指令、某個位址範圍或指令計數器達到某一數值時Run跟蹤可以自動地暫停[pause]。
在多線程程式裡OllyDbg可以自動管理線程[threads],如果您單步調試或跟蹤程式,它會自動回復當前線程而掛起其它線程。如果您運行程式,OllyDbg 會恢複先前的線程狀態。
您可以為記憶體塊建立快照(叫做備份)。OllyDbg會高亮顯示所有的改動。您可以把備份儲存到檔案或從檔案中讀取出來,從而發現兩次啟動並執行不同之處。您可以查看備份,搜尋下一處改動,恢複全部或選定的改動。補丁管理器[Patch manager]記錄了上次應用到程式中的所有補丁,在下次調試時可以再次應用它們。
您可以很容易地把您的補丁加在可執行檔上。OllyDbg 會自動進行修正。
您不能在帶有 Win32 的16位 Windows 下使用 OllyDbg。這種32位擴充作業系統無法實現某些必需的調試功能。
您既不能調試 DOS 程式也不能調試16位 NE(New Executable)格式檔案,我也沒有打算在未來的版本中支援這些。安息吧,古老而美好的命令提示字元!