將自己在工作中的記錄的一些windbg的命令記錄下來,方便查閱,此頁面會不斷更新:
內核調試時OutputDebugString函數輸出內容windbg無法看到不修改注冊表的解決辦法:ed nt!Kd_DEFAULT_Mask 8
參考自:https://blog.csdn.net/xbgprogrammer/article/details/43021689
windbg加載符號相關:
加載符號時開啟嘈雜模式:!sym noisy
加載符號時開啟靜默模式:!sym quiet
CTRL+S設置符號表路徑:F:\VsCode\TestHelloWorld\x64\Debug;SRV*F:\virtual_Symbol\win10_21H2_x64* http://msdl.microsoft.com/download/symbols
一般F:\VsCode\TestHelloWorld\x64\Debug放的是調試程序對應的pdb,如果在此目錄下或者F:\virtual_Symbol\win10_21H2_x64下都找不到符號文件,那么就到微軟符號服務器下載,可以設置多個路徑在最前面,通過;分割。
加載用戶空間符號:.reload /user
重新加載: .reload /f xxx.exe/dll/sys
強制加載某個不匹配的PDB文件: .reload /i xxx.exe/dll/sys
查找模塊內函數:
例如查看MessageBoxW: x User32!*MessageBoxW*
查看模塊:
查看當前加載所有模塊:lm
查看某個模塊詳細信息: lm vm XXX 不加后綴
查看用戶態回調函數表:
用戶態下使用命令 !peb
dt nt!_PEB xxx 偏移大概0x58的位置 就是KernelCallbackTable,
也可以使用命令 dt nt!_PEB KernelCallbackTable XXX 含義為XXX為_PEB結構體,查詢結構體中的KernelCallbackTable變量
找到之后使用名 dps XXX 或者 dqs、dds根據64位、32位不同
雙機調試,使用VirtualKD-Redux軟件可以很方便的進行雙機調試
雙機調試下調試用戶態程序:最好可以讓用戶態程序運行時暫時中斷下來如:getchar()、MessageBox、system("pause")等等。
在宿主機上的windbg中使用菜單Debug->Break或者鍵盤CTRL+Pause,即可使被調試機器中斷下來:
使用命令 !process 0 0 xxx.exe 可以查看特定進程對應的_EPROCESS地址,例如:
kd> !process 0 0 cmd.exe
PROCESS ffffe5048cbae340
SessionId: 2 Cid: 11b0 Peb: 65471e6000 ParentCid: 1618
DirBase: 3a560002 ObjectTable: ffffbe09a24b2080 HandleCount: 73.
Image: cmd.exe
會話ID為2,進程ID為0x11b0,peb地址為65471e6000,父進程id為1618,DirBase不太懂,好像比較復雜,暫時放下,ObjectTable為句柄表地址,HandleCount為句柄數量。
要調試此回話需要使用如下幾條命令:
.process /i xxx xx為EPROCESS的地址
g
.reload /user
如果沒有加載主程序的pdb .reload /f XXX.exe/dll/sys 為應用程序模塊
如果還是沒有加載主程序的pdb .reload /i xxx.exe/dll/sys,如果還是沒有加載,檢查.sympath是否包含pdb路徑
雙機調試快速調試用戶程序:在應用程序中源碼中加入DebugBreak()或者int 3斷點,程序運行后,宿主機調試器會自動中斷下來:
使用命令: .reload /user 加載用戶態符號
在查看棧回溯:k
此時已經在用戶空間了,可以進行調試。
查看進程token
一些結構體 dt nt!_EPROCESS
偏移0x4b8 為 TOKEN, 結構體為 _EX_FAST_REF
+0x000 Object :
+0x000 RefCnt :
+0x000 Value
如果找到pid為4的system進程,獲取Object 的值,然后寫入到想提權的進程Object屬性中,即可提權權限到sytem級別
使用命令 dt nt!_TOKEN object的值,
偏移0x40為Privileges,結構體為 _SEP_TOKEN_PRIVILEGES
[+0x000] Present : 0x800000000000 [Type: unsigned __int64]
[+0x008] Enabled : 0x40800000000000 [Type: unsigned __int64]
[+0x010] EnabledByDefault : 0x0 [Type: unsigned __int64]
其中Present代表着是否可以開啟某項權限,Enabled代表是否開啟了某項權限,EnabledByDefault 為是否默認開啟了某項權限,
要提權時可以修改token為system的token,也可以換一種方式:開啟SeDebugPrivilege權限,默認情況下只有過了UAC的high權限及權限之上的程序才可以打開此權限,如果存在內核漏洞
設置Present及Enabled為0x100000即可,因為此漏洞利用方式需要利用進程注入技術,需要打開winlogon.exe,並且寫入數據,而OpenProcess打開system進程時會去判斷當前進程是否開啟了SeDebugPrivilege權限,如果開啟了此權限,即可打開system進程,至於為什么是0x100000,可以在windbg下輸入!token命令:
kd> !token
Thread is not impersonating. Using process token...
_EPROCESS 0xffffe50489885080, _TOKEN 0x0000000000000000
.........
Privs:
02 0x000000002 SeCreateTokenPrivilege Attributes -
03 0x000000003 SeAssignPrimaryTokenPrivilege Attributes -
04 0x000000004 SeLockMemoryPrivilege Attributes - Enabled Default
05 0x000000005 SeIncreaseQuotaPrivilege Attributes -
07 0x000000007 SeTcbPrivilege Attributes - Enabled Default
08 0x000000008 SeSecurityPrivilege Attributes -
09 0x000000009 SeTakeOwnershipPrivilege Attributes -
10 0x00000000a SeLoadDriverPrivilege Attributes -
11 0x00000000b SeSystemProfilePrivilege Attributes - Enabled Default
12 0x00000000c SeSystemtimePrivilege Attributes -
13 0x00000000d SeProfileSingleProcessPrivilege Attributes - Enabled Default
14 0x00000000e SeIncreaseBasePriorityPrivilege Attributes - Enabled Default
15 0x00000000f SeCreatePagefilePrivilege Attributes - Enabled Default
16 0x000000010 SeCreatePermanentPrivilege Attributes - Enabled Default
17 0x000000011 SeBackupPrivilege Attributes -
18 0x000000012 SeRestorePrivilege Attributes -
19 0x000000013 SeShutdownPrivilege Attributes -
20 0x000000014 SeDebugPrivilege Attributes - Enabled Default
21 0x000000015 SeAuditPrivilege Attributes - Enabled Default
22 0x000000016 SeSystemEnvironmentPrivilege Attributes -
23 0x000000017 SeChangeNotifyPrivilege Attributes - Enabled Default
25 0x000000019 SeUndockPrivilege Attributes -
28 0x00000001c SeManageVolumePrivilege Attributes -
29 0x00000001d SeImpersonatePrivilege Attributes - Enabled Default
30 0x00000001e SeCreateGlobalPrivilege Attributes - Enabled Default
31 0x00000001f SeTrustedCredManAccessPrivilege Attributes -
32 0x000000020 SeRelabelPrivilege Attributes -
33 0x000000021 SeIncreaseWorkingSetPrivilege Attributes - Enabled Default
34 0x000000022 SeTimeZonePrivilege Attributes - Enabled Default
35 0x000000023 SeCreateSymbolicLinkPrivilege Attributes - Enabled Default
36 0x000000024 SeDelegateSessionUserImpersonatePrivilege Attributes - Enabled Default
在cmd下輸入命令 whoami /priv 也可以看到與上面相似的結果
其實這些權限每個占一位,而SeDebugPrivilege 占的是第二十位,1<<20二進制為100000000000000000000,十六進制為0x100000,之后OpenProcess打開高權限進程時即可通過驗證,其實設置為-1即0xFFFFFFFFFFFFFFFF也可以,不過這樣設置的話,在cmd下使用命令 whoami /priv會出現問題,可能是因為有很多標志不存在,但是還是設置為1了。
本地內核態調試:
可以使用SysinternalsSuite套件的工具之一livekd,不需要在電腦上配置參數,對於本地查看內核態結構體比較方便,啟動一個管理員CMD,使用如下命令:
livekd.exe -k "D:\Program Files (x86)\Windows Kits\10\Debuggers\x64\windbg.exe" 或者kd.exe,使用kd.exe啟動的是控制台,使用不太方便,
在win10下需要打開測試模式再進行本地內核調試,打開方式如下:
使用windbg.exe比較方便,可以使用windbg下的內核命令查看結構體,應該是調試器與livekdd.sys進行交互,有一些局限:
無法修改內核數據,這個比較正常,而且獲取到的信息不是實時的,例如我當前啟動了三個cmd.exe,使用命令!process 0 0 cmd.exe只能查到三個,如果再啟動一個cmd.exe,然后使用再次輸入此命令:還是只能查到三個cmd.exe,除非重新啟動livekd.exe程序。
windbg編輯內存
ed 地址 數據 編輯四字節數據
eb 地址 數據 編輯1字節數據
ea 地址 數據 編輯ASCII字符串數據 不以0結尾
eza 地址 數據 編輯ASCII字符串數據 以0結尾
eu 地址 數據 編輯unicode字符串數據 不以0結尾
ezu 地址 數據 編輯unicode字符串數據 以0結尾
查看進程的入口點代碼
u $exentry
調試服務進程
在服務主進程中啟動一個線程調用如下代碼,
while (!IsDebuggerPresent())
Sleep(1);
DebugBreak();
這樣掛到調試器后會自動斷下來,這種方式進程會占用較多的cpu,可以修改sleep的時間。
遠程調試服務進程,使用客戶端服務器模式,如果已經設置Windbg為即時調試器,修改注冊表\HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Microsoft\Windows NT\CurrentVersion\AeDebug
子項Debugger的值為 "D:\Program Files (x86)\Windows Kits\10\Debuggers\x86\windbg.exe" -p %ld -e %ld -QY -c ".server tcp:port=2000"
服務啟動后,如果出現無法處理的異常,會自動啟動即時調試器,但是服務處於session 0,所以剛才啟動的這個windbg界面不可見,在啟動windbg時命令行參數中,讓windbg作為服務端,使用Process Explorer查看
可以看到正在監聽2000端口,在本機啟動一個windbg,點擊左上角File->Connect to Remote Debugger Session 打開對話框,輸入tcp:port=2000,server=127.0.0.1,點擊Ok按鈕,后即可連接到作為服務端的windbg,進行調試。
在調用棧中 查看函數傳入參數類型 kPL
查詢函數傳入參數類型 字節數 x /D ntdll!*
查詢進程中的鎖 使用!locks命令 !cs -l命令
對於雙誤錯誤來說,硬件會使用新的進程來處理錯誤,硬件會修改cr3為新進程的cr3,之后會執行藍屏操作,此時操作系統還沒有切換新的進程,對於處理這類問題,查看是從哪個任務切換過來的,使用命令.tss 段選擇子 即可切換回雙誤的線程。
kvnL可以查看棧回溯中更詳細的信息。
.srcpath D:\source 后面跟路徑可以設置源文件的路徑。
!pte address 命令可以查看某個頁面是否 合法。
在每次頁錯誤異常時,CPU會把訪問的地址寫到CR2寄存器中。
使用bp /p EPROCESS nt!ZwCreateFile 可以觀察特定進程調用ZwCreateFile函數的行為。
32位下 調試時監視文件操作:
bp KERNELBASE!CreateFileW+0x5 "dU /c 50 poi(@ebp+8);gc" /c 后面數字 是一行多少個字符。
延遲加載符號命令
bm modulename!function
查看每個線程的ID和Last Error值
~*e ?@$tid;!gle
加載用於解析托管語義的SOS擴展命令模塊 .reload sos mscorwks mscorwks是模塊名,然后執行!clrstack 觀察托管方法的調用經過。
使用SOS的!threads 觀察線程的異常,使用!do(含義為dumpobject) +異常對象的地址 可以顯示異常對象的詳情。
也可以使用SOS的!printexception命令打印出當前線程的異常信息,可以更簡便地得到與上面!do命令結果同樣的錯誤描述信息。
分析轉儲文件時,通過.excr元命令可以訪問異常數據塊,讀取異常數據流,回到異常現場。
.cxr 命令
使用ildasm工具可以 查看c#模塊的代碼
執行!pcr命令來觀察處理器控制區,查看CPU當時的狀態。在內核調試時 使用 dg @fs命令查看當前CPU的PCR,結構體為dt _KPCR
!drvobj 驅動名稱 可以查看驅動的更多信息,找到設備對象后,可以使用!devstack 設備對象地址 查看設備棧信息。
在windbg中使用命令 ~*e .ttime 可以查看各個線程的創建時間,內核運行時間,用戶態運行時間。
使用.ttime 可以查看當前線程創建時間、運行時間。
顯示線程id和線程運行時間
~*e ?@$tid;.ttime 切換到某個線程 ~~[tid]s
windbg中使用循環命令尋找鏈表
recx=poi(ecx);r ecx;z(ecx!=0)
一次執行到下一條分支語句 windbg的tb命令
一次執行到下一個函數調用 windbg的tc命令
一下子返回到上一級函數 windbg的gu命令和gdb的finish命令。
訪問指定的設備空間(I/O)時斷下來,IO訪問斷點,windbg的ba i
使用windbg的 r 命令顯示通用寄存器,
使用 rdmsr和wrmsr命令來訪問MSR寄存器
使用 ib/iw/id命令來讀取IO端口
使用 ob/ow/od命令來寫IO端口
使用 !apic 命令來顯示CPU內部的中斷控制器寄存器
使用 !idt 命令來觀察中斷描述符表
使用 !pci 命令來觀察PCI總線上的設備。
windbg中查看結構體如CONTEXT,dt _CONTEXT 加下划線,這是因為按照C語言的規范,編譯器產生符號時會在源程序的名字前加一個下划線。
!idt -a 可以觀察idt表
查看SSDT,之后再做記錄,暫時不太熟練,還不會
KeServiceDescriptorTable
KeServiceDescriptorTableShadow
軟件工程師至少要對寄存器(通用寄存器、MSR寄存器)、IO端口、中斷、物理內存、PCI總線等概念有比較深刻的理解,否則就始終根基不牢。