|
論壇說明 | 標記討論區已讀 |
歡迎您來到『史萊姆論壇』 ^___^ 您目前正以訪客的身份瀏覽本論壇,訪客所擁有的權限將受到限制,您可以瀏覽本論壇大部份的版區與文章,但您將無法參與任何討論或是使用私人訊息與其他會員交流。若您希望擁有完整的使用權限,請註冊成為我們的一份子,註冊的程序十分簡單、快速,而且最重要的是--註冊是完全免費的! 請點擊這裡:『註冊成為我們的一份子!』 |
|
主題工具 | 顯示模式 |
2006-05-25, 03:44 PM | #1 (permalink) |
榮譽會員
|
軟體 - OllyDbg完全教學
一,什麼是 OllyDbg?
OllyDbg 是一種具有可視化介面的 32 位彙編-分析偵錯器。它的特別之處在於可以在沒有來源碼時解決問題,並且可以處理其它編譯器無法解決的難題。 Version 1.10 是最終的發怖版本。 這個工程已經停止,我不再繼續支持這個軟體了。但不用擔心:全新打造的 OllyDbg 2.00 不久就會面世! 執行環境: OllyDbg 可以以在任何採用奔騰處理器的 Windows 95、98、ME、NT 或是 XP(未經完全測試)作業系統中工作,但我們強烈建議您採用300-MHz以上的奔騰處理器以達到最佳效果。還有,OllyDbg 是極占記憶體的,因此如果您需要使用諸如追蹤偵錯〔Trace〕之類的增強功能話,建議您最好使用128MB以上的記憶體。 支持的處理器: OllyDbg 支持所有 80x86、奔騰、MMX、3DNOW!、Athlon 增強指令集、SSE指令集以及相關的資料格式,但是不支持SSE2指令集。 組態: 有多達百餘個(天呀!)選項用來設定 OllyDbg 的外觀和執行。 資料格式: OllyDbg 的資料視窗能夠顯示的所有資料格式:HEX、ASCII、UNICODE、 16/32位有/無符號/HEX整數、32/64/80位浮點數、位址、反彙編(MASM、IDEAL或是HLA)、PE文件頭或執行緒資料塊。 說明 : 此文件中包含了關於理解和使用 OllyDbg 的必要的訊息。如果您還有 Windows API 求助文件的話(由於版權的問題 win32.hlp 沒有包括在內),您可以將它掛在 OllyDbg 中,這樣就可以快速獲得系統函數的相關說明 。 啟動: 您可以採用指令行的形式指定可執行文件、也可以從表單中選項,或直接拖放到OllyDbg中,或者重新啟動上一個被偵錯程序,或是掛接〔Attach〕一個正在執行的程序。OllyDbg支持即時偵錯。OllyDbg根本不需要安裝,可直接在軟碟中執行! 偵錯DLLs: 您可以利用OllyDbg偵錯標準動態連接庫 (DLLs)。OllyDbg 會自動執行一個可執行程序。這個程序會載入連接庫,並允許您使用連接庫的輸出函數。 源碼級偵錯: OllyDbg 可以識別所有 Borland 和 Microsoft 格式的偵錯訊息。這些訊息包括來源碼、函數名、標籤、全局變數、靜態變數。有限度的支持動態(棧)變數和結構。 程式碼高亮: OllyDbg 的反彙編器可以高亮不同檔案類型的指令(如:跳轉、條件跳轉、壓入推疊、出棧、使用、返回、特殊的或是無效的指令)和不同的操作數(一般〔general〕、 FPU/SSE、段/系統暫存器、在棧或記憶體中的操作數,常量)。您可以設定個性化高亮方案。 執行緒: OllyDbg 可以偵錯多執行緒程序。因此您可以在多個執行緒之間轉換,掛起、恢復、終止執行緒或是改變執行緒優先等級。並且執行緒視窗將會顯示每個執行緒的錯誤(就像使用 GETLASTERROR 返回一樣)。 分析:OllyDbg 的最大特點之一就是分析。它會分析函數程序、循環語句、選項語句、表〔tables〕、常量、程式碼中的字串串、欺騙性指令〔tricky constructs〕、API使用、函數中參數的數目,import表等等。. 這些分析增加了二進制程式碼的可讀性,減少了出現錯誤的可能性,使得我們的偵錯工作更加容易。 Object掃瞄。 OllyDbg 可以掃瞄Object文件/庫(包括 OMF 和 COFF 格式),解壓程式碼段〔code segments〕並且對其位置進行轉發IP。 Implib掃瞄。 由於一些DLL文件的輸出函數使用的索引號,對於人來說,這些索引號沒有實際含義。如果您有與DLL相應的輸入庫〔import library〕,OllyDbg 就可以將序號轉換成符號名稱。 完全支持Unicode: 幾乎所有支持 ASCII 的操作同時也支持 UNICODE,反之亦然。 名稱: OllyDbg 可以根據 Borland 和 Microsoft 格式的偵錯訊息,顯示輸入/輸出符號及名稱。Object 掃瞄器可以識別庫函數。其中的名稱和註釋您可任意增加。如果DLL中的某些函數是通過索引號輸出的,則您可通過掛接輸入庫〔import library〕來恢復原來的函數名稱。不僅如此,OllyDbg還能識別大量的常量符號名(如:視窗消息、錯誤程式碼、位域〔bit fields〕…)並能夠解碼為已知的函數使用。 已知函數:OllyDbg 可以識別 2300 多個 C 和 Windows API 中的常用函數及其使用的參數。您可以增加描述訊息、預定義解碼。您還可以在已知函數設定 Log 斷點並可以對參數進行記錄。 函數使用: OllyDbg 可以在沒有偵錯訊息或函數程序使用非標準的開始部分〔prolog〕和結尾部分〔epilog〕的情況下,對遞回使用進行回溯。 譯者註: 004010D0 push ebp \ 004010D1 mov ebp,esp | 004010D3 sub esp,10h |prolog 004010D6 push ebx | 004010D7 push esi | 004010D8 push edi / …… 004010C5 pop edi \ 004010C6 pop esi | 004010C7 pop ebx |epilog 004010C8 mov esp,ebp | 004010CA pop ebp | 004010CB ret / 棧:在棧視窗中,OllyDbg 能智能識別返回位址和棧框架〔Stack Frames〕。並會留下一些先前的使用。如果程序停在已知函數上,堆疊視窗將會對其參數進行分析解碼。 譯者註:棧框架〔Stack Frames〕是指一個記憶體區域,用於存放函數參數和局部變數。 SEH 鏈: 跟蹤棧並顯示結構化異常關鍵句鏈。全部鏈會顯示在一個單獨的視窗中。 搜尋:方法真是太多了!可精確、模糊搜尋指令或指令序列,搜尋常數,搜尋二進制、文本字串串,搜尋全部指令位址,搜尋全部常量或位址域〔address range〕,搜尋所有能跳到選定位址的跳轉,搜尋所有使用和被使用的函數,搜尋所有參考字串串,在不同模組中搜尋所有使用、搜尋函數名稱,在全部已分配的記憶體中搜尋二進制序列。如果搜尋到多個結果,您可以對其進行快速操作。 視窗:OllyDbg 能夠列出關於偵錯程序中的各種視窗,並且可以在視窗、類甚至選定的消息上設定斷點。 資源:如果 Windows API 函數使用了參考資源串,OllyDbg 可以顯示它。其支持顯示的檔案類型僅限於附帶資源〔attached resources〕的列表、資料顯示及二進制編輯、。 斷點: OllyDbg 支持各種斷點:一般斷點、條件斷點、記錄斷點(比如記錄函數參數到記錄視窗)、記憶體讀寫斷點、硬體斷點(只適用於ME/NT/2000)等。在Hit跟蹤情況下,可以在模組的每條指令上都設定INT3斷點。在使用500-MHZ處理器的 Windows NT 中,OllyDbg 每秒可以處理高達 5000 個中斷。 監視與監察器:每個監視都是一個陳述式並能既時顯示陳述式的值。您可以使用暫存器、常數、位址陳述式、布爾值以及任何複雜代數運算,您還可以比較ASCII和UNICODE 字串串。監察器〔inspectors〕是一種包含了兩個的索引序列的監視〔Watches〕,它以二維表的形式呈現,可以允楹徒峁菇薪飴敕治觥?nbsp; Heap walk.:在關於Win95的系統中,OllyDbg 可以列出所有的已分配的堆。 關鍵句:在關於NT的系統中,OllyDbg 可列出被偵錯程序的所有系統關鍵句。 執行:.您可以單步執行、步入子程序或者步過子程序。您也可以執行程序直到函數返回時、執行到指定位址處,還可以自動執行。當程序執行時,您仍然可以操縱程序並能夠檢視記憶體、設定斷點甚至修改程式碼。您也可以任意的暫停或重新啟動被偵錯的程序。 Hit跟蹤:.Hit跟蹤可以顯示出目前已執行的指令或函數程序,說明 您檢驗程式碼的各個分支。Hit跟蹤會在指定指令到達之前設定斷點,而在這個指令執行後,會把這個斷點清除掉。 譯者註:Hit在英文中是「擊中」的意思,指令如果執行了就表示這個指令被「擊中」了,沒有執行的指令就是「未擊中」,這樣我們就很容易看出被偵錯程序哪些部分執行了,而哪些沒有執行。 Run跟蹤: Run跟蹤可以單步執行程序,它會在一個很大的循環緩衝區中模擬執行程序。這個模擬器包含了除了SSE指令集以外的所以暫存器、標誌、執行緒錯誤、消息、已經函數的參數。您可以儲存指令,這樣可以非常方便地偵錯自修改程式碼(譯者註:比如加殼程序)。您可以設定條件中斷,條件包括位址範圍、陳述式、指令。您可以將Run 跟蹤訊息儲存到一個文件中,這樣就可以對比兩次執行的差別。Run跟蹤可以回溯分析已執行過的上百萬條指令的各種細節。 統計: 統計〔Profiler〕可以在跟蹤時計算某些指令出現的次數。因此您就能瞭解程式碼的哪一部分被頻繁執行。 修正檔: 內裝彙編器能夠自動找到修改過的程式碼段。二進制編輯器則會以ASCII、UNICODE或者十六進制的形式同步顯示修改後的資料。修改後的資料同其它資料一樣,能夠進行複製-貼上操作。原來的資料會自動制作備份,以便資料恢復時使用。您可以把修改的部分直接複製到執行文件中,OllyDbg會自動修正。OllyDbg還會記錄以前偵錯程序中使用的所有修正檔。您可以通過空格鍵實現修正檔的啟動或者禁止。 自解壓文件: 當偵錯自解壓文件時,您往往希望跳過解壓部分,直接停在程序的原始入口點。OllyDbg的自解壓跟蹤將會使您實現這一目的。如果是加保護的自解壓段,自解壓跟蹤往往會失敗。而一旦OllyDbg找到了入口點,它將會跳過解壓部分,並準確的到達入口點。 插件:您可以把自己的插件增加到 OllyDbg 中,以增加新的功能。OllyDbg 的插件能夠訪問幾乎所有重要的資料的結構、能夠在 OllyDbg 的視窗中增加表單和快捷鍵,能夠使用100個以上的插件API函數。插件API函數有詳細的說明我的文件。預設值安裝已經包含了兩個插件:指令行插件和書籤插件。 UDD:OllyDbg 把所有程式或模組相關的訊息儲存至單獨的文件中,並在模組重新載入時繼續使用。這些訊息包括了標籤、註釋、斷點、監視、分析資料、條件等等 更多:這裡介紹的功能,僅僅是 OllyDbg 的部分功能。因為其具有如此豐富的功能,以至於 OllyDbg 能成為非常方便的偵錯器! 二,一般原理〔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)格式文件,我也沒有打算在未來的版本中支持這些。安息吧,古老而美好的命令提示字元! 三,反彙編器〔Disassembler〕 反彙編器識別所有的標準80x86、保護、FPU、MMX和3DNow!指令集(包括Athlon增強的MMX指令集)。但它不識別ISSI指令,儘管計劃要在下個版本中支持這種指令。某些過時或者未公開的指令,像LOADALL,也不支持。 反彙編器可以正確解碼16位位址。但它假設所有的段都是32位的(段內容使用32位)。這對於PE〔Portable Executable〕格式文件總是真的。OllyDbg不支持16位的NE 〔New Executables〕格式。 如果您熟悉MASM或者TASM,那麼反彙編的程式碼對於您沒有任何問題。但是,一些特例也是存在的。以下指令的解碼與Intel的標準不同: AAD (ASCII Adjust AX Before Division) - 該指令的解碼後的一般形式為:AAD imm8 AAM (ASCII Adjust AX After Multiply) - 該指令(非十進制數)的一般解碼形式為:AAM imm8 SLDT (Store Local Descriptor Table register) - 操作數總被解碼為16位。這個指令的32位形式會在目的操作數的低16位中儲存於段選項器,並保留高16位不變。 SALC (Sign-extend Carry bit to AL, undocumented) - OllyDbg 支持這個未公開指令。 PINSRW (Insert Word From Integer Register, Athlon extension to MMX) - 在AMD的官方我的文件中,這個指令的記憶體形式使用了16位記憶體操作數;然而暫存器形式需要32位暫存器,但只使用了低16位。為了方便處理,反彙編器解碼暫存器為16 位形式。而彙編器兩種形式都支持。 CVTPS2PI and CVTTPS2PI (Convert Packed Single-Precision Floating to Packed Doubleword, Convert with Truncation Packed Single-Precision Floating to Packed Doubleword) - 在這些指令中,第一個操作數是MMX暫存器,第二個或者是128位XMM暫存器或者是64位記憶體區域。為了方便處理,記憶體操作數也被解碼為128位。 有些指令的助記符要依賴操作數的大小: 不分大小的形式 明確的16位形式 明確的32位形式 PUSHA PUSHAW PUSHAD POPA POPAW POPAD LOOP LOOPW LOOPD LOOPE LOOPWE LOOPDE LOOPNE LOOPWNE LOOPDNE PUSHF PUSHFW PUSHFD POPF POPFW POPFD IRET IRETW IRETD 您可以改變解碼大小敏感助記符〔decoding of size-sensitive mnemonics〕.。根據選項,反彙編器從三種可能中選項之一進行解碼。這個選項也會影響彙編器的預設值處理方式。 解碼MMX和3DNow!指令總是開啟的,儘管您的處理器並不支持這些指令。 四,分析器〔Analysis〕 OllyDbg 整合了一個快速而強大的程式碼分析器。您可以從快捷表單,或者在CPU視窗的反彙編面板中按 Ctrl+A ,或者在可執行模組中選項「分析全部模組〔Analyze all modules〕」,來使用它。 分析器有很高的啟發性。它能區分程式碼和資料,標記入口和跳轉目的位址,識別轉換表〔switch tables〕,ASCII 和 UNICODE 串,定位函數程序,循環,高階轉換〔 high-level switches〕並且能解碼標準API函數的參數(示例〔example〕)。OllyDbg 的其他部分也廣泛的使用了分析後的資料。 這是如何實現的?我將為您揭開這一神秘面紗。第一遍,OllyDbg反彙編程式碼段中所有可能的位址,並計算使用的每個目的位址的個數。當然,很多使用是假的,但不可能兩個錯誤的使用都指向了相同的指令,當然如果有三個的話,就更不可能了。因此如果有三個或者更多的使用指向了相同的位址,我可以肯定的說這個位址是某個頻繁使用的子程序的入口。從定位的入口出發,我繼續跟蹤所有的跳轉和函數使用,等等。按這種方法,我可能準確定位99.9% 的指令。但是,某些字元並不在這個鏈條上。我再用20多種高效的啟發方法(最簡單的方法,比如「直接訪問前64K記憶體是不允許的,像在MOV [0],EAX中」)來探測他們 有時,分析器在您感興趣的地方分析錯誤。有兩種解決方法:或者從選的部分移除分析(快捷鍵退格鍵),這樣 OllyDbg 將使用預設值的解碼(反彙編)方式;或者設定 解碼提示〔decoding hints〕並重新分析。注意:在某些情況下,當分析器認為您的提示是不合適的,或者有衝突,則可能忽略您的設定。 探測程序的函數程序也很簡單。在分析器眼中看來,程序只是一個連綿不斷的程式碼,從一個入口開始,可能達到(至少從理論上)所有的指令(除了NOP以及類似的用於填充間隙的指令)。您可能指定三個識別等級。嚴格的函數程序要求有準確的一個入口,並且至少有一個返回。在啟發等級下,分析器只要求程序有一個入口。而如果您選項模糊模式,差不多連貫的程式碼都會被識別為單獨的程序。現代編譯器進行全局程式碼最佳化,有可能把一個程序分成幾個部份。在這種情況下,模糊模式非常有用。但是也會誤識別的機率也就更高。 同樣地,循環是一個封閉的連續的指令序列,並有一個到開始處的跳轉作為一個入口,還有若干個出口。循環與進階操作指令 do, while 和 for 相對應。OllyDbg 能夠識別任何複雜的嵌套循環。他們會在反彙編欄〔Disassembly〕中用長而粗括號標記。如果入口不是循環的第一個指令,OllyDbg會用一個小三角進行標記。 為了實現一個轉換〔switch〕, 許多編譯器,讀取轉換變數〔switch variable〕到暫存器中,然後減它,像如下的程式碼序列: MOV EDX,<switch variable> SUB EDX,100 JB DEFAULTCASE JE CASE100 ; Case 100 DEC EDX JNE DEFAULTCASE ... ; Case 101 這個序列可能還包含一到兩階的轉換表、直接比較、最佳化和其他元素。如果在比較或跳轉的很深處,這就很難知道哪是一個分支〔Case〕。OllyDbg 會說明 您,它會標記所有的分支,包括預設值的,甚至嘗試分析每個分支的含義,如'A'、WM_PAINT 或者 EXCEPTION_ACCESS_VIOLATION。如果指令序列沒有修改暫存器(也就是僅僅由比較組成),那麼這可能不是轉換,而很有可能是選項嵌套: if (i==0) {...} else if (i==5) {...} else if (i==10) {...} 如果需要OllyDbg將選項嵌套解碼成選項語句,請在分析1〔Analysis1〕中設定相關選項。 OllyDbg包含多達1900條常用API函數,這些都作為內部預處理資源。這個列表包含了KERNEL32, GDI32, USER32, ADVAPI32, COMDLG32, SHELL32, VERSION, SHLWAPI, COMCTL32, WINSOCK, WS2_32 和 MSVCRT。您可以增加自己的函數描述〔add your own descriptions〕。如果分析器遇到的使用,使用了已知的函數名(或者跳轉到這樣的函數),它將在使用之前立即解碼PUSH指令。因此,您只需略微一看就能明白函數使用的含義。OllyDbg還包含了大約400多種的標準C函數。如果您有原始的庫文件,我推薦您在分析前掃瞄目標文件。這樣OllyDbg將能解碼這些C函數的參數。 如果選項「猜測未知函數的參數個數」開啟,分析器將會決定這個使用函數程序使用的長度為雙字的參數個數。並且標記他們為參數1〔Arg1〕,參數2〔 Arg2〕,等等。注意:無論如何,暫存器參數是無法識別的,所以不會增加參數的數目。分析器使用了一種比較安全的方法。例如,它不能識別的沒有參數的函數程序,或者該程序POP 指令直接做返回前的暫存器恢復,而不銷毀參數。然而,識別出來的函數參數數目通常非常高,這大大加大了程式碼的可讀性。 分析器能夠跟蹤整型暫存器的內容。現代最佳化編譯器,特別是奔騰系列,頻繁地使用暫存器讀取常量和位址,或使用盡量少的使用記憶體。如果某個常量讀取到暫存器中,分析器會注意它,並嘗試解碼函數和其參數。分析器還能完成簡單的算術計算,甚至可以跟蹤壓入推疊和出棧。 分析器不能區分不同類的名稱〔different kinds of names〕. 。如果您將某些函數指定為已知的名稱,OllyDbg將會解碼所有到該位址的使用。這是幾個預定義的特殊名稱 WinMain, DllEntryPoint and WinProc。您可能使用這些標籤標記主程序、DLL的的入口以及視窗程序(注意:OllyDbg不檢查用戶自訂的標籤是否唯一)。另外,假定預定義參數assume predefined arguments是一種更好的方法 不幸的是,沒有一般規則能夠做到100%的準確分析。在某些情況下,例如當模組包含了P-Code或程式碼段中包換了大量的資料,分析器可能將一些資料解釋成程式碼。如果統計分析顯示程式碼部分很可能是壓縮包或者經過加密了,分析器會發出警告。如果您想使用Hit跟蹤〔Hit trace〕,我建議您不要使用模糊分析〔fuzzy analysis〕,因為設定斷點的地方可能正是資料部分。 自解壓文件〔Self-extractable files〕 通常有一個自抽取器,在「正式」程式碼段之外。如果您選項自解壓選項〔SFX option〕中的「增強程式碼段,包含抽取器〔Extend code section to include self-extractor〕」,OllyDbg將會增強程式碼段,形式上允許分析它,並可以使用Hit跟蹤〔Hit〕 trace和Run跟蹤〔Run trace〕。 五,Object掃瞄器〔Object scanner〕 掃瞄器將特定的目標文件或者目標庫(包括OMF和COFF兩種格式),抽取出程式碼段,然後將這些段定位在當前模組的程式碼節〔Code section〕中.如果段定位好了,掃瞄器將從目標文件中的偵錯訊息抽取名稱(也就是所謂的庫標籤〔library labels〕)。這極大的增加了程式碼與資料的可讀性. 掃瞄器並不會對已識別的目標文件進行標籤匹配,所以它不能識別非常小或相似的函數(比如:兩個函數只是在重定位有區別)。因此要經常檢查掃瞄器傳送到登入視窗的警告列表! 六,Implib掃瞄器 〔Implib scanner〕 某些DLL的輸出符號僅僅是一個序號。許多符號都是井號加數位(比如:MFC42.#1003),這非常不便於理解。幸運的是,軟體零售商提供了輸入連接程式庫(implibs),它與序號符號名相關。 使用implib掃瞄器的方法:從主表單中選項偵錯〔Debug〕|選項輸入連接庫〔Select import libraries〕。當您載入應用程式時,OllyDbg會讀取連接庫並從內裝表格〔 internal tables〕中抽取符號名。每次遇到序號符號,而對應的連接庫已經註冊到OllyDbg中時,這個序號符號會被取代。 七,如何開始偵錯〔How to start debugging session〕 最簡單的方法是:執行 OllyDbg,點擊表單上的文件〔File〕|開啟〔Open〕,選項您想偵錯的程序。如果程序需要指令行參數,您可以在對話視窗底部的輸入欄中,輸入參數或者選項以前偵錯時輸入過的一條參數。 OllyDbg 能夠偵錯獨立的DLL〔stand-alone DLLs〕。在這種情況下,OllyDbg 會新增並執行一個小的應用程式來載入連接庫並根據您的需要使用輸出函數。 如果您想重新啟動上一次偵錯的程序,只要按一下 Ctrl+F2(這是重新啟動程序的快捷鍵),這樣 OllyDbg 會以同樣的參數執行這個程序。另一種做法是在表單中選項文件〔File〕,從歷史列表中選項程序。您也可以在 Windows 檔案總管中將可執行文件或 DLL 文件拖拉到 OllyDbg 中。 當然,您可以在 OllyDbg 啟動時,執行指定帶有執行參數的被偵錯程序。例如:您可以在桌面新增一個 OllyDbg 的建立捷逕,右擊並選項「內容」,在「建立捷逕」中的「目標」中增加偵錯的程序的全路徑。這樣,您每次雙按建立捷逕時,OllyDbg 將自動執行被偵錯程序。注意:DLL文件不支持這種方式。 您可以把正在執行的工作掛接到 OllyDbg 中。在表單中開啟 文件〔File〕|掛接〔Attach〕,從工作列表中選項要掛接的工作。注意:在您關閉 OllyDbg 的同時,這個工作也會被關閉。不要掛接系統工作,否則可能會導致整個作業系統的崩潰。(事實上在大多數情況下,作業系統禁止您掛接敏感工作)。 OllyDbg 可以作為即時〔just-in-time〕偵錯器。這需要在系統註冊表中註冊。在表單中選項選項〔Options〕|即時偵錯〔Just-in-time debugging〕 並在彈出的對話視窗中按下按鈕「設定OllyDbg為即時偵錯器」〔Make OllyDbg just-in-time debugger〕。今後,如果某個應用程式發生了非法操作,系統將提示您是否用 OllyDbg 偵錯這個程序。作業系統會啟動 OllyDbg 並直接停在發生異常的地方。如果您選項了「掛接時不詢問」〔attaching without confirmation〕,則在即時偵錯時OllyDbg不會彈出詢問對話視窗。如果想恢復成以前的即時偵錯器〔Restore old just-in-time debuger〕,按相應的按鈕即可。 另一種方法是把 OllyDbg 增加到與可執行文件關聯的快捷表單中(這個想法是 Jochen Gerster 提出的)。在主表單中,選項選項〔Options〕|增加到檔案總管中〔Add to Explorer〕。以後您可以在所有的文件列表中,右擊可執行文件或DLL,在快捷表單中選項OllyDbg。這個功能會新增四個註冊表鍵值: HKEY_CLASSES_ROOT\exefile\shell\Open with OllyDbg HKEY_CLASSES_ROOT\exefile\shell\Open with OllyDbg\command HKEY_CLASSES_ROOT\dllfile\shell\Open with OllyDbg HKEY_CLASSES_ROOT\dllfile\shell\Open with OllyDbg\command OllyDbg能夠偵錯控制台程序(關於文字的)。 OllyDbg不能偵錯.NET應用程式。.NET程序是由微軟的中間語言這種偽指令組成的,或是on-the-fly to native ?6 commands編譯的。 注意:如果您執行的是Windows NT、2000 或XP作業系統,您應該擁有管理員權限以便能夠偵錯程序。。, 八,CPU 視窗〔CPU window〕 對於用戶來說,CPU視窗在OllyDbg中是最重要的視窗。您偵錯自己程序的絕大部分操作都要在這個視窗中進行。它包括以下五個面板(這五個面板的大小都是可以調節的): 反彙編〔Disassembler〕 訊息〔Information〕 資料〔Dump〕 暫存器〔Registers〕 棧〔Stack〕 按TAB鍵,可以切換到下一個CPU面板中(順時針方向)。 按Shift+TAB,可以切換到前一個CPU面板(逆時針方向)。 九,斷點〔Breakpoints〕 OllyDbg支持數種不同檔案類型的斷點: - 一般斷點〔Ordinary breakpoint〕, 將您想中斷的指令的第一個字元,用一個特殊指令INT3(偵錯器陷阱)來替代。您可以在反彙編視窗中選要設斷點的指令行並按下 F2 鍵就可以設定一個此檔案類型的斷點。也可以在快捷表單中設定。再次按下 F2 鍵時,斷點將被移除。注意,程序將在設斷指令被執行之前中斷下來。 INT3斷點的設定數量是沒有限制的。當您關閉被偵錯程序或者偵錯器的時候,OllyDbg將自動把這些斷點儲存到硬碟中,永遠不要試圖在資料段或者指令的中間設定這種斷點,如果您試圖在程式碼段以外設定斷點,OllyDbg將會警告。您可以在安全性選項〔Security options〕中永遠關閉這個提示,在某些情況下偵錯器會插入原有的的臨時INT3 斷點。 - 條件斷點〔Conditional breakpoint〕 (快捷鍵 Shift+F2) 是一個帶有條件陳述式的普通INT3斷點。當偵錯器遇到這類斷點時,它將計算陳述式的值,如果結果非零或者陳述式無效,將暫停被偵錯程序,當然,由條件為假的斷點引起的預先配置是非常高的(主要歸因於作業系統的反應時間)。在Windows NT、奔騰Ⅱ/450處理器環境下 OllyDbg每秒最多處理2500個條件為假的斷點。條件斷點的一個典型使用情況就是在Windows消息上設定斷點(比如 WM_PAINT)。為此,您可以將偽變數 MSG 同適當的參數說明聯合使用。如果視窗被啟動,參考一下後面的消息斷點描述。 - 條件記錄斷點 〔Conditional logging breakpoint〕 (Shift+F4)是一種條件斷點,每當遇到此類斷點或者滿足條件時,它將記錄已知函數陳述式或參數的值。例如,您可以在一些視窗程序函數上設定記錄斷點並列出對該函數的所有使用。或者只對接收到的WM_COMMAND消息標幟符設斷,或者對新增文件的函數(CreateFile)設斷,並且記錄以唯讀方式開啟的檔案名等,記錄斷點和條件斷點速度相當,並且從記錄視窗中瀏覽上百條消息要比按上百次F9輕鬆的多,您可以為陳述式選項一個預先定義好的解釋說明。 您可以設定通過的次數 - 每次符合暫停條件時,計數器就會減一。如果通過計數在減一前,不等於零,OllyDbg就會繼續執行。如果一個循環執行100次(十進制),在循環體內設定一個斷點,並設定通過次數為99(十進制)。OllyDbg將會在最後一次執行循環體時暫停。 另外,條件記錄斷點允許您傳送一個或多個指令給插件〔plugins〕。例如,您需要使用指令行插件改變一個暫存器的內容,然後繼續執行程序。 - 消息斷點〔Message breakpoint〕和條件記錄斷點基本相同,除了OllyDbg會自動產生一個條件,這個條件允許在視窗程序的入口處設定某些消息(比如WM_PSINT)斷點,您可以在視窗〔Windows〕中設定它。 - 跟蹤斷點〔Trace breakpoint〕 是在每個選指令上設定的一種特殊的INT3斷點。如果您設定了Hit跟蹤〔hit trace〕 ,斷點會在指令執行後移除,並在該位址處做一個標記。如果您使用的是Run跟蹤〔run trace〕 ,OllyDbg會增加跟蹤資料記錄並且斷點仍然是保持啟動狀態。 - 記憶體斷點〔Memory breakpoint〕 OllyDbg每一時刻只允許有一個記憶體斷點。您可以在反彙編視窗、CPU視窗、資料視窗中選項一部分記憶體,然後使用快捷表單設定記憶體斷點。如果有以前的記憶體斷點,將被自動移除。您有兩個選項:在記憶體訪問(讀,寫,執行)時中斷,或記憶體寫入時中斷。設定此類斷點時,OllyDbg將會改變所選部分的記憶體塊的內容。在與80x86相容的處理器上將會有4096字元的記憶體被分配並保護起來。即使您僅僅選項了一個字元,OllyDbg 也會將整個記憶體塊都保護起來。這將會引起大量的錯誤警告,請小心使用此類斷點。某些系統函數(特別是在Windows95/98下)在訪問受保護的記憶體時不但不會產生偵錯事件反而會造成被偵錯程序的崩潰。 - 硬斷點〔Hardware breakpoint〕(僅在Windows ME,NT或2000下可用)在80x86相容的處理器上,允許您設定4個硬體斷點。和記憶體斷點不同,硬體斷點並不會降低執行速度,但是最多只能覆蓋四個字元。在單步執行或者跟蹤程式碼時,OllyDbg能夠使用硬斷點替代INT3斷點。 - 記憶體訪問一次性斷點〔Single-shot break on memory access〕 (僅在Windows NT或2000下可用)。您可以通過記憶體視窗的快捷表單(或按F2),對整個記憶體塊設定該類斷點。當您想捕捉使用或返回到某個模組時,該類斷點就顯得特別有用。中斷髮生以後,斷點將被移除。 - 暫停Run跟蹤〔Run trace pause〕 (快捷鍵:Ctrl+T)是在每一步Run跟蹤〔run trace〕 時都要檢查的一個條件集.您可以在EIP進入某個範圍或超出某個範圍時暫停,某個條件為真時暫停,或者指令與指定的模式匹配時暫停,或者當指令可疑的時候暫停。注意,這一選項會極大的(高達20%)降低Run跟蹤的速度。 OllyDbg也可以在一些偵錯事件〔debugging events〕上暫停程序執行。比如載入或卸載DLL,啟動或終止執行緒,或者程序發出偵錯字串串的時候。 10,資料視窗〔Dump〕 資料視窗用於顯示記憶體或文件的內容。您可以從以下預處理格式〔predefined formats〕中選項一種顯示方式:字元〔byte〕、文本〔text〕、整數〔integer〕、浮點數〔float 〕、位址〔address〕,反彙編〔disassembly〕、 PE頭〔PE Header〕。 所有的dump視窗支持制作備份〔backup〕、搜尋和編輯操作。CPU 視窗〔CPU window〕的Dump面板允許您對可執行程式碼的資料和可執行文件(.exe,或.dll)的記憶體映射做如下操作:定義標籤〔labels〕、設定 記憶體斷點〔memory breakpoints〕, 尋找參考〔references〕。資料表單〔Dump menu〕只顯示與選部分相關的指令。 如果 制作備份〔backup〕可用,則按下第一個列標題欄,會在位址〔Address〕/制作備份〔Backup〕 兩種顯示模式之間切換。點擊其他列標題欄,會改變Dump模式。 像反彙編視窗一樣,資料視窗也儲存了大量檢視記憶體位址的歷史記錄。您可以通過「+」和「-」鍵來訪問您過去檢視過的資料位址空間。 要翻動一字元的資料,可以按住Ctrl l鍵並按上/下方向鍵。 可執行模組視窗〔Executable modules window〕 可執行模組視窗(快捷鍵:Alt+E)列出了當前被偵錯工作載入的所有可執行模組。它也顯示了很多有用的訊息,比如模組大小、入口位址、模組版本、以及可執行文件路徑等。一些訊息,如以十進制顯示的模組大小、入口位址的符號名、是否為系統模組等,通常是被隱藏的。如果想看,可以增加相應欄的寬度。快捷表單支持以下操作: 重新整理〔Actualize〕 - 重新掃瞄模組並去除對新載入模組的高亮顯示。在大多數情況下,OllyDbg會自動完成該操作。 檢視記憶體〔View memory〕 - 開啟記憶體視窗,並定位到屬於該模組映射的第一個記憶體塊處。 在CPU視窗中檢視程式碼〔View code in CPU〕 (快捷鍵:Enter鍵鍵) - 在反彙編視窗中顯示模組的可執行程式碼。 跟進到入口〔Follow entry〕 - 在反彙編視窗中跟進到模組的入口處。 在CPU視窗中檢視資料〔Dump data in CPU〕 -在CPU視窗的資料面板中顯示模組的資料段。塊程式碼段。 顯示名稱〔View names〕 (快捷鍵:Ctrl+N) -顯示當前模組定義或使用的全部名稱〔names〕(包括輸出表、引入表、連接庫、用戶自訂)。 標記為系統DLL〔Mark as system DLL〕, 標記為非系統DLL〔Mark as non-system DLL〕 - 將選模組標記為系統或非系統內容。如果設定為系統內容,則在Run跟蹤〔Run trace〕 時會直接執行(不進行跟蹤)這個模組,從而大大加快跟蹤速度。預設值情況下,所有駐停留在系統目錄(通常在Windows 95/98下為c:\windows\system ,在WinNT/2000/XP下為c:\winnt\system32)的模組都認為是系統模組。 立即更新.udd文件〔Update .udd file now〕 -向文件「<模組名>.udd」寫入模組相關的全部資料,udd文件儲存了在偵錯期間設定的斷點、標籤、註釋、監視、分析等訊息。當模組卸載時OllyDbg會自動新增.udd文件。 檢視可執行文件〔View executable file〕 - 顯示可執行文件的全部內容。 檢視全部資源〔View all resources〕 - 以列表形式顯示模組定義的全部資源,並帶有一個簡簡信息。OllyDbg並不把資源當作單獨實體來支持。您可以抽取〔Dump〕並以二進制的形式進行編輯。 檢視資源字串串〔View resource strings〕 -以列表形式顯示資源字串串及其標幟符。 檢視Run跟蹤的統計〔View run trace profile〕 - 在此模組中計算統計〔profile〕 。相關資訊:Run跟蹤〔Run trace〕. 分析全部模組〔Analyze all modules〕 -允許同時分析全部模組。分析將從程式碼中抽取大量的有用訊息;程式碼經過份析後再進去行偵錯,通常會非常快並且可靠。 滑鼠雙按某一行,將會在反彙編視窗中顯示模組的執行程式碼。 十,記憶體映射視窗〔Memory map window〕 記憶體映射視窗顯示了被偵錯程序分配的所有記憶體塊。因為沒有標準的方法來完成這項工作,所以OllyDbg可能會把一個大的記憶體塊分成幾個部分。然而,在大多數情況下,並非一定要精確處理。如果想檢視由應用程式通過使用GlobalAlloc()和LocalAlloc()等申請的記憶體塊列表,請使用堆列表〔Heap list〕。 如果記憶體塊是可執行模組的一個節,OllyDbg則會報告這個記憶體塊所包含的資料檔案類型:程式碼、資料、資源等。 Windows95/98是和WindowsNT/2000是有一些區別的。在Windows95/98下,OllyDbg是不能顯示被映射文件的名稱的。另外,Windows95/98不允許的訪存檔案類型為讀和寫,然而,在WindowsNT/2000下,OllyDbg卻有擁有更多功能,包括執行訪問,寫複製〔copy-on-write〕以及監視標誌位。OllyDbg忽略寫複製〔copy-on-write〕內容。 如果OllyDbg發現程序分配了新記憶體或者重新分配了已經存在的記憶體塊,它將在記憶體映射視窗中高亮顯示相應的記錄,去掉高亮度顯示,可以選項快捷表單中的重新整理〔 Actualize〕項。 您可以按Alt+M來使用記憶體視窗。 以下是快捷表單中可以選項的表單項: 重新整理〔Actualize〕 - 更新已分配記憶體的列表並去除對新記憶體塊的高亮顯示。 在反彙編視窗中檢視〔View in Disassembler〕 -在反彙編視窗中檢視:在反彙編視窗中開啟記憶體塊,這一選項僅在某些模組的記憶體塊中包含可執行程式碼或者自解壓器時可用。 在CPU資料視窗中檢視〔Dump in CPU〕 - 在CPU的資料視窗中顯示記憶體塊的內容。 資料視窗〔Dump〕 - 在單獨視窗中顯示記憶體塊內容。如果記憶體塊的檔案類型已知,則OllyDbg會自動選項顯示格式。 檢視全部資源〔View all resources〕 - 如果記憶體塊包含資源資料,則列出所有資源及相關資料。OllyDbg並不把資源當作單獨實體來支持。您可以顯示其資料並以二進制的形式進行編輯。 檢視資源字串串〔View resource strings〕 - 如果記憶體塊包含資源資料,則列出全部資源字串串及其標幟符。 搜尋〔Search〕 - 允許搜尋所有的記憶體塊,從選項處開始,搜尋匹配的二進制串。如果找到,則OllyDbg將顯示該記憶體塊。記憶體映像視窗和資料視窗共享同一種搜尋模式,所以您可以在彈出的資料視窗中立即繼續搜尋該二進制串出現的下一位置。按Esc鍵可以關閉資料視窗。 搜尋下一個〔Search next〕(快捷鍵:Ctrl+L) - 繼續上次搜尋。 設定訪問中斷〔Set break-on-access〕 (快捷鍵:F2,僅在WindowsNT/2000下可用) - 保護整個記憶體塊。當中斷髮生後OllyDbg暫停被偵錯程序並清除斷點。這類斷點在您想捕捉使用或返回到某個模組的時候特別有用。 清除訪問中斷〔Remove break-on-access〕 (快捷鍵:F2) - 從記憶體塊中清除訪問中斷保護。 設定記憶體訪問斷點〔Set memory breakpoint on access〕 - 在整個記憶體塊上設定斷點,每當該記憶體塊被訪問時程序都將中斷。OllyDbg只支持一個記憶體訪問斷點。在 Windows95/98下,當系統程序訪問含有記憶體斷點的記憶體塊時,可能會導致所被偵錯程序崩潰,因此,不到萬不得已,請不要設定這種斷點。 設定記憶體寫入斷點〔Set memory breakpoint on write〕 - 在整個記憶體塊上設定斷點,每當該記憶體塊被寫入資料時程序都將中斷。在Windows95/98下,當系統程序訪問含有記憶體斷點的記憶體塊時,可能會導致所被偵錯程序崩潰,因此,不到萬不得已,請不要設定這種斷點。 清除記憶體斷點〔Remove memory breakpoint〕 - 清除記憶體斷點。 清除自解壓記憶體斷點〔Remove SFX memory breakpoint〕 - 停止搜尋自解壓程序〔self-extractable (SFX) program〕的真實入口。這個搜尋使用了特殊檔案類型的記憶體斷點。 訪問設定〔Set access〕 -設定整個記憶體塊的保護內容,可選項的有: 禁止訪問〔No access〕 唯讀〔Read only〕 讀/寫〔Read/write〕 執行〔Execute〕 執行/讀〔Execute/read〕 完全訪問〔Full access〕 複製到剪下板〔Copy to clipboard〕 整行〔Whole line〕 -以多行文本(包括解釋)的方式把所選記錄複製到剪下板,如果複製時想排除某些列,可將該列的寬度置為最小(該欄剩餘的邊框將變灰)。 整個表格〔Whole table〕 -以多行文本的方式將整個記憶體映像訊息複製到剪下板,該文本的第一行為視窗標題("記憶體映射〔Memory map〕"), 第二行為列標題欄,後面幾行的內容為記憶體資料記錄。複製將保持列的寬度。如果複製時想排除某些列,可將該列的寬度置為最小(該欄剩餘的邊框將變灰)。 十一,監視與監察器〔Watches and inspectors〕 監視〔Watch〕 視窗包含若干個陳述式〔expressions〕。它在第二列裡顯示這些陳述式的值。OllyDbg 會把這些陳述式儲存到主模組的.UDD文件中,因此它們在下一次偵錯時同樣有效。 監察器〔inspector〕是顯示若干變數、1/2維陣列或是選定項目結構陣列〔selected items of array of structures〕的獨立視窗。它的陳述式與監視視窗中的基本相同,只是多包含了兩個參數:%A和%B。您可以指定這兩個參數的界限,OllyDbg 將會用所有可能的組合替代陳述式中的%A和%B。從0開始一直到界限(不包含界限),並在表格中顯示結果。參數%B(列數)的界限不能超過16。 例如,如果您指定了陳述式%A+%B,並且限定%A和%B的上限為3,您將獲得如下的表格: 十三,執行緒〔Threads〕 OllyDbg 以簡單而有效的執行緒管理為特色。如果您單步偵錯、跟蹤、執行到返回或者執行到所選,則執行緒管理器將停止除當前執行緒以外的所有執行緒。即使當前執行緒被掛起,它也會將其恢復。在這種情況下,如果您手動掛起或者恢復執行緒,動作將被延期。如果您執行被偵錯的應用程式,OllyDbg將恢復最初的執行緒狀態。(從偵錯器的角度來看,Hit跟蹤〔hit trace〕和自由執行是等效的)。 依據這種方案,執行緒視窗可能會有如下五種執行緒狀態: 啟動〔Active〕 - 執行緒執行中,或被偵錯訊息暫停t 掛起〔Suspended〕 - 執行緒被掛起 跟蹤〔Traced〕 - 執行緒被掛起,但OllyDbg正在單步跟蹤此執行緒 暫停〔Paused〕 - 執行緒是活動的,但OllyDbg臨時將其掛起,並在跟蹤其它的執行緒 結束〔Finished〕 - 執行緒結束 . 執行緒視窗同時也顯示了最後的執行緒錯誤(GetlastError函數的返回值)並計算該執行緒以用戶模式和系統模式(僅NT/2000/XP)執行的時間。執行緒視窗還會高亮主執行緒的標幟符。 以下在快捷表單中可用: 重新整理〔Actualize〕 - 標記所有執行緒為舊的。 掛起〔Suspend〕 - 掛起執行緒。 恢復〔Resume〕 - 恢復先前掛起的執行緒。 設定優先等級〔Set priority〕 - 調整工作中執行緒的優先等級。以下選項可用: 空閒〔Idle〕 - 工作中執行緒的最低優先等級 最低〔Lowest〕 低〔Low〕 標準〔Normal〕 高〔High〕 最高〔Highest〕 時間臨界〔Time critical〕 - 最高優先等級 在CPU視窗開啟〔Open in CPU〕(雙按)- 在CPU視窗中顯示所選執行緒的當前狀態。 十四,複製到剪下板〔Copy to clipboard〕 整行〔Whole line〕 -全部行--以多行文本的形式並帶註釋將所選記錄複製到剪下板。如果在複製時想排除某個欄目,可以將該欄的寬度置為最小(欄目的殘留部分將變灰)。 整個表格〔Whole table〕 - 整個表格--以多行文本的形式將整個記憶體映像複製到剪下板,該文本的第一行包含視窗標題(「記憶體映射〔Memory map〕」),第二行是欄目標題,所有後繼行是記憶體資料記錄。複製將保持欄目的寬度。如果在複製時想排除某些欄目,可以將該欄的寬度置為最小(欄目的殘留部分將變灰)。 十五,使用棧〔Call stack〕 使用棧視窗(快捷鍵:Alt+K)根據選定執行緒的棧,嘗試反向跟蹤函數使用順序並將其顯示出來,同時包含被使用函數的已知的或隱含的參數。如果使用函數新增了標準的堆疊框架(PUSH EBP; MOV EBP,ESP),則這個工作非常容易完成。現代的最佳化編譯器並不會為棧框架而操心,所以OllyDbg另闢蹊徑,採用了一個變通的辦法。例如,跟蹤程式碼到下一個返回處,並計算其中全部的壓入推疊、出棧,及 ESP 的修改。如果不成功,則嘗試另外一種辦法,這個辦法風險更大,速度也更慢:移動棧,搜尋所有可能的返回位址,並檢查這個位址是否被先前的已分析的指令使用。如果還不行,則會採用啟髮式搜尋。棧移動〔Stack Walk〕可能會非常慢。OllyDbg 僅在使用棧視窗開啟時才會使用。 使用棧視窗包含5個欄目:位址〔Address〕、棧〔Stack〕、程序〔Procedure〕,使用來自〔Called from〕,框架〔Frame〕。位址〔Adress〕欄包含棧位址,棧〔Stack〕 欄顯示了相應的返回位址或參數值。 函數〔Procedure〕(或 函數/參數〔Procedure / arguments〕)顯示了被使用函數的位址,在某些情況下,OllyDbg並不能保證該位址是正確的並會增加如上標記之一: ? 找到的入口點不可靠 可能〔Maybe〕 OllyDbg無法找到精確的入口點,報告的位址是用啟髮式算法猜測的。 包含〔Includes〕 OllyDbg無法找到入口點,僅知道該函數包含顯示的位址 通過按例標題欄上的按鈕或從表單中選項「隱藏/顯示參數〔Hide/Show arguments〕」,可以在顯示或隱藏函數的參數之間切換。 使用來自〔Called from〕用於顯示使用該函數的指令位址。最後一欄是框架〔Frame〕這一欄預設值是隱藏的,如果框架游標的值(暫存器EBP)已知的話,則該欄用於顯示這個值。 當使用函數經過份析〔analyzed〕.後,棧移動會更可靠並且迅速。 十六,使用樹〔Call tree〕 使用樹(快捷鍵:在反彙編視窗中Ctrl+K)利用分析〔Analysis〕的結果來找出指定函數程序直接或間接使用的函數列表,同時列出指定函數程序被使用的位址。為了避免由此可能造成的副作用。使用樹會判斷選定函數是否明確地是遞回的。「明確地」意味著它不會跟蹤目標未知的使用,比如CALL EAX。如果函數程序中有未知使用,使用樹將會增加標記「未知目標」。 某些函數使用將會增加如下註釋之一: 葉子〔Leaf〕 不使用其他函數 純函數〔Pure〕 不使用函數,不會產生副作用 單返回〔RETN〕 只有一個RETN 指令 系統〔Sys〕 系統動態連接庫中的函數。系統動態連接庫定義為儲存在系統目錄下的動態連接庫。 如果想在使用樹上移動,可以雙按「被使用〔Called from〕」或「使用/直接使用〔Calls/Calls directly〕」兩欄中的位址。使用樹視窗儲存了移動記錄(快捷鍵「-」和「+」)。 如果被偵錯的程序包含幾個模組,推薦您分析所有模組。Call tree 不會試圖處理系統函數。 十七,選項〔Options〕 外觀選項〔Appearance options〕 一般〔General〕 預設值〔Defaults〕 對話視窗〔Dialogs〕 目錄〔Directories〕 字體〔Fonts〕 顏色〔Colours〕 程式碼高亮〔Code highlighting〕 偵錯選項〔Debugging options〕 (Alt+O) 安全〔Security〕 偵錯〔Debug〕 事件〔Events〕 異常〔Exceptions〕 跟蹤〔Trace〕 自解壓〔SFX〕 字串串〔Strings〕 位址〔Addresses〕 指令〔Commands〕 反彙編〔Disasm〕 CPU 暫存器〔Registers〕 棧〔Stack〕 分析1〔Analysis 1〕 分析2〔Analysis 2〕 分析3〔Analysis 3〕 即時偵錯〔Just-in-time debugging〕 增加到檔案總管〔Add to Explorer〕 十八,搜尋〔Search〕 OllyDbg 允許您使用以下的搜尋方式: 符號名(標籤)〔Symbolic name (label)〕 二進制串〔binary string〕 常量〔constant〕 指令〔command〕 指令序列〔sequence of commands〕 模組間使用〔intermodular calls〕 修改過的指令或資料〔modified command or data〕 自訂標籤〔user-defined label〕 自訂註釋〔user-defined comment 文本字串串〔text string〕 Run跟蹤的記錄〔record in run trace〕 參考指令〔referencing commands〕 十九,自解壓文件〔Self-extracting (SFX) files〕 自解壓文件由抽取程序和壓縮的原程序兩部分組成。當遇到自解壓文件(SFX)文件時,我們通常希望跳過解壓部分,而直接跳到原始程序的入口(真正的入口)。 OllyDbg 包含了幾個便於完成這一工作的功能。 通常抽取程序的載入位址都在執行程式碼之外。在這種情況下,OllyDbg 將這類文件均視作為自解壓文件(SFX)。 當自解壓選項〔SFX options〕要求跟蹤真正入口時,OllyDbg 在整個程式碼節〔Code section〕設定記憶體斷點,最初這裡是空的,或者只包含壓縮資料。當程序試圖執行某個在這個保護區域的指令,而這些指令不是 RET 和 JMP 時,OllyDbg 會報告真正的入口。這就是抽取工作的原理。 上面的方法非常慢。有另外一種比較快的方法。每次讀取資料發生異常時,OllyDbg 使這個4K記憶體區域變為可讀,而使原先可讀的區域變為無效。而每次發生寫資料異常時, OllyDbg 使這個區域變為可寫,而使原先可寫的區域變為無效。當程序執行在保留的保護區域中的指令時,OllyDbg 報告真正的入口。但是,當真正的入口點在可讀或可寫區域內部時,報告的位址就可能有誤。 您可以改正入口位置,選項新的入口,從反彙編視窗的快捷表單中選項「斷點〔Breakpoint〕|設定真正的自解壓入口〔Set real SFX entry here〕」。如果相應的SFX選項是開啟的,OllyDbg下次可以迅速而可靠的跳過自抽取程序。 注意:OllyDbg 在跟蹤採取了保護或者反偵錯技術的解壓程序時通常會失敗。 二十,單步執行與自動執行〔Step-by-step execution and animation〕 您可以通過按 F7(單步步入)或 F8(單步步過),對程序進行單步偵錯。這兩個單步執行操作的主要區別在於:如果現用的指令是一個子函數,按F7,將會進入子函數,並停在子函數的第一條指令上;而按 F8,將會一次執行完這個子函數。如果您單步步過的子函數中含有斷點或其他偵錯事件,執行將會被暫停,但 OllyDbg 會在子函數的後一條指令上,自動下一個斷點,而這個斷點您遲早會碰到。 如果被偵錯程序停在異常上,您可以跳過它,並轉到被偵錯程序建立的關鍵句處。只需簡單的 Shift 鍵和任何一個單步指令。 如果需要連續按F7、F8鍵上百次,您可以使用自動執行(Ctrl+F7或者Ctrl+F8)功能。在這種情況下,OllyDbg 將自動重複F7或者F8操作,並且既時更新所有的視窗。這個程序會在下面情況停止: |
__________________ |
|
送花文章: 3,
|
向 psac 送花的會員:
|
Jamaalacugs (2018-04-20)
感謝您發表一篇好文章 |
2006-05-25, 03:46 PM | #2 (permalink) |
榮譽會員
|
按 Esc 鍵或發出任何單步指令
- OllyDbg 遇到斷點 - 被偵錯程序發生異常 使用「+」和「-」按鍵,可以回朔以前的執行歷史〔execution history〕. 注意:當執行停止時 OllyDbg 將會重新整理大部分視窗。如果動態執行程序非常慢,可以嘗試關掉或最小化沒有用的視窗。 另外,更快捷的找到以前執行指令的辦法是Run跟蹤〔run trace〕。它將新增一個執行傳輸協定並告知您指定指令的執行時間和次數 二一,Hit跟蹤〔Hit trace〕 Hit跟蹤能夠讓您辨別哪一部分程式碼執行了,哪一部分沒有。OllyDbg的實現方法相當簡單。它將選區域的每一條指令處均設定一個INT3斷點。當中斷髮生的時候,OllyDbg便把它去除掉,並把該指令標誌為命中〔hit〕。因為每個跟蹤斷點只執行一次,所以這種方法速度非常快。 在使用Hit跟蹤的時候,一定要注意不能在資料中設定斷點,否則應用程式極有可能崩潰。因此,您必須開啟相關的表單選項,以進行程式碼分析〔analyze〕。我推薦您選項嚴格或啟髮式函數識別〔strict or heuristical procedure recognition〕。如果選項模糊〔Fuzzy〕的話,可能會產生很多難以容忍的錯誤,而且經常把本不是函數的程式碼段識別成函數。 只要您在模組中設定了跟蹤斷點,哪怕只設了一個,OllyDbg都會分配兩倍於程式碼段大小的緩衝區。 注意:當您結束Hit跟蹤的時候,Run跟蹤也會同時結束。 Run 跟蹤〔Run trace〕 Run跟蹤是一種反方向跟蹤程序執行的方式,可以瞭解以前發生的事件。您還可以使用Run跟蹤來瞭解執行的簡單統計〔profile〕。基本上,OllyDbg 是一步一步地執行被偵錯程序的,就像動畫〔animation〕演示一樣,但不會既時重新整理視窗,最重要的是它能將位址、暫存器的內容、消息以及已知的操作數記錄到Run跟蹤緩衝區中。如果被偵錯的程式碼是自修改的,您就能夠儲存原始的指令。可以通過按Ctrl+F11(Run跟蹤步入,進入子函數)或者Ctrl+F12(Run跟蹤步過,一次執行完子函數)開始Run跟蹤,並用F12或者Esc鍵停止跟蹤。 您可以指定在Run跟蹤時執行每一步的條件集(快捷鍵:Ctrl+T)。如果條件符合,Run跟蹤將暫停。條件包括: ?當EIP在某個位址範圍內時暫停〔Pause when EIP is in the address range〕; ?當EIP在某個位址範圍之外時暫停〔Pause when EIP is outside the address range〕; ?當某個條件為真時暫停〔Pause when some condition is true〕; ?當下一條指令可疑時暫停〔Pause when next command is suspicious〕,比如: 可能為非法指令(根據在分析3〔Analysis 3〕中設定的規則而定),訪問不存在的記憶體,設定了單步陷阱標誌〔single-step trap flag〕或者越ESP界訪問棧。注意這個選項會明顯地(大約20%)減慢Run跟蹤的速度; ?當指令執行達到指定的次數(更確切的說,是增加到Run跟蹤的緩衝區裡面的指令數量)時暫停〔Pause after specified number of commands is traced〕。注意計數器不能自動歸零。也就是說,如果您設定指令次數為10,則在第10次執行到該指令時暫停,並不是該指令每執行10次就暫停一次。 ?當下一條指令符合指定的樣式之一時暫停〔Pause when next command matches one of the specified patterns〕。您可以使用模糊指令和操作數〔imprecise commands and operands〕及匹配32位暫存器RA和RB,像R32一樣,這兩個暫存器可以替代任何通用32位暫存器,但是在同一條指令中其值是不能變的。而 RA 和 RB 在同一條指令中,則一定是不同的。例如,在程序中含有 XOR EAX,EAX; XOR ESI,EDX 兩條指令,兩條指令均符合樣式 XOR R32,R32;第一條指令符合樣式XOR RA,RA ;而等二條指令 XOR ESI,EDX 符合樣式XOR RA,RB。 毫無疑問,Run跟蹤需要足夠的記憶體,每條指令平均需要佔用16到35字元,同時速度也非常慢。在500-MHZ處理器、Windows NT環境下,它每秒能跟蹤5000條指令。 Windows95更慢:每秒鍾僅2200條指令。但是在許多情況下,例如當一個程序跳轉到不存在的位址的時候,這是找到原因的唯一方法。您可以在Run跟蹤時將准線性指令序列(即序列尾部只有唯一出口)跳過。當OllyDbg遇到這些需跳過的指令序列時,會設定一個臨時斷點,然後跟進到序列中,並一次執行完。當然了,如果排除指令中返回或跳轉的位址在跟蹤範圍之外,將可能導致跟蹤發生錯誤;因此OllyDbg會檢查您想跳過的程式碼塊,如果存在上述情況,會向您詢問。 在大多數情況下,您對跟蹤系統API程式碼不感興趣。跟蹤選項總是跟過系統DLL〔Always trace over system DLLs〕允許您在 跟蹤/自動 模式下跟過API函數。如果模組在系統目錄下,OllyDbg就假設該模組是系統的。您可以在模組〔Modules〕視窗中標記任意DLL是系統的或者非系統的。 為了使執行速度更快,您可以通過設定Run跟蹤斷點,先將Run跟蹤限制在選定的指令或程式碼塊上,然後再執行程序。我把這種做法稱作「強迫Run跟蹤」。一般來說,移除Run跟蹤斷點不會移除Hit跟蹤斷點。但如果您移除了hit跟蹤斷點,同時您也移除了Run跟蹤斷點。 跟蹤指令會儲存到跟蹤緩衝區中,這個緩衝區在跟蹤開始時自動新增。您可以在選項中指定它的大小(最高64MB)。這個緩衝區是循環貯列,當滿了的時候,會丟棄老的記錄。 您可以通過從OllyDbg主表單中選項「偵錯〔Debug〕|開啟或者清除Run跟蹤〔Open or clear run trace〕」,來開啟或者清除Run跟蹤緩衝區。在Run跟蹤緩衝區開啟後, OllyDbg 會記錄在執行程序中的所有暫停,甚至那些不是由Run跟蹤引起的暫停。例如,您可以通過按 F7 或者 F8 單步執行程序,然後通過使用+鍵和-鍵來反方向跟蹤程序的執行。注意:如果Run跟蹤緩衝區已經關閉,則用這些鍵瀏覽的是歷史〔history〕記錄。在您檢視Run跟蹤記錄時,暫存器和訊息面板會變灰,來強調它們所顯示的暫存器並不是實際的暫存器。跟蹤緩衝區並不儲存推疊頂端或由暫存器所指向的內容。暫存器、訊息和棧在Run跟蹤的時候使用實際的記憶體狀態來解釋暫存器的變化。 OllyDbg能夠記下每個指令在Run跟蹤緩衝區裡面出現的次數。在反彙編視窗快捷表單中,選項是「檢視〔View〕|統計作為註釋〔Profile as comments〕」。這個指令使用統計取代了註釋欄。或者,如果列標題欄可見,則可以按下它幾次直到它顯示統計訊息。注意顯示出來的數位是動態的,而且不計算已經從跟蹤緩衝區中丟棄的指令。您還可以在單獨的統計視窗〔Profile window〕中,按觸發次數排序,來檢視整個模組的統計資料。 在反彙編視窗的快捷表單中選項「Run跟蹤〔Run trace〕|增加到所有函數入口處〔Add entries of all procedures〕」,這樣能夠檢查每個可識別的函數被使用的次數。另一個指令「Run跟蹤〔Run trace〕|增加到函數中所有的分支〔Add branches in procedure〕」會強行跟蹤此函數中所有識別的跳轉目的位址的內容。在這種情況下,統計功能能夠找到最頻繁執行的分支,您可以最佳化這部分的程式碼,以提高速度。 在反彙編視窗中的某條指令上使用快捷表單中選項「搜尋〔Search for〕|Run跟蹤的最新記錄〔Last record in run trace〕」用於尋找該指令是否被執行過,如果執行過,最後一次執行在哪裡。 Run跟蹤視窗顯示跟蹤緩衝區的內容。對每個指令來說包括被指令改變的整數暫存器的內容(更準確的說是給定的記錄變成下一條記錄的變化)。如果您雙按某條指令,視窗會選項在跟蹤緩衝區裡全部含有該指令的記錄,而且您可以通過按+和-鍵來快速的瀏覽;如果您在偵錯選項〔Debugging options〕中設定了 「跟蹤〔Trace〕|同步CPU和 Run跟蹤〔Synchronize CPU and Run trace〕」,雙按記錄則會跟進到對應的反彙編視窗中位置。 注意:當您結束Hit跟蹤時,您同時也強行結束了Run跟蹤。 通用快捷鍵〔Global shortcuts〕 無論現用的OllyDbg視窗是什麼,這些快捷鍵均有效: Ctrl+F2 - 重新啟動程序,即重新啟動被偵錯程序。如果當前沒有偵錯的程序,OllyDbg會執行歷史列表〔history list〕中的第一個程序。程序重新啟動後,將會移除所有記憶體斷點和硬體斷點。 譯者註:從實際使用效果看,硬體斷點在程序重新啟動後並沒有移除。 Alt+F2 - 關閉,即關閉被偵錯程序。如果程序仍在執行,會彈出一個提示訊息,詢問您是否要關閉程序。 F3 - 彈出「開啟32位.EXE文件」對話視窗〔Open 32-bit .EXE file〕,您可以選項可執行文件,並可以輸入執行參數。 Alt+F5 - 讓OllyDbg總在最前面。如果被偵錯程序在某個斷點處發生中斷,而這時偵錯程序彈出一個總在最前面的視窗(一般為模式消息或模式對話視窗〔modal message or dialog〕),它可能會遮住OllyDbg的一部分,但是我們又不能移動最小化這個視窗。啟動OllyDbg(比如按工具列上的標籤)並按Alt+F5,OllyDbg將設定成總在最前面,會反過來遮住剛才那個視窗。如果您再按一下Alt+F5,OllyDbg會恢復到正常狀態。OllyDbg是否處於總在最前面狀態,將會儲存,在下一次偵錯時依然有效。當前是否處於總在最前面狀態,會顯示在狀態列中。 F7 - 單步步入到下一條指令,如果當前指令是一個函數〔Call〕,則會停在這個函數體的第一條指令上。如果當前指令是是含有REP前綴,則只執行一次重複操作。 Shift+F7 - 與F7相同,但是如果被偵錯程序發生異常而中止,偵錯器會首先嘗試步入被偵錯程序指定的異常處理(請參考忽略Kernel32中的記憶體非法訪問)。 Ctrl+F7 - 自動步入,在所有的函數使用中一條一條地執行指令(就像您按住F7鍵不放一樣,只是更快一些)。當您執行其他一些單步指令,或者程序到達斷點,或者發生異常時,自動步入程序都會停止。每次單步步入,OllyDbg都會更新所有的視窗。所以為了提高自動步入的速度,請您關閉不必要成視窗,對於保留的視窗最好盡量的小。按Esc鍵,可以停止自動步入。 F8 - 單步步過到下一條指令。如果當前指令是一個函數,則一次執行完這個函數(除非這個函數內部包含斷點,或發生了異常)。如果當前指令是含有REP前綴,則會執行完重複操作,並停在下一條指令上。 Shift+F8 - 與F8相同,但是如果被偵錯程序發生異常而中止,偵錯器會首先嘗試步過被偵錯程序指定的異常處理(請參考忽略Kernel32中的記憶體非法訪問)。 Ctrl+F8 - 自動步過,一條一條的執行指令,但並不進入函數使用內部(就像您按住F8鍵不放一樣,只是更快一些)。當您執行其他一些單步指令,或者程序到達斷點,或者發生異常時,自動步過程序都會停止。每次單步步過,OllyDbg都會更新所有的視窗。所以為了提高自動步過的速度,請您關閉不必要成視窗,對於保留的視窗最好盡量的小。按Esc鍵,可以停止自動步過。 F9 - 讓程序繼續執行。 Shift+F9 - 與F9相同,但是如果被偵錯程序發生異常而中止,偵錯器會首先嘗試執行被偵錯程序指定的異常處理(請參考忽略Kernel32中的記憶體非法訪問)。 Ctrl+F9 - 執行直到返回,跟蹤程序直到遇到返回,在此期間不進入子函數也不更新CPU資料。因為程序是一條一條指令執行的,所以速度可能會慢一些。按Esc鍵,可以停止跟蹤。 Alt+F9 - 執行直到返回到用戶程式碼段,跟蹤程序直到指令所屬於的模組不在系統目錄中,在此期間不進入子函數也不更新CPU資料。因為程序是一條一條執行的,所以速度可能會慢一些。按Esc鍵,可以停止跟蹤。 Ctrl+F11 -Run跟蹤步入,一條一條執行指令,進入每個子函數使用,並把暫存器的訊息加入到Run跟蹤的儲存於資料中。Run跟蹤不會同步更新CPU視窗。 F12 - 停止程序執行,同時暫停被偵錯程序的所有執行緒。請不要手動恢復執行緒執行,最好使用繼續執行快捷鍵或表單選項(像 F9)。 Ctrl+F12 - Run跟蹤 步過,一條一條執行指令,但是不進入子函數使用,,並把暫存器的訊息加入到Run跟蹤的儲存於資料中。Run跟蹤不會同步更新CPU視窗。 Esc - 如果當前處於自動執行或跟蹤狀態,則停止自動執行或跟蹤;如果CPU顯示的是跟蹤資料,則顯示真實資料。 Alt+B - 顯示斷點視窗。在這個視窗中,您可以編輯、移除、或跟進到斷點處。 Alt+C - 顯示CPU視窗。 Alt+E - 顯示模組列表〔list of modules〕。 Alt+K - 顯示使用棧〔Call stack〕視窗。 Alt+L - 顯示日誌視窗。 Alt+M - 顯示記憶體視窗。 Alt+O - 顯示選項對話視窗〔Options dialog〕 Ctrl+P - 顯示修正檔視窗。 Ctrl+T - 開啟 暫停 Run跟蹤 對話視窗 Alt+X - 關閉 OllyDbg。 大多數視窗都支持以下的鍵盤指令: Alt+F3 - 關閉當前視窗。 Ctrl+F4 - 關閉當前視窗。 F5 - 最大化當前視窗或將當前視窗大小改為正常化。 F6 - 切換到下一個視窗。 Shift+F6 - 切換到前一個視窗。 F10 - 開啟與當前視窗或面板相關的快捷表單。 左方向鍵 - 顯示視窗左方一個字元寬度的內容。 Ctrl+左方向鍵 - 顯示視窗左方一欄的內容。 右方向鍵 - 顯示視窗右方一個字元寬度的內容 Ctrl+右方向鍵 - 顯示視窗右方一欄的內容 反彙編視窗中的快捷鍵〔Disassembler shortcuts〕 當CPU視窗中的反彙編面板〔Disassembler pane〕處於啟動狀態時,您可以使用以下快捷鍵: Enter鍵鍵 - 將選的指令增加到指令歷史〔command history〕中,如果當前指令是一個跳轉、函數或者是轉換表的一個部分,則進入到目的位址。 退格鍵 - 移除選部分的自動分析訊息。如果分析器將程式碼誤識別為資料,這個快捷鍵就非常有用。請參考解碼提示〔decoding hints〕. Alt+退格鍵 - 撤消所選部分的修改,以制作備份資料的相應內容取代所選部分。僅當制作備份資料存在且與所選部分不同時可用。 Ctrl+F1 -如果API求助文件已經選項,將開啟與首個選項行內的符號名相關聯的說明主題。 F2 -在首個選項的指令上開關INT3 斷點〔Breakpoint〕,也可以雙按該行第二列。 Shift+F2 -在首個選項指令設定條件斷點,參見忽略Kernel32中記憶體訪問異常〔Ignore memory access violations in Kernel32〕。 F4 -執行到所選行,在首個選項的指令上設定一次性斷點,然後繼續執行偵錯程序,直到OllyDbg捕獲到異常或者停止在該斷點上。在程序執行到該指令之前,該一次性斷點一直有效。如有必要,可在斷點視窗〔Breakpoints window〕中移除它。 Shift+F4 -設定記錄斷點(一種條件斷點,當條件滿足時一些陳述式的值會記錄下來), 詳情參見斷點〔Breakpoint〕。 Ctrl+F5 -開啟與首個選項的指令相對應的源文件。 Alt+F7 -轉到上一個找到的參考。 Alt+F8 -轉到下一個找到參考。 Ctrl+A -分析當前模組的程式碼段。 Ctrl+B - 開始二進制搜尋。 Ctrl+C -複製所選內容到記事本。複製時會簡單地按列寬截斷不可見內容,如果希望排除不需要的列,可把這些列的寬度調整到最小。 Ctrl+E -以二進制(十六進制)格式編輯所選內容。 Ctrl+F -開始指令搜尋。 Ctrl+G -轉到某位址。該指令將彈出輸入位址或陳述式的視窗。該指令不會修改 EIP。 Ctrl+J -列出所有的涉及到該位置的使用和跳轉,在您用這個功能之前,您必須使用分析程式碼功能。 Ctrl+K - 檢視與當前函數相關的使用樹〔Call tree〕。在您用這個功能之前,您必須使用分析程式碼功能。 Ctrl+L - 搜尋下一個,重複上一次的搜尋內容。 Ctrl+N - 開啟當前模組的名稱(標籤)列表。 Ctrl+O - 掃瞄object文件。掃瞄Object文件。該指令會顯示掃瞄Object文件對話視窗,您可以在該對話視窗中選項Object文件或者lib文件,並掃瞄這個文件,試圖找到在實際程式碼段中用到的目標模組。 Ctrl+R -搜尋所選指令的參考。該指令掃瞄啟動模組的全部可執行程式碼,以找到涉及到首個選的指令的全部相關參考(包括:常量、跳轉及使用),您可以在參考中使用快捷鍵 Alt+F7 和 Alt+F8來瀏覽這些參考。為便於您使用,被參考的指令也包含在該列表中。 Ctrl+S -指令搜尋。該指令顯示指令尋找〔Find command〕對話視窗供您輸入彙編指令,並從當前指令開始搜尋。 星號〔Asterisk〕(*) -轉到原始位置(啟動執行緒的EIP處)。 Ctrl+星號(*) - 指定新的起始位置,設定當前所選執行緒的EIP為首個選項字元的位址。您可以在選項EIP並撤消該操作。 加號〔Plus〕(+) -如果run跟蹤〔run trace〕 沒有啟動,則根據指令歷史〔command history〕跳到下一條執行過指令的地方;否則跳到Run跟蹤的下一個記錄。 Ctrl+加號 - 跳到前一個函數開始處。(注意只是跳到,並不執行) 減號〔Minus〕(-) - 如果run跟蹤〔run trace〕 沒有啟動,則根據指令歷史〔command history〕跳到前一條執行過指令的地方;否則跳到Run跟蹤的前一個記錄。 Ctrl+減號 - 跳到下一個函數開始處。(注意只是跳到,並不執行) 空格〔Space〕 - 修改指令。您可在顯示對話視窗中以彙編語言修改實際指令或輸入新指令,這些指令將取代實際程式碼,您也可以在想要修改的指令處雙按滑鼠。 冒號〔Colon〕( - 增加標籤。顯示增加標籤視窗〔Add label〕或修改標籤視窗〔Change label〕,您可在此輸入與首個選項的指令中的第一個字元相關聯的標籤(符號名)。注意,在多種編程語言中,冒號可以是標籤的一部分。 分號〔Semicolon〕( - 增加註釋〔comment〕。顯示增加註釋視窗〔Add label〕或修改註釋視窗〔Change label〕,您可在此輸入與首條所選指令的第一個字元相關聯的註釋(註釋串會顯示在最後一列中)。注意,多種彙編語言使用分號作為註釋開始。您也可以在註釋列雙按需要註釋的指令行。 插件〔Plugins〕 插件是一個DLL,存放在OllyDbg的目錄中,用於增加 OllyDbg 的功能。您可以從 OllyDbg 的主頁上(http://home.t-online.de/home/Ollydbg)免費下載插件開發工具包 plug110.zip。 插件可以設定斷點,增加標籤和註釋,修改暫存器和記憶體。插件可以增加到主表單和很多的視窗(比如反彙編視窗、記憶體視窗)的快捷表單中,也可以攔截快捷鍵。插件還可以新增MDI(多我的文件介面)視窗。插件還可以根據模組訊息和OllyDbg.ini文件,將自己資料寫到.udd文件中;並能讀取描述被偵錯程序的各種資料結構。插件API包含了多達170 個函數。 許多第三方插件都可以從Internet網上獲得,比如由網友TBD新增並維護的OllyDbg的論壇(http://ollydbg.win32asmcommunity.net)。 安裝插件的方法:將DLL複製到插件目錄〔plugin directory〕中,然後重新啟動Ollydbg。預設值情況下,這個插件目錄為ollydbg.exe文件所在的目錄。 現在的版本中已經包含了兩個「原始」插件: 書籤〔Bookmark〕 and 指令行〔Command line〕. 他們的來源碼都儲存在plug110.zip.文件中。這些插件都是免費的,您可以任意修改或使用它們。 技巧提示〔Tips and tricks〕 ?OllyDbg 可以作為二進制編輯器使用。選項視圖〔View〕→文件〔File〕並選定需要檢視的文件。文件不能大於剩餘記憶體數量。 ?假使您修改了記憶體中的執行文件,這時您想恢復修改的部分,但是您忘記哪裡被修改了,您可以把原始文件當作制作備份進行載入,這樣您就可以找到修改的部分了。 分析前,先掃瞄 OBJ 文件。這時 OllyDbg 會對已知 C 函數的參數進行解碼。 一些表格中包含了隱藏資料。可以通過增加列寬來顯示出來。 所有資料視窗(包括反彙編視窗),可以通過雙按顯示相對的位址。 您可以通過 Ctrl +↑ 或 Ctrl+↓ 對資料視窗翻動一個字元。 偵錯獨立的DLL〔Debugging of stand-alone DLLs〕 開啟DLL,也可以直接將其從檔案總管拖放到 OllyDbg 上。OllyDbg 會詢問您並將該檔案的全路徑作為參數傳送給loaddll.exe.。然後連接庫被載入並停在程式碼的入口( <DllEntryPoint>)。您可以設定斷點,執行或跟蹤啟動程式碼,等等。在啟始化完成後,應該程序會再次暫停。這次停在標籤名為 Firstbp 的位置,其在立即進入主消息循環之前。 現在,您可以使用DLL函數。從主表單選項「偵錯〔Debug〕|使用DLL輸出〔Call DLL export〕」。這時會彈出一個對話視窗。由於這個對話視窗是無模式對話視窗,因此您仍然能夠使用OllyDbg的全部功能,比如檢視程式碼、資料,檢視斷點,修改記憶體等等。 選項您想使用的函數。例如我們將開始使用 USER32.DLL 裡的MessageBox 函數。注意loaddll.exe 已經使用了這個連接庫,因此會假定這個 DLL 已經啟始化而不再使用入口。MessageBox 這個函數名是通用函數名,實事上,這個函數有處理 ASCII 的 MessageBoxA 和處理 Unicode 的MessageBoxW 兩種。我們繼續往下看: |
送花文章: 3,
|
有 2 位會員向 psac 送花:
|
2006-05-25, 03:48 PM | #3 (permalink) |
榮譽會員
|
在我們選項這個函數後,右邊的訊息框中會出現 Number of arguments: 4(有四個參數)的字樣。OllyDbg 會根據函數尾部的RET 10語句來正確識別參數的數量。RET nnn
是使用PASCAL使用約定的函數的典型特徵。(參數被放壓入推疊中,第一個參數會被最後一個壓壓入推疊中,函數使用完畢後,參數會被遺棄)。大多數的 Windows API 函數都是 PASCAL形式的。 下一步,我們要設定棧中參數的個數。在這個例子中,不必做進行這個操作,因為OllyDbg已經知道了MessageBoxW函數的參數數量。但是,如果您願意的話,也可以按下左邊的複選框,改變成您認為合適的參數數量 現在填寫參數列表。這個對話視窗中支持至多10個參數. 參數可以是任何有效的陳述式,而不必使用暫存器。如果操作數指向了記憶體,則參數右邊的緩衝區視窗會顯示記憶體中的資料。Loaddll.exe 有10個大小為1K的緩衝區,這些緩衝區被標記為Arg1 .. Arg10,,您可以方便自由的使用它們。 另外,對話視窗還支持兩個偽變數:由loaddll.exe新增的父視窗關鍵句, 以及loaddll的實例關鍵句。為了方便您的使用,在您第一次使用使用輸出函數時,OllyDbg就已經將這兩個偽變數加到了歷史列表中去了。 MessageBoxW e函數需要4個參數: ?父視窗關鍵句。 這裡我們選項 ;handle of owner window. Here, we simply select ; ?在訊息框中UNICODE文本的位址。選項Arg2並按Enter鍵。緩衝區視窗會以16進制的格式顯現記憶體中的緩衝區。這個緩衝區啟始化全是0。點擊第一個字元,並按快捷鍵 Ctrl+E(另外, 也可以從表單中選項「二進制〔Binary〕|編輯〔Edit〕」)。這時會出現一個對話視窗,在對話視窗中按鍵輸入「Text in box」或者其他希望顯示的字串串; ?訊息框標題的UNICODE文本的位址。選項Arg3並在Unicode格式的記憶體中寫上「Box title」; ?訊息框的風格。使用常量MB_xxx進行組合.OllyDbg 可以識別這些常量。在這裡我們按鍵輸入:MB_OK|MB_ICONEXCLAMATION。 這裡不需要暫存器參數。 現在我們準備使用輸出函數。選項「在使用時隱藏〔Hide on call〕」意思是說,當函數執行時對話視窗將會從螢幕消失。當我們執行一個會執行很長時間的函數,或者設定了斷點的時候,這個選項非常的有用。您也可以手動關閉對話視窗。當函數執行完畢後,OllyDbg會重新自動開啟。「使用輸出函數」對話視窗。選項「在使用後暫停〔Pause after call〕」意思是說,在執行完函數後,loaddll將會被暫停。 按「使用〔Call〕按鈕」後,OllyDbg 會自動制作備份所有的記憶體、校驗、參數、暫存器等訊息。並隱藏對話視窗,然後使用 MessageBoxW 函數。和期望的一樣,訊息框在螢幕中出現了: |
送花文章: 3,
|
有 2 位會員向 psac 送花:
|
2006-05-25, 03:48 PM | #4 (permalink) |
榮譽會員
|
函數 MessageBoxW 不會修改參數。如果您使用的函數更新了記憶體,比如函數 GetWindowName,修改的字元將會在資料區裡高亮。注意:EAX 返回值為1,表示成功。
其他的例子請訪問我的網站: http://home.t-online.de/home/Ollydbg/Loaddll.htm. 不幸的是,您不能通過這種方式偵錯OllyDbg的插件,插件關聯到ollydbg.exe文件,Windows系統不能在同一個應用程式裡載入並執行兩個可執行文件。 解碼提示〔Decoding hints〕 在某些情況下,分析器不能區分程式碼和資料。讓我們看看下面的例子: const char s[11] = "0123456789"; ... for (i=0x30; i<0x3a; i++) t[i-0x30]=s[i-0x30]; 好的編譯器將會將上面的程式碼最佳化成如下樣子: e for (i=0x30; i<0x3a; i++) (t-0x30)=(s-0x30); 這裡t-0x30 和 s-0x30 都是常量,並編譯成如下形式: MOV AL,[BYTE s_minus_30+EBX] MOV [BYTE t_minus_30+EBX],AL 編譯器也可能將常量字串串"0123456789"插入到執行程式碼中。在1.10版本中,我打算用暫存器的值來決定是否的資料或程式碼。當遇到上面的指令,分析器將假定位址 s_minus_30處包含字串資料。但事實上,可能那裡是程式碼。 萬一出現上述問題,我們應該怎麼辦呢?有兩種辦法:最快最笨的辦法是:將分析錯誤的部分移除(快捷鍵:退格鍵),這樣OllyDbg將使用預設值的反彙編器進行解碼。 更好的辦法是使用解碼提示〔decoding hints〕。您可以告訴OllyDbg如何解釋選的記憶體內容。這種方法在重新分析(Ctrl+A)時,解釋依然有效。 設定提示的方法:在反彙編視窗中,選需要修正提示的程式碼或資料,然後在快捷表單中選項 分析〔Analysis〕|在下次分析時,將選項部分視為〔During next analysis, treat selection as〕。選項以下選項之一: 指令〔Command〕 - 第一個被選的字元開始的有效指令。這條指令,還有所有後面的部分,直到有Jump或Return指令出現,以及含有Jump或Call指令所到達位置的部分,都會被視為指令; 字元〔Byte〕, 字〔Word〕, 雙字〔Doubleword〕 - 選的前1、2、4字元視為對應大小的資料; 所有選指令〔Commands〕 - 全部選部分(直到第一個無效指令)和可以到達由有效指令集組成的目的位址; 字元〔Bytes〕, 字〔Words〕, 雙字〔Doublewords〕, - 全部選部分以1、2、或 4字元分組; ASCII字串串〔ASCII text〕, UNICODE字串串〔UNICODE text〕 - 全部選部分為ASCII 或 UNICODE 字串串; 預設值(移除提示)〔Default (remove hints)〕 - 從選部分中移除全面提示; 移除全部提示〔Remove all hints〕 - 從全部模組中移除解碼提示。 OllyDbg 儲存提示到.udd文件中。 陳述式賦值〔Evaluation of expressions〕 [code] OllyDbg能夠支持非常複雜的陳述式。陳述式的語法格式將在這個主題的後面進行介紹,但我想您對此不一定真的感興趣。那麼我先舉幾個實例來說明: 10 - 常量 0x10 (無符號)。所有整數常量都認為是十六進制的,除非後面跟了點; 10. - 十進制常量10(帶符號); 'A' - 字串常量 0x41; EAX - 暫存器EAX的內容,解釋為無符號數; EAX. -暫存器EAX的內容,解釋為帶符號數; [123456] - 在位址123456處的無符號雙字內容。預設值情況,OllyDbg假定是雙字長操作數; DWORD PTR [123456] - 同上。關鍵字 PTR 可選; [SIGNED BYTE 123456] - 在位址123456處帶符號單字元。OllyDbg支持類MASM和類IDEAL兩種記憶體陳述式; STRING [123456] - 以位址123456作為開始,以零作為結尾的ASCII字串串。中括號是必須的,因為您要顯示記憶體的內容; [[123456]] - 在位址123456處儲存於的雙字所指向的位址內的雙字內容; 2+3*4 - 值為14。OllyDbg 按標準C語言的優先等級進行算術執行; (2+3)*4 - 值為20。使用括號改變運算順序。 EAX.<0. - 如果EAX在0到0x7FFFFFFF之間,則值為0,否則值為1。注意0也是有符號的。當帶符號數與無符號數比較時,OllyDbg會將帶符號數轉成無符號數。 EAX<0 - 總為0(假),因為無符號數永遠是正的。 MSG==111 - 如果消息為WM_COMMAND,則為真。0x0111是指令 WM_COMMAND 的數值。MSG只能用於設定在工作消息函數的條件斷點內。 [STRING 123456]=="Brown fox" - 如果從位址0x00123456開始的記憶體為ASCII字串串"Brown fox"、"BROWN FOX JUMPS"、 "brown fox???",或類似的串,那麼其值為1。比較不區分大小寫和文本長度。 EAX=="Brown fox" - 同上,EAX按游標對待。 UNICODE [EAX]=="Brown fox" - OllyDbg認為EAX是一個指向UNICODE串的游標,並將其轉換為ASCII,然後與文本常量進行比較。 [ESP+8]==WM_PAINT - i在陳述式中您可以使用上百種Windows API符號常量。 ([BYTE ESI+DWORD DS:[450000+15*(EAX-1)]] & 0F0)!=0 - 這絕對是個有效的陳述式。 現在我們介紹語法格式。在大括號({})內的每個元素都只能出現一次,括號內的元素順序可以交換: 陳述式 = 記憶體中間碼|記憶體中間碼<二元操作符>記憶體中間碼 記憶體中間碼 = 中間碼| { 符號標誌 大小標誌 前綴} [陳述式 ] 中間碼 = (陳述式)| 一元操作符 記憶體中間碼 | 帶符號暫存器 | 暫存器 | FPU暫存器 | 段暫存器 | 整型常量 | 浮點常量 | 串常量 | 參數 | 偽變數 一元操作符 = ! | ~ | + | 帶符號暫存器 = 暫存器. 暫存器 = AL | BL | CL ... | AX | BX | CX ... | EAX | EBX | ECX ... FPU暫存器 = ST | ST0 | ST1 ... 段暫存器 = CS | DS | ES | SS | FS | GS 整型常量 = <十進制常量>. | <十六進制常量> | <字串常量> | <API符號常量> 浮點常量 = <符點常量> 串常量 = "<串常量>" 符號標誌 = SIGNED | UNSIGNED 大小標誌 = BYTE | CHAR | WORD | SHORT | DWORD | LONG | QWORD | FLOAT | DOUBLE | FLOAT10 | STRING | UNICODE 前綴 = 中間碼: 參數 = %A | %B // 僅允許在監察器〔inspector〕 中使用 偽變數 = MSG // 視窗消息中的程式碼 這個語法並不嚴格。在解釋[WORD [EAX]]或類似的陳述式時會產生歧義。可以理解為以暫存器EAX所指向位址的兩字元內容為位址,所指向的雙字內容;也可以理解為以暫存器EAX所指向位址的四字元內容為位址,所指向的兩字元內容。而OllyDbg會將修飾符盡可能的放在位址最外面,所以在這種情況下,[WORD [EAX]] 等價於 WORD [[EAX]]。 預設值情況下,BYTE、WORD 和 DWORD 都是無符號的,而CHAR、SHORT 和 LONG都是帶符號的。也可以使用明確的修飾符SIGNED 或 UNSIGNED。例如在二元操作時,如果一個操作數是浮點的,那麼另外一個就要轉成浮點數;或者如果一個是無符號膽,那麼另外一個要轉成無符號的。浮點檔案類型不支持UNSIGNED。大小修飾符後面跟 MASM相容關鍵字PTR(如:BYTE PTR)也允許的,也可以不要PTR。暫存器名和大小修飾符不區分大小寫。 您可以使用下面類C的運算符(0級最高): 優先等級 檔案類型 運算符 0 一元運算符 ! ~ + - 1 乘除運算 * / % 2 加減運算 + - 3 位移動 << >> 4 比較 < <= > >= 5 比較 == != 6 按位與 & 7 按位異或 ^ 8 按位或 | 9 邏輯與 && 10 邏輯或 || 在計算時,中間結果以 DWORD 或 FLOAT10 形式儲存。某些檔案類型組合和操作是不允許的。例如:QWODRD 檔案類型只能顯示;STRING 和 UNICODE 只能進行加減操作(像C語言裡的游標)以及與 STRING、UNICODE 檔案類型或串常量進行比較操作;您不能按位移動 浮點〔FLOAT〕 檔案類型,等等。 自訂函數描述〔Custom function descriptions〕 概論〔Introduction〕 OllyDbg包含(做為內部資源)1900多種標準函數以及400多種標準C函數的名稱和參數。分析器〔Analyzer〕 用這些描述使被偵錯程序更加易懂。比較下面一個例子,分析器的函數CreateFont: PUSH OT.00469F2A ; ASCII "Times New Roman" PUSH 12 PUSH 2 PUSH 0 PUSH 0 PUSH 0 PUSH 0 PUSH 0 MOV EAX,DWORD PTR [49FA70] PUSH EAX PUSH 190 PUSH 0 PUSH 0 PUSH 0 PUSH 10 CALL <JMP.&GDI32.CreateFontA> 這是分析後的: MOV EAX,DWORD PTR [49FA70] PUSH OT.00469F2A ; ?FaceName = "Times New Roman" PUSH 12 ; ?PitchAndFamily = VARIABLE_PITCH|FF_ROMAN PUSH 2 ; ?Quality = PROOF_QUALITY PUSH 0 ; ?ClipPrecision = CLIP_DEFAULT_PRECIS PUSH 0 ; ?OutputPrecision = OUT_DEFAULT_PRECIS PUSH 0 ; ?CharSet = ANSI_CHARSET PUSH 0 ; ?StrikeOut = FALSE PUSH 0 ; ?Underline = FALSE PUSH EAX ; ?Italic => TRUE PUSH 190 ; ?Weight = FW_NORMAL PUSH 0 ; ?Orientation = 0 PUSH 0 ; ?Escapement = 0 PUSH 0 ; ?Width = 0 PUSH 10 ; ?Height = 10 (16.) CALL <JMP.&GDI32.CreateFontA> ; ?CreateFontA 顯然,後面的程式碼更容易理解。API函數CreateFont 有14個參數。分析器標記所有這些參數的名稱並解碼他們的值。如果暫存器跟蹤開啟,那麼分析器同時會解碼參數Italic 的值為位址49FA70處雙字長的內容。解碼使用參數的真實值,所以如果[49FA70]裡的內容改變了,那麼參數Italic的值也會隨之改變。當EIP指向跳轉或使用該函數的指令,或指向入口時,OllyDbg也會在棧中對已知函數的參數進行解碼。 OllyDbg可以對象printf()這樣參數個數可變的函數進行參數解碼: PUSH EAX ; ?<%.*s> PUSH E8 ; ?<*> = E8 (232.) PUSH EBX ; ?<%08X> PUSH Mymodule.004801D2 ; ?format = "Size %08X (%.*s) bytes" PUSH ESI ; ?s CALL Mymodule.sprintf ; ?sprintf 您可以定義自己的函數。每次您開啟某個應用程式時,OllyDbg都會重新設定函數參數表並用內嵌描述添充這個表。然後嘗試開啟文件「<OllyDbg目錄>\common.arg」和「<OllyDbg目錄>\<應用程式名>.arg」,這裡<應用程式名>使用8.3格式(DOS)被偵錯程式文件名(不帶路徑和副檔名)。 下面看一個簡單的.arg文件實例: INFO Simple .ARG file that decodes CreateHatchBrush TYPE HS_X IF 0 "HS_HORIZONTAL" IF 1 "HS_VERTICAL" IF 2 "HS_FDIAGONAL" IF 3 "HS_BDIAGONAL" IF 4 "HS_CROSS" IF 5 "HS_DIAGCROSS" ELSEINT END TYPE COLORREF IF 0 "<BLACK>" IF 00FFFFFF "<WHITE>" OTHERWISE TEXT "RGB(" FIELD 000000FF UINT TEXT "," FIELD 0000FF00 UINT TEXT "," FIELD 00FF0000 UINT TEXT ")" END STDFUNC CreateHatchBrush "style" HS_X "colorref" COLORREF END 標準Windos API函數CreateHatchBrush(int style,int colorref) 有兩個參數。第一個必須是陰影風格〔hatch style〕,第二個是常量由紅色、綠色、藍色組成,並用一個32 位整數的低三字元表示。為瞭解碼這些參數,文件定義了兩個新的參數檔案類型:HS_X 和 COLORREF。 陰影風格是一個簡單的枚舉檔案類型,如0表示HS_HORIZONTAL(水準風格)、1表示HS_VERTICAL(垂直風格)。IF關鍵字比較參數與第一個操作數(注意:其總是十六進制的),如果相同則顯示第二個操作數里的文本。但萬一匹配失敗會如何?關鍵字ELSEINT 會然OllyDbg會將參數解釋為一個整數。 COLORREF 更複雜一些。首先嘗試解碼兩個廣泛使用的顏色值:黑(全0組成)與白(全0xFF組成)。如果匹配失敗,COLORREF嘗試解碼顏色為一個結構包含紅、綠、藍的亮度。FIELD會用第一個操作數與參數進行邏輯與操作。然後轉換結果為整數,並同時按位右移第一個操作及該整數,直到第一個操作數的二進制個位數位為1,這時整數按位右移的結果以無符號10進制顯示出來。這個例子做了三次這樣的操作,以分離出每個顏色成份。TEXT關鍵字用於無條件顯示文本。如果參數為00030201,那麼 COLORREF將其解碼為RGB(1.,2.,3.)。 大多斷API函數都會從棧中移除參數並保護暫存器EBX, EBP, ESI 和 EDI。宣告這樣的函數為STDFUNC,以告訴分析器該函數做了這樣的事情。否則請其描述為FUNCTION 。 萬一某個參數由多個域及位元 值組成,比如上面提到的fdwPitchAndFamily ,我們該怎麼辦?請看下面這個例子: TYPE FF_PITCH MASK 03 IF 00 "DEFAULT_PITCH" IF 01 "FIXED_PITCH" IF 02 "VARIABLE_PITCH" ELSEHEX TEXT "|" MASK 0C BIT 04 "4|" BIT 08 "8|" MASK FFFFFFF0 IF 00 "FF_DONTCARE" IF 10 "FF_ROMAN" IF 20 "FF_SWISS" IF 30 "FF_MODERN" IF 40 "FF_SCRIPT" IF 50 "FF_DECORATIVE" ELSEHEX END 前兩個位元 位(第0和等1位)表示傾斜度,必須一起解碼。我們使用 MASK 03 來抽取這兩個位元 並通過IF序列來解碼。增加了連接符「|」,分別抽取第2和第3個位元 位,並分別單獨解碼。最後抽取剩餘部分並進行解碼。 OllyDbg 會移除產生串尾部的連接符「|」、空格、冒號、逗號、分號和等號。 目前版本的分析僅能夠解碼32位參數。如您不能解碼雙精度浮點或長雙精度浮點的函數參數。 格式描述 自訂解碼訊息由函數描述和檔案類型描述兩部分組成。函數描述部分非常的簡單: FUNCTION|STDFUNC [模組名]函數名 <第一個參數的名稱> <第一個參數的檔案類型> …… <最後一個參數的名稱> <最後一個參數的檔案類型> END 如果函數從棧中移除參數並保護暫存器EBX, EBP, ESI 和 EDI,請使用關鍵字STDFUNC。大多少函數都遵循這樣的規則。其他情況則宣告為FUNCTION。模組(EXE 或 DLL)名是可選的。如果模組名被忽略,OllyDbg會對嘗試匹配任何模組。模組名不區分大小寫。 函數名稱總是區分大小寫的。有針對UNICODE的函數必須使用後面 A 或 W 加以區分,比如SetWindowTextA.。 參數的順序又C風格的參數使用慣例一致。而16位Windows和32位API函數也是按慣例使用。如果參數名由多個字組成,或者包含特殊字串,那麼請將其用兩個單引號引起來。與在C語言中一樣,省略號(參┤且桓鎏厥獾募鍬加糜詒硎靜問靠殺洹K匭朐諍枋齙淖詈蟆llyDbg不會嘗試解碼這樣的參數。如果函數的參數為空,則按functionname(void)對待 OllyDbg 僅支持32位的參數。某些參數已經預定義好了: INT 以十六進制和帶符號整數兩種格式顯示值 UINT 以十六進制和無符號整數兩種格式顯示值 HEX 以十六進制格式顯示值 BOOL TRUE 或 FALSE CHAR ASCII 字串 WCHAR UNICODE 字串 FLOAT 32位浮點數 ERRCODE 系統錯誤程式碼(像由函數GetLastError()報告的) ADDR, PTR 位址(特殊情況:NULL) ASCII ASCII 串游標 UNICODE UNICODE 串游標 FORMAT 在類似函數printf()(不包括wscanfW()!)使用的 ASCII 格式串 WFORMAT 類似函數wsprintfW()(不包括scanf()!)使用的 UNICODE 格式串 RECT RECT(矩形)結構游標 MESSAGE MSG(ASCII 視窗消息)結構游標 WMESSAGE MSG(UNICODE 視窗消息)結構游標 HANDLE 關鍵句(特殊情況:NULL, ERROR_INVALID_HANDLE) HWND 視窗關鍵句 HMODULE 模組關鍵句 RSRC_STRING 帶索引的資源串 NULL, DUMMY 有參數,但解碼時跳過了 您不能重定義預定義檔案類型。自訂檔案類型允許您將參數分離成幾個域並分別解碼。檔案類型描述有以下幾種格式: TYPE 檔案類型名 [TEXT "任何文本"] [<域選項器>] <域解碼> <域解碼> [TEXT "任何文本"] [PURGE] ... <域選項器> <域解碼> <域解碼> [TEXT "任何文本"] END 檔案類型名的程度限制在16個字串以內。 OllyDbg會無條件將"任何文本"作為產生的解碼。域選項器抽取一部分參數用於解碼。以下域選項器,可以用於抽取域: MASK 十六進制掩碼 - 域等於參數同十六進制掩碼按位與(AND)的結果。 FIELD 十六進制掩碼 - 參數同十六進制掩碼按位與(AND)的數值,然後OllyDbg同時按位右移掩碼和計算的數值直到掩碼的二進制個位為1,這時數值按位右移的結果就是域的值。例如參數0xC250, FIELD F0,得到的結果是5。 SIGFIELD十六進制掩碼 -參數同十六進制掩碼按位與(AND)的數值,然後OllyDbg同時按位右移掩碼和計算的數值直到掩碼的二進制個位為1,這時數值按位右移的結果轉成帶符號32位數就是域的值。例如參數0xC250 ,SIGFIELD FF00,得到的結果是0xFFFFFFC2。 簡單域的解碼會一次顯示整個域的內容: HEX - 以十六進制形式顯示域內容; INT - 以帶符號十進制形式顯示域內容(帶小數點); UINT -以無符號十進制形式顯示域內容(帶小數點); CHAR - 以 ASCII 字串形式顯示域內容。 域若是一個枚舉檔案類型,則可以使用IF序列,如果必要的話還可以在IF序列後跟關鍵字 TRYxxx 與 ELSExxx: IF 十六進制值 "文本" - 如果域等於十六進制值,則將文本作為輸出字串串; TRYASCII - 如果域是一個指向ASCII串的游標,則顯示這個串; TRYUNICODE - 如果域是一個指向UNICODE串的游標,則顯示這個串; TRYORDINAL - 如果域是一序號(有16位均為0),則會顯示為序號(「#」後跟整數); OTHERWISE - 如果前面IF語句為真,則停止解碼,否則繼續解碼; ELSEINT - 如果前面所有的 IF 和 TRYxxx 語句均失敗,則以帶符號十進制數形式(帶小數點)顯示這個域; ELSEHEX -如果前面所有的 IF 和 TRYxxx 語句均為失敗,則以十六進制形式顯示這個域; ELSECHAR -如果前面所有的 IF 和 TRYxxx 語句均為失敗,則以 ASCII 字串形式顯示這個域; ELSEWCHAR -如果前面所有的 IF 和 TRYxxx 語句均為失敗,則以 UNICODE 字串形式顯示這個域。 如果域是一個二進制位集,則可以使用BIT序列,如果必要的話可以後面跟關鍵字 BITZ 與 BITHEX : BIT 十六進制掩碼 "文本" - 如果值與十六進制掩碼按位與(AND)的結果不是0,則將文本做為輸出串; BITZ十六進制掩碼 "文本" - 如果值與十六進制掩碼按位與(AND)的結果是0,則將文本做為輸出串; BITHEX十六進制掩碼 - 如果值與十六進制掩碼按位與(AND)的結果不是0,則將結果以十六進制形式顯示。 特殊關鍵字 PURGE 會從輸出串尾部移除以下幾種符號: 空格 ' ' 逗號 ',' 或 '|' 冒號 ':' 等於 '=' 這會讓某些解碼情況變的簡單。關鍵字END是檔案類型定義結尾標記並會自動執行PURGE指令。 預編譯檔案類型 OllyDbg在預編譯資源時,已經包含150多種檔案類型描述。以下列出了一部分。您可以在自訂文件中直接使用這些檔案類型: LANG_X - 作業系統語言ID(0 - 未知、 9 - 語言、 C - 法語,等等) GENERIC_X - 訪問檔案類型(GENERIC_READ, GENERIC_WRITE...) FILE_SHARE_X - 共享檔案類型(FILE_SHARE_READ, FILE_SHARE_WRITE) CREATEFILE_X - 文件新增模式(CREATE_NEW, OPEN_EXISTING...) FILE_ATTRIBUTE_X - 文件內容(READONLY, SYSTEM, DELETE_ON_CLOSE...) RT_AXX - 資源檔案類型(RT_CURSOR, RT_GROUP_ICON, ASCII string...) RT_WXX - 資源檔案類型(RT_CURSOR, RT_GROUP_ICON, UNICODE string...) COORD - 坐標結構 "(X=xxx,Y=yyy)" STD_IO_X - 標準關鍵句(STD_INPUT_HANDLE, STD_ERROR_HANDLE...) GMEM_X - 全局記憶體檔案類型(GMEM_FIXED, GPTR...) LMEM_X - 局部記憶體檔案類型(LMEM_FIXED, LPTR...) FSEEK_X - 文件尋找檔案類型(FILE_BEGIN, FILE_CURRENT...) OF_X - 文件模式(fOF_READ, OF_SHARE_COMPAT, OF_VERIFY...) O_X - 文件新增模式(O_RDONLY, O_BINARY, SH_COMPAT...) SEMAPHORE_X - 信號量檔案類型(SEMAPHORE_ALL_ACCESS, SYNCHRONIZE...) SLEEP_TIMEOUT - 超時(INFINITE 或時間) ROP - 一些標準柵格運算標誌程式碼(ROP)(SRCCOPY, MERGEPAINT...) COLORREF - RGB 顏色值("<WHITE>", "RGB(rr.,gg.,bb.)"...) WS_X - 視窗風格(WS_OVERLAPPED, WS_POPUP...) WS_EX_X - 增強視窗風格(WS_EX_DLGMODALFRAME, WS_EX_TOPMOST...) MF_X - 表單標誌(MF_BYPOSITION, MF_ENABLED...) WM_X - ASCII視窗消息檔案類型(WM_CREATE, WM_KILLFOCUS, CB_SETCURSEL...) WM_W - UNICODE視窗消息檔案類型(WM_CREATE, WM_KILLFOCUS, CB_SETCURSEL...) VK_X - 虛擬鍵盤程式碼(VK_LBUTTON, VK_TAB, VK_F10...) MB_X - message box style (MB_OK, MB_ICONHAND...) HKEY_X - 預定義註冊表關鍵句(HKEY_CLASSES_ROOT, HKEY_LOCAL_MACHINE...) 還有更多的預編譯檔案類型。如果常量在它文件被定義為ABC_ xxxxxxxx,那麼一般就有ABC_X預編譯檔案類型。 注意: 1.如果OllyDbg是即時偵錯器,並且在Windows 95下掛接執行了DebugBreak() 的應用程式,則這個應用程式在掛接後,還會執行。在關於NT的系統下,應用程式應該會在 DebugBreak()暫停。 2. 指令 SMSW (儲存機器狀態字〔Store Machine Status Word〕)。 這個指令僅接受暫存器 AX 作為參數,而程序編譯成EAX接受參數。 |
送花文章: 3,
|
向 psac 送花的會員:
|
Jamaalacugs (2018-04-20)
感謝您發表一篇好文章 |