天天看點

5min學會WinDBG條件斷點1.前言2.WinDBG斷點3.WinDBG條件斷點

1.前言

       很多時候我們可以使用Spy++檢視某個視窗的消息,但是有一定的局限性。

       以編輯控件為例,我們打開Spy++截獲應用程式的EM_GETTEXTRANGE消息,卻隻能看到TEXTRANGE結構的指針值,看不到結構的内容。

5min學會WinDBG條件斷點1.前言2.WinDBG斷點3.WinDBG條件斷點

        如果想要詳細檢視消息的WPARAM和LPARAM參數,Spy++是無能為力的。

        但是可以通過WinDBG的條件斷點卻可以輕松實作。

        我們先從最簡單的WinDBG斷點開始,将斷點打在USER32!SendMessage函數上,就可以看到應用程式傳遞了什麼參數。

2.WinDBG斷點

       首先,設定符号路徑(假設放在本地的目錄E:\symbols):

SRV*E:\symbols*http://msdl.microsoft.com/download/symbols
           

       然後,将WinDBG調試器附加到目标程序并且中斷程式。

       接着,就可以打斷點了。

bp USER32!SendMessageW

bp USER32!SendMessageA
           

        打完斷點之後,繼續執行程式。

g
           

       觸發應用程式發送Windows消息,例如可以将滑鼠移動到程式客戶區将發送WM_MouseMOVE消息。輸入以下指令,可以看到函數調用堆棧和傳入的參數。

kvn
dd esp
           

        整體效果如下圖所示:

5min學會WinDBG條件斷點1.前言2.WinDBG斷點3.WinDBG條件斷點

       可以看到 'kvn' 指令輸出的 '00'行,第二個值 '0a09c81'是函數傳回位址,第三個值開始就是函數參數。結合SendMessage的定義可以知道‘0022065c’為視窗句柄,‘00000229’為消息值。

       根據'dd esp'輸出結果,可以看到,esp+4開始從左到右依次就是SendMessage的4個參數

       現在萬事具備,如何加上條件呢?

3.WinDBG條件斷點

       我們先來最簡單的。在斷點命中時,輸出一句'Hello SendMessage'

       重新定義斷點:

bp USER32!SendMessageW " .printf \"Hello SendMessage\t\" "
           

       這樣定義斷點的意義就是,斷點命中時,執行後面的WinDBG腳本。怎麼樣?是不是超簡單。

       運作程式:

g
           

       觸發應用程式發送Windows消息之後,可以得到以下結果:

5min學會WinDBG條件斷點1.前言2.WinDBG斷點3.WinDBG條件斷點

      可以看到,确實輸出了'Hello SendMessage’,并且執行中斷在了'User32!SendMessageW'。

       接着,我們來嘗試篩選消息EM_GETTEXTRANGE。由2可以,esp+4就是視窗句柄,esp+8就是消息值。

       重新定義斷點:

bp USER32!SendMessageW ".if(poi(esp+8) == 0x44B) {.printf \"EM_GETTEXTRANGE\n\"} .else {gc}"
           

       腳本的意義是,執行一個if-else語句。當消息值為EM_GETTEXTRANGE時,列印文本,否則從斷點繼續執行。具體來講,poi的含義跟C/C++的解引用是類似的。

       執行程式:

g
           

       觸發應用程式發送EM_GETTEXTRANGE消息,可得到結果如下:

5min學會WinDBG條件斷點1.前言2.WinDBG斷點3.WinDBG條件斷點

       可以看到,指定的文本确實輸出了,程式也中斷了。說明應用程式确實發送了EM_GETTEXTRANGE消息。那麼怎麼檢視這條消息的參數呢?

       如果想要更複雜的功能,我們通常就會使用腳本檔案來達到這個目的了,誰也不想在一行上寫完所有代碼邏輯。WinDBG裡也是支援這種功能的,我們可以指定命中斷點時,執行指定的腳本檔案。

       中斷程式,重新定義斷點,假設腳本檔案在'D:\script.txt':

bp USER32!SendMessageW "$$>< D:\script.txt"
           

       再次繼續執行程式

g
           

       觸發應用程式發送EM_GETTEXTRANGE後,可以得到如下執行結果:

5min學會WinDBG條件斷點1.前言2.WinDBG斷點3.WinDBG條件斷點

       可以看到,我們輸出了更多的資訊,把 EM_GETTEXTRANGE的LPARAM參數指向的TEXTRANGE結構都列印出來了。下面給出腳本。

$$ put MessageID into presudo register t0
r $t0 = poi(esp + 8)

$$ put pointer to TEXTRANGE Structure into presudo register t1
r $t1 = poi(esp + 0x10)

.if($t0 == 0x44B) {
    .printf "\nEM_GETTEXTRANGE\n"
    .printf "TEXTRANGE Structure:\nchrg.cpMin = %d\nchrg.cpMax = %d\nlpstrText = 0x%x\n", poi($t1), poi($t1 + 4), poi($t1 + 8)

    gu
    du poi($t1 +8)
    .printf "\n"
    gc
    
} .else {
    gc
}
           

       其中:

       '$$'開始的行是注釋

       r $t0 = poi(esp + 8)則是定義了僞寄存器

       當我們得到指定消息時,先列印參數情況,然後調用gu指令讓SendMessageW繼續執行後傳回,這樣我們就可以得到正确的結果。就儲存在TEXTRANGE結構的lpstrText裡。

       怎麼樣,是不是非常簡單。5min立馬就學會了WinDBG條件斷點。