文章一:http://blog.csdn.net/wowolook/article/details/7607206
1.前言
在我跨入ollydbg的門的時候,就對ollydbg里面的各種斷點充滿了疑問,以前我總是不明白普通斷點,內存斷點,硬件斷點有什么區別,他們為什么有些時候不能混用,他們的原理是什么,在學習了前輩們的文章以后,終於明白了一些東西。希望這篇文章能讓你對硬件斷點的原理和使用有一些幫助
2.正文
--------------------------------------------------
i.硬件斷點的原理
在寄存器中,有這么一些寄存器,它們用於調試。人們把他們稱為調試寄存器,調試寄存器一共有8個名字分別從Dr0-Dr7。所以我們也把調試寄存器簡單的稱為Drx。
對於Dr0-Dr3的四個調試寄存器,他們的作用是存放中斷的地址,例如:401000
對於Dr4,Dr5這兩個寄存器我們一般不使用他們,保留
對於Dr6,Dr7這兩個寄存器的作用是用來記錄你在Dr0-Dr3中下斷的地址的屬性,比如:對這個401000是硬件讀還是寫,或者是執行;是對字節還是對字,或者是雙字。
好了,從這里你可能明白一些東西。
1. 為什么在OD里面只能下4個硬件斷點?
2. 為什么下硬件斷點有byte,word,dword只分?
3. 為什么下硬件斷點有讀,寫,執行只分?
ii.關於F4,F8,F7,F2的區別
在ollydbug的help里面只是提到如何使用F7和F8的使用,並沒說明他們的實現原理
現在我們來做一個實驗
實驗一(F4的原理)
1.隨便找一個程序,載入OD,構造一個死循環
就象這樣:
00400154 > 90 nop //EP停在這里
00400155 90 nop
00400156 90 nop
00400157 90 nop
00400158 ^ EB FA jmp short 天2國際.<ModuleEntryPoint> //構造一個死循環
0040015A 61 popad
0040015B 94 xchg eax,esp
2.對0040015A這一行按下F4,由於死循環,程序一直運行
3.調試器的窗口里,右鍵--查看調試寄存器
結果在Drx里面顯示:
DR0 0040015A //地址
DR1 00000000
DR2 00000000
DR3 00000000
DR6 FFFF0FF0 //斷點屬性
DR7 00000401
實驗二(F8原理)
1.隨便找一個程序,載入OD,構造一個子程序的死循環
就像這樣
00400154 t> E8 0100D03F call 4010015A //EP,停在這里
00400159 90 nop
0040015A 90 nop
0040015B 90 nop
0040015C 90 nop //對這里下F2斷點
0040015D C3 retn // 返回
2.按下F8,由於INT3斷點,程序中斷在0040015C
3.調試器的窗口里,右鍵--查看調試寄存器
結果在Drx里面顯示:
DR0 00400159 //call的返回地址
DR1 00000000
DR2 00000000
DR3 00000000
DR6 FFFF4FF1 //斷點屬性
DR7 00000401
實驗三(F7原理)
1.隨便找一個程序,載入OD
2.雙擊調試器的窗口里的T標志,將TF從原來的0變成1
3.F9運行
結果程序斷在了下面的一行
實驗四(F2的原理)
1.用98的notepad吧,載入OD,構造一個死循環
004010CC N> 90 nop //EP,挺在這里
004010CD 90 nop
004010CE ^ EB FC jmp short NOTEPAD.<ModuleEntryPoint> //死循環
004010D0 90 nop //在這里按下F2,普通斷點
004010D1 90 nop
2.按下F9,由於死循環,程序一直運行着
3.使用LordPE(不要用ollydump)將這個程序dump下來
4.重新載入OD
來看看成什么樣子了
004010CC d> $ 90 nop
004010CD . 90 nop
004010CE .^ EB FC jmp short dumped.<ModuleEntryPoint>
004010D0 CC int3 //這里變成了CC了
004010D1 90 nop
--------------------------------------------------
3.總結
從實驗一和實驗二我們能清楚的看到,F4是直接將該行的地址放入drx里面,F8是將下一行的地址放入到drx里面,他們都使用了調試寄存器。從實驗三中我們知道對於F7來說很可能使用的是將TF置一的辦法,也就是說當我們按下F7的時候OD把TF置一。對於F2來說他是將,第一個字節悄悄的修改成了CC,雖然並沒有顯示給我看到這個是一個CC,當我們按下F2的時候,OD還沒有運行,只是把這個表示記錄下來,當運行的時候他就把所有標記的字節修改了,盡管還是顯示原來的代碼,當然當他一暫停下來就又修改回來了。
上面的是實驗中,F7的原理只是猜測,還沒有很好的辦法能證明他就是使用TF,下面我繼續猜測一下內存斷點的原理
1.將設置的內存斷點的地址記錄下來
2.對這個地址的內存頁面修改其屬性
如果是內存寫斷點,就修改為RE(可讀,可執行)
如果是內存訪問斷點,就修改為NO ACCESS(不可訪問)
3.只要訪問到這個頁面就會產生相應的異常,然后由OD來判斷是否與記錄的斷點一致,從而是否中斷下來
--------------------------------------------------
4.后話
對於上面的F7和內存斷點的原理,我還沒想出什么好的辦法去找出OD的原理,或許去調試一下ollydbg.exe是一個不錯的建議。如果有哪位兄弟知道有什么好辦法,希望能告訴我。當然也很歡迎各位和我討論。
文章二:http://www.voidcn.com/blog/nightsay/article/p-3414045.html
今天繼續接着上次的分析,來繼續分析OD原理,這次先分析OD最基本的功能,斷點,單步和運行到指定位置。
類似的文章前輩們已經寫了很多了,這里只是將前輩們的思路實踐了一下,順便加入一點自己的理解和認識!
一般載入OD之后,往往大家會先下斷點,或者直接單步運行。
一般當我們着手分析一個程序的時候總是會下一個INT 3斷點,其實這個就是F2的原理
隨便載入一個程序,點一下F2,然后用ollydbg保存的時候,發現提示說是文件未被修改,其實這個也能理解,因為我們按下F2的時候,程序還沒被運行,所以dump下來吧,但是dump需要要求程序連同f2能夠斷下,所以改一下程序:
構建一個這樣的死循環,這樣,程序在運行的時候會一直在013B2165前運行,而斷點在后,內存中斷點被記錄,所以dump下來就可以看到程序的變化
Dump下重新加載:
Int 3粗線了,原理得證明(基址加載的時候肯定會變化)
F4原理:
改一個這樣的程序
看一下調試寄存器
F4后將F4地址放在了調試寄存器里,運行程序的時候就會中斷到那個地方
F8(步過)原理:
隨便寫一個程序,然后修改一下匯編,使之構成一個循環
在00F11DE8處F2斷點
在函數的時候F8步過,發現函數停在00F11DE8處,然后在調試窗口右擊查看調試寄存器,發現
關於調試寄存器,具體說明請看裝載的這篇文章,
有了對調試寄存器大致的了解之后,貌似我們弄懂了一些在逆向時候的問題
比如為什么硬件斷點只能有4個(只有4個調試寄存器)
我們發現在DR0處存放了一個中斷地址,但是這個地址不是F2斷的地方,而是函數的下一條地址,那么在單步的時候,我們在查看一下調試寄存器:
發現調試寄存器根本沒有變化,其實這個很好理解,因為在沒有執行到函數之前的F8其實就是相當於F2功能
F7原理:步入
這個說法不一,查詢了前輩們的說法,認為是標志寄存器T的原因:
當TF被設置位1時,CPU進入單步模式,所謂單步模式就是CPU在每執行一步指令后都產生一個單步中斷。主要用於程序的調試。8086/8088中沒有專門用來置位和清零TF的命令,需要用其他辦法。
自己想了一個方法證明:
構造一個這樣的循環:
在運行到call的時候,改變T的標志位,然后直接讓程序運行,發現程序停在開始處,得證。
在這和之后,在貼一段前輩們的總結:
將TF置1:程序將斷在下一條原子操作處,並將TF位清零。原子操作是指不會被線程調度機制打斷的操作;這種操作一旦開始,就一直運行倒結束,中間不會有任何 context switch (切換到另一個線程)。call指令是原子操作,它的作用是:將返回地址壓棧,並跳轉。所以,在調用call的時候,如果我們將TF置1,那么程序將在call指令的功能完成以后(即將返回地址壓棧並跳轉)斷下來。而執行call內的語句則僅僅是call的邏輯功能(我們理解的功能),並非實際的功能(CPU理解的功能)。
以上差不多硬件斷點的一些原理都介紹了,驗證的方法其實就是怎么去構造那段匯編代碼,其實這個也很好想啊,想驗證對函數的操作,步入或者步過,就要構造一個call啊,想要了解運行到斷點處和光標處,就要想着讓他跳轉啊,所以有jmp,然后之所以都構成循環,是因為讓程序停在我們需要驗證的地方啊。