OLLYDBG是一個新的動態追蹤工具,將IDA與SoftICE結合起來的思想,Ring 3級調試器,非常容易上手,己代替SoftICE成為當今最為流行的調試解密工具了。同時還支持外掛程式擴展功能,是目前最強大的調試工具。
基本介紹
- 中文名:OLLYDBG
- 外文名:OLYDBG
- 類別:軟體
- 平台:Windows
- 編寫:C++ Builder
界面構成,詳細介紹,常見問題,
界面構成
OllyDbg發行版是一個ZIP壓縮檔,只要解壓運行OllyDbg.exe即可。運行OllyDbg打開進程,主視窗顯示反彙編清單。各視窗的外觀屬性如:“標題欄(bar)、字型(font)”等在右鍵選單"界面選項(appearance)"里控制
代碼視窗
代碼視窗(OllyDbg幫助檔案自稱反彙編視窗)顯示被調試程式的代碼。他有四個列
最後一列注釋(Comment)顯示相關API參數或運行簡表,非常有用,有點類似於IDA Pro。
在代碼視窗(地址行,不是列標題)雙擊時完成動作。
●地址(Address)列:顯示相對被雙擊地址的地址,再次雙擊返回標準地址模式;
●HEX數據(HEX dump)列:設定或取消無條件斷點,按F2鍵也能設定斷點;
●反彙編(Disassembly)列:調試編輯器,可直接修改彙編代碼;
●注釋(Comment)列:允許增加或編輯注釋。
信息視窗(Information window)
動態跟蹤時,與指令相關的各暫存器的值、API函式調用提示、跳轉提示等信息顯示。
數據視窗
以十六進制或記憶體方式顯示檔案在內容中的數據,類似於softICE的數據視窗。要顯示數據可單擊右鍵"轉到→表達式(Go to→expression)"或按Ctrl+G鍵打開地址視窗,輸入地址。
暫存器(Registers window)
顯示CPU各暫存器的值,支持浮點(FPU)、MMX,3DNow!暫存器,可以單擊滑鼠右鍵切換。
堆疊視窗(Stack window)
堆疊視窗非常重要,各API函式、子程式等都利用它傳遞參數、變數等。OllyDbg堆疊視窗功能強大。如果傳遞的參數都是字元串,OllyDbg會在注釋里直接將其顯示出來,再也不用像SoftICE那樣經常用D命令查看記憶體數據了。
詳細介紹
運行環境:OllyDbg 可以以在任何採用奔騰處理器的 Windows 95、98、ME、NT 或是 XP(未經完全測試)作業系統中工作,但我們強烈建議您採用300-MHz以上的奔騰處理器以達到最佳效果。還有,OllyDbg 是極占記憶體的,因此如果您需要使用諸如追蹤調試[Trace]之類的擴展功能話,建議您最好使用128MB以上的記憶體。
* 目前測試 OllyDbg 可以運行在任意Windows x86架構的平台下。
配置:有多達百餘個選項用來設定 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 會自動運行一個可執行程式。這個程式會載入程式庫,並允許您調用程式庫的輸出函式。
FPU/SSE、段/系統暫存器、在棧或記憶體中的運算元,常量)。您可以定製個性化高亮方案。
執行緒:OllyDbg 可以調試多執行緒程式。因此您可以在多個執行緒之間轉換,掛起、恢復、終止執行緒或是改變執行緒優先權。並且執行緒視窗將會顯示每個執行緒的錯誤(就像調用 GETLASTERROR 返回一樣)。
分析:OllyDbg 的最大特點之一就是分析。它會分析函式過程、循環語句、選擇語句、表[tables]、常量、代碼中的字元串、欺騙性指令[tricky constructs]、API調用、函式中參數的數目,import表等等.. 這些分析增加了二進制代碼的可讀性,減少了出錯的可能性,使得我們的調試工作更加容易。
Object掃描。OllyDbg 可以掃描Object檔案/庫(包括 OMF 和 COFF 格式),解壓代碼段[code segments]並且對其位置進行定向。
Implib掃描。由於一些DLL檔案的輸出函式使用的索引號,對於人來說,這些索引號沒有實際含義。如果您有與DLL相應的輸入庫[import library],OllyDbg 就可以將序號轉換成符號名稱。
完全支持Unicode:幾乎所有支持 ASCⅡ 的操作同時也支持 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 箇中斷。
監視與監察器:每個監視都是一個表達式並能實時顯示表達式的值。您可以使用暫存器、常數、地址表達式、布爾值以及任何複雜代數運算,您還可以比較ASCⅡ和UNICODE
字元串。監察器[inspectors]是一種包含了兩個的索引序列的監視[Watches],它以二維表的形式呈現,可以對數組和結構進行解碼分析。
Heap walk.:在基於Win95的系統中,OllyDbg 可以列出所有的已分配的堆。
句柄:在基於NT的系統中,OllyDbg 可列出被調試程式的所有系統句柄。
執行:.您可以單步執行、步入子程式或者步過子程式。您也可以執行程式直到函式返回時、執行到指定地址處,還可以自動執行。當程式運行時,您仍然可以操縱程式並能夠查看記憶體、設定斷點甚至修改代碼。您也可以任意的暫停或重啟被調試的程式。
Hit跟蹤:.Hit跟蹤可以顯示出目前已執行的指令或函式過程,幫助您檢驗代碼的各個分支。Hit跟蹤會在指定指令到達之前設定斷點,而在這個指令執行後,會把這個斷點清除掉。
譯者註:Hit在英文中是“擊中”的意思,指令如果運行了就表示這個指令被“擊中”了,沒有執行的指令就是“未擊中”,這樣我們就很容易看出被調試程式哪些部分運行了,而哪些沒有運行。
Run跟蹤:Run跟蹤可以單步執行程式,它會在一個很大的循環緩衝區中模擬運行程式。這個模擬器包含了除了SSE指令集以外的所以暫存器、標誌、執行緒錯誤、訊息、已經函式的參數。您可以保存命令,這樣可以非常方便地調試自修改代碼(譯者註:比如加殼程式)。您可以設定條件中斷,條件包括地址範圍、表達式、命令。您可以將Run
跟蹤信息保存到一個檔案中,這樣就可以對比兩次運行的差別。Run跟蹤可以回溯分析已執行過的上百萬條命令的各種細節。
OllyDbg完全支持 UNICODE,幾乎所有對 ASCⅡ字元串的操作都可以同樣套用於 UNICODE。
彙編指令都是很相似的。您經常會搞不清自己是不是已經跟蹤過某一段代碼。在 OllyDbg 中您可以加入自己的標籤[labels]和注釋[comments]。這些極大地方便了調試。注意一旦您注釋了某個DLL,以後每次載入這個DLL時,注釋和標籤都有效----儘管您在調試不同的程式。
]是不可能的。當程式運行到已知的函式時,棧視窗[stack window]解析它的參數,調用棧[Call stack]視窗顯示到達當前位置所調用函式的序列。
多種不同的搜尋[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位擴展作業系統無法實現某些必需的調試功能。
函式[Procedure](或 函式/參數[Procedure / arguments])顯示了被調用函式的地址,在某些情況下,OllyDbg並不能保證該地址是正確的並會添加如下標記之一:
找到的入口點不可靠
可能[Maybe] OllyDbg無法找到精確的入口點,報告的地址是用啟發式算法猜測的。
包含[Includes] OllyDbg無法找到入口點,僅知道該函式包含顯示的地址
通過按例標題欄上的按鈕或從選單中選擇“隱藏/顯示參數[Hide/Show arguments]”,可以在顯示或隱藏函式的參數之間切換。
調用來自[Called from]用於顯示調用該函式的命令地址。最後一欄是框架[Frame]這一欄默認是隱藏的,如果框架指針的值(暫存器EBP)已知的話,則該欄用於顯示這個值。
當調用函式經過分析[analyzed].後,棧移動會更可靠並且迅速。十六,調用樹[Call tree]
調用樹(快捷鍵:在反彙編視窗中Ctrl+K)利用分析[Analysis]的結果來找出指定函式過程直接或間接調用的函式列表,同時列出指定函式過程被調用的地址。為了避免由此可能造成的副作用。調用樹會判斷選定函式是否明確地是遞歸的。“明確地”意味著它不會跟蹤目標未知的調用,比如CALL EAX。如果函式過程中有未知調用,調用樹將會添加標記“未知目標”。
某些函式調用將會添加如下注釋之一:
當自解壓選項[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]
如果被調試程式停在異常上,您可以跳過它,並轉到被調試程式建立的句柄處。只需簡單的 Shift 鍵和任何一個單步命令。
如果需要連續按F7、F8鍵上百次,您可以使用自動執行(Ctrl+F7或者Ctrl+F8)功能。在這種情況下,OllyDbg 將自動重複F7或者F8操作,並且實時更新所有的視窗。這個過程會在下面情況停止:
- 按 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跟蹤也會同時退出。
[color=blue]Run 跟蹤[Run trace][/color]
Run跟蹤是一種反方向跟蹤程式執行的方式,可以了解以前發生的事件。您還可以使用Run跟蹤來了解運行的簡單統計[profile]。基本上,OllyDbg 是一步一步地執行被調試程式的,就像動畫[animation]演示一樣,但不會實時刷新視窗,最重要的是它能將地址、暫存器的內容、訊息以及已知的運算元記錄到Run跟蹤緩衝區中。如果被調試的代碼是自修改的,您就能夠保存原始的命令。可以通過按Ctrl+F11(Run跟蹤步入,進入子函式)或者Ctrl+F12(Run跟蹤步過,一次執行完子函式)開始Run跟蹤,並用F12或者Esc鍵停止跟蹤。
您可以指定在Run跟蹤時執行每一步的條件集(快捷鍵:Ctrl+T)。如果條件符合,Run跟蹤將暫停。條件包括:
當CPU視窗中的反彙編面板[Disassembler pane]處於激活狀態時,您可以使用以下快捷鍵:
回車鍵- 將選中的命令添加到命令歷史[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 的主頁上([url]http://home.t-online. de/home/Ollydbg[/url])免費下載外掛程式開發工具包
plug110.zip。
外掛程式可以設定斷點,增加標籤和注釋,修改暫存器和記憶體。外掛程式可以添加到主選單和很多的視窗(比如反彙編視窗、記憶體視窗)的快捷選單中,也可以攔截快捷鍵。外掛程式還可以創建MDI(多文檔界面)視窗。外掛程式還可以根據模組信息和OllyDbg.ini檔案,將自己數據寫到.udd檔案中;並能讀取描述被調試程式的各種數據結構。外掛程式API包含了多達170
個函式。
許多第三方外掛程式都可以從Internet網上獲得,比如由網友TBD創建並維護的OllyDbg的論壇([url]http://ollydbg.win32asmcommunity. net[/url])。
安裝外掛程式的方法:將DLL複製到外掛程式目錄[plugin directory]中,然後重新啟動Ollydbg。默認情況下,這個外掛程式目錄為ollydbg.exe檔案所在的目錄。
現在的版本中已經包含了兩個“原始”外掛程式:書籤[Bookmark] and 命令行[Command line]. 他們的原始碼都保存在plug110.zip.檔案中。這些外掛程式都是免費的,您可以任意修改或使用它們。
[color=blue]技巧提示[Tips and tricks][/color]
?OllyDbg 可以作為二進制編輯器使用。選擇視圖[View]→檔案[File]並選定需要查看的檔案。檔案不能大於剩餘記憶體數量。
?假使您修改了記憶體中的執行檔案,這時您想恢復修改的部分,但是您忘記哪裡被修改了,您可以把原始檔案當作備份進行載入,這樣您就可以找到修改的部分了。
分析前,先掃描 OBJ 檔案。這時 OllyDbg 會對已知 C 函式的參數進行解碼。
一些表格中包含了隱藏數據。可以通過增加列寬來顯示出來。
所有數據視窗(包括反彙編視窗),可以通過雙擊顯示相對的地址。
您可以通過 Ctrl +↑ 或 Ctrl+↓ 對數據視窗翻動一個位元組。
[color=darkblue]調試獨立的DLL[Debugging of stand-alone DLLs][/color]
現在,您可以調用DLL函式。從主選單選擇“調試[Debug]|調用DLL輸出[Call DLL export]”。這時會彈出一個對話框。由於這個對話框是無模式對話框,因此您仍然能夠使用OllyDbg的全部功能,比如查看代碼、數據,查看斷點,修改記憶體等等。
選擇您想調用的函式。例如我們將開始使用 USER32.DLL 里的MessageBox 函式。注意loaddll.exe 已經使用了這個程式庫,因此會假定這個 DLL 已經初始化而不再調用入口。MessageBox 這個函式名是通用函式名,實事上,這個函式有處理 ASCⅡ 的 MessageBoxA 和處理 Unicode 的MessageBoxW 兩種。我們繼續往下看:在我們選擇這個函式後,右邊的訊息框中會出現 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 ;
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 函式。
函式 MessageBoxW 不會修改參數。如果您調用的函式更新了記憶體,比如函式 GetWindowName,修改的位元組將會在數據區里高亮。注意:EAX 返回值為1,表示成功。
不幸的是,您不能通過這種方式調試OllyDbg的外掛程式,外掛程式關聯到ollydbg.exe檔案,Windows系統不能在同一個應用程式里載入並運行兩個執行檔。
[color=blue]解碼提示[Decoding hints][/color]
在某些情況下,分析器不能區分代碼和數據。讓我們看看下面的例子:
const char s[11] = "0123456789";
...
for (i=0x30; i記憶體中間碼
記憶體中間碼 = 中間碼| { 符號標誌 大小標誌 前綴} [表達式]
一元操作符 = ! | ~ | + |
帶符號暫存器 = 暫存器.
暫存器= AL | BL | CL ... | AX | BX | CX ... | EAX | EBX | ECX ...
FPU暫存器 = ST | ST0 | ST1 ...
段暫存器= CS | DS | ES | SS | FS | GS
整型常量 = . | | |
浮點常量 =
串常量 = ""
符號標誌 = 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 ; ASCⅡ "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
這是分析後的:
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 ;CreateFontA
顯然,後面的代碼更容易理解。API函式CreateFont 有14個參數。分析器標記所有這些參數的名稱並解碼他們的值。如果暫存器跟蹤開啟,那么分析器同時會解碼參數Italic
的值為地址49FA70處雙字長的內容。解碼使用參數的真實值,所以如果[49FA70]里的內容改變了,那么參數Italic的值也會隨之改變。當EIP指向跳轉或調用該函式的命令,或指向入口時,OllyDbg也會在棧中對已知函式的參數進行解碼。
OllyDbg可以對像printf()這樣參數個數可變的函式進行參數解碼:
PUSH EAX ;
PUSH E8 ; = E8 (232.)
PUSH EBX ;
PUSH Mymodule.004801D2 ;format = "Size %08X (%.*s) bytes"
PUSH ESI ;s
CALL Mymodule.sprintf ;sprintf
您可以定義自己的函式。每次您打開某個應用程式時,OllyDbg都會重新設定函式參數表並用內嵌描述添充這個表。然後嘗試打開檔案“\common.arg”和“\.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 ""
IF 00FFFFFF ""
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 "FⅨED_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_DECORATⅣE"
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語言中一樣,OllyDbg不會嘗試解碼這樣的參數。如果函式的參數為空,則按functionname(void)對待
OllyDbg 僅支持32位的參數。某些參數已經預定義好了:
INT ;以十六進制和帶符號整數兩種格式顯示值
UINT ;以十六進制和無符號整數兩種格式顯示值
HEX ;以十六進制格式顯示值
BOOL TRUE 或 FALSE
CHAR ASCⅡ 字元
WCHAR UNICODE字元
FLOAT 32位浮點數
ERRCODE 系統錯誤代碼(像由函式GetLastError()報告的)
ADDR,PTR ;地址(特殊情況:NULL)
ASCⅡ ASCⅡ 串指針
UNICODE UNICODE 串指針
FORMAT 在類似函式printf()(不包括wscanfW()!)使用的 ASCⅡ 格式串
WFORMAT 類似函式wsprintfW()(不包括scanf()!)使用的 UNICODE 格式串
RECT RECT(矩形)結構指針
MESSAGE MSG(ASCⅡ 視窗訊息)結構指針
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 - 以 ASCⅡ 字元形式顯示域內容。
域若是一個枚舉類型,則可以使用IF序列,如果必要的話還可以在IF序列後跟關鍵字 TRYxxx 與 ELSExxx:
IF 十六進制值 "文本" - 如果域等於十六進制值,則將文本作為輸出字元串;
TRYASCⅡ - 如果域是一個指向ASCⅡ串的指針,則顯示這個串;
TRYUNICODE - 如果域是一個指向UNICODE串的指針,則顯示這個串;
TRYORDINAL - 如果域是一序號(有16位均為0),則會顯示為序號(“#”後跟整數);
OTHERWISE - 如果前面IF語句為真,則停止解碼,否則繼續解碼;
ELSEINT - 如果前面所有的 IF 和 TRYxxx 語句均失敗,則以帶符號十進制數形式(帶小數點)顯示這個域;
ELSEHEX -如果前面所有的 IF 和 TRYxxx 語句均為失敗,則以十六進制形式顯示這個域;
ELSECHAR -如果前面所有的 IF 和 TRYxxx 語句均為失敗,則以 ASCⅡ 字元形式顯示這個域;
ELSEWCHAR -如果前面所有的 IF 和 TRYxxx 語句均為失敗,則以 UNICODE 字元形式顯示這個域。
如果域是一個二進制位集,則可以使用BIT序列,如果必要的話可以後面跟關鍵字 BITZ 與 BITHEX :
BIT 十六進制掩碼 "文本" - 如果值與十六進制掩碼按位與(AND)的結果不是0,則將文本做為輸出串;
BITZ十六進制掩碼 "文本" - 如果值與十六進制掩碼按位與(AND)的結果是0,則將文本做為輸出串;
BITHEX十六進制掩碼 - 如果值與十六進制掩碼按位與(AND)的結果不是0,則將結果以十六進制形式顯示。
常見問題
怎樣保存ollydbg的調試信息以便下次使用?
調試選單->;選擇符號路徑 然後在彈出的對話框設定路徑即可。注意調試檔案為udd格式,,當被調試檔案路徑發生變化時調試信息不再可用,,比如:你在C糟有一個檔案用ollydby調試並加入注視或斷點後,,把這個檔案移到別的路徑下,再用ollydbg打開調試信息注視和斷點不被顯示。
注意:斷點和注釋視窗只能查看到當前模組的斷點和注釋,且當前被ollydbg分析為代碼的斷點和注釋才能被看到。