好長(zhǎng)一段時(shí)間沒寫文章了,最近一直忙于為項(xiàng)目的可調(diào)式性做一些腳本和擴(kuò)展工具,鑒于對(duì)windbg強(qiáng)大威力的震撼,以及相對(duì)較少的資料,筆者決定寫一系列關(guān)于如何開發(fā)Windbg腳本和擴(kuò)展命令的文章,您的支持是我最大的動(dòng)力,希望本系列文章對(duì)您有所幫助。
那么一個(gè)完整的windbg script是什么樣子的呢?首先讓我們看如下示例:
$$ 該腳本是列出用戶進(jìn)程和棧
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
}
相對(duì)于Windbg腳本,windbg擴(kuò)展比較復(fù)雜,而且通常需要花費(fèi)更大的精力寫出同樣的功能,但是它帶來的一個(gè)好處就是你可以獲得更多的功能,你甚至可以通過這些擴(kuò)展寫一個(gè)調(diào)試器,那么一個(gè)完整的windbg擴(kuò)展又是什么樣子的呢?該擴(kuò)展dll打印出一個(gè)全局字符串的值。
以C++語言編寫的windbg擴(kuò)展示例:
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;
}
總結(jié)
基于筆者的研究發(fā)現(xiàn),國(guó)內(nèi)做相關(guān)研究的人并不多,其實(shí)國(guó)外也就幾個(gè)業(yè)內(nèi)比較牛的人做的相對(duì)比較好,但是這些工具的作用足以讓你震撼,今天開個(gè)頭,有興趣的朋友可以繼續(xù)關(guān)注后續(xù)文章。