天天看點

!heap 和 _HEAP_ENTRY

WinDBG提供了!heap指令幫助我們查找heap,同時我們也可以通過dt和MS SYMBOL來了解memory layout。

假設我們有下面一個小程式。

複制代碼

int _tmain(int argc, _TCHAR* argv[])

{

char * pChar = new char[2];

pChar[0] = 'a';

  delete [] pChar;

return 0;

}

在WinDbg裡面啟動這個程式,運作到new操作結束。這時候我們可以得到pChar指針。

我們可以通過!heap -x 來查找對應的Heap Block

!heap -x 00343818

00343810 00343818 00340000 00340640 20 38 1e busy extra fill

從上面我們知道,這個heap block位址是00343810,使用者記憶體位址是00343818,整個heap block大小是0x20。Heap Block Meta Data占據了前面8個位元組 (這也解釋了為什麼使用者記憶體位址的起始位址)。未使用的空間有1e(因為我們申請了2個byte) Flags是busy。

有了Heap Block位址,我們就可以運作下面指令

0:000> dt _HEAP_ENTRY 0X00343810

ntdll!_HEAP_ENTRY

+0x000 Size : 4

+0x002 PreviousSize : 7

+0x000 SubSegmentCode : 0x00070004

+0x004 SmallTagIndex : 0x49 'I'

+0x005 Flags : 0x7 ''

+0x006 UnusedBytes : 0x1e ''

+0x007 SegmentIndex : 0 ''

我們可以看到Size 是4.為什麼是4了?因為這兒的機關不是byte,而是heap granularity。通常是8.是以我們可以計算:4*8=32=0x20。

我們再看一下記憶體布局。

0:000> dd 00343810

00343810 00070004 001e0749 abab0198 abababab

00343820 feeeabab feeefeee 00000000 00000000

上圖是每個Heap Block的說明。對比我們的memory layout,我們就可以得到類似的資訊。

我們也可以下面的指令來得到更詳細的資訊。

0:000> !heap -i 00343810

Detailed information for block entry 00343810

Assumed heap : 0x00340000 (Use !heap -i NewHeapHandle to change)

Owning segment : 0x00340000 (offset 0)

Block flags : 0x7 (busy extra fill )

Total block size : 0x4 units (0x20 bytes)

Requested size : 0x2 bytes (unused 0x1e bytes)

Previous block size: 0x7 units (0x38 bytes)

Previous block : 0x003437d8

Next block : 0x00343830

運作完pChar[0] = 'a';這條指令,我們再看看記憶體。

0:000> dc 00343818

00343818 abab0161 abababab feeeabab feeefeee a...............

我們可以看到'a'寫進去了。