Exploit開發系列教程-Windbg
本系列教程主要講述Modern Windows Exploit Development。
學習本系列教程首先要求你熟悉x86組合語言,並且因為根據本系列教程所講述的內容可以非常容易地進行相關內容的實踐性操作,所以你應該能較好地重現我進行過的相關實驗。在本系列教程的後幾部分,我們將會進行關於Internet Explorer 10和Internet Explorer 11的攻擊實驗。我的主要目的不僅是向你講述攻擊Internet Explorer的方法,還向你講述進行如此複雜的攻擊前首先需要進行的相關研究,進而讓你實現預期的目標。本系列教程有部分內容將會講述對Internet Explorer進行逆向工程的細節,進而會了解到物件在記憶體中的佈局情況和根據我們已經瞭解到的情況來進行利用的方法。
我推薦你在64位的Windows 7 SP1 上建立兩臺虛擬機器:一臺用於進行與Internet Explorer 10相關的實驗,另一臺用於進行與Internet Explorer 11相關的實驗。 我希望你喜歡本系列教程!
來源:http://expdev-kiuhnm.rhcloud.com/2015/05/17/windbg/
這篇文章描述windbg的一些重要命令及其最重要的選項.當然,我們在下篇文章中,當有需要時,也將瞭解到其他的命令及選項.
版本
為避免出現問題:
請用32-bit版的WinDbg來除錯32位的可執行程式;用64-bit版的WinDbg來除錯64位的可執行程式。
符號
開啟某一WinDbg例項,如果你正使用Windbg除錯某一程式,那麼關閉WinDbg並將它重新開啟)。 在File→Symbol File Path 裡
輸入:SRV*C:\windbgsymbols*http://msdl.microsoft.com/download/symbols
儲存工作區 (File→Save Workspace).
如上的星號是定義符。如上指定目錄為本地符號快取目錄。paths/urls位於第二個星號後(如果有更多的paths/urls,那麼使用‘;’分割)。用星號具體指定符號的位置。
除錯時新增符號
要在除錯時追加符號的搜尋路徑,使用命令:.sympath+ c:\symbolpath
(使用的命令如沒有’+’,其作用是替換預設的搜尋路徑)
過載符號表:.reload
檢查符號
如果需要了解模組載入了哪些符號,使用命令:x *!
X命令支援使用萬用字元並可在搜尋一個或多個模組中的符號時使用.例如,我們可以搜尋kernel32內帶有virtual字樣開頭的所有符號:
#!bash
0:000> x kernel32!virtual*
757d4b5f kernel32!VirtualQueryExStub (<no parameter info>)
7576d950 kernel32!VirtualAllocExStub (<no parameter info>)
757f66f1 kernel32!VirtualAllocExNuma (<no parameter info>)
757d4b4f kernel32!VirtualProtectExStub (<no parameter info>)
757542ff kernel32!VirtualProtectStub (<no parameter info>)
7576d975 kernel32!VirtualFreeEx (<no parameter info>)
7575184b kernel32!VirtualFree (<no parameter info>)
75751833 kernel32!VirtualAlloc (<no parameter info>)
757543ef kernel32!VirtualQuery (<no parameter info>)
757510c8 kernel32!VirtualProtect (<no parameter info>)
757ff14d kernel32!VirtualProtectEx (<no parameter info>)
7575183e kernel32!VirtualFreeStub (<no parameter info>)
75751826 kernel32!VirtualAllocStub (<no parameter info>)
7576d968 kernel32!VirtualFreeExStub (<no parameter info>)
757543fa kernel32!VirtualQueryStub (<no parameter info>)
7576eee1 kernel32!VirtualUnlock (<no parameter info>)
7576ebdb kernel32!VirtualLock (<no parameter info>)
7576d95d kernel32!VirtualAllocEx (<no parameter info>)
757d4b3f kernel32!VirtualAllocExNumaStub (<no parameter info>)
757ff158 kernel32!VirtualQueryEx (<no parameter info>)
在模組部分使用萬用字元:
#!bash
0:000> x *!messagebox*
7539fbd1 USER32!MessageBoxIndirectA (<no parameter info>)
7539fcfa USER32!MessageBoxExW (<no parameter info>)
7539f7af USER32!MessageBoxWorker (<no parameter info>)
7539fcd6 USER32!MessageBoxExA (<no parameter info>)
7539fc9d USER32!MessageBoxIndirectW (<no parameter info>)
7539fd1e USER32!MessageBoxA (<no parameter info>)
7539fd3f USER32!MessageBoxW (<no parameter info>)
7539fb28 USER32!MessageBoxTimeoutA (<no parameter info>)
7539facd USER32!MessageBoxTimeoutW (<no parameter info>)
如想臨時改變策略,立刻將所有模組的符號載入到WinDbg偵錯程式,可以使用:ld*
這可能會花去一段時間.可透過 Debug→Break 來停止除錯。
幫助
僅需輸入.hh
或按F1開啟幫助視窗。用以下命令得到指定命令的幫助資訊:
.hh <command>
<command>
為你想得到幫助資訊的某個指定命令,或按F1,選擇Index(索引)來搜尋命令,從而得到其幫助資訊.
除錯模式
本地除錯
可以除錯某一新程式或某一正在執行的程式:
透過File→Open Executable
執行新程式以進行除錯
透過File→Attach to a Process
附加到某一正執行的程式
遠端除錯
至少使用如下兩個選項來遠端除錯程式
1 如果你已在機器A上本地除錯某一程式,那麼使用如下命令(選擇你想要的埠):
.server tcp:port=1234
此時開啟伺服器(WinDbg內).轉到 File→Connect to Remote Sessions
並輸入:
tcp:Port=1234,Server=<IP of Machine A>
來指定埠和IP.
2 在機器A,用如下命令執行dbgsrv:
dbgsrv.exe -t tcp:port=1234
即可以在機器A啟動伺服器.
在機器B執行Windbg,接著File→Connect to Remote Stub
,輸入
tcp:Port=1234,Server=<IP of Machine A>
這裡需要設定適當的引數。
你將看到File→Open Executable
已無法選擇,但你可以透過File→Attach to a process
附加到程式 .這時可在機器A上看到程式列表。
如果要在機器A停止伺服器,可用Task Manager(工作管理員)接著kill dbgsrv.exe。
模組
當你載入某一可執行程式或附加到某一程式時,WinDbg將列出已載入的模組.如果你要再次列出模組,那麼可輸入:lmf 列出指定模組(ntdll.dll),可用: lmf m ntdll
得到模組(ntdll.dll)的映象頭部資訊: !dh ntdll
帶有‘!’符號的命令為擴充套件命令,這裡的作用是顯示指定模組的詳細資訊,等等。從某一外部DLL中匯出某一外部命令,並且WinDbg內部會呼叫該命令。使用者可建立他們自己的擴充套件程式來擴充套件WinDbg的功能。
當然了,你也可以使用模組的起始地址:
#!bash
0:000> lmf m ntdll
start end module name
77790000 77910000 ntdll ntdll.dll
0:000> !dh 77790000
表示式
WinDbg支援使用表示式,這意味著,當需要某一值時,你可直接輸入該值或輸入與該值等價的表示式。例如,如果EIP是77c6cb70
,那麼bp77c6cb71
和bp EIP+1
等價。
你也可以使用符號:u ntdll!CsrSetPriorityClass+0x41
和暫存器:dd ebp+4
數字預設用base 16
表示,新增字首來明確使用的base所表示的進位制格式:
#!bash
0x123: base 16 (hexadecimal)
0n123: base 10 (decimal)
0t123: base 8 (octal)
0y111: base 2 (binary)
用命令.format來展示某一值的多種格式
#!bash
0:000> .formats 123
Evaluate expression:
Hex: 00000000`00000123
Decimal: 291
Octal: 0000000000000000000443
Binary: 00000000 00000000 00000000 00000000 00000000 00000000 00000001 00100011
Chars: .......#
Time: Thu Jan 01 01:04:51 1970
Float: low 4.07778e-043 high 0
Double: 1.43773e-321
用’?’來對某個表示式求值,例如:? eax+4
暫存器與偽暫存器
在WinDbg中可支援多種偽暫存器(含有某些值). 用字首‘$‘來指明其是偽暫存器.在使用暫存器或偽暫存器時,[email protected],[email protected]器而不是某一符號。
這有一些偽暫存器的範例:
$teb
或 @$teb
(TEB的地址)
$peb
或 @$peb
(PEB的地址)
$thread
或 @$thread
(當前執行緒)
異常
用sxe命令可中斷某一特定的異常.例如,中斷某一已被載入的模組,可輸入:
sxe ld <module name 1>,...,<module name N>
例如,
sxe ld user32
檢視異常型別的列表:sx
用sxi
命令忽略某一異常: sxi ld
使用該命令可讓第一次輸入的命令失效。
執行到single-chance和second-chance的異常處將會使Windbg中斷 。它們並非是不同的異常型別。執行到異常處時,WinDbg將停止執行 ,並提示該位置為single-chance異常。 Single-chance意味著異常事件還沒被髮送到被除錯的程式。當我們恢復執行時,WinDbg將異常事件傳送到被除錯的程式。如果被除錯程式不處理異常,WinDbg將再次停止執行並提示此處為second-chance異常。
在我們測試EMET5.2時,我們需要忽略single-chance的單步異常(single step exceptions)。用如下命令實現: sxd sse
斷點
軟體斷點:
在某指令上設定斷點時,WinDbg將指令的第一位元組儲存於記憶體並用0xCC覆蓋它(操作碼為”int 3”)。
當“int 3”指令被執行時,斷點即被觸發,那麼執行將會被停止,且WinDbg透過重置它的首位元組來重置該指令。
輸入如下命令在位於0x4110a0地址的指令上設定斷點:
bp 4110a0
第三次執行時啟用0x4110a0地址的斷點:
bp 4110a0 3
恢復執行(並在第一次觸發的斷點上停止)輸入如下:g
這是“go“的縮寫.
執行直到到達某地址 (含有程式碼 ), 輸入:g <code location>
WinDbg內將會在指定的位置上設定軟體斷點(如‘bp’),但此處的斷點被觸發後將會被刪除.主要原因是使用‘g’設的是一次性軟體斷點.
硬體斷點
使用特定的CPU暫存器設定硬體斷點,它比軟體斷點更通用.事實上,它可中斷執行或記憶體訪問.硬體斷點不會修改任意程式碼,甚至帶有self modifying code。不幸的是,最多隻能下4個硬體斷點。
最簡單的形式如下,命令格式為:
ba <mode> <size> <address> <passes (default=1)>
<mode> 可以是
‘e‘ (用於執行
‘r‘ (用於讀取儲存器
‘w‘ (用於寫儲存器
<size>
是監控訪問(當<mode>
是‘e’時,它總為1)指明位置的大小,其以位元組的形式表示。
<address>
為設定斷點的位置,<passes>
啟用斷點時(檢視’bp’用法的範例)需要的傳遞數,其起到計數器的作用.
筆記:在執行某一程式前,該程式不可能使用硬體斷點。因為透過修改CPU暫存器(dr0,dr1,等等…)可以設定硬體斷點,在開啟程式及它的執行緒被建立時,暫存器將會被重置。
處理斷點
列出斷點型別:bl
‘bl’表示斷點列表(breakpoint list). 例如:
0:000> bl
0 e 77c6cb70 0002 (0002) 0:**** ntdll!CsrSetPriorityClass+0x40
區域的位置,從左到右表示如下:
0:斷點ID
e: 斷點狀態,可以設定(enabled)或關閉(disabled).
77c6cb70: 記憶體地址
0002(0002): 在啟用前餘下的傳遞數(起到計數器作用),利用所有傳遞數來等待啟用(當斷點被建立時,將會指定該值) 0:***|*: 相關聯的程式和執行緒.用星號代表該斷點不是thread-specific。
ntdll!CsrSetPriorityClass+0x40: 設定斷點的位置(模組, 函式和偏移)
關閉(disable)某一斷點
bd <breakpoint id>
刪除斷點
bc <breakpoint ID>
刪除所有斷點
bc *
斷點命令
每次某個斷點被觸發後將自動執行某個命令,可以使用如下命令:
bp 40a410 ".echo \"Here are the registers:\n\"; r"
另一個範例:自定義命令如下:
bp jscript9+c2c47 ".printf \"new Array Data: addr = 0x%p\\n\",eax;g"
逐步執行
逐步執行有至少三種型別:
步進/跟蹤(命令:t) 該命令中斷每條指令的執行.如果執行到call指令或int指令,那麼該命令將各自在呼叫函式的第一條指令或int handler上中斷。 步過 (命令: p) 該命令能讓每條指令(沒有calls或ints,等等)執行後中斷,如果你剛好執行到call或int指令,那麼會在call或int指令執行後中斷 步出 (命令: gu) 該命令(go up) 能讓WinDbg恢復程式的執行,並且能在下一條ret指令執行後中斷。在exit函式中經常使用到該命令。
還有其它兩個用於exit函式的命令:
tt (trace to next return):等價於重複使用’t’命令並且在執行過程中遭遇的第一條ret指令上停止執行。 pt (step to next return):等價於重複使用‘p’命令並且在執行過程中遭遇的第一條ret指令上停止執行。
記錄:使用tt命令會執行到函式內,如果你想到達當前函式的ret指令,那麼改為使用pt命令。 pt和gu命令的不同點在於,使用pt命令將會在ret指令上中斷,使用gu命令將會在ret指令後的下一條指令上中斷。
這裡是包含‘p‘ 和‘t‘命令的不同形式:
pa/ta <address>: step/trace 到地址。
pc/tc: step/trace 到 下一條 call/int 指令。
pt/tt: step/trace 到下一條 ret (discussed above at point 3)指令。
pct/tct: step/trace 到下一 條call/int 或 ret指令。
ph/th: step/trace 到下一分支的指令。
檢視記憶體
可使用‘d’或它的變數中的其中一種型別來展示(display)記憶體中的內容,
db: display bytes
dw: display words (2 bytes)
dd: display dwords (4 bytes)
dq: display qwords (8 bytes)
dyb: display bits
da: display null-terminated ASCII strings
du: display null-terminated Unicode strings
輸入 .hh d 來檢視其它變數。 ‘d’命令用相同的格式展示資料,正如大多數的d*命令那樣(或如果不是單一資料則使用db)。
這些命令的(簡化)格式為:d* [range]
這裡,使用星號來描繪我們已列出的如上所有的變化,並且方框內應指明所選的範圍。如果沒有選好範圍,那麼在使用d*命令展示一部分資料後,將展示記憶體部分的資料。
可以用許多種方式指定範圍:
<start address> <end address>
範例,db 77cac000 77cac0ff
<start address> L<number of elements>
範例,dd 77cac000 L10
檢視 10 dwords(始於 77cac000地址). Note: 因為範圍比256 MB還要大,我們必須使用L?而不是L來指定行數。<start address>
- 在只是指定起始地址時,用WinDbg將可以檢視到128位元組的內容。
編輯(edit)記憶體
要編輯(edit)記憶體,使用:
e[d|w|b] <address> [<new value 1> ... <new value N>]
[d|w|b]是相關選項,它指定編輯的元素型別(d = dword, w = word, b = byte)。 如果新值被省略了,那麼你在WinDbg中可以互動式地輸入它們。
這是範例:ed eip cc cc
用值0xCC來覆蓋地址(在eip內)上的頭兩個dwords。
搜尋記憶體
使用‘s’命令來搜尋記憶體。它的格式為:
s [-d|-w|-b|-a|-u] <start address> L?<number of elements> <search values>
d,w,b,a,u
分別代表dword, word, byte, ascii
和 unicode.
<search values>
是序列值(用於搜尋)
例如:
s -d eip L?1000 cc cc
在記憶體區間內搜尋兩個連續的dwords 0xcc 0xcc
。[eip, eip + 1000*4 – 1]
。
指標
使用如下命令解引用某個指標:
dd poi(ebp+4)
用該命令,poi(ebp+4)對地址ebp+4求值,其結果的型別為dword或qword(在64位模式下)。
使用於多個方面的命令
檢視暫存器資訊,輸入如下:r
檢視特定暫存器資訊,例如eax和adx,輸入:r eax, edx
列印前三行EIP指向的指令,用命令如下:u EIP L3
‘u‘ 是unassemble的縮寫並且‘L‘可讓指定你想檢視資訊的行數.列出呼叫棧(call stack)可以使用k
轉儲結構
如下是一些檢視結構體資訊的命令:
建議搭建的工作區環境如下
建立視窗後儲存工作區(File→Save Workspace)
相關文章
- Exploit開發系列教程-Heap2020-08-19
- Exploit開發系列教程-Mona 2& SEH2020-08-19
- Exploit開發系列教程-Exploitme2 (Stack cookies & SEH)2020-08-19Cookie
- Exploit開發系列教程-Exploitme1 (“ret eip” overwrite) &More space on stack2020-08-19
- [翻譯]Windows Exploit開發教程第十二章-EMET 5.22020-01-31Windows
- [翻譯]Windows Exploit開發系列教程第七部分:返回導向程式設計(ROP)2021-06-02Windows程式設計
- windbg除錯系列教程:sos擴充套件的介紹和使用2022-02-22除錯套件
- [翻譯]Windows Exploit開發教程第十四章Part1.IE112019-03-02WindowsIE11
- [翻譯]Windows Exploit開發教程第十四章Part2.IE112018-09-22WindowsIE11
- [翻譯]Windows Exploit開發教程第十章 Exploitme4(ASLR)2020-02-17Windows
- [翻譯]Windows Exploit開發教程第九章-Exploitme3 (DEP)2020-02-18Windows
- 硬體開發系列教程2024-03-10
- [翻譯]Windows Exploit開發教程第十一章 Exploitme5(heap spraying & UAF)2020-01-31Windows
- [翻譯]Windows Exploit開發教程第十三章Part5.IE10 UAF漏洞2019-03-07WindowsIE10
- [翻譯]Windows Exploit開發教程第十三章Part4.IE10 上帝模式(2)2020-02-02WindowsIE10模式
- [翻譯]Windows Exploit開發教程第十三章Part3.IE10 上帝模式(1)2020-02-09WindowsIE10模式
- [翻譯]Windows Exploit開發教程第十三章Part1.IE10-IE逆向工程2020-02-11WindowsIE10
- C#微信開發系列教程2018-07-24C#
- 微信程式開發系列教程(一)開發環境搭建2018-08-21開發環境
- Selenium系列教程-02 使用Chrome開發者工具2018-05-30Chrome
- odoo 開發入門教程系列-QWeb簡史2023-04-21OdooWeb
- Flutter開發系列教程之網路請求2019-07-31Flutter
- odoo 開發入門教程系列-約束(Constraints)2023-04-07OdooAI
- odoo 開發入門教程系列-繼承(Inheritance)2023-04-14Odoo繼承
- 『React Navigation 3x系列教程』createMaterialTopTabNavigator開發指南2019-01-07ReactNavigation
- 『React Navigation 3x系列教程』createDrawerNavigator開發指南2019-01-21ReactNavigation
- Web閱讀器開發系列教程(入門篇)2019-03-02Web
- 『React Navigation 3x系列教程』createBottomTabNavigator開發指南2018-12-30ReactNavigation
- odoo 開發入門教程系列-模組互動2023-04-16Odoo
- .NET高階除錯系列-Windbg除錯入門篇2020-06-27高階除錯
- Web閱讀器開發系列教程(Vue環境篇)2018-10-29WebVue
- unity 開發2D坦克大戰教程 系列二2024-03-10Unity
- 『React Navigation 3x系列教程』之createStackNavigator開發指南2018-12-24ReactNavigation
- 兄弟連百度應用開發系列視訊教程2018-06-15
- Selenium系列教程-03使用開發者工具進行元素定位2018-05-30
- 全新系列教程即將開啟2019-03-14
- odoo 開發入門教程系列-一些使用者介面2023-03-25Odoo
- odoo 開發入門教程系列-準備一些操作(Action)?2023-04-02Odoo