!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
Entry     User      Heap      Segment       Size  PrevSize  Unused    Flags
-----------------------------------------------------------------------------
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'写进去了。



原文地址:https://www.cnblogs.com/xiaxi/p/1947077.html