Windbg入門實戰講解
聚鋒實驗室:gongmo
windbg作為windows調試的神器。是查看內核某些結構體,挖掘漏洞,調試系統內核,調試驅動等必不可少的工具。但是由于windbg命令眾多,界面友好程度較差,從而造成新人上手不易,望而卻步。本文拋磚引玉,從基礎入手,講解windbg。希望同作為新人的我們一起進步!
注意:本文省略部分為:1.如何加載系統符號。2.如何開啟雙機調試。因為這部分的內容,網絡上太多了。讀者可自行百度。但是請注意:這兩部分也是很重要的。
0×1 程序代碼
為了整體掌握windbg的調試流程。本文實例采用自己編寫。好處是可以更為主動的熟悉windbg的調試命令,更加直觀的查看windbg的顯示結果。
0×2 windbg調試入口
打開windbg,點擊:File->Open Executable,選中編譯好的exe文件。Windbg會自動給程序下一個斷點。但是我們不知道這個斷點是否屬于我們程序的區域。所以,我們先要看下,斷點是斷在了什么地方。我們在windbg命令中輸入!address 斷點地址。如下圖所示:
圖中不僅僅顯示了斷點所在的“領空區域”,還顯示了一些文件的其他屬性。由于此時的斷點不再我們需要的領空,所以下面要使用上文提過的偽寄存器了。我們在windbg中輸入:bp $exentry。也可以輸入bp @$exentry。@的作用是讓windbg不再去尋找系統符號,從而加快了執行速度。Bp呢,我們依舊可以看下windbg的幫助文檔。從中,我們可以知道,bp就是給地址下一個斷點。好讓程序中斷下來。那$exentry又是什么呢?我們可以在Help->Content點擊索引,輸入:pseudo查看。$exentry就是我們的程序入口點啦。
之后我們輸入bl命令;可以查看我們下的斷點。
輸入g命令;g就是運行程序的意思。運行程序,程序就會停在我們的程序入口點了,也就是oep。
但這依然不是我們想要的。這下系統符號表的作用就體現出來了。雖然本程序加載的系統符號表是vs2015debug時候自動生成的,但是這個系統符號表與從微軟下載的系統符號表的作用是一樣的。
我們在windbg中輸入:bp main;就這么簡單。注意:這個符號表是利用的本地符號表。輸入g命令;windbg會自動給我們斷在main函數中。
G命令結束后,這里我們需要注意一下:點擊windbg工具條的Source mode off。當Souce mode on的時候,debug的單步命令會直接按照函數的步驟執行,而不是從真正單步匯編命令,這點上大家可以嘗試切換不同的開關。具體執行如下圖所示:
0×3重點命令
1) 棧內容查看
這里很重要的一點是:本程序是為了體會windbg的流程和指令。所以,不會回避源代碼的顯示問題。我們單步到程序的第一個call函數中,可以用F8或者F11步入其中。輸入命令:kv。或者點擊View->Call Stack查看。此時,我們可以看到棧中的信息是一樣的。從中,我們也可以看出kv就是顯示堆棧詳細信息的命令啦。k命令在windows漏洞挖掘,了解windows執行過程中是非常有用的命令之一。
從下圖中,我們也可以看到kv命令后,001218a7正是第一個call函數的返回地址。00000001和00000002正是傳遞給f_add的參數。在CVE漏洞號碼驗證的程序中,經常看到大神門查看棧信息就是如此。而ChildEBP信息是什么呢?如下圖所示,通過圖所示看到:ChildEBP原來就是子函數棧基址的指針地址啦。RetAddr 就是返回的函數地址,Args to Child 就是顯示的參數啦。
2)字符串的查看
繼續F10,運行完第一個call函數后,windbg顯示了一個‘string’的字符。那么想要知道這個字符是什么呢?怎么查看呢?我們這里使用了db命令,就是以byte的形式顯示內存數據。Dd命令就沒有后面的字符串啦,比較單調,讀者可以自己嘗試。
我們運行到四個參數的f_add函數中去,kb查看棧的信息,此時,發現Args to child只能顯示3個參數,如果有多個參數怎么辦呢?可以使用kp或者kP命令,他們的結果是一樣的,知識換行與否。結果如下圖所示:
3)結構查看
假如我們不知道st_m的結構,想要產看一下st_m的結構是什么,可以使用 dt st_m;可以看到如下結果。3個int類型,每個占用4字節。
有了這些知識,我們就可以簡單的進行一些windows的調試;不信,看下面的例子。
0×4 Windows雙機調試(實戰)
此次利用的漏洞來源: www.exploit-db.com 屬于SEH Buffer Overflow類型。
執行前:
執行后:
1)尋找指定進程和附加
打開wavtomp3這個軟件。我們通過.process 0 0命令,查看XP中運行的進程。然后找到指定進程后,通過.process /i 進程地址。切換到實際需要的進程中去。切換后;記得‘g’運行下。
2)尋找適合的斷點
合適的斷點在許多的調試中很重要,斷點需要經驗的積累和技術的積累。沒有一招吃遍天下的斷點。本文因為是SHE的緩沖區溢出。并且在用戶層觸發異常,所以這里我們直接可以下斷:bp RtlpExecuteHandlerForException。也可以求穩一點;給ReadFile函數下斷點: bp ReadFile 。但是請注意:一定要.reload /f下函數的符號表。否則斷點不一定成功。下斷后如下圖所示:
3)分析代碼
運行程序后;可以斷在RtlDisPatchException部分函數內。通過r命令,查看寄存器,通過db查看內存字節。例如想查看esp寄存器的值,只需要:dd esp即可。如下圖所示:
圖中dex的數值是shellcode文本的長度。Eip已經已經指向了異常部分。Esp指向的是棧頂。通過db esp-100 L200查看了從esp這個地址從上往下的
0×200單位的字節。
單步執行下去(F10)。遇到第一個call;圖中跟入如下圖:
上圖中,executehandler2()函數傳遞了5個參數。而shellcode執行就在executehandler2()中的call ecx。我們利用命令觀看:dd 0104fb24地址中的第一個參數就是我們要的執行函數的地址。也是_EXCEPTION_REGISTRATION_RECORD結構的Handler回調函數地址 。
見下圖: 圖中通過!exchain查看了異常的地址。通過!slist $teb _EXCEPTION_REGISTRATION_RECORD查看了當前異常鏈的內容。從下圖也能證明,異常鏈的Handler是回調函數。
繼續單步跟入(F8),我們發現這里其實要彈出一個Messagebox的異常對話框的。內容如下:
繼續單步,就會jmp到shellcode的內容了。或者我們可以用通過一種結構來觀察。此時在windbg中,輸入!teb;可以看到目前的teb結構目前的值。Dt _NT_TIB又可以觀察到nt_tib內部結構。
通過上下圖對比,可以看到圖中我們的shellcode:0x909006eb和0x004043a4就是覆蓋了fs:[0],分別指向了下一個異常塊和本次的回調函數。所以上文有一個call ecx,其實是call 0x004043a4。已經指向了我們想要的東西。
下面這個圖;已經是我們想要執行的指令的代碼了。三個部分的代碼都是一樣的。
4)結束語
本文主要強調對windbg的調試操作命令做說明。對日后如何調試windows系統有所幫助。在安全行業的道路上,希望大家共勉。