Windbg腳本和擴展工具開篇
好長一段時間沒寫文章了,最近一直忙於為項目的可調式性做一些腳本和擴展工具,鑒於對windbg強大威力的震撼,以及相對較少的資料,筆者決定寫一系列關於如何開發Windbg腳本和擴展命令的文章,您的支持是我最大的動力,希望本系列文章對您有所幫助。
那么一個完整的windbg script是什么樣子的呢?首先讓我們看如下示例:
$$ 該腳本是列出用戶進程和棧
r $t0 = nt!PsActiveProcessHead
. for (r $t1 = poi(@$t0); (@$t1 != 0) & (@$t1 != @$t0); r $t1 = poi(@$t1))
{
r? $t2 = #CONTAINING_RECORD(@$t1, nt!_EPROCESS, ActiveProcessLinks);
.process @$t2
.reload
!process @$t2
}
. for (r $t1 = poi(@$t0); (@$t1 != 0) & (@$t1 != @$t0); r $t1 = poi(@$t1))
{
r? $t2 = #CONTAINING_RECORD(@$t1, nt!_EPROCESS, ActiveProcessLinks);
.process @$t2
.reload
!process @$t2
}
相對於Windbg腳本,windbg擴展比較復雜,而且通常需要花費更大的精力寫出同樣的功能,但是它帶來的一個好處就是你可以獲得更多的功能,你甚至可以通過這些擴展寫一個調試器,那么一個完整的windbg擴展又是什么樣子的呢?該擴展dll打印出一個全局字符串的值。
以C++語言編寫的windbg擴展示例:
HRESULT CALLBACK
PrintPTR(PDEBUG_CLIENT pDebugClient, PCSTR args)
{
UNREFERENCED_PARAMETER(args);
IDebugSymbols* pDebugSymbols;
if (SUCCEEDED(pDebugClient->QueryInterface(__uuidof(IDebugSymbols), ( void **)&pDebugSymbols)))
{ // Resolve the symbol
ULONG64 ulAddress = 0;
if (SUCCEEDED(pDebugSymbols->GetOffsetByName( " TestSTLMap!g_wString ", &ulAddress)))
{
IDebugDataSpaces* pDebugDataSpaces;
if (SUCCEEDED(pDebugClient->QueryInterface(__uuidof(IDebugDataSpaces), ( void **)&pDebugDataSpaces)))
{ // Read the value of the pointer from the target address space
ULONG64 ulPtr = 0;
if (SUCCEEDED(pDebugDataSpaces->ReadPointersVirtual( 1, ulAddress, &ulPtr)))
{
PDEBUG_CONTROL pDebugControl;
if (SUCCEEDED(pDebugClient->QueryInterface(__uuidof(IDebugControl), ( void **)&pDebugControl)))
{ // Output the values
pDebugControl->Output(DEBUG_OUTPUT_NORMAL, " %p TestSTLMap!g_wString= 0x%p\n ", ulAddress, ulPtr);
pDebugControl->Output(DEBUG_OUTPUT_NORMAL, " %mu\n ", ulPtr);
pDebugControl->Release();
}
}
pDebugDataSpaces->Release();
}
pDebugSymbols->Release();
}
}
return S_OK;
}
PrintPTR(PDEBUG_CLIENT pDebugClient, PCSTR args)
{
UNREFERENCED_PARAMETER(args);
IDebugSymbols* pDebugSymbols;
if (SUCCEEDED(pDebugClient->QueryInterface(__uuidof(IDebugSymbols), ( void **)&pDebugSymbols)))
{ // Resolve the symbol
ULONG64 ulAddress = 0;
if (SUCCEEDED(pDebugSymbols->GetOffsetByName( " TestSTLMap!g_wString ", &ulAddress)))
{
IDebugDataSpaces* pDebugDataSpaces;
if (SUCCEEDED(pDebugClient->QueryInterface(__uuidof(IDebugDataSpaces), ( void **)&pDebugDataSpaces)))
{ // Read the value of the pointer from the target address space
ULONG64 ulPtr = 0;
if (SUCCEEDED(pDebugDataSpaces->ReadPointersVirtual( 1, ulAddress, &ulPtr)))
{
PDEBUG_CONTROL pDebugControl;
if (SUCCEEDED(pDebugClient->QueryInterface(__uuidof(IDebugControl), ( void **)&pDebugControl)))
{ // Output the values
pDebugControl->Output(DEBUG_OUTPUT_NORMAL, " %p TestSTLMap!g_wString= 0x%p\n ", ulAddress, ulPtr);
pDebugControl->Output(DEBUG_OUTPUT_NORMAL, " %mu\n ", ulPtr);
pDebugControl->Release();
}
}
pDebugDataSpaces->Release();
}
pDebugSymbols->Release();
}
}
return S_OK;
}
總結
基於筆者的研究發現,國內做相關研究的人並不多,其實國外也就幾個業內比較牛的人做的相對比較好,但是這些工具的作用足以讓你震撼,今天開個頭,有興趣的朋友可以繼續關注后續文章。
